0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/delay.h>
0009 #include <linux/err.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/mod_devicetable.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/property.h>
0015 #include <linux/iopoll.h>
0016 #include <linux/io.h>
0017 #include <linux/iio/iio.h>
0018
0019
0020 #define MT6577_AUXADC_CON0 0x00
0021 #define MT6577_AUXADC_CON1 0x04
0022 #define MT6577_AUXADC_CON2 0x10
0023 #define MT6577_AUXADC_STA BIT(0)
0024
0025 #define MT6577_AUXADC_DAT0 0x14
0026 #define MT6577_AUXADC_RDY0 BIT(12)
0027
0028 #define MT6577_AUXADC_MISC 0x94
0029 #define MT6577_AUXADC_PDN_EN BIT(14)
0030
0031 #define MT6577_AUXADC_DAT_MASK 0xfff
0032 #define MT6577_AUXADC_SLEEP_US 1000
0033 #define MT6577_AUXADC_TIMEOUT_US 10000
0034 #define MT6577_AUXADC_POWER_READY_MS 1
0035 #define MT6577_AUXADC_SAMPLE_READY_US 25
0036
0037 struct mtk_auxadc_compatible {
0038 bool sample_data_cali;
0039 bool check_global_idle;
0040 };
0041
0042 struct mt6577_auxadc_device {
0043 void __iomem *reg_base;
0044 struct clk *adc_clk;
0045 struct mutex lock;
0046 const struct mtk_auxadc_compatible *dev_comp;
0047 };
0048
0049 static const struct mtk_auxadc_compatible mt8186_compat = {
0050 .sample_data_cali = false,
0051 .check_global_idle = false,
0052 };
0053
0054 static const struct mtk_auxadc_compatible mt8173_compat = {
0055 .sample_data_cali = false,
0056 .check_global_idle = true,
0057 };
0058
0059 static const struct mtk_auxadc_compatible mt6765_compat = {
0060 .sample_data_cali = true,
0061 .check_global_idle = false,
0062 };
0063
0064 #define MT6577_AUXADC_CHANNEL(idx) { \
0065 .type = IIO_VOLTAGE, \
0066 .indexed = 1, \
0067 .channel = (idx), \
0068 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
0069 }
0070
0071 static const struct iio_chan_spec mt6577_auxadc_iio_channels[] = {
0072 MT6577_AUXADC_CHANNEL(0),
0073 MT6577_AUXADC_CHANNEL(1),
0074 MT6577_AUXADC_CHANNEL(2),
0075 MT6577_AUXADC_CHANNEL(3),
0076 MT6577_AUXADC_CHANNEL(4),
0077 MT6577_AUXADC_CHANNEL(5),
0078 MT6577_AUXADC_CHANNEL(6),
0079 MT6577_AUXADC_CHANNEL(7),
0080 MT6577_AUXADC_CHANNEL(8),
0081 MT6577_AUXADC_CHANNEL(9),
0082 MT6577_AUXADC_CHANNEL(10),
0083 MT6577_AUXADC_CHANNEL(11),
0084 MT6577_AUXADC_CHANNEL(12),
0085 MT6577_AUXADC_CHANNEL(13),
0086 MT6577_AUXADC_CHANNEL(14),
0087 MT6577_AUXADC_CHANNEL(15),
0088 };
0089
0090
0091 #define VOLTAGE_FULL_RANGE 1500
0092 #define AUXADC_PRECISE 4096
0093
0094 static int mt_auxadc_get_cali_data(int rawdata, bool enable_cali)
0095 {
0096 return rawdata;
0097 }
0098
0099 static inline void mt6577_auxadc_mod_reg(void __iomem *reg,
0100 u32 or_mask, u32 and_mask)
0101 {
0102 u32 val;
0103
0104 val = readl(reg);
0105 val |= or_mask;
0106 val &= ~and_mask;
0107 writel(val, reg);
0108 }
0109
0110 static int mt6577_auxadc_read(struct iio_dev *indio_dev,
0111 struct iio_chan_spec const *chan)
0112 {
0113 u32 val;
0114 void __iomem *reg_channel;
0115 int ret;
0116 struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
0117
0118 reg_channel = adc_dev->reg_base + MT6577_AUXADC_DAT0 +
0119 chan->channel * 0x04;
0120
0121 mutex_lock(&adc_dev->lock);
0122
0123 mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_CON1,
0124 0, 1 << chan->channel);
0125
0126
0127 ret = readl_poll_timeout(reg_channel, val,
0128 ((val & MT6577_AUXADC_RDY0) == 0),
0129 MT6577_AUXADC_SLEEP_US,
0130 MT6577_AUXADC_TIMEOUT_US);
0131 if (ret < 0) {
0132 dev_err(indio_dev->dev.parent,
0133 "wait for channel[%d] ready bit clear time out\n",
0134 chan->channel);
0135 goto err_timeout;
0136 }
0137
0138
0139 mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_CON1,
0140 1 << chan->channel, 0);
0141
0142
0143 udelay(MT6577_AUXADC_SAMPLE_READY_US);
0144
0145 if (adc_dev->dev_comp->check_global_idle) {
0146
0147 ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2,
0148 val, ((val & MT6577_AUXADC_STA) == 0),
0149 MT6577_AUXADC_SLEEP_US,
0150 MT6577_AUXADC_TIMEOUT_US);
0151 if (ret < 0) {
0152 dev_err(indio_dev->dev.parent,
0153 "wait for auxadc idle time out\n");
0154 goto err_timeout;
0155 }
0156 }
0157
0158
0159 ret = readl_poll_timeout(reg_channel, val,
0160 ((val & MT6577_AUXADC_RDY0) != 0),
0161 MT6577_AUXADC_SLEEP_US,
0162 MT6577_AUXADC_TIMEOUT_US);
0163 if (ret < 0) {
0164 dev_err(indio_dev->dev.parent,
0165 "wait for channel[%d] data ready time out\n",
0166 chan->channel);
0167 goto err_timeout;
0168 }
0169
0170
0171 val = readl(reg_channel) & MT6577_AUXADC_DAT_MASK;
0172
0173 mutex_unlock(&adc_dev->lock);
0174
0175 return val;
0176
0177 err_timeout:
0178
0179 mutex_unlock(&adc_dev->lock);
0180
0181 return -ETIMEDOUT;
0182 }
0183
0184 static int mt6577_auxadc_read_raw(struct iio_dev *indio_dev,
0185 struct iio_chan_spec const *chan,
0186 int *val,
0187 int *val2,
0188 long info)
0189 {
0190 struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
0191
0192 switch (info) {
0193 case IIO_CHAN_INFO_PROCESSED:
0194 *val = mt6577_auxadc_read(indio_dev, chan);
0195 if (*val < 0) {
0196 dev_err(indio_dev->dev.parent,
0197 "failed to sample data on channel[%d]\n",
0198 chan->channel);
0199 return *val;
0200 }
0201 if (adc_dev->dev_comp->sample_data_cali)
0202 *val = mt_auxadc_get_cali_data(*val, true);
0203
0204
0205 *val = *val * VOLTAGE_FULL_RANGE / AUXADC_PRECISE;
0206
0207 return IIO_VAL_INT;
0208
0209 default:
0210 return -EINVAL;
0211 }
0212 }
0213
0214 static const struct iio_info mt6577_auxadc_info = {
0215 .read_raw = &mt6577_auxadc_read_raw,
0216 };
0217
0218 static int mt6577_auxadc_resume(struct device *dev)
0219 {
0220 struct iio_dev *indio_dev = dev_get_drvdata(dev);
0221 struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
0222 int ret;
0223
0224 ret = clk_prepare_enable(adc_dev->adc_clk);
0225 if (ret) {
0226 pr_err("failed to enable auxadc clock\n");
0227 return ret;
0228 }
0229
0230 mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0231 MT6577_AUXADC_PDN_EN, 0);
0232 mdelay(MT6577_AUXADC_POWER_READY_MS);
0233
0234 return 0;
0235 }
0236
0237 static int mt6577_auxadc_suspend(struct device *dev)
0238 {
0239 struct iio_dev *indio_dev = dev_get_drvdata(dev);
0240 struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
0241
0242 mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0243 0, MT6577_AUXADC_PDN_EN);
0244 clk_disable_unprepare(adc_dev->adc_clk);
0245
0246 return 0;
0247 }
0248
0249 static int mt6577_auxadc_probe(struct platform_device *pdev)
0250 {
0251 struct mt6577_auxadc_device *adc_dev;
0252 unsigned long adc_clk_rate;
0253 struct iio_dev *indio_dev;
0254 int ret;
0255
0256 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
0257 if (!indio_dev)
0258 return -ENOMEM;
0259
0260 adc_dev = iio_priv(indio_dev);
0261 indio_dev->name = dev_name(&pdev->dev);
0262 indio_dev->info = &mt6577_auxadc_info;
0263 indio_dev->modes = INDIO_DIRECT_MODE;
0264 indio_dev->channels = mt6577_auxadc_iio_channels;
0265 indio_dev->num_channels = ARRAY_SIZE(mt6577_auxadc_iio_channels);
0266
0267 adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0);
0268 if (IS_ERR(adc_dev->reg_base)) {
0269 dev_err(&pdev->dev, "failed to get auxadc base address\n");
0270 return PTR_ERR(adc_dev->reg_base);
0271 }
0272
0273 adc_dev->adc_clk = devm_clk_get(&pdev->dev, "main");
0274 if (IS_ERR(adc_dev->adc_clk)) {
0275 dev_err(&pdev->dev, "failed to get auxadc clock\n");
0276 return PTR_ERR(adc_dev->adc_clk);
0277 }
0278
0279 ret = clk_prepare_enable(adc_dev->adc_clk);
0280 if (ret) {
0281 dev_err(&pdev->dev, "failed to enable auxadc clock\n");
0282 return ret;
0283 }
0284
0285 adc_clk_rate = clk_get_rate(adc_dev->adc_clk);
0286 if (!adc_clk_rate) {
0287 ret = -EINVAL;
0288 dev_err(&pdev->dev, "null clock rate\n");
0289 goto err_disable_clk;
0290 }
0291
0292 adc_dev->dev_comp = device_get_match_data(&pdev->dev);
0293
0294 mutex_init(&adc_dev->lock);
0295
0296 mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0297 MT6577_AUXADC_PDN_EN, 0);
0298 mdelay(MT6577_AUXADC_POWER_READY_MS);
0299
0300 platform_set_drvdata(pdev, indio_dev);
0301
0302 ret = iio_device_register(indio_dev);
0303 if (ret < 0) {
0304 dev_err(&pdev->dev, "failed to register iio device\n");
0305 goto err_power_off;
0306 }
0307
0308 return 0;
0309
0310 err_power_off:
0311 mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0312 0, MT6577_AUXADC_PDN_EN);
0313 err_disable_clk:
0314 clk_disable_unprepare(adc_dev->adc_clk);
0315 return ret;
0316 }
0317
0318 static int mt6577_auxadc_remove(struct platform_device *pdev)
0319 {
0320 struct iio_dev *indio_dev = platform_get_drvdata(pdev);
0321 struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
0322
0323 iio_device_unregister(indio_dev);
0324
0325 mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0326 0, MT6577_AUXADC_PDN_EN);
0327
0328 clk_disable_unprepare(adc_dev->adc_clk);
0329
0330 return 0;
0331 }
0332
0333 static DEFINE_SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops,
0334 mt6577_auxadc_suspend,
0335 mt6577_auxadc_resume);
0336
0337 static const struct of_device_id mt6577_auxadc_of_match[] = {
0338 { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat },
0339 { .compatible = "mediatek,mt2712-auxadc", .data = &mt8173_compat },
0340 { .compatible = "mediatek,mt7622-auxadc", .data = &mt8173_compat },
0341 { .compatible = "mediatek,mt8173-auxadc", .data = &mt8173_compat },
0342 { .compatible = "mediatek,mt8186-auxadc", .data = &mt8186_compat },
0343 { .compatible = "mediatek,mt6765-auxadc", .data = &mt6765_compat },
0344 { }
0345 };
0346 MODULE_DEVICE_TABLE(of, mt6577_auxadc_of_match);
0347
0348 static struct platform_driver mt6577_auxadc_driver = {
0349 .driver = {
0350 .name = "mt6577-auxadc",
0351 .of_match_table = mt6577_auxadc_of_match,
0352 .pm = pm_sleep_ptr(&mt6577_auxadc_pm_ops),
0353 },
0354 .probe = mt6577_auxadc_probe,
0355 .remove = mt6577_auxadc_remove,
0356 };
0357 module_platform_driver(mt6577_auxadc_driver);
0358
0359 MODULE_AUTHOR("Zhiyong Tao <zhiyong.tao@mediatek.com>");
0360 MODULE_DESCRIPTION("MTK AUXADC Device Driver");
0361 MODULE_LICENSE("GPL v2");