blob: 1121f57aecf3897c40a880d435a910c56a959b7c [file] [log] [blame]
Pratik Patel9a9313d2013-03-20 12:03:27 -07001/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
Pratik Patel7831c082011-06-08 21:44:37 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
Pratik Patelcf418622011-09-22 11:15:11 -070015#include <linux/init.h>
16#include <linux/device.h>
Pratik Patel7831c082011-06-08 21:44:37 -070017#include <linux/platform_device.h>
18#include <linux/io.h>
19#include <linux/err.h>
Pratik Patel16aefdb2012-05-30 10:41:23 -070020#include <linux/slab.h>
Pratik Patel9a9313d2013-03-20 12:03:27 -070021#include <linux/delay.h>
22#include <linux/mutex.h>
Pratik Patelf17b1472012-05-25 22:23:52 -070023#include <linux/clk.h>
Pratik Patel5f6d1af2012-06-13 15:48:13 -070024#include <linux/of_coresight.h>
Pratik Patel1746b8f2012-06-02 21:11:41 -070025#include <linux/coresight.h>
Pratik Patel9a9313d2013-03-20 12:03:27 -070026#include <linux/regulator/consumer.h>
27#include <linux/gpio.h>
28#include <linux/of_gpio.h>
29#include <mach/gpiomux.h>
Pratik Patel7831c082011-06-08 21:44:37 -070030
Pratik Patel1746b8f2012-06-02 21:11:41 -070031#include "coresight-priv.h"
Pratik Patel7831c082011-06-08 21:44:37 -070032
Pratik Patel16aefdb2012-05-30 10:41:23 -070033#define tpiu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
34#define tpiu_readl(drvdata, off) __raw_readl(drvdata->base + off)
Pratik Patel7831c082011-06-08 21:44:37 -070035
Pratik Patel3b0ca882012-06-01 16:54:14 -070036#define TPIU_LOCK(drvdata) \
Pratik Patel7831c082011-06-08 21:44:37 -070037do { \
38 mb(); \
Pratik Patel6fb38342012-06-03 14:51:38 -070039 tpiu_writel(drvdata, 0x0, CORESIGHT_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -070040} while (0)
Pratik Patel3b0ca882012-06-01 16:54:14 -070041#define TPIU_UNLOCK(drvdata) \
Pratik Patel7831c082011-06-08 21:44:37 -070042do { \
Pratik Patel6fb38342012-06-03 14:51:38 -070043 tpiu_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -070044 mb(); \
45} while (0)
46
Pratik Patel3b0ca882012-06-01 16:54:14 -070047#define TPIU_SUPP_PORTSZ (0x000)
48#define TPIU_CURR_PORTSZ (0x004)
49#define TPIU_SUPP_TRIGMODES (0x100)
50#define TPIU_TRIG_CNTRVAL (0x104)
51#define TPIU_TRIG_MULT (0x108)
52#define TPIU_SUPP_TESTPATM (0x200)
53#define TPIU_CURR_TESTPATM (0x204)
54#define TPIU_TEST_PATREPCNTR (0x208)
55#define TPIU_FFSR (0x300)
56#define TPIU_FFCR (0x304)
57#define TPIU_FSYNC_CNTR (0x308)
58#define TPIU_EXTCTL_INPORT (0x400)
59#define TPIU_EXTCTL_OUTPORT (0x404)
60#define TPIU_ITTRFLINACK (0xEE4)
61#define TPIU_ITTRFLIN (0xEE8)
62#define TPIU_ITATBDATA0 (0xEEC)
63#define TPIU_ITATBCTR2 (0xEF0)
64#define TPIU_ITATBCTR1 (0xEF4)
65#define TPIU_ITATBCTR0 (0xEF8)
66
Pratik Patel9a9313d2013-03-20 12:03:27 -070067enum tpiu_out_mode {
68 TPIU_OUT_MODE_NONE,
69 TPIU_OUT_MODE_MICTOR,
70 TPIU_OUT_MODE_SDC,
71};
72
73enum tpiu_set {
74 TPIU_SET_NONE,
75 TPIU_SET_A,
76 TPIU_SET_B,
77};
78
Pratik Patel16aefdb2012-05-30 10:41:23 -070079struct tpiu_drvdata {
Pratik Patel3b0ca882012-06-01 16:54:14 -070080 void __iomem *base;
81 struct device *dev;
82 struct coresight_device *csdev;
83 struct clk *clk;
Pratik Patel9a9313d2013-03-20 12:03:27 -070084 struct mutex mutex;
85 enum tpiu_out_mode out_mode;
86 struct regulator *reg;
87 unsigned int reg_low;
88 unsigned int reg_high;
89 unsigned int reg_lpm;
90 unsigned int reg_hpm;
Aparna Dasa177eb72013-07-23 16:03:28 -070091 struct regulator *reg_io;
92 unsigned int reg_low_io;
93 unsigned int reg_high_io;
94 unsigned int reg_lpm_io;
95 unsigned int reg_hpm_io;
Pratik Patel9a9313d2013-03-20 12:03:27 -070096 enum tpiu_set set;
97 unsigned int seta_gpiocnt;
98 unsigned int *seta_gpios;
99 struct gpiomux_setting *seta_cfgs;
100 unsigned int setb_gpiocnt;
101 unsigned int *setb_gpios;
102 struct gpiomux_setting *setb_cfgs;
103 bool enable;
Pratik Patel7831c082011-06-08 21:44:37 -0700104};
105
Pratik Patel9a9313d2013-03-20 12:03:27 -0700106struct gpiomux_setting old_cfg;
107
108static void tpiu_flush_and_stop(struct tpiu_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700109{
Pratik Patel9a9313d2013-03-20 12:03:27 -0700110 int count;
111 uint32_t ffcr;
112
113 ffcr = tpiu_readl(drvdata, TPIU_FFCR);
114 ffcr |= BIT(12);
115 tpiu_writel(drvdata, ffcr, TPIU_FFCR);
116 ffcr |= BIT(6);
117 tpiu_writel(drvdata, ffcr, TPIU_FFCR);
118 /* Ensure flush completes */
119 for (count = TIMEOUT_US; BVAL(tpiu_readl(drvdata, TPIU_FFCR), 6) != 0
120 && count > 0; count--)
121 udelay(1);
122 WARN(count == 0, "timeout while flushing TPIU, TPIU_FFCR: %#x\n",
123 tpiu_readl(drvdata, TPIU_FFCR));
124}
125
126static int __tpiu_enable_seta(struct tpiu_drvdata *drvdata)
127{
128 int i, ret;
129
130 if (!drvdata->seta_gpiocnt)
131 return -EINVAL;
132
133 for (i = 0; i < drvdata->seta_gpiocnt; i++) {
134 ret = gpio_request(drvdata->seta_gpios[i], NULL);
135 if (ret) {
136 dev_err(drvdata->dev,
137 "gpio_request failed for seta_gpio: %u\n",
138 drvdata->seta_gpios[i]);
139 goto err0;
140 }
141 ret = msm_gpiomux_write(drvdata->seta_gpios[i],
142 GPIOMUX_ACTIVE,
143 &drvdata->seta_cfgs[i],
144 &old_cfg);
145 if (ret < 0) {
146 dev_err(drvdata->dev,
147 "gpio write failed for seta_gpio: %u\n",
148 drvdata->seta_gpios[i]);
149 goto err1;
150 }
151 }
152 return 0;
153err1:
154 gpio_free(drvdata->seta_gpios[i]);
155err0:
156 i--;
157 while (i >= 0) {
158 gpio_free(drvdata->seta_gpios[i]);
159 i--;
160 }
161 return ret;
162}
163
164static int __tpiu_enable_setb(struct tpiu_drvdata *drvdata)
165{
166 int i, ret;
167
168 if (!drvdata->setb_gpiocnt)
169 return -EINVAL;
170
171 for (i = 0; i < drvdata->setb_gpiocnt; i++) {
172 ret = gpio_request(drvdata->setb_gpios[i], NULL);
173 if (ret) {
174 dev_err(drvdata->dev,
175 "gpio_request failed for setb_gpio: %u\n",
176 drvdata->setb_gpios[i]);
177 goto err0;
178 }
179 ret = msm_gpiomux_write(drvdata->setb_gpios[i],
180 GPIOMUX_ACTIVE,
181 &drvdata->setb_cfgs[i],
182 &old_cfg);
183 if (ret < 0) {
184 dev_err(drvdata->dev,
185 "gpio write failed for setb_gpio: %u\n",
186 drvdata->setb_gpios[i]);
187 goto err1;
188 }
189 }
190 return 0;
191err1:
192 gpio_free(drvdata->setb_gpios[i]);
193err0:
194 i--;
195 while (i >= 0) {
196 gpio_free(drvdata->setb_gpios[i]);
197 i--;
198 }
199 return ret;
200}
201
202static int __tpiu_enable_to_mictor(struct tpiu_drvdata *drvdata)
203{
204 int ret;
205
206 if (drvdata->set == TPIU_SET_A) {
207 ret = __tpiu_enable_seta(drvdata);
208 if (ret)
209 return ret;
210 } else if (drvdata->set == TPIU_SET_B) {
211 ret = __tpiu_enable_setb(drvdata);
212 if (ret)
213 return ret;
214 }
215
Pratik Patel3b0ca882012-06-01 16:54:14 -0700216 TPIU_UNLOCK(drvdata);
217
Pratik Patel9a9313d2013-03-20 12:03:27 -0700218 tpiu_writel(drvdata, 0x8000, TPIU_CURR_PORTSZ);
219 tpiu_writel(drvdata, 0x101, TPIU_FFCR);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700220
221 TPIU_LOCK(drvdata);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700222
223 return 0;
224}
225
Pratik Patela60feab2013-04-12 11:38:58 -0700226static int tpiu_reg_set_optimum_mode(struct regulator *reg,
227 unsigned int reg_hpm)
228{
229 if (regulator_count_voltages(reg) <= 0)
230 return 0;
231
232 return regulator_set_optimum_mode(reg, reg_hpm);
233}
234
235static int tpiu_reg_set_voltage(struct regulator *reg, unsigned int reg_low,
236 unsigned int reg_high)
237{
238 if (regulator_count_voltages(reg) <= 0)
239 return 0;
240
241 return regulator_set_voltage(reg, reg_low, reg_high);
242}
243
Pratik Patel9a9313d2013-03-20 12:03:27 -0700244static int __tpiu_enable_to_sdc(struct tpiu_drvdata *drvdata)
245{
246 int ret;
247
Aparna Dasa177eb72013-07-23 16:03:28 -0700248 if (!drvdata->reg || !drvdata->reg_io)
Pratik Patel9a9313d2013-03-20 12:03:27 -0700249 return -EINVAL;
250
Pratik Patela60feab2013-04-12 11:38:58 -0700251 ret = tpiu_reg_set_optimum_mode(drvdata->reg, drvdata->reg_hpm);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700252 if (ret < 0)
253 return ret;
Pratik Patela60feab2013-04-12 11:38:58 -0700254 ret = tpiu_reg_set_voltage(drvdata->reg, drvdata->reg_low,
255 drvdata->reg_high);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700256 if (ret)
257 goto err0;
258 ret = regulator_enable(drvdata->reg);
259 if (ret)
260 goto err1;
Aparna Dasa177eb72013-07-23 16:03:28 -0700261 ret = tpiu_reg_set_optimum_mode(drvdata->reg_io, drvdata->reg_hpm_io);
262 if (ret < 0)
263 goto err2;
264 ret = tpiu_reg_set_voltage(drvdata->reg_io, drvdata->reg_low_io,
265 drvdata->reg_high_io);
266 if (ret)
267 goto err3;
268 ret = regulator_enable(drvdata->reg_io);
269 if (ret)
270 goto err4;
Pratik Patel9a9313d2013-03-20 12:03:27 -0700271
Pratik Patel3a621192013-05-09 16:50:16 -0700272 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_FIXED);
273 if (ret)
274 goto err5;
275
Pratik Patel9a9313d2013-03-20 12:03:27 -0700276 msm_tlmm_misc_reg_write(TLMM_SDC2_HDRV_PULL_CTL, 0x16D);
277 msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 1);
278
279 TPIU_UNLOCK(drvdata);
280
281 tpiu_writel(drvdata, 0x8, TPIU_CURR_PORTSZ);
282 tpiu_writel(drvdata, 0x103, TPIU_FFCR);
283
284 TPIU_LOCK(drvdata);
285
286 return 0;
Pratik Patel3a621192013-05-09 16:50:16 -0700287err5:
288 regulator_disable(drvdata->reg_io);
Aparna Dasa177eb72013-07-23 16:03:28 -0700289err4:
290 tpiu_reg_set_voltage(drvdata->reg_io, 0, drvdata->reg_high_io);
291err3:
292 tpiu_reg_set_optimum_mode(drvdata->reg_io, 0);
293err2:
294 regulator_disable(drvdata->reg);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700295err1:
Pratik Patela60feab2013-04-12 11:38:58 -0700296 tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700297err0:
Pratik Patela60feab2013-04-12 11:38:58 -0700298 tpiu_reg_set_optimum_mode(drvdata->reg, 0);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700299 return ret;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700300}
301
302static int tpiu_enable(struct coresight_device *csdev)
303{
304 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
305 int ret;
306
307 ret = clk_prepare_enable(drvdata->clk);
308 if (ret)
309 return ret;
310
Pratik Patel9a9313d2013-03-20 12:03:27 -0700311 mutex_lock(&drvdata->mutex);
312
313 if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
314 ret = __tpiu_enable_to_mictor(drvdata);
315 else
316 ret = __tpiu_enable_to_sdc(drvdata);
317 if (ret)
318 goto err;
319 drvdata->enable = true;
320
321 mutex_unlock(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700322
323 dev_info(drvdata->dev, "TPIU enabled\n");
324 return 0;
Pratik Patel9a9313d2013-03-20 12:03:27 -0700325err:
326 mutex_unlock(&drvdata->mutex);
327 clk_disable_unprepare(drvdata->clk);
328 return ret;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700329}
330
331static void __tpiu_disable(struct tpiu_drvdata *drvdata)
332{
333 TPIU_UNLOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700334
Pratik Patel9a9313d2013-03-20 12:03:27 -0700335 tpiu_flush_and_stop(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700336
Pratik Patel3b0ca882012-06-01 16:54:14 -0700337 TPIU_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700338}
339
Pratik Patel9a9313d2013-03-20 12:03:27 -0700340static void __tpiu_disable_seta(struct tpiu_drvdata *drvdata)
341{
342 int i;
343
344 for (i = 0; i < drvdata->seta_gpiocnt; i++)
345 gpio_free(drvdata->seta_gpios[i]);
346}
347
348static void __tpiu_disable_setb(struct tpiu_drvdata *drvdata)
349{
350 int i;
351
352 for (i = 0; i < drvdata->setb_gpiocnt; i++)
353 gpio_free(drvdata->setb_gpios[i]);
354}
355
356static void __tpiu_disable_to_mictor(struct tpiu_drvdata *drvdata)
357{
358 __tpiu_disable(drvdata);
359
360 if (drvdata->set == TPIU_SET_A)
361 __tpiu_disable_seta(drvdata);
362 else if (drvdata->set == TPIU_SET_B)
363 __tpiu_disable_setb(drvdata);
364}
365
366static void __tpiu_disable_to_sdc(struct tpiu_drvdata *drvdata)
367{
368 __tpiu_disable(drvdata);
369
370 msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 0);
371
Pratik Patel3a621192013-05-09 16:50:16 -0700372 clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
373
Pratik Patel9a9313d2013-03-20 12:03:27 -0700374 regulator_disable(drvdata->reg);
Pratik Patela60feab2013-04-12 11:38:58 -0700375 tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
Aparna Dasee8f0712013-08-19 11:16:40 -0700376 tpiu_reg_set_optimum_mode(drvdata->reg, 0);
377
378 regulator_disable(drvdata->reg_io);
379 tpiu_reg_set_voltage(drvdata->reg_io, 0, drvdata->reg_high_io);
380 tpiu_reg_set_optimum_mode(drvdata->reg_io, 0);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700381}
382
Pratik Patel3b0ca882012-06-01 16:54:14 -0700383static void tpiu_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700384{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700385 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
386
Pratik Patel9a9313d2013-03-20 12:03:27 -0700387 mutex_lock(&drvdata->mutex);
388
389 if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
390 __tpiu_disable_to_mictor(drvdata);
391 else
392 __tpiu_disable_to_sdc(drvdata);
393 drvdata->enable = false;
394
395 mutex_unlock(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700396
397 clk_disable_unprepare(drvdata->clk);
398
Pratik Patel16aefdb2012-05-30 10:41:23 -0700399 dev_info(drvdata->dev, "TPIU disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700400}
401
Pratik Patelcf7d0452012-07-02 13:57:20 -0700402static void tpiu_abort(struct coresight_device *csdev)
403{
404 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
405
406 __tpiu_disable(drvdata);
407
408 dev_info(drvdata->dev, "TPIU aborted\n");
409}
410
Pratik Patel3b0ca882012-06-01 16:54:14 -0700411static const struct coresight_ops_sink tpiu_sink_ops = {
412 .enable = tpiu_enable,
413 .disable = tpiu_disable,
Pratik Patelcf7d0452012-07-02 13:57:20 -0700414 .abort = tpiu_abort,
Pratik Patel3b0ca882012-06-01 16:54:14 -0700415};
416
Pratik Patel9a9313d2013-03-20 12:03:27 -0700417static ssize_t tpiu_show_out_mode(struct device *dev,
418 struct device_attribute *attr, char *buf)
419{
420 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
421
422 return scnprintf(buf, PAGE_SIZE, "%s\n",
423 drvdata->out_mode == TPIU_OUT_MODE_MICTOR ?
424 "mictor" : "sdc");
425}
426
427static ssize_t tpiu_store_out_mode(struct device *dev,
428 struct device_attribute *attr,
429 const char *buf, size_t size)
430{
431 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
432 char str[10] = "";
433 int ret;
434
435 if (strlen(buf) >= 10)
436 return -EINVAL;
437 if (sscanf(buf, "%s", str) != 1)
438 return -EINVAL;
439
440 mutex_lock(&drvdata->mutex);
441 if (!strcmp(str, "mictor")) {
442 if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
443 goto out;
444
445 if (!drvdata->enable) {
446 drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
447 goto out;
448 }
449 __tpiu_disable_to_sdc(drvdata);
450 ret = __tpiu_enable_to_mictor(drvdata);
451 if (ret) {
452 dev_err(drvdata->dev, "failed to enable mictor\n");
453 goto err;
454 }
455 drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
456 } else if (!strcmp(str, "sdc")) {
457 if (drvdata->out_mode == TPIU_OUT_MODE_SDC)
458 goto out;
459
460 if (!drvdata->enable) {
461 drvdata->out_mode = TPIU_OUT_MODE_SDC;
462 goto out;
463 }
464 __tpiu_disable_to_mictor(drvdata);
465 ret = __tpiu_enable_to_sdc(drvdata);
466 if (ret) {
467 dev_err(drvdata->dev, "failed to enable sdc\n");
468 goto err;
469 }
470 drvdata->out_mode = TPIU_OUT_MODE_SDC;
471 }
472out:
473 mutex_unlock(&drvdata->mutex);
474 return size;
475err:
476 mutex_unlock(&drvdata->mutex);
477 return ret;
478}
479static DEVICE_ATTR(out_mode, S_IRUGO | S_IWUSR, tpiu_show_out_mode,
480 tpiu_store_out_mode);
481
Pratik Patel3b0ca882012-06-01 16:54:14 -0700482static const struct coresight_ops tpiu_cs_ops = {
483 .sink_ops = &tpiu_sink_ops,
484};
485
Pratik Patel9a9313d2013-03-20 12:03:27 -0700486static ssize_t tpiu_show_set(struct device *dev,
487 struct device_attribute *attr, char *buf)
488{
489 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
490
491 return scnprintf(buf, PAGE_SIZE, "%s\n",
492 drvdata->set == TPIU_SET_A ?
493 "a" : "b");
494}
495
496static ssize_t tpiu_store_set(struct device *dev, struct device_attribute *attr,
497 const char *buf, size_t size)
498{
499 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
500 char str[10] = "";
501 int ret;
502
503 if (strlen(buf) >= 10)
504 return -EINVAL;
505 if (sscanf(buf, "%s", str) != 1)
506 return -EINVAL;
507
508 mutex_lock(&drvdata->mutex);
509 if (!strcmp(str, "a")) {
510 if (drvdata->set == TPIU_SET_A)
511 goto out;
512
513 if (!drvdata->enable || drvdata->out_mode !=
514 TPIU_OUT_MODE_MICTOR) {
515 drvdata->set = TPIU_SET_A;
516 goto out;
517 }
518 __tpiu_disable_setb(drvdata);
519 ret = __tpiu_enable_seta(drvdata);
520 if (ret) {
521 dev_err(drvdata->dev, "failed to enable set A\n");
522 goto err;
523 }
524 drvdata->set = TPIU_SET_A;
525 } else if (!strcmp(str, "b")) {
526 if (drvdata->set == TPIU_SET_B)
527 goto out;
528
529 if (!drvdata->enable || drvdata->out_mode !=
530 TPIU_OUT_MODE_MICTOR) {
531 drvdata->set = TPIU_SET_B;
532 goto out;
533 }
534 __tpiu_disable_seta(drvdata);
535 ret = __tpiu_enable_setb(drvdata);
536 if (ret) {
537 dev_err(drvdata->dev, "failed to enable set B\n");
538 goto err;
539 }
540 drvdata->set = TPIU_SET_B;
541 }
542out:
543 mutex_unlock(&drvdata->mutex);
544 return size;
545err:
546 mutex_unlock(&drvdata->mutex);
547 return ret;
548}
549static DEVICE_ATTR(set, S_IRUGO | S_IWUSR, tpiu_show_set, tpiu_store_set);
550
551static struct attribute *tpiu_attrs[] = {
552 &dev_attr_out_mode.attr,
553 &dev_attr_set.attr,
554 NULL,
555};
556
557static struct attribute_group tpiu_attr_grp = {
558 .attrs = tpiu_attrs,
559};
560
561static const struct attribute_group *tpiu_attr_grps[] = {
562 &tpiu_attr_grp,
563 NULL,
564};
565
566static int __devinit tpiu_parse_of_data(struct platform_device *pdev,
567 struct tpiu_drvdata *drvdata)
568{
569 struct device_node *node = pdev->dev.of_node;
570 struct device_node *reg_node = NULL;
571 struct device *dev = &pdev->dev;
572 const __be32 *prop;
573 int i, len, gpio, ret;
574 uint32_t *seta_cfgs, *setb_cfgs;
575
576 reg_node = of_parse_phandle(node, "vdd-supply", 0);
577 if (reg_node) {
578 drvdata->reg = devm_regulator_get(dev, "vdd");
579 if (IS_ERR(drvdata->reg))
580 return PTR_ERR(drvdata->reg);
581
582 prop = of_get_property(node, "qcom,vdd-voltage-level", &len);
583 if (!prop || (len != (2 * sizeof(__be32)))) {
Pratik Patela60feab2013-04-12 11:38:58 -0700584 dev_err(dev, "sdc voltage levels not specified\n");
Pratik Patel9a9313d2013-03-20 12:03:27 -0700585 } else {
586 drvdata->reg_low = be32_to_cpup(&prop[0]);
587 drvdata->reg_high = be32_to_cpup(&prop[1]);
588 }
589
590 prop = of_get_property(node, "qcom,vdd-current-level", &len);
591 if (!prop || (len != (2 * sizeof(__be32)))) {
Pratik Patela60feab2013-04-12 11:38:58 -0700592 dev_err(dev, "sdc current levels not specified\n");
Pratik Patel9a9313d2013-03-20 12:03:27 -0700593 } else {
594 drvdata->reg_lpm = be32_to_cpup(&prop[0]);
595 drvdata->reg_hpm = be32_to_cpup(&prop[1]);
596 }
597 of_node_put(reg_node);
598 } else {
599 dev_err(dev, "sdc voltage supply not specified or available\n");
600 }
601
Aparna Dasa177eb72013-07-23 16:03:28 -0700602 reg_node = of_parse_phandle(node, "vdd-io-supply", 0);
603 if (reg_node) {
604 drvdata->reg_io = devm_regulator_get(dev, "vdd-io");
605 if (IS_ERR(drvdata->reg_io))
606 return PTR_ERR(drvdata->reg_io);
607
608 prop = of_get_property(node, "qcom,vdd-io-voltage-level", &len);
609 if (!prop || (len != (2 * sizeof(__be32)))) {
610 dev_err(dev, "sdc io voltage levels not specified\n");
611 } else {
612 drvdata->reg_low_io = be32_to_cpup(&prop[0]);
613 drvdata->reg_high_io = be32_to_cpup(&prop[1]);
614 }
615
616 prop = of_get_property(node, "qcom,vdd-io-current-level", &len);
617 if (!prop || (len != (2 * sizeof(__be32)))) {
618 dev_err(dev, "sdc io current levels not specified\n");
619 } else {
620 drvdata->reg_lpm_io = be32_to_cpup(&prop[0]);
621 drvdata->reg_hpm_io = be32_to_cpup(&prop[1]);
622 }
623 of_node_put(reg_node);
624 } else {
625 dev_err(dev,
626 "sdc io voltage supply not specified or available\n");
627 }
628
Pratik Patel9a9313d2013-03-20 12:03:27 -0700629 drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
630 drvdata->set = TPIU_SET_B;
631
632 drvdata->seta_gpiocnt = of_gpio_named_count(node, "qcom,seta-gpios");
633 if (drvdata->seta_gpiocnt) {
634 drvdata->seta_gpios = devm_kzalloc(dev,
635 sizeof(*drvdata->seta_gpios) *
636 drvdata->seta_gpiocnt, GFP_KERNEL);
637 if (!drvdata->seta_gpios)
638 return -ENOMEM;
639
640 for (i = 0; i < drvdata->seta_gpiocnt; i++) {
641 gpio = of_get_named_gpio(node, "qcom,seta-gpios", i);
642 if (!gpio_is_valid(gpio))
643 return gpio;
644
645 drvdata->seta_gpios[i] = gpio;
646 }
647
648 drvdata->seta_cfgs = devm_kzalloc(dev,
649 sizeof(*drvdata->seta_cfgs) *
650 drvdata->seta_gpiocnt, GFP_KERNEL);
651 if (!drvdata->seta_cfgs)
652 return -ENOMEM;
653
654 seta_cfgs = devm_kzalloc(dev, sizeof(*seta_cfgs) *
655 drvdata->seta_gpiocnt, GFP_KERNEL);
656 if (!seta_cfgs)
657 return -ENOMEM;
658
659 ret = of_property_read_u32_array(node, "qcom,seta-gpios-func",
660 (u32 *)seta_cfgs,
661 drvdata->seta_gpiocnt);
662 if (ret)
663 return ret;
664
665 for (i = 0; i < drvdata->seta_gpiocnt; i++)
666 drvdata->seta_cfgs[i].func = seta_cfgs[i];
667
668 ret = of_property_read_u32_array(node, "qcom,seta-gpios-drv",
669 (u32 *)seta_cfgs,
670 drvdata->seta_gpiocnt);
671 if (ret)
672 return ret;
673
674 for (i = 0; i < drvdata->seta_gpiocnt; i++)
675 drvdata->seta_cfgs[i].drv = seta_cfgs[i];
676
677 ret = of_property_read_u32_array(node, "qcom,seta-gpios-pull",
678 (u32 *)seta_cfgs,
679 drvdata->seta_gpiocnt);
680 if (ret)
681 return ret;
682
683 for (i = 0; i < drvdata->seta_gpiocnt; i++)
684 drvdata->seta_cfgs[i].pull = seta_cfgs[i];
685
686 ret = of_property_read_u32_array(node, "qcom,seta-gpios-dir",
687 (u32 *)seta_cfgs,
688 drvdata->seta_gpiocnt);
689 if (ret)
690 return ret;
691
692 for (i = 0; i < drvdata->seta_gpiocnt; i++)
693 drvdata->seta_cfgs[i].dir = seta_cfgs[i];
Pratik Patel4b2cb3b2013-05-13 12:29:41 -0700694
695 devm_kfree(dev, seta_cfgs);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700696 } else {
697 dev_err(dev, "seta gpios not specified\n");
698 }
699
700 drvdata->setb_gpiocnt = of_gpio_named_count(node, "qcom,setb-gpios");
701 if (drvdata->setb_gpiocnt) {
702 drvdata->setb_gpios = devm_kzalloc(dev,
703 sizeof(*drvdata->setb_gpios) *
704 drvdata->setb_gpiocnt, GFP_KERNEL);
705 if (!drvdata->setb_gpios)
706 return -ENOMEM;
707
708 for (i = 0; i < drvdata->setb_gpiocnt; i++) {
709 gpio = of_get_named_gpio(node, "qcom,setb-gpios", i);
710 if (!gpio_is_valid(gpio))
711 return gpio;
712
713 drvdata->setb_gpios[i] = gpio;
714 }
715
716 drvdata->setb_cfgs = devm_kzalloc(dev,
717 sizeof(*drvdata->setb_cfgs) *
718 drvdata->setb_gpiocnt, GFP_KERNEL);
719 if (!drvdata->setb_cfgs)
720 return -ENOMEM;
721
722 setb_cfgs = devm_kzalloc(dev, sizeof(*setb_cfgs) *
723 drvdata->setb_gpiocnt, GFP_KERNEL);
724 if (!setb_cfgs)
725 return -ENOMEM;
726
727 ret = of_property_read_u32_array(node, "qcom,setb-gpios-func",
728 (u32 *)setb_cfgs,
729 drvdata->setb_gpiocnt);
730 if (ret)
731 return ret;
732
733 for (i = 0; i < drvdata->setb_gpiocnt; i++)
734 drvdata->setb_cfgs[i].func = setb_cfgs[i];
735
736 ret = of_property_read_u32_array(node, "qcom,setb-gpios-drv",
737 (u32 *)setb_cfgs,
738 drvdata->setb_gpiocnt);
739 if (ret)
740 return ret;
741
742 for (i = 0; i < drvdata->setb_gpiocnt; i++)
743 drvdata->setb_cfgs[i].drv = setb_cfgs[i];
744
745 ret = of_property_read_u32_array(node, "qcom,setb-gpios-pull",
746 (u32 *)setb_cfgs,
747 drvdata->setb_gpiocnt);
748 if (ret)
749 return ret;
750
751 for (i = 0; i < drvdata->setb_gpiocnt; i++)
752 drvdata->setb_cfgs[i].pull = setb_cfgs[i];
753
754 ret = of_property_read_u32_array(node, "qcom,setb-gpios-dir",
755 (u32 *)setb_cfgs,
756 drvdata->setb_gpiocnt);
757 if (ret)
758 return ret;
759
760 for (i = 0; i < drvdata->setb_gpiocnt; i++)
761 drvdata->setb_cfgs[i].dir = setb_cfgs[i];
Pratik Patel4b2cb3b2013-05-13 12:29:41 -0700762
763 devm_kfree(dev, setb_cfgs);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700764 } else {
765 dev_err(dev, "setb gpios not specified\n");
766 }
767
768 return 0;
769}
770
Pratik Patel7831c082011-06-08 21:44:37 -0700771static int __devinit tpiu_probe(struct platform_device *pdev)
772{
773 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -0700774 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -0700775 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700776 struct tpiu_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -0700777 struct resource *res;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700778 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -0700779
Pratik Patel49306402013-06-14 01:02:08 -0700780 if (coresight_fuse_access_disabled())
781 return -EPERM;
782
Pratik Patel5f6d1af2012-06-13 15:48:13 -0700783 if (pdev->dev.of_node) {
784 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
785 if (IS_ERR(pdata))
786 return PTR_ERR(pdata);
787 pdev->dev.platform_data = pdata;
788 }
789
Pratik Patel4a1b2522012-06-17 15:31:15 -0700790 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
791 if (!drvdata)
792 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700793 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700794 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700795
Aparna Dasc9907512013-03-08 10:20:52 -0800796 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpiu-base");
Pratik Patel4a1b2522012-06-17 15:31:15 -0700797 if (!res)
798 return -ENODEV;
Pratik Patel2c09b762012-07-21 15:54:54 -0700799
Pratik Patel4a1b2522012-06-17 15:31:15 -0700800 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
801 if (!drvdata->base)
802 return -ENOMEM;
Pratik Patelf17b1472012-05-25 22:23:52 -0700803
Pratik Patel9a9313d2013-03-20 12:03:27 -0700804 mutex_init(&drvdata->mutex);
805
Pratik Patel4a1b2522012-06-17 15:31:15 -0700806 drvdata->clk = devm_clk_get(dev, "core_clk");
807 if (IS_ERR(drvdata->clk))
808 return PTR_ERR(drvdata->clk);
Pratik Patel2c09b762012-07-21 15:54:54 -0700809
Pratik Patel6fb38342012-06-03 14:51:38 -0700810 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patelf17b1472012-05-25 22:23:52 -0700811 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -0700812 return ret;
Pratik Patelf17b1472012-05-25 22:23:52 -0700813
Pratik Patelc496b662012-06-17 18:42:44 -0700814 ret = clk_prepare_enable(drvdata->clk);
815 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -0700816 return ret;
Pratik Patel2c09b762012-07-21 15:54:54 -0700817
818 /* Disable tpiu to support older targets that need this */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700819 __tpiu_disable(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -0700820
Pratik Patelc496b662012-06-17 18:42:44 -0700821 clk_disable_unprepare(drvdata->clk);
822
Pratik Patel9a9313d2013-03-20 12:03:27 -0700823 if (pdev->dev.of_node) {
824 ret = tpiu_parse_of_data(pdev, drvdata);
825 if (ret)
826 return ret;
827 }
828
Pratik Patel4a1b2522012-06-17 15:31:15 -0700829 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
830 if (!desc)
831 return -ENOMEM;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700832 desc->type = CORESIGHT_DEV_TYPE_SINK;
833 desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;
834 desc->ops = &tpiu_cs_ops;
835 desc->pdata = pdev->dev.platform_data;
836 desc->dev = &pdev->dev;
Pratik Patel9a9313d2013-03-20 12:03:27 -0700837 desc->groups = tpiu_attr_grps;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700838 desc->owner = THIS_MODULE;
839 drvdata->csdev = coresight_register(desc);
Pratik Patel4a1b2522012-06-17 15:31:15 -0700840 if (IS_ERR(drvdata->csdev))
841 return PTR_ERR(drvdata->csdev);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700842
Pratik Patel4a1b2522012-06-17 15:31:15 -0700843 dev_info(dev, "TPIU initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700844 return 0;
Pratik Patel7831c082011-06-08 21:44:37 -0700845}
846
Pratik Patelf6fe9182012-03-20 14:04:18 -0700847static int __devexit tpiu_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700848{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700849 struct tpiu_drvdata *drvdata = platform_get_drvdata(pdev);
850
851 coresight_unregister(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -0700852 return 0;
853}
854
Pratik Patel9eae4822012-05-14 17:34:53 -0700855static struct of_device_id tpiu_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -0700856 {.compatible = "arm,coresight-tpiu"},
Pratik Patel9eae4822012-05-14 17:34:53 -0700857 {}
858};
859
Pratik Patel7831c082011-06-08 21:44:37 -0700860static struct platform_driver tpiu_driver = {
861 .probe = tpiu_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -0700862 .remove = __devexit_p(tpiu_remove),
Pratik Patel7831c082011-06-08 21:44:37 -0700863 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700864 .name = "coresight-tpiu",
Pratik Patel9eae4822012-05-14 17:34:53 -0700865 .owner = THIS_MODULE,
866 .of_match_table = tpiu_match,
Pratik Patel7831c082011-06-08 21:44:37 -0700867 },
868};
869
Pratik Patelf6fe9182012-03-20 14:04:18 -0700870static int __init tpiu_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700871{
872 return platform_driver_register(&tpiu_driver);
873}
Pratik Patelf6fe9182012-03-20 14:04:18 -0700874module_init(tpiu_init);
Pratik Patel7831c082011-06-08 21:44:37 -0700875
Pratik Patelf6fe9182012-03-20 14:04:18 -0700876static void __exit tpiu_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700877{
878 platform_driver_unregister(&tpiu_driver);
879}
Pratik Patelf6fe9182012-03-20 14:04:18 -0700880module_exit(tpiu_exit);
881
882MODULE_LICENSE("GPL v2");
883MODULE_DESCRIPTION("CoreSight Trace Port Interface Unit driver");