1 /* 2 * TI Touch Screen / ADC MFD driver 3 * 4 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation version 2. 9 * 10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 11 * kind, whether express or implied; without even the implied warranty 12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16 #include <linux/module.h> 17 #include <linux/slab.h> 18 #include <linux/err.h> 19 #include <linux/io.h> 20 #include <linux/clk.h> 21 #include <linux/regmap.h> 22 #include <linux/mfd/core.h> 23 #include <linux/pm_runtime.h> 24 #include <linux/of.h> 25 #include <linux/of_device.h> 26 #include <linux/sched.h> 27 28 #include <linux/mfd/ti_am335x_tscadc.h> 29 30 static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg) 31 { 32 unsigned int val; 33 34 regmap_read(tsadc->regmap_tscadc, reg, &val); 35 return val; 36 } 37 38 static void tscadc_writel(struct ti_tscadc_dev *tsadc, unsigned int reg, 39 unsigned int val) 40 { 41 regmap_write(tsadc->regmap_tscadc, reg, val); 42 } 43 44 static const struct regmap_config tscadc_regmap_config = { 45 .name = "ti_tscadc", 46 .reg_bits = 32, 47 .reg_stride = 4, 48 .val_bits = 32, 49 }; 50 51 void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) 52 { 53 unsigned long flags; 54 55 spin_lock_irqsave(&tsadc->reg_lock, flags); 56 tsadc->reg_se_cache |= val; 57 if (tsadc->adc_waiting) 58 wake_up(&tsadc->reg_se_wait); 59 else if (!tsadc->adc_in_use) 60 tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); 61 62 spin_unlock_irqrestore(&tsadc->reg_lock, flags); 63 } 64 EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache); 65 66 static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc) 67 { 68 DEFINE_WAIT(wait); 69 u32 reg; 70 71 reg = tscadc_readl(tsadc, REG_ADCFSM); 72 if (reg & SEQ_STATUS) { 73 tsadc->adc_waiting = true; 74 prepare_to_wait(&tsadc->reg_se_wait, &wait, 75 TASK_UNINTERRUPTIBLE); 76 spin_unlock_irq(&tsadc->reg_lock); 77 78 schedule(); 79 80 spin_lock_irq(&tsadc->reg_lock); 81 finish_wait(&tsadc->reg_se_wait, &wait); 82 83 /* 84 * Sequencer should either be idle or 85 * busy applying the charge step. 86 */ 87 reg = tscadc_readl(tsadc, REG_ADCFSM); 88 WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP)); 89 tsadc->adc_waiting = false; 90 } 91 tsadc->adc_in_use = true; 92 } 93 94 void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) 95 { 96 spin_lock_irq(&tsadc->reg_lock); 97 am335x_tscadc_need_adc(tsadc); 98 99 tscadc_writel(tsadc, REG_SE, val); 100 spin_unlock_irq(&tsadc->reg_lock); 101 } 102 EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once); 103 104 void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc) 105 { 106 unsigned long flags; 107 108 spin_lock_irqsave(&tsadc->reg_lock, flags); 109 tsadc->adc_in_use = false; 110 tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); 111 spin_unlock_irqrestore(&tsadc->reg_lock, flags); 112 } 113 EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done); 114 115 void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) 116 { 117 unsigned long flags; 118 119 spin_lock_irqsave(&tsadc->reg_lock, flags); 120 tsadc->reg_se_cache &= ~val; 121 tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); 122 spin_unlock_irqrestore(&tsadc->reg_lock, flags); 123 } 124 EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); 125 126 static void tscadc_idle_config(struct ti_tscadc_dev *config) 127 { 128 unsigned int idleconfig; 129 130 idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM | 131 STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN; 132 133 tscadc_writel(config, REG_IDLECONFIG, idleconfig); 134 } 135 136 static int ti_tscadc_probe(struct platform_device *pdev) 137 { 138 struct ti_tscadc_dev *tscadc; 139 struct resource *res; 140 struct clk *clk; 141 struct device_node *node = pdev->dev.of_node; 142 struct mfd_cell *cell; 143 struct property *prop; 144 const __be32 *cur; 145 u32 val; 146 int err, ctrl; 147 int clock_rate; 148 int tsc_wires = 0, adc_channels = 0, total_channels; 149 int readouts = 0; 150 151 if (!pdev->dev.of_node) { 152 dev_err(&pdev->dev, "Could not find valid DT data.\n"); 153 return -EINVAL; 154 } 155 156 node = of_get_child_by_name(pdev->dev.of_node, "tsc"); 157 of_property_read_u32(node, "ti,wires", &tsc_wires); 158 of_property_read_u32(node, "ti,coordiante-readouts", &readouts); 159 160 node = of_get_child_by_name(pdev->dev.of_node, "adc"); 161 of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { 162 adc_channels++; 163 if (val > 7) { 164 dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n", 165 val); 166 return -EINVAL; 167 } 168 } 169 total_channels = tsc_wires + adc_channels; 170 if (total_channels > 8) { 171 dev_err(&pdev->dev, "Number of i/p channels more than 8\n"); 172 return -EINVAL; 173 } 174 if (total_channels == 0) { 175 dev_err(&pdev->dev, "Need atleast one channel.\n"); 176 return -EINVAL; 177 } 178 179 if (readouts * 2 + 2 + adc_channels > 16) { 180 dev_err(&pdev->dev, "Too many step configurations requested\n"); 181 return -EINVAL; 182 } 183 184 /* Allocate memory for device */ 185 tscadc = devm_kzalloc(&pdev->dev, 186 sizeof(struct ti_tscadc_dev), GFP_KERNEL); 187 if (!tscadc) { 188 dev_err(&pdev->dev, "failed to allocate memory.\n"); 189 return -ENOMEM; 190 } 191 tscadc->dev = &pdev->dev; 192 193 err = platform_get_irq(pdev, 0); 194 if (err < 0) { 195 dev_err(&pdev->dev, "no irq ID is specified.\n"); 196 goto ret; 197 } else 198 tscadc->irq = err; 199 200 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 201 tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res); 202 if (IS_ERR(tscadc->tscadc_base)) 203 return PTR_ERR(tscadc->tscadc_base); 204 205 tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev, 206 tscadc->tscadc_base, &tscadc_regmap_config); 207 if (IS_ERR(tscadc->regmap_tscadc)) { 208 dev_err(&pdev->dev, "regmap init failed\n"); 209 err = PTR_ERR(tscadc->regmap_tscadc); 210 goto ret; 211 } 212 213 spin_lock_init(&tscadc->reg_lock); 214 init_waitqueue_head(&tscadc->reg_se_wait); 215 216 pm_runtime_enable(&pdev->dev); 217 pm_runtime_get_sync(&pdev->dev); 218 219 /* 220 * The TSC_ADC_Subsystem has 2 clock domains 221 * OCP_CLK and ADC_CLK. 222 * The ADC clock is expected to run at target of 3MHz, 223 * and expected to capture 12-bit data at a rate of 200 KSPS. 224 * The TSC_ADC_SS controller design assumes the OCP clock is 225 * at least 6x faster than the ADC clock. 226 */ 227 clk = clk_get(&pdev->dev, "adc_tsc_fck"); 228 if (IS_ERR(clk)) { 229 dev_err(&pdev->dev, "failed to get TSC fck\n"); 230 err = PTR_ERR(clk); 231 goto err_disable_clk; 232 } 233 clock_rate = clk_get_rate(clk); 234 clk_put(clk); 235 tscadc->clk_div = clock_rate / ADC_CLK; 236 237 /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ 238 tscadc->clk_div--; 239 tscadc_writel(tscadc, REG_CLKDIV, tscadc->clk_div); 240 241 /* Set the control register bits */ 242 ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; 243 tscadc_writel(tscadc, REG_CTRL, ctrl); 244 245 /* Set register bits for Idle Config Mode */ 246 if (tsc_wires > 0) { 247 tscadc->tsc_wires = tsc_wires; 248 if (tsc_wires == 5) 249 ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB; 250 else 251 ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB; 252 tscadc_idle_config(tscadc); 253 } 254 255 /* Enable the TSC module enable bit */ 256 ctrl |= CNTRLREG_TSCSSENB; 257 tscadc_writel(tscadc, REG_CTRL, ctrl); 258 259 tscadc->used_cells = 0; 260 tscadc->tsc_cell = -1; 261 tscadc->adc_cell = -1; 262 263 /* TSC Cell */ 264 if (tsc_wires > 0) { 265 tscadc->tsc_cell = tscadc->used_cells; 266 cell = &tscadc->cells[tscadc->used_cells++]; 267 cell->name = "TI-am335x-tsc"; 268 cell->of_compatible = "ti,am3359-tsc"; 269 cell->platform_data = &tscadc; 270 cell->pdata_size = sizeof(tscadc); 271 } 272 273 /* ADC Cell */ 274 if (adc_channels > 0) { 275 tscadc->adc_cell = tscadc->used_cells; 276 cell = &tscadc->cells[tscadc->used_cells++]; 277 cell->name = "TI-am335x-adc"; 278 cell->of_compatible = "ti,am3359-adc"; 279 cell->platform_data = &tscadc; 280 cell->pdata_size = sizeof(tscadc); 281 } 282 283 err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells, 284 tscadc->used_cells, NULL, 0, NULL); 285 if (err < 0) 286 goto err_disable_clk; 287 288 device_init_wakeup(&pdev->dev, true); 289 platform_set_drvdata(pdev, tscadc); 290 return 0; 291 292 err_disable_clk: 293 pm_runtime_put_sync(&pdev->dev); 294 pm_runtime_disable(&pdev->dev); 295 ret: 296 return err; 297 } 298 299 static int ti_tscadc_remove(struct platform_device *pdev) 300 { 301 struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev); 302 303 tscadc_writel(tscadc, REG_SE, 0x00); 304 305 pm_runtime_put_sync(&pdev->dev); 306 pm_runtime_disable(&pdev->dev); 307 308 mfd_remove_devices(tscadc->dev); 309 310 return 0; 311 } 312 313 #ifdef CONFIG_PM 314 static int tscadc_suspend(struct device *dev) 315 { 316 struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); 317 318 tscadc_writel(tscadc_dev, REG_SE, 0x00); 319 pm_runtime_put_sync(dev); 320 321 return 0; 322 } 323 324 static int tscadc_resume(struct device *dev) 325 { 326 struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); 327 u32 ctrl; 328 329 pm_runtime_get_sync(dev); 330 331 /* context restore */ 332 ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; 333 tscadc_writel(tscadc_dev, REG_CTRL, ctrl); 334 335 if (tscadc_dev->tsc_cell != -1) { 336 if (tscadc_dev->tsc_wires == 5) 337 ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB; 338 else 339 ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB; 340 tscadc_idle_config(tscadc_dev); 341 } 342 ctrl |= CNTRLREG_TSCSSENB; 343 tscadc_writel(tscadc_dev, REG_CTRL, ctrl); 344 345 tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div); 346 347 return 0; 348 } 349 350 static const struct dev_pm_ops tscadc_pm_ops = { 351 .suspend = tscadc_suspend, 352 .resume = tscadc_resume, 353 }; 354 #define TSCADC_PM_OPS (&tscadc_pm_ops) 355 #else 356 #define TSCADC_PM_OPS NULL 357 #endif 358 359 static const struct of_device_id ti_tscadc_dt_ids[] = { 360 { .compatible = "ti,am3359-tscadc", }, 361 { } 362 }; 363 MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids); 364 365 static struct platform_driver ti_tscadc_driver = { 366 .driver = { 367 .name = "ti_am3359-tscadc", 368 .pm = TSCADC_PM_OPS, 369 .of_match_table = ti_tscadc_dt_ids, 370 }, 371 .probe = ti_tscadc_probe, 372 .remove = ti_tscadc_remove, 373 374 }; 375 376 module_platform_driver(ti_tscadc_driver); 377 378 MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver"); 379 MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); 380 MODULE_LICENSE("GPL"); 381