0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/slab.h>
0010 #include <linux/err.h>
0011 #include <linux/io.h>
0012 #include <linux/clk.h>
0013 #include <linux/regmap.h>
0014 #include <linux/mfd/core.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/of.h>
0017 #include <linux/of_device.h>
0018 #include <linux/sched.h>
0019
0020 #include <linux/mfd/ti_am335x_tscadc.h>
0021
0022 static const struct regmap_config tscadc_regmap_config = {
0023 .name = "ti_tscadc",
0024 .reg_bits = 32,
0025 .reg_stride = 4,
0026 .val_bits = 32,
0027 };
0028
0029 void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tscadc, u32 val)
0030 {
0031 unsigned long flags;
0032
0033 spin_lock_irqsave(&tscadc->reg_lock, flags);
0034 tscadc->reg_se_cache |= val;
0035 if (tscadc->adc_waiting)
0036 wake_up(&tscadc->reg_se_wait);
0037 else if (!tscadc->adc_in_use)
0038 regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache);
0039
0040 spin_unlock_irqrestore(&tscadc->reg_lock, flags);
0041 }
0042 EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache);
0043
0044 static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tscadc)
0045 {
0046 DEFINE_WAIT(wait);
0047 u32 reg;
0048
0049 regmap_read(tscadc->regmap, REG_ADCFSM, ®);
0050 if (reg & SEQ_STATUS) {
0051 tscadc->adc_waiting = true;
0052 prepare_to_wait(&tscadc->reg_se_wait, &wait,
0053 TASK_UNINTERRUPTIBLE);
0054 spin_unlock_irq(&tscadc->reg_lock);
0055
0056 schedule();
0057
0058 spin_lock_irq(&tscadc->reg_lock);
0059 finish_wait(&tscadc->reg_se_wait, &wait);
0060
0061
0062
0063
0064
0065 regmap_read(tscadc->regmap, REG_ADCFSM, ®);
0066 WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP));
0067 tscadc->adc_waiting = false;
0068 }
0069 tscadc->adc_in_use = true;
0070 }
0071
0072 void am335x_tsc_se_set_once(struct ti_tscadc_dev *tscadc, u32 val)
0073 {
0074 spin_lock_irq(&tscadc->reg_lock);
0075 am335x_tscadc_need_adc(tscadc);
0076
0077 regmap_write(tscadc->regmap, REG_SE, val);
0078 spin_unlock_irq(&tscadc->reg_lock);
0079 }
0080 EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
0081
0082 void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tscadc)
0083 {
0084 unsigned long flags;
0085
0086 spin_lock_irqsave(&tscadc->reg_lock, flags);
0087 tscadc->adc_in_use = false;
0088 regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache);
0089 spin_unlock_irqrestore(&tscadc->reg_lock, flags);
0090 }
0091 EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done);
0092
0093 void am335x_tsc_se_clr(struct ti_tscadc_dev *tscadc, u32 val)
0094 {
0095 unsigned long flags;
0096
0097 spin_lock_irqsave(&tscadc->reg_lock, flags);
0098 tscadc->reg_se_cache &= ~val;
0099 regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache);
0100 spin_unlock_irqrestore(&tscadc->reg_lock, flags);
0101 }
0102 EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
0103
0104 static void tscadc_idle_config(struct ti_tscadc_dev *tscadc)
0105 {
0106 unsigned int idleconfig;
0107
0108 idleconfig = STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP_ADCREFM;
0109 if (ti_adc_with_touchscreen(tscadc))
0110 idleconfig |= STEPCONFIG_YNN | STEPCONFIG_YPN;
0111
0112 regmap_write(tscadc->regmap, REG_IDLECONFIG, idleconfig);
0113 }
0114
0115 static int ti_tscadc_probe(struct platform_device *pdev)
0116 {
0117 struct ti_tscadc_dev *tscadc;
0118 struct resource *res;
0119 struct clk *clk;
0120 struct device_node *node;
0121 struct mfd_cell *cell;
0122 struct property *prop;
0123 const __be32 *cur;
0124 bool use_tsc = false, use_mag = false;
0125 u32 val;
0126 int err;
0127 int tscmag_wires = 0, adc_channels = 0, cell_idx = 0, total_channels;
0128 int readouts = 0, mag_tracks = 0;
0129
0130
0131 tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL);
0132 if (!tscadc)
0133 return -ENOMEM;
0134
0135 tscadc->dev = &pdev->dev;
0136
0137 if (!pdev->dev.of_node) {
0138 dev_err(&pdev->dev, "Could not find valid DT data.\n");
0139 return -EINVAL;
0140 }
0141
0142 tscadc->data = of_device_get_match_data(&pdev->dev);
0143
0144 if (ti_adc_with_touchscreen(tscadc)) {
0145 node = of_get_child_by_name(pdev->dev.of_node, "tsc");
0146 of_property_read_u32(node, "ti,wires", &tscmag_wires);
0147 err = of_property_read_u32(node, "ti,coordinate-readouts",
0148 &readouts);
0149 if (err < 0)
0150 of_property_read_u32(node, "ti,coordiante-readouts",
0151 &readouts);
0152
0153 of_node_put(node);
0154
0155 if (tscmag_wires)
0156 use_tsc = true;
0157 } else {
0158
0159
0160
0161
0162
0163 mag_tracks = 0;
0164 tscmag_wires = mag_tracks * 2;
0165 if (tscmag_wires)
0166 use_mag = true;
0167 }
0168
0169 node = of_get_child_by_name(pdev->dev.of_node, "adc");
0170 of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
0171 adc_channels++;
0172 if (val > 7) {
0173 dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n",
0174 val);
0175 of_node_put(node);
0176 return -EINVAL;
0177 }
0178 }
0179
0180 of_node_put(node);
0181
0182 total_channels = tscmag_wires + adc_channels;
0183 if (total_channels > 8) {
0184 dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
0185 return -EINVAL;
0186 }
0187
0188 if (total_channels == 0) {
0189 dev_err(&pdev->dev, "Need at least one channel.\n");
0190 return -EINVAL;
0191 }
0192
0193 if (use_tsc && (readouts * 2 + 2 + adc_channels > 16)) {
0194 dev_err(&pdev->dev, "Too many step configurations requested\n");
0195 return -EINVAL;
0196 }
0197
0198 err = platform_get_irq(pdev, 0);
0199 if (err < 0)
0200 return err;
0201 else
0202 tscadc->irq = err;
0203
0204 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0205 tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
0206 if (IS_ERR(tscadc->tscadc_base))
0207 return PTR_ERR(tscadc->tscadc_base);
0208
0209 tscadc->tscadc_phys_base = res->start;
0210 tscadc->regmap = devm_regmap_init_mmio(&pdev->dev,
0211 tscadc->tscadc_base,
0212 &tscadc_regmap_config);
0213 if (IS_ERR(tscadc->regmap)) {
0214 dev_err(&pdev->dev, "regmap init failed\n");
0215 return PTR_ERR(tscadc->regmap);
0216 }
0217
0218 spin_lock_init(&tscadc->reg_lock);
0219 init_waitqueue_head(&tscadc->reg_se_wait);
0220
0221 pm_runtime_enable(&pdev->dev);
0222 pm_runtime_get_sync(&pdev->dev);
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233 clk = devm_clk_get(&pdev->dev, NULL);
0234 if (IS_ERR(clk)) {
0235 dev_err(&pdev->dev, "failed to get fck\n");
0236 err = PTR_ERR(clk);
0237 goto err_disable_clk;
0238 }
0239
0240 tscadc->clk_div = (clk_get_rate(clk) / tscadc->data->target_clk_rate) - 1;
0241 regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div);
0242
0243
0244
0245
0246
0247
0248 tscadc->ctrl = CNTRLREG_STEPID;
0249 if (ti_adc_with_touchscreen(tscadc)) {
0250 tscadc->ctrl |= CNTRLREG_TSC_STEPCONFIGWRT;
0251 if (use_tsc) {
0252 tscadc->ctrl |= CNTRLREG_TSC_ENB;
0253 if (tscmag_wires == 5)
0254 tscadc->ctrl |= CNTRLREG_TSC_5WIRE;
0255 else
0256 tscadc->ctrl |= CNTRLREG_TSC_4WIRE;
0257 }
0258 } else {
0259 tscadc->ctrl |= CNTRLREG_MAG_PREAMP_PWRDOWN |
0260 CNTRLREG_MAG_PREAMP_BYPASS;
0261 }
0262 regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl);
0263
0264 tscadc_idle_config(tscadc);
0265
0266
0267 regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl | CNTRLREG_SSENB);
0268
0269
0270 if (use_tsc || use_mag) {
0271 cell = &tscadc->cells[cell_idx++];
0272 cell->name = tscadc->data->secondary_feature_name;
0273 cell->of_compatible = tscadc->data->secondary_feature_compatible;
0274 cell->platform_data = &tscadc;
0275 cell->pdata_size = sizeof(tscadc);
0276 }
0277
0278
0279 if (adc_channels > 0) {
0280 cell = &tscadc->cells[cell_idx++];
0281 cell->name = tscadc->data->adc_feature_name;
0282 cell->of_compatible = tscadc->data->adc_feature_compatible;
0283 cell->platform_data = &tscadc;
0284 cell->pdata_size = sizeof(tscadc);
0285 }
0286
0287 err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
0288 tscadc->cells, cell_idx, NULL, 0, NULL);
0289 if (err < 0)
0290 goto err_disable_clk;
0291
0292 platform_set_drvdata(pdev, tscadc);
0293 return 0;
0294
0295 err_disable_clk:
0296 pm_runtime_put_sync(&pdev->dev);
0297 pm_runtime_disable(&pdev->dev);
0298
0299 return err;
0300 }
0301
0302 static int ti_tscadc_remove(struct platform_device *pdev)
0303 {
0304 struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev);
0305
0306 regmap_write(tscadc->regmap, REG_SE, 0x00);
0307
0308 pm_runtime_put_sync(&pdev->dev);
0309 pm_runtime_disable(&pdev->dev);
0310
0311 mfd_remove_devices(tscadc->dev);
0312
0313 return 0;
0314 }
0315
0316 static int __maybe_unused ti_tscadc_can_wakeup(struct device *dev, void *data)
0317 {
0318 return device_may_wakeup(dev);
0319 }
0320
0321 static int __maybe_unused tscadc_suspend(struct device *dev)
0322 {
0323 struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev);
0324
0325 regmap_write(tscadc->regmap, REG_SE, 0x00);
0326 if (device_for_each_child(dev, NULL, ti_tscadc_can_wakeup)) {
0327 u32 ctrl;
0328
0329 regmap_read(tscadc->regmap, REG_CTRL, &ctrl);
0330 ctrl &= ~(CNTRLREG_POWERDOWN);
0331 ctrl |= CNTRLREG_SSENB;
0332 regmap_write(tscadc->regmap, REG_CTRL, ctrl);
0333 }
0334 pm_runtime_put_sync(dev);
0335
0336 return 0;
0337 }
0338
0339 static int __maybe_unused tscadc_resume(struct device *dev)
0340 {
0341 struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev);
0342
0343 pm_runtime_get_sync(dev);
0344
0345 regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div);
0346 regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl);
0347 tscadc_idle_config(tscadc);
0348 regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl | CNTRLREG_SSENB);
0349
0350 return 0;
0351 }
0352
0353 static SIMPLE_DEV_PM_OPS(tscadc_pm_ops, tscadc_suspend, tscadc_resume);
0354
0355 static const struct ti_tscadc_data tscdata = {
0356 .adc_feature_name = "TI-am335x-adc",
0357 .adc_feature_compatible = "ti,am3359-adc",
0358 .secondary_feature_name = "TI-am335x-tsc",
0359 .secondary_feature_compatible = "ti,am3359-tsc",
0360 .target_clk_rate = TSC_ADC_CLK,
0361 };
0362
0363 static const struct ti_tscadc_data magdata = {
0364 .adc_feature_name = "TI-am43xx-adc",
0365 .adc_feature_compatible = "ti,am4372-adc",
0366 .secondary_feature_name = "TI-am43xx-mag",
0367 .secondary_feature_compatible = "ti,am4372-mag",
0368 .target_clk_rate = MAG_ADC_CLK,
0369 };
0370
0371 static const struct of_device_id ti_tscadc_dt_ids[] = {
0372 { .compatible = "ti,am3359-tscadc", .data = &tscdata },
0373 { .compatible = "ti,am4372-magadc", .data = &magdata },
0374 { }
0375 };
0376 MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids);
0377
0378 static struct platform_driver ti_tscadc_driver = {
0379 .driver = {
0380 .name = "ti_am3359-tscadc",
0381 .pm = &tscadc_pm_ops,
0382 .of_match_table = ti_tscadc_dt_ids,
0383 },
0384 .probe = ti_tscadc_probe,
0385 .remove = ti_tscadc_remove,
0386
0387 };
0388
0389 module_platform_driver(ti_tscadc_driver);
0390
0391 MODULE_DESCRIPTION("TI touchscreen/magnetic stripe reader/ADC MFD controller driver");
0392 MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
0393 MODULE_LICENSE("GPL");