0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/mfd/ntxec.h>
0020 #include <linux/module.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/pwm.h>
0023 #include <linux/regmap.h>
0024 #include <linux/types.h>
0025
0026 struct ntxec_pwm {
0027 struct device *dev;
0028 struct ntxec *ec;
0029 struct pwm_chip chip;
0030 };
0031
0032 static struct ntxec_pwm *ntxec_pwm_from_chip(struct pwm_chip *chip)
0033 {
0034 return container_of(chip, struct ntxec_pwm, chip);
0035 }
0036
0037 #define NTXEC_REG_AUTO_OFF_HI 0xa1
0038 #define NTXEC_REG_AUTO_OFF_LO 0xa2
0039 #define NTXEC_REG_ENABLE 0xa3
0040 #define NTXEC_REG_PERIOD_LOW 0xa4
0041 #define NTXEC_REG_PERIOD_HIGH 0xa5
0042 #define NTXEC_REG_DUTY_LOW 0xa6
0043 #define NTXEC_REG_DUTY_HIGH 0xa7
0044
0045
0046
0047
0048
0049 #define TIME_BASE_NS 125
0050
0051
0052
0053
0054
0055
0056 #define MAX_PERIOD_NS (TIME_BASE_NS * 0xffff)
0057
0058 static int ntxec_pwm_set_raw_period_and_duty_cycle(struct pwm_chip *chip,
0059 int period, int duty)
0060 {
0061 struct ntxec_pwm *priv = ntxec_pwm_from_chip(chip);
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 struct reg_sequence regs[] = {
0075 { NTXEC_REG_PERIOD_HIGH, ntxec_reg8(period >> 8) },
0076 { NTXEC_REG_DUTY_HIGH, ntxec_reg8(duty >> 8) },
0077 { NTXEC_REG_PERIOD_LOW, ntxec_reg8(period) },
0078 { NTXEC_REG_DUTY_LOW, ntxec_reg8(duty) },
0079 };
0080
0081 return regmap_multi_reg_write(priv->ec->regmap, regs, ARRAY_SIZE(regs));
0082 }
0083
0084 static int ntxec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm_dev,
0085 const struct pwm_state *state)
0086 {
0087 struct ntxec_pwm *priv = ntxec_pwm_from_chip(chip);
0088 unsigned int period, duty;
0089 int res;
0090
0091 if (state->polarity != PWM_POLARITY_NORMAL)
0092 return -EINVAL;
0093
0094 period = min_t(u64, state->period, MAX_PERIOD_NS);
0095 duty = min_t(u64, state->duty_cycle, period);
0096
0097 period /= TIME_BASE_NS;
0098 duty /= TIME_BASE_NS;
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 if (state->enabled && duty != 0) {
0110 res = ntxec_pwm_set_raw_period_and_duty_cycle(chip, period, duty);
0111 if (res)
0112 return res;
0113
0114 res = regmap_write(priv->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(1));
0115 if (res)
0116 return res;
0117
0118
0119 res = regmap_write(priv->ec->regmap, NTXEC_REG_AUTO_OFF_HI, ntxec_reg8(0xff));
0120 if (res)
0121 return res;
0122
0123 return regmap_write(priv->ec->regmap, NTXEC_REG_AUTO_OFF_LO, ntxec_reg8(0xff));
0124 } else {
0125 return regmap_write(priv->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(0));
0126 }
0127 }
0128
0129 static const struct pwm_ops ntxec_pwm_ops = {
0130 .owner = THIS_MODULE,
0131 .apply = ntxec_pwm_apply,
0132
0133
0134
0135
0136 };
0137
0138 static int ntxec_pwm_probe(struct platform_device *pdev)
0139 {
0140 struct ntxec *ec = dev_get_drvdata(pdev->dev.parent);
0141 struct ntxec_pwm *priv;
0142 struct pwm_chip *chip;
0143
0144 pdev->dev.of_node = pdev->dev.parent->of_node;
0145
0146 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0147 if (!priv)
0148 return -ENOMEM;
0149
0150 priv->ec = ec;
0151 priv->dev = &pdev->dev;
0152
0153 chip = &priv->chip;
0154 chip->dev = &pdev->dev;
0155 chip->ops = &ntxec_pwm_ops;
0156 chip->npwm = 1;
0157
0158 return devm_pwmchip_add(&pdev->dev, chip);
0159 }
0160
0161 static struct platform_driver ntxec_pwm_driver = {
0162 .driver = {
0163 .name = "ntxec-pwm",
0164 },
0165 .probe = ntxec_pwm_probe,
0166 };
0167 module_platform_driver(ntxec_pwm_driver);
0168
0169 MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
0170 MODULE_DESCRIPTION("PWM driver for Netronix EC");
0171 MODULE_LICENSE("GPL");
0172 MODULE_ALIAS("platform:ntxec-pwm");