Merge https://gitlab.denx.de/u-boot/custodians/u-boot-fsl-qoriq
[platform/kernel/u-boot.git] / drivers / pwm / cros_ec_pwm.c
1 // SPDX-License-Identifier: GPL-2.0+
2
3 #include <common.h>
4 #include <cros_ec.h>
5 #include <dm.h>
6 #include <errno.h>
7 #include <log.h>
8 #include <pwm.h>
9
10 struct cros_ec_pwm_priv {
11         bool enabled;
12         uint duty;
13 };
14
15 static int cros_ec_pwm_set_config(struct udevice *dev, uint channel,
16                                   uint period_ns, uint duty_ns)
17 {
18         struct cros_ec_pwm_priv *priv = dev_get_priv(dev);
19         uint duty;
20         int ret;
21
22         debug("%s: period_ns=%u, duty_ns=%u asked\n", __func__,
23               period_ns, duty_ns);
24
25         /* No way to set the period, only a relative duty cycle */
26         duty = EC_PWM_MAX_DUTY * duty_ns / period_ns;
27         if (duty > EC_PWM_MAX_DUTY)
28                 duty = EC_PWM_MAX_DUTY;
29
30         if (!priv->enabled) {
31                 priv->duty = duty;
32                 debug("%s: duty=%#x to-be-set\n", __func__, duty);
33                 return 0;
34         }
35
36         ret = cros_ec_set_pwm_duty(dev->parent, channel, duty);
37         if (ret) {
38                 debug("%s: duty=%#x failed\n", __func__, duty);
39                 return ret;
40         }
41
42         priv->duty = duty;
43         debug("%s: duty=%#x set\n", __func__, duty);
44
45         return 0;
46 }
47
48 static int cros_ec_pwm_set_enable(struct udevice *dev, uint channel,
49                                   bool enable)
50 {
51         struct cros_ec_pwm_priv *priv = dev_get_priv(dev);
52         int ret;
53
54         ret = cros_ec_set_pwm_duty(dev->parent, channel,
55                                    enable ? priv->duty : 0);
56         if (ret) {
57                 debug("%s: enable=%d failed\n", __func__, enable);
58                 return ret;
59         }
60
61         priv->enabled = enable;
62         debug("%s: enable=%d (duty=%#x) set\n", __func__,
63               enable, priv->duty);
64
65         return 0;
66 }
67
68 static const struct pwm_ops cros_ec_pwm_ops = {
69         .set_config     = cros_ec_pwm_set_config,
70         .set_enable     = cros_ec_pwm_set_enable,
71 };
72
73 static const struct udevice_id cros_ec_pwm_ids[] = {
74         { .compatible = "google,cros-ec-pwm" },
75         { }
76 };
77
78 U_BOOT_DRIVER(cros_ec_pwm) = {
79         .name   = "cros_ec_pwm",
80         .id     = UCLASS_PWM,
81         .of_match = cros_ec_pwm_ids,
82         .ops    = &cros_ec_pwm_ops,
83         .priv_auto = sizeof(struct cros_ec_pwm_priv),
84 };