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/init.h> 18 #include <linux/slab.h> 19 #include <linux/err.h> 20 #include <linux/io.h> 21 #include <linux/clk.h> 22 #include <linux/regmap.h> 23 #include <linux/mfd/core.h> 24 #include <linux/pm_runtime.h> 25 26 #include <linux/mfd/ti_am335x_tscadc.h> 27 #include <linux/input/ti_am335x_tsc.h> 28 #include <linux/platform_data/ti_am335x_adc.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 static void tscadc_idle_config(struct ti_tscadc_dev *config) 52 { 53 unsigned int idleconfig; 54 55 idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM | 56 STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN; 57 58 tscadc_writel(config, REG_IDLECONFIG, idleconfig); 59 } 60 61 static int ti_tscadc_probe(struct platform_device *pdev) 62 { 63 struct ti_tscadc_dev *tscadc; 64 struct resource *res; 65 struct clk *clk; 66 struct mfd_tscadc_board *pdata = pdev->dev.platform_data; 67 struct mfd_cell *cell; 68 int err, ctrl; 69 int clk_value, clock_rate; 70 int tsc_wires, adc_channels = 0, total_channels; 71 72 if (!pdata) { 73 dev_err(&pdev->dev, "Could not find platform data\n"); 74 return -EINVAL; 75 } 76 77 if (pdata->adc_init) 78 adc_channels = pdata->adc_init->adc_channels; 79 80 tsc_wires = pdata->tsc_init->wires; 81 total_channels = tsc_wires + adc_channels; 82 83 if (total_channels > 8) { 84 dev_err(&pdev->dev, "Number of i/p channels more than 8\n"); 85 return -EINVAL; 86 } 87 88 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 89 if (!res) { 90 dev_err(&pdev->dev, "no memory resource defined.\n"); 91 return -EINVAL; 92 } 93 94 /* Allocate memory for device */ 95 tscadc = devm_kzalloc(&pdev->dev, 96 sizeof(struct ti_tscadc_dev), GFP_KERNEL); 97 if (!tscadc) { 98 dev_err(&pdev->dev, "failed to allocate memory.\n"); 99 return -ENOMEM; 100 } 101 tscadc->dev = &pdev->dev; 102 103 err = platform_get_irq(pdev, 0); 104 if (err < 0) { 105 dev_err(&pdev->dev, "no irq ID is specified.\n"); 106 goto ret; 107 } else 108 tscadc->irq = err; 109 110 res = devm_request_mem_region(&pdev->dev, 111 res->start, resource_size(res), pdev->name); 112 if (!res) { 113 dev_err(&pdev->dev, "failed to reserve registers.\n"); 114 return -EBUSY; 115 } 116 117 tscadc->tscadc_base = devm_ioremap(&pdev->dev, 118 res->start, resource_size(res)); 119 if (!tscadc->tscadc_base) { 120 dev_err(&pdev->dev, "failed to map registers.\n"); 121 return -ENOMEM; 122 } 123 124 tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev, 125 tscadc->tscadc_base, &tscadc_regmap_config); 126 if (IS_ERR(tscadc->regmap_tscadc)) { 127 dev_err(&pdev->dev, "regmap init failed\n"); 128 err = PTR_ERR(tscadc->regmap_tscadc); 129 goto ret; 130 } 131 132 pm_runtime_enable(&pdev->dev); 133 pm_runtime_get_sync(&pdev->dev); 134 135 /* 136 * The TSC_ADC_Subsystem has 2 clock domains 137 * OCP_CLK and ADC_CLK. 138 * The ADC clock is expected to run at target of 3MHz, 139 * and expected to capture 12-bit data at a rate of 200 KSPS. 140 * The TSC_ADC_SS controller design assumes the OCP clock is 141 * at least 6x faster than the ADC clock. 142 */ 143 clk = clk_get(&pdev->dev, "adc_tsc_fck"); 144 if (IS_ERR(clk)) { 145 dev_err(&pdev->dev, "failed to get TSC fck\n"); 146 err = PTR_ERR(clk); 147 goto err_disable_clk; 148 } 149 clock_rate = clk_get_rate(clk); 150 clk_put(clk); 151 clk_value = clock_rate / ADC_CLK; 152 if (clk_value < MAX_CLK_DIV) { 153 dev_err(&pdev->dev, "clock input less than min clock requirement\n"); 154 err = -EINVAL; 155 goto err_disable_clk; 156 } 157 /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ 158 clk_value = clk_value - 1; 159 tscadc_writel(tscadc, REG_CLKDIV, clk_value); 160 161 /* Set the control register bits */ 162 ctrl = CNTRLREG_STEPCONFIGWRT | 163 CNTRLREG_TSCENB | 164 CNTRLREG_STEPID | 165 CNTRLREG_4WIRE; 166 tscadc_writel(tscadc, REG_CTRL, ctrl); 167 168 /* Set register bits for Idle Config Mode */ 169 tscadc_idle_config(tscadc); 170 171 /* Enable the TSC module enable bit */ 172 ctrl = tscadc_readl(tscadc, REG_CTRL); 173 ctrl |= CNTRLREG_TSCSSENB; 174 tscadc_writel(tscadc, REG_CTRL, ctrl); 175 176 /* TSC Cell */ 177 cell = &tscadc->cells[TSC_CELL]; 178 cell->name = "tsc"; 179 cell->platform_data = tscadc; 180 cell->pdata_size = sizeof(*tscadc); 181 182 /* ADC Cell */ 183 cell = &tscadc->cells[ADC_CELL]; 184 cell->name = "tiadc"; 185 cell->platform_data = tscadc; 186 cell->pdata_size = sizeof(*tscadc); 187 188 err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells, 189 TSCADC_CELLS, NULL, 0, NULL); 190 if (err < 0) 191 goto err_disable_clk; 192 193 device_init_wakeup(&pdev->dev, true); 194 platform_set_drvdata(pdev, tscadc); 195 196 return 0; 197 198 err_disable_clk: 199 pm_runtime_put_sync(&pdev->dev); 200 pm_runtime_disable(&pdev->dev); 201 ret: 202 return err; 203 } 204 205 static int ti_tscadc_remove(struct platform_device *pdev) 206 { 207 struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev); 208 209 tscadc_writel(tscadc, REG_SE, 0x00); 210 211 pm_runtime_put_sync(&pdev->dev); 212 pm_runtime_disable(&pdev->dev); 213 214 mfd_remove_devices(tscadc->dev); 215 216 return 0; 217 } 218 219 #ifdef CONFIG_PM 220 static int tscadc_suspend(struct device *dev) 221 { 222 struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); 223 224 tscadc_writel(tscadc_dev, REG_SE, 0x00); 225 pm_runtime_put_sync(dev); 226 227 return 0; 228 } 229 230 static int tscadc_resume(struct device *dev) 231 { 232 struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); 233 unsigned int restore, ctrl; 234 235 pm_runtime_get_sync(dev); 236 237 /* context restore */ 238 ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_TSCENB | 239 CNTRLREG_STEPID | CNTRLREG_4WIRE; 240 tscadc_writel(tscadc_dev, REG_CTRL, ctrl); 241 tscadc_idle_config(tscadc_dev); 242 tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB); 243 restore = tscadc_readl(tscadc_dev, REG_CTRL); 244 tscadc_writel(tscadc_dev, REG_CTRL, 245 (restore | CNTRLREG_TSCSSENB)); 246 247 return 0; 248 } 249 250 static const struct dev_pm_ops tscadc_pm_ops = { 251 .suspend = tscadc_suspend, 252 .resume = tscadc_resume, 253 }; 254 #define TSCADC_PM_OPS (&tscadc_pm_ops) 255 #else 256 #define TSCADC_PM_OPS NULL 257 #endif 258 259 static struct platform_driver ti_tscadc_driver = { 260 .driver = { 261 .name = "ti_tscadc", 262 .owner = THIS_MODULE, 263 .pm = TSCADC_PM_OPS, 264 }, 265 .probe = ti_tscadc_probe, 266 .remove = ti_tscadc_remove, 267 268 }; 269 270 module_platform_driver(ti_tscadc_driver); 271 272 MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver"); 273 MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); 274 MODULE_LICENSE("GPL"); 275