Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Expose a PWM controlled by the ChromeOS EC to the host processor.
0004  *
0005  * Copyright (C) 2016 Google, Inc.
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/platform_data/cros_ec_commands.h>
0010 #include <linux/platform_data/cros_ec_proto.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/pwm.h>
0013 #include <linux/slab.h>
0014 
0015 #include <dt-bindings/mfd/cros_ec.h>
0016 
0017 /**
0018  * struct cros_ec_pwm_device - Driver data for EC PWM
0019  *
0020  * @dev: Device node
0021  * @ec: Pointer to EC device
0022  * @chip: PWM controller chip
0023  * @use_pwm_type: Use PWM types instead of generic channels
0024  */
0025 struct cros_ec_pwm_device {
0026     struct device *dev;
0027     struct cros_ec_device *ec;
0028     struct pwm_chip chip;
0029     bool use_pwm_type;
0030 };
0031 
0032 /**
0033  * struct cros_ec_pwm - per-PWM driver data
0034  * @duty_cycle: cached duty cycle
0035  */
0036 struct cros_ec_pwm {
0037     u16 duty_cycle;
0038 };
0039 
0040 static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *c)
0041 {
0042     return container_of(c, struct cros_ec_pwm_device, chip);
0043 }
0044 
0045 static int cros_ec_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
0046 {
0047     struct cros_ec_pwm *channel;
0048 
0049     channel = kzalloc(sizeof(*channel), GFP_KERNEL);
0050     if (!channel)
0051         return -ENOMEM;
0052 
0053     pwm_set_chip_data(pwm, channel);
0054 
0055     return 0;
0056 }
0057 
0058 static void cros_ec_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
0059 {
0060     struct cros_ec_pwm *channel = pwm_get_chip_data(pwm);
0061 
0062     kfree(channel);
0063 }
0064 
0065 static int cros_ec_dt_type_to_pwm_type(u8 dt_index, u8 *pwm_type)
0066 {
0067     switch (dt_index) {
0068     case CROS_EC_PWM_DT_KB_LIGHT:
0069         *pwm_type = EC_PWM_TYPE_KB_LIGHT;
0070         return 0;
0071     case CROS_EC_PWM_DT_DISPLAY_LIGHT:
0072         *pwm_type = EC_PWM_TYPE_DISPLAY_LIGHT;
0073         return 0;
0074     default:
0075         return -EINVAL;
0076     }
0077 }
0078 
0079 static int cros_ec_pwm_set_duty(struct cros_ec_pwm_device *ec_pwm, u8 index,
0080                 u16 duty)
0081 {
0082     struct cros_ec_device *ec = ec_pwm->ec;
0083     struct {
0084         struct cros_ec_command msg;
0085         struct ec_params_pwm_set_duty params;
0086     } __packed buf;
0087     struct ec_params_pwm_set_duty *params = &buf.params;
0088     struct cros_ec_command *msg = &buf.msg;
0089     int ret;
0090 
0091     memset(&buf, 0, sizeof(buf));
0092 
0093     msg->version = 0;
0094     msg->command = EC_CMD_PWM_SET_DUTY;
0095     msg->insize = 0;
0096     msg->outsize = sizeof(*params);
0097 
0098     params->duty = duty;
0099 
0100     if (ec_pwm->use_pwm_type) {
0101         ret = cros_ec_dt_type_to_pwm_type(index, &params->pwm_type);
0102         if (ret) {
0103             dev_err(ec->dev, "Invalid PWM type index: %d\n", index);
0104             return ret;
0105         }
0106         params->index = 0;
0107     } else {
0108         params->pwm_type = EC_PWM_TYPE_GENERIC;
0109         params->index = index;
0110     }
0111 
0112     return cros_ec_cmd_xfer_status(ec, msg);
0113 }
0114 
0115 static int cros_ec_pwm_get_duty(struct cros_ec_pwm_device *ec_pwm, u8 index)
0116 {
0117     struct cros_ec_device *ec = ec_pwm->ec;
0118     struct {
0119         struct cros_ec_command msg;
0120         union {
0121             struct ec_params_pwm_get_duty params;
0122             struct ec_response_pwm_get_duty resp;
0123         };
0124     } __packed buf;
0125     struct ec_params_pwm_get_duty *params = &buf.params;
0126     struct ec_response_pwm_get_duty *resp = &buf.resp;
0127     struct cros_ec_command *msg = &buf.msg;
0128     int ret;
0129 
0130     memset(&buf, 0, sizeof(buf));
0131 
0132     msg->version = 0;
0133     msg->command = EC_CMD_PWM_GET_DUTY;
0134     msg->insize = sizeof(*resp);
0135     msg->outsize = sizeof(*params);
0136 
0137     if (ec_pwm->use_pwm_type) {
0138         ret = cros_ec_dt_type_to_pwm_type(index, &params->pwm_type);
0139         if (ret) {
0140             dev_err(ec->dev, "Invalid PWM type index: %d\n", index);
0141             return ret;
0142         }
0143         params->index = 0;
0144     } else {
0145         params->pwm_type = EC_PWM_TYPE_GENERIC;
0146         params->index = index;
0147     }
0148 
0149     ret = cros_ec_cmd_xfer_status(ec, msg);
0150     if (ret < 0)
0151         return ret;
0152 
0153     return resp->duty;
0154 }
0155 
0156 static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
0157                  const struct pwm_state *state)
0158 {
0159     struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
0160     struct cros_ec_pwm *channel = pwm_get_chip_data(pwm);
0161     u16 duty_cycle;
0162     int ret;
0163 
0164     /* The EC won't let us change the period */
0165     if (state->period != EC_PWM_MAX_DUTY)
0166         return -EINVAL;
0167 
0168     if (state->polarity != PWM_POLARITY_NORMAL)
0169         return -EINVAL;
0170 
0171     /*
0172      * EC doesn't separate the concept of duty cycle and enabled, but
0173      * kernel does. Translate.
0174      */
0175     duty_cycle = state->enabled ? state->duty_cycle : 0;
0176 
0177     ret = cros_ec_pwm_set_duty(ec_pwm, pwm->hwpwm, duty_cycle);
0178     if (ret < 0)
0179         return ret;
0180 
0181     channel->duty_cycle = state->duty_cycle;
0182 
0183     return 0;
0184 }
0185 
0186 static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
0187                   struct pwm_state *state)
0188 {
0189     struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
0190     struct cros_ec_pwm *channel = pwm_get_chip_data(pwm);
0191     int ret;
0192 
0193     ret = cros_ec_pwm_get_duty(ec_pwm, pwm->hwpwm);
0194     if (ret < 0) {
0195         dev_err(chip->dev, "error getting initial duty: %d\n", ret);
0196         return;
0197     }
0198 
0199     state->enabled = (ret > 0);
0200     state->period = EC_PWM_MAX_DUTY;
0201 
0202     /*
0203      * Note that "disabled" and "duty cycle == 0" are treated the same. If
0204      * the cached duty cycle is not zero, used the cached duty cycle. This
0205      * ensures that the configured duty cycle is kept across a disable and
0206      * enable operation and avoids potentially confusing consumers.
0207      *
0208      * For the case of the initial hardware readout, channel->duty_cycle
0209      * will be 0 and the actual duty cycle read from the EC is used.
0210      */
0211     if (ret == 0 && channel->duty_cycle > 0)
0212         state->duty_cycle = channel->duty_cycle;
0213     else
0214         state->duty_cycle = ret;
0215 }
0216 
0217 static struct pwm_device *
0218 cros_ec_pwm_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
0219 {
0220     struct pwm_device *pwm;
0221 
0222     if (args->args[0] >= pc->npwm)
0223         return ERR_PTR(-EINVAL);
0224 
0225     pwm = pwm_request_from_chip(pc, args->args[0], NULL);
0226     if (IS_ERR(pwm))
0227         return pwm;
0228 
0229     /* The EC won't let us change the period */
0230     pwm->args.period = EC_PWM_MAX_DUTY;
0231 
0232     return pwm;
0233 }
0234 
0235 static const struct pwm_ops cros_ec_pwm_ops = {
0236     .request = cros_ec_pwm_request,
0237     .free = cros_ec_pwm_free,
0238     .get_state  = cros_ec_pwm_get_state,
0239     .apply      = cros_ec_pwm_apply,
0240     .owner      = THIS_MODULE,
0241 };
0242 
0243 /*
0244  * Determine the number of supported PWMs. The EC does not return the number
0245  * of PWMs it supports directly, so we have to read the pwm duty cycle for
0246  * subsequent channels until we get an error.
0247  */
0248 static int cros_ec_num_pwms(struct cros_ec_pwm_device *ec_pwm)
0249 {
0250     int i, ret;
0251 
0252     /* The index field is only 8 bits */
0253     for (i = 0; i <= U8_MAX; i++) {
0254         ret = cros_ec_pwm_get_duty(ec_pwm, i);
0255         /*
0256          * We look for SUCCESS, INVALID_COMMAND, or INVALID_PARAM
0257          * responses; everything else is treated as an error.
0258          * The EC error codes map to -EOPNOTSUPP and -EINVAL,
0259          * so check for those.
0260          */
0261         switch (ret) {
0262         case -EOPNOTSUPP:   /* invalid command */
0263             return -ENODEV;
0264         case -EINVAL:       /* invalid parameter */
0265             return i;
0266         default:
0267             if (ret < 0)
0268                 return ret;
0269             break;
0270         }
0271     }
0272 
0273     return U8_MAX;
0274 }
0275 
0276 static int cros_ec_pwm_probe(struct platform_device *pdev)
0277 {
0278     struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
0279     struct device *dev = &pdev->dev;
0280     struct device_node *np = pdev->dev.of_node;
0281     struct cros_ec_pwm_device *ec_pwm;
0282     struct pwm_chip *chip;
0283     int ret;
0284 
0285     if (!ec) {
0286         dev_err(dev, "no parent EC device\n");
0287         return -EINVAL;
0288     }
0289 
0290     ec_pwm = devm_kzalloc(dev, sizeof(*ec_pwm), GFP_KERNEL);
0291     if (!ec_pwm)
0292         return -ENOMEM;
0293     chip = &ec_pwm->chip;
0294     ec_pwm->ec = ec;
0295 
0296     if (of_device_is_compatible(np, "google,cros-ec-pwm-type"))
0297         ec_pwm->use_pwm_type = true;
0298 
0299     /* PWM chip */
0300     chip->dev = dev;
0301     chip->ops = &cros_ec_pwm_ops;
0302     chip->of_xlate = cros_ec_pwm_xlate;
0303     chip->of_pwm_n_cells = 1;
0304 
0305     if (ec_pwm->use_pwm_type) {
0306         chip->npwm = CROS_EC_PWM_DT_COUNT;
0307     } else {
0308         ret = cros_ec_num_pwms(ec_pwm);
0309         if (ret < 0) {
0310             dev_err(dev, "Couldn't find PWMs: %d\n", ret);
0311             return ret;
0312         }
0313         chip->npwm = ret;
0314     }
0315 
0316     dev_dbg(dev, "Probed %u PWMs\n", chip->npwm);
0317 
0318     ret = pwmchip_add(chip);
0319     if (ret < 0) {
0320         dev_err(dev, "cannot register PWM: %d\n", ret);
0321         return ret;
0322     }
0323 
0324     platform_set_drvdata(pdev, ec_pwm);
0325 
0326     return ret;
0327 }
0328 
0329 static int cros_ec_pwm_remove(struct platform_device *dev)
0330 {
0331     struct cros_ec_pwm_device *ec_pwm = platform_get_drvdata(dev);
0332     struct pwm_chip *chip = &ec_pwm->chip;
0333 
0334     pwmchip_remove(chip);
0335 
0336     return 0;
0337 }
0338 
0339 #ifdef CONFIG_OF
0340 static const struct of_device_id cros_ec_pwm_of_match[] = {
0341     { .compatible = "google,cros-ec-pwm" },
0342     { .compatible = "google,cros-ec-pwm-type" },
0343     {},
0344 };
0345 MODULE_DEVICE_TABLE(of, cros_ec_pwm_of_match);
0346 #endif
0347 
0348 static struct platform_driver cros_ec_pwm_driver = {
0349     .probe = cros_ec_pwm_probe,
0350     .remove = cros_ec_pwm_remove,
0351     .driver = {
0352         .name = "cros-ec-pwm",
0353         .of_match_table = of_match_ptr(cros_ec_pwm_of_match),
0354     },
0355 };
0356 module_platform_driver(cros_ec_pwm_driver);
0357 
0358 MODULE_ALIAS("platform:cros-ec-pwm");
0359 MODULE_DESCRIPTION("ChromeOS EC PWM driver");
0360 MODULE_LICENSE("GPL v2");