0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/err.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/io.h>
0012 #include <linux/kernel.h>
0013 #include <linux/mod_devicetable.h>
0014 #include <linux/module.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/regulator/consumer.h>
0017 #include <linux/slab.h>
0018
0019 #include <linux/iio/iio.h>
0020 #include <linux/iio/sysfs.h>
0021
0022 #define VF610_DACx_STATCTRL 0x20
0023
0024 #define VF610_DAC_DACEN BIT(15)
0025 #define VF610_DAC_DACRFS BIT(14)
0026 #define VF610_DAC_LPEN BIT(11)
0027
0028 #define VF610_DAC_DAT0(x) ((x) & 0xFFF)
0029
0030 enum vf610_conversion_mode_sel {
0031 VF610_DAC_CONV_HIGH_POWER,
0032 VF610_DAC_CONV_LOW_POWER,
0033 };
0034
0035 struct vf610_dac {
0036 struct clk *clk;
0037 struct device *dev;
0038 enum vf610_conversion_mode_sel conv_mode;
0039 void __iomem *regs;
0040 struct mutex lock;
0041 };
0042
0043 static void vf610_dac_init(struct vf610_dac *info)
0044 {
0045 int val;
0046
0047 info->conv_mode = VF610_DAC_CONV_LOW_POWER;
0048 val = VF610_DAC_DACEN | VF610_DAC_DACRFS |
0049 VF610_DAC_LPEN;
0050 writel(val, info->regs + VF610_DACx_STATCTRL);
0051 }
0052
0053 static void vf610_dac_exit(struct vf610_dac *info)
0054 {
0055 int val;
0056
0057 val = readl(info->regs + VF610_DACx_STATCTRL);
0058 val &= ~VF610_DAC_DACEN;
0059 writel(val, info->regs + VF610_DACx_STATCTRL);
0060 }
0061
0062 static int vf610_set_conversion_mode(struct iio_dev *indio_dev,
0063 const struct iio_chan_spec *chan,
0064 unsigned int mode)
0065 {
0066 struct vf610_dac *info = iio_priv(indio_dev);
0067 int val;
0068
0069 mutex_lock(&info->lock);
0070 info->conv_mode = mode;
0071 val = readl(info->regs + VF610_DACx_STATCTRL);
0072 if (mode)
0073 val |= VF610_DAC_LPEN;
0074 else
0075 val &= ~VF610_DAC_LPEN;
0076 writel(val, info->regs + VF610_DACx_STATCTRL);
0077 mutex_unlock(&info->lock);
0078
0079 return 0;
0080 }
0081
0082 static int vf610_get_conversion_mode(struct iio_dev *indio_dev,
0083 const struct iio_chan_spec *chan)
0084 {
0085 struct vf610_dac *info = iio_priv(indio_dev);
0086
0087 return info->conv_mode;
0088 }
0089
0090 static const char * const vf610_conv_modes[] = { "high-power", "low-power" };
0091
0092 static const struct iio_enum vf610_conversion_mode = {
0093 .items = vf610_conv_modes,
0094 .num_items = ARRAY_SIZE(vf610_conv_modes),
0095 .get = vf610_get_conversion_mode,
0096 .set = vf610_set_conversion_mode,
0097 };
0098
0099 static const struct iio_chan_spec_ext_info vf610_ext_info[] = {
0100 IIO_ENUM("conversion_mode", IIO_SHARED_BY_DIR,
0101 &vf610_conversion_mode),
0102 {},
0103 };
0104
0105 #define VF610_DAC_CHAN(_chan_type) { \
0106 .type = (_chan_type), \
0107 .output = 1, \
0108 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
0109 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
0110 .ext_info = vf610_ext_info, \
0111 }
0112
0113 static const struct iio_chan_spec vf610_dac_iio_channels[] = {
0114 VF610_DAC_CHAN(IIO_VOLTAGE),
0115 };
0116
0117 static int vf610_read_raw(struct iio_dev *indio_dev,
0118 struct iio_chan_spec const *chan,
0119 int *val, int *val2,
0120 long mask)
0121 {
0122 struct vf610_dac *info = iio_priv(indio_dev);
0123
0124 switch (mask) {
0125 case IIO_CHAN_INFO_RAW:
0126 *val = VF610_DAC_DAT0(readl(info->regs));
0127 return IIO_VAL_INT;
0128 case IIO_CHAN_INFO_SCALE:
0129
0130
0131
0132
0133
0134 *val = 3300 ;
0135 *val2 = 12;
0136 return IIO_VAL_FRACTIONAL_LOG2;
0137
0138 default:
0139 return -EINVAL;
0140 }
0141 }
0142
0143 static int vf610_write_raw(struct iio_dev *indio_dev,
0144 struct iio_chan_spec const *chan,
0145 int val, int val2,
0146 long mask)
0147 {
0148 struct vf610_dac *info = iio_priv(indio_dev);
0149
0150 switch (mask) {
0151 case IIO_CHAN_INFO_RAW:
0152 mutex_lock(&info->lock);
0153 writel(VF610_DAC_DAT0(val), info->regs);
0154 mutex_unlock(&info->lock);
0155 return 0;
0156
0157 default:
0158 return -EINVAL;
0159 }
0160 }
0161
0162 static const struct iio_info vf610_dac_iio_info = {
0163 .read_raw = &vf610_read_raw,
0164 .write_raw = &vf610_write_raw,
0165 };
0166
0167 static const struct of_device_id vf610_dac_match[] = {
0168 { .compatible = "fsl,vf610-dac", },
0169 { }
0170 };
0171 MODULE_DEVICE_TABLE(of, vf610_dac_match);
0172
0173 static int vf610_dac_probe(struct platform_device *pdev)
0174 {
0175 struct iio_dev *indio_dev;
0176 struct vf610_dac *info;
0177 int ret;
0178
0179 indio_dev = devm_iio_device_alloc(&pdev->dev,
0180 sizeof(struct vf610_dac));
0181 if (!indio_dev) {
0182 dev_err(&pdev->dev, "Failed allocating iio device\n");
0183 return -ENOMEM;
0184 }
0185
0186 info = iio_priv(indio_dev);
0187 info->dev = &pdev->dev;
0188
0189 info->regs = devm_platform_ioremap_resource(pdev, 0);
0190 if (IS_ERR(info->regs))
0191 return PTR_ERR(info->regs);
0192
0193 info->clk = devm_clk_get(&pdev->dev, "dac");
0194 if (IS_ERR(info->clk)) {
0195 dev_err(&pdev->dev, "Failed getting clock, err = %ld\n",
0196 PTR_ERR(info->clk));
0197 return PTR_ERR(info->clk);
0198 }
0199
0200 platform_set_drvdata(pdev, indio_dev);
0201
0202 indio_dev->name = dev_name(&pdev->dev);
0203 indio_dev->info = &vf610_dac_iio_info;
0204 indio_dev->modes = INDIO_DIRECT_MODE;
0205 indio_dev->channels = vf610_dac_iio_channels;
0206 indio_dev->num_channels = ARRAY_SIZE(vf610_dac_iio_channels);
0207
0208 mutex_init(&info->lock);
0209
0210 ret = clk_prepare_enable(info->clk);
0211 if (ret) {
0212 dev_err(&pdev->dev,
0213 "Could not prepare or enable the clock\n");
0214 return ret;
0215 }
0216
0217 vf610_dac_init(info);
0218
0219 ret = iio_device_register(indio_dev);
0220 if (ret) {
0221 dev_err(&pdev->dev, "Couldn't register the device\n");
0222 goto error_iio_device_register;
0223 }
0224
0225 return 0;
0226
0227 error_iio_device_register:
0228 vf610_dac_exit(info);
0229 clk_disable_unprepare(info->clk);
0230
0231 return ret;
0232 }
0233
0234 static int vf610_dac_remove(struct platform_device *pdev)
0235 {
0236 struct iio_dev *indio_dev = platform_get_drvdata(pdev);
0237 struct vf610_dac *info = iio_priv(indio_dev);
0238
0239 iio_device_unregister(indio_dev);
0240 vf610_dac_exit(info);
0241 clk_disable_unprepare(info->clk);
0242
0243 return 0;
0244 }
0245
0246 static int vf610_dac_suspend(struct device *dev)
0247 {
0248 struct iio_dev *indio_dev = dev_get_drvdata(dev);
0249 struct vf610_dac *info = iio_priv(indio_dev);
0250
0251 vf610_dac_exit(info);
0252 clk_disable_unprepare(info->clk);
0253
0254 return 0;
0255 }
0256
0257 static int vf610_dac_resume(struct device *dev)
0258 {
0259 struct iio_dev *indio_dev = dev_get_drvdata(dev);
0260 struct vf610_dac *info = iio_priv(indio_dev);
0261 int ret;
0262
0263 ret = clk_prepare_enable(info->clk);
0264 if (ret)
0265 return ret;
0266
0267 vf610_dac_init(info);
0268
0269 return 0;
0270 }
0271
0272 static DEFINE_SIMPLE_DEV_PM_OPS(vf610_dac_pm_ops, vf610_dac_suspend,
0273 vf610_dac_resume);
0274
0275 static struct platform_driver vf610_dac_driver = {
0276 .probe = vf610_dac_probe,
0277 .remove = vf610_dac_remove,
0278 .driver = {
0279 .name = "vf610-dac",
0280 .of_match_table = vf610_dac_match,
0281 .pm = pm_sleep_ptr(&vf610_dac_pm_ops),
0282 },
0283 };
0284 module_platform_driver(vf610_dac_driver);
0285
0286 MODULE_AUTHOR("Sanchayan Maity <sanchayan.maity@toradex.com>");
0287 MODULE_DESCRIPTION("Freescale VF610 DAC driver");
0288 MODULE_LICENSE("GPL v2");