blob: 73800dd9001226dbf4d6565b9a799b642cf8d237 [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;
91 enum tpiu_set set;
92 unsigned int seta_gpiocnt;
93 unsigned int *seta_gpios;
94 struct gpiomux_setting *seta_cfgs;
95 unsigned int setb_gpiocnt;
96 unsigned int *setb_gpios;
97 struct gpiomux_setting *setb_cfgs;
98 bool enable;
Pratik Patel7831c082011-06-08 21:44:37 -070099};
100
Pratik Patel9a9313d2013-03-20 12:03:27 -0700101struct gpiomux_setting old_cfg;
102
103static void tpiu_flush_and_stop(struct tpiu_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700104{
Pratik Patel9a9313d2013-03-20 12:03:27 -0700105 int count;
106 uint32_t ffcr;
107
108 ffcr = tpiu_readl(drvdata, TPIU_FFCR);
109 ffcr |= BIT(12);
110 tpiu_writel(drvdata, ffcr, TPIU_FFCR);
111 ffcr |= BIT(6);
112 tpiu_writel(drvdata, ffcr, TPIU_FFCR);
113 /* Ensure flush completes */
114 for (count = TIMEOUT_US; BVAL(tpiu_readl(drvdata, TPIU_FFCR), 6) != 0
115 && count > 0; count--)
116 udelay(1);
117 WARN(count == 0, "timeout while flushing TPIU, TPIU_FFCR: %#x\n",
118 tpiu_readl(drvdata, TPIU_FFCR));
119}
120
121static int __tpiu_enable_seta(struct tpiu_drvdata *drvdata)
122{
123 int i, ret;
124
125 if (!drvdata->seta_gpiocnt)
126 return -EINVAL;
127
128 for (i = 0; i < drvdata->seta_gpiocnt; i++) {
129 ret = gpio_request(drvdata->seta_gpios[i], NULL);
130 if (ret) {
131 dev_err(drvdata->dev,
132 "gpio_request failed for seta_gpio: %u\n",
133 drvdata->seta_gpios[i]);
134 goto err0;
135 }
136 ret = msm_gpiomux_write(drvdata->seta_gpios[i],
137 GPIOMUX_ACTIVE,
138 &drvdata->seta_cfgs[i],
139 &old_cfg);
140 if (ret < 0) {
141 dev_err(drvdata->dev,
142 "gpio write failed for seta_gpio: %u\n",
143 drvdata->seta_gpios[i]);
144 goto err1;
145 }
146 }
147 return 0;
148err1:
149 gpio_free(drvdata->seta_gpios[i]);
150err0:
151 i--;
152 while (i >= 0) {
153 gpio_free(drvdata->seta_gpios[i]);
154 i--;
155 }
156 return ret;
157}
158
159static int __tpiu_enable_setb(struct tpiu_drvdata *drvdata)
160{
161 int i, ret;
162
163 if (!drvdata->setb_gpiocnt)
164 return -EINVAL;
165
166 for (i = 0; i < drvdata->setb_gpiocnt; i++) {
167 ret = gpio_request(drvdata->setb_gpios[i], NULL);
168 if (ret) {
169 dev_err(drvdata->dev,
170 "gpio_request failed for setb_gpio: %u\n",
171 drvdata->setb_gpios[i]);
172 goto err0;
173 }
174 ret = msm_gpiomux_write(drvdata->setb_gpios[i],
175 GPIOMUX_ACTIVE,
176 &drvdata->setb_cfgs[i],
177 &old_cfg);
178 if (ret < 0) {
179 dev_err(drvdata->dev,
180 "gpio write failed for setb_gpio: %u\n",
181 drvdata->setb_gpios[i]);
182 goto err1;
183 }
184 }
185 return 0;
186err1:
187 gpio_free(drvdata->setb_gpios[i]);
188err0:
189 i--;
190 while (i >= 0) {
191 gpio_free(drvdata->setb_gpios[i]);
192 i--;
193 }
194 return ret;
195}
196
197static int __tpiu_enable_to_mictor(struct tpiu_drvdata *drvdata)
198{
199 int ret;
200
201 if (drvdata->set == TPIU_SET_A) {
202 ret = __tpiu_enable_seta(drvdata);
203 if (ret)
204 return ret;
205 } else if (drvdata->set == TPIU_SET_B) {
206 ret = __tpiu_enable_setb(drvdata);
207 if (ret)
208 return ret;
209 }
210
Pratik Patel3b0ca882012-06-01 16:54:14 -0700211 TPIU_UNLOCK(drvdata);
212
Pratik Patel9a9313d2013-03-20 12:03:27 -0700213 tpiu_writel(drvdata, 0x8000, TPIU_CURR_PORTSZ);
214 tpiu_writel(drvdata, 0x101, TPIU_FFCR);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700215
216 TPIU_LOCK(drvdata);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700217
218 return 0;
219}
220
221static int __tpiu_enable_to_sdc(struct tpiu_drvdata *drvdata)
222{
223 int ret;
224
225 if (!drvdata->reg)
226 return -EINVAL;
227
228 ret = regulator_set_optimum_mode(drvdata->reg, drvdata->reg_hpm);
229 if (ret < 0)
230 return ret;
231 ret = regulator_set_voltage(drvdata->reg, drvdata->reg_low,
232 drvdata->reg_high);
233 if (ret)
234 goto err0;
235 ret = regulator_enable(drvdata->reg);
236 if (ret)
237 goto err1;
238
239 msm_tlmm_misc_reg_write(TLMM_SDC2_HDRV_PULL_CTL, 0x16D);
240 msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 1);
241
242 TPIU_UNLOCK(drvdata);
243
244 tpiu_writel(drvdata, 0x8, TPIU_CURR_PORTSZ);
245 tpiu_writel(drvdata, 0x103, TPIU_FFCR);
246
247 TPIU_LOCK(drvdata);
248
249 return 0;
250err1:
251 regulator_set_voltage(drvdata->reg, 0, drvdata->reg_high);
252err0:
253 regulator_set_optimum_mode(drvdata->reg, 0);
254 return ret;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700255}
256
257static int tpiu_enable(struct coresight_device *csdev)
258{
259 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
260 int ret;
261
262 ret = clk_prepare_enable(drvdata->clk);
263 if (ret)
264 return ret;
265
Pratik Patel9a9313d2013-03-20 12:03:27 -0700266 mutex_lock(&drvdata->mutex);
267
268 if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
269 ret = __tpiu_enable_to_mictor(drvdata);
270 else
271 ret = __tpiu_enable_to_sdc(drvdata);
272 if (ret)
273 goto err;
274 drvdata->enable = true;
275
276 mutex_unlock(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700277
278 dev_info(drvdata->dev, "TPIU enabled\n");
279 return 0;
Pratik Patel9a9313d2013-03-20 12:03:27 -0700280err:
281 mutex_unlock(&drvdata->mutex);
282 clk_disable_unprepare(drvdata->clk);
283 return ret;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700284}
285
286static void __tpiu_disable(struct tpiu_drvdata *drvdata)
287{
288 TPIU_UNLOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700289
Pratik Patel9a9313d2013-03-20 12:03:27 -0700290 tpiu_flush_and_stop(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700291
Pratik Patel3b0ca882012-06-01 16:54:14 -0700292 TPIU_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700293}
294
Pratik Patel9a9313d2013-03-20 12:03:27 -0700295static void __tpiu_disable_seta(struct tpiu_drvdata *drvdata)
296{
297 int i;
298
299 for (i = 0; i < drvdata->seta_gpiocnt; i++)
300 gpio_free(drvdata->seta_gpios[i]);
301}
302
303static void __tpiu_disable_setb(struct tpiu_drvdata *drvdata)
304{
305 int i;
306
307 for (i = 0; i < drvdata->setb_gpiocnt; i++)
308 gpio_free(drvdata->setb_gpios[i]);
309}
310
311static void __tpiu_disable_to_mictor(struct tpiu_drvdata *drvdata)
312{
313 __tpiu_disable(drvdata);
314
315 if (drvdata->set == TPIU_SET_A)
316 __tpiu_disable_seta(drvdata);
317 else if (drvdata->set == TPIU_SET_B)
318 __tpiu_disable_setb(drvdata);
319}
320
321static void __tpiu_disable_to_sdc(struct tpiu_drvdata *drvdata)
322{
323 __tpiu_disable(drvdata);
324
325 msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 0);
326
327 regulator_disable(drvdata->reg);
328 regulator_set_optimum_mode(drvdata->reg, 0);
329 regulator_set_voltage(drvdata->reg, 0, drvdata->reg_high);
330}
331
Pratik Patel3b0ca882012-06-01 16:54:14 -0700332static void tpiu_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700333{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700334 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
335
Pratik Patel9a9313d2013-03-20 12:03:27 -0700336 mutex_lock(&drvdata->mutex);
337
338 if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
339 __tpiu_disable_to_mictor(drvdata);
340 else
341 __tpiu_disable_to_sdc(drvdata);
342 drvdata->enable = false;
343
344 mutex_unlock(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700345
346 clk_disable_unprepare(drvdata->clk);
347
Pratik Patel16aefdb2012-05-30 10:41:23 -0700348 dev_info(drvdata->dev, "TPIU disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700349}
350
Pratik Patelcf7d0452012-07-02 13:57:20 -0700351static void tpiu_abort(struct coresight_device *csdev)
352{
353 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
354
355 __tpiu_disable(drvdata);
356
357 dev_info(drvdata->dev, "TPIU aborted\n");
358}
359
Pratik Patel3b0ca882012-06-01 16:54:14 -0700360static const struct coresight_ops_sink tpiu_sink_ops = {
361 .enable = tpiu_enable,
362 .disable = tpiu_disable,
Pratik Patelcf7d0452012-07-02 13:57:20 -0700363 .abort = tpiu_abort,
Pratik Patel3b0ca882012-06-01 16:54:14 -0700364};
365
Pratik Patel9a9313d2013-03-20 12:03:27 -0700366static ssize_t tpiu_show_out_mode(struct device *dev,
367 struct device_attribute *attr, char *buf)
368{
369 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
370
371 return scnprintf(buf, PAGE_SIZE, "%s\n",
372 drvdata->out_mode == TPIU_OUT_MODE_MICTOR ?
373 "mictor" : "sdc");
374}
375
376static ssize_t tpiu_store_out_mode(struct device *dev,
377 struct device_attribute *attr,
378 const char *buf, size_t size)
379{
380 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
381 char str[10] = "";
382 int ret;
383
384 if (strlen(buf) >= 10)
385 return -EINVAL;
386 if (sscanf(buf, "%s", str) != 1)
387 return -EINVAL;
388
389 mutex_lock(&drvdata->mutex);
390 if (!strcmp(str, "mictor")) {
391 if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
392 goto out;
393
394 if (!drvdata->enable) {
395 drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
396 goto out;
397 }
398 __tpiu_disable_to_sdc(drvdata);
399 ret = __tpiu_enable_to_mictor(drvdata);
400 if (ret) {
401 dev_err(drvdata->dev, "failed to enable mictor\n");
402 goto err;
403 }
404 drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
405 } else if (!strcmp(str, "sdc")) {
406 if (drvdata->out_mode == TPIU_OUT_MODE_SDC)
407 goto out;
408
409 if (!drvdata->enable) {
410 drvdata->out_mode = TPIU_OUT_MODE_SDC;
411 goto out;
412 }
413 __tpiu_disable_to_mictor(drvdata);
414 ret = __tpiu_enable_to_sdc(drvdata);
415 if (ret) {
416 dev_err(drvdata->dev, "failed to enable sdc\n");
417 goto err;
418 }
419 drvdata->out_mode = TPIU_OUT_MODE_SDC;
420 }
421out:
422 mutex_unlock(&drvdata->mutex);
423 return size;
424err:
425 mutex_unlock(&drvdata->mutex);
426 return ret;
427}
428static DEVICE_ATTR(out_mode, S_IRUGO | S_IWUSR, tpiu_show_out_mode,
429 tpiu_store_out_mode);
430
Pratik Patel3b0ca882012-06-01 16:54:14 -0700431static const struct coresight_ops tpiu_cs_ops = {
432 .sink_ops = &tpiu_sink_ops,
433};
434
Pratik Patel9a9313d2013-03-20 12:03:27 -0700435static ssize_t tpiu_show_set(struct device *dev,
436 struct device_attribute *attr, char *buf)
437{
438 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
439
440 return scnprintf(buf, PAGE_SIZE, "%s\n",
441 drvdata->set == TPIU_SET_A ?
442 "a" : "b");
443}
444
445static ssize_t tpiu_store_set(struct device *dev, struct device_attribute *attr,
446 const char *buf, size_t size)
447{
448 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
449 char str[10] = "";
450 int ret;
451
452 if (strlen(buf) >= 10)
453 return -EINVAL;
454 if (sscanf(buf, "%s", str) != 1)
455 return -EINVAL;
456
457 mutex_lock(&drvdata->mutex);
458 if (!strcmp(str, "a")) {
459 if (drvdata->set == TPIU_SET_A)
460 goto out;
461
462 if (!drvdata->enable || drvdata->out_mode !=
463 TPIU_OUT_MODE_MICTOR) {
464 drvdata->set = TPIU_SET_A;
465 goto out;
466 }
467 __tpiu_disable_setb(drvdata);
468 ret = __tpiu_enable_seta(drvdata);
469 if (ret) {
470 dev_err(drvdata->dev, "failed to enable set A\n");
471 goto err;
472 }
473 drvdata->set = TPIU_SET_A;
474 } else if (!strcmp(str, "b")) {
475 if (drvdata->set == TPIU_SET_B)
476 goto out;
477
478 if (!drvdata->enable || drvdata->out_mode !=
479 TPIU_OUT_MODE_MICTOR) {
480 drvdata->set = TPIU_SET_B;
481 goto out;
482 }
483 __tpiu_disable_seta(drvdata);
484 ret = __tpiu_enable_setb(drvdata);
485 if (ret) {
486 dev_err(drvdata->dev, "failed to enable set B\n");
487 goto err;
488 }
489 drvdata->set = TPIU_SET_B;
490 }
491out:
492 mutex_unlock(&drvdata->mutex);
493 return size;
494err:
495 mutex_unlock(&drvdata->mutex);
496 return ret;
497}
498static DEVICE_ATTR(set, S_IRUGO | S_IWUSR, tpiu_show_set, tpiu_store_set);
499
500static struct attribute *tpiu_attrs[] = {
501 &dev_attr_out_mode.attr,
502 &dev_attr_set.attr,
503 NULL,
504};
505
506static struct attribute_group tpiu_attr_grp = {
507 .attrs = tpiu_attrs,
508};
509
510static const struct attribute_group *tpiu_attr_grps[] = {
511 &tpiu_attr_grp,
512 NULL,
513};
514
515static int __devinit tpiu_parse_of_data(struct platform_device *pdev,
516 struct tpiu_drvdata *drvdata)
517{
518 struct device_node *node = pdev->dev.of_node;
519 struct device_node *reg_node = NULL;
520 struct device *dev = &pdev->dev;
521 const __be32 *prop;
522 int i, len, gpio, ret;
523 uint32_t *seta_cfgs, *setb_cfgs;
524
525 reg_node = of_parse_phandle(node, "vdd-supply", 0);
526 if (reg_node) {
527 drvdata->reg = devm_regulator_get(dev, "vdd");
528 if (IS_ERR(drvdata->reg))
529 return PTR_ERR(drvdata->reg);
530
531 prop = of_get_property(node, "qcom,vdd-voltage-level", &len);
532 if (!prop || (len != (2 * sizeof(__be32)))) {
533 of_node_put(reg_node);
534 return -EINVAL;
535 } else {
536 drvdata->reg_low = be32_to_cpup(&prop[0]);
537 drvdata->reg_high = be32_to_cpup(&prop[1]);
538 }
539
540 prop = of_get_property(node, "qcom,vdd-current-level", &len);
541 if (!prop || (len != (2 * sizeof(__be32)))) {
542 of_node_put(reg_node);
543 return -EINVAL;
544 } else {
545 drvdata->reg_lpm = be32_to_cpup(&prop[0]);
546 drvdata->reg_hpm = be32_to_cpup(&prop[1]);
547 }
548 of_node_put(reg_node);
549 } else {
550 dev_err(dev, "sdc voltage supply not specified or available\n");
551 }
552
553 drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
554 drvdata->set = TPIU_SET_B;
555
556 drvdata->seta_gpiocnt = of_gpio_named_count(node, "qcom,seta-gpios");
557 if (drvdata->seta_gpiocnt) {
558 drvdata->seta_gpios = devm_kzalloc(dev,
559 sizeof(*drvdata->seta_gpios) *
560 drvdata->seta_gpiocnt, GFP_KERNEL);
561 if (!drvdata->seta_gpios)
562 return -ENOMEM;
563
564 for (i = 0; i < drvdata->seta_gpiocnt; i++) {
565 gpio = of_get_named_gpio(node, "qcom,seta-gpios", i);
566 if (!gpio_is_valid(gpio))
567 return gpio;
568
569 drvdata->seta_gpios[i] = gpio;
570 }
571
572 drvdata->seta_cfgs = devm_kzalloc(dev,
573 sizeof(*drvdata->seta_cfgs) *
574 drvdata->seta_gpiocnt, GFP_KERNEL);
575 if (!drvdata->seta_cfgs)
576 return -ENOMEM;
577
578 seta_cfgs = devm_kzalloc(dev, sizeof(*seta_cfgs) *
579 drvdata->seta_gpiocnt, GFP_KERNEL);
580 if (!seta_cfgs)
581 return -ENOMEM;
582
583 ret = of_property_read_u32_array(node, "qcom,seta-gpios-func",
584 (u32 *)seta_cfgs,
585 drvdata->seta_gpiocnt);
586 if (ret)
587 return ret;
588
589 for (i = 0; i < drvdata->seta_gpiocnt; i++)
590 drvdata->seta_cfgs[i].func = seta_cfgs[i];
591
592 ret = of_property_read_u32_array(node, "qcom,seta-gpios-drv",
593 (u32 *)seta_cfgs,
594 drvdata->seta_gpiocnt);
595 if (ret)
596 return ret;
597
598 for (i = 0; i < drvdata->seta_gpiocnt; i++)
599 drvdata->seta_cfgs[i].drv = seta_cfgs[i];
600
601 ret = of_property_read_u32_array(node, "qcom,seta-gpios-pull",
602 (u32 *)seta_cfgs,
603 drvdata->seta_gpiocnt);
604 if (ret)
605 return ret;
606
607 for (i = 0; i < drvdata->seta_gpiocnt; i++)
608 drvdata->seta_cfgs[i].pull = seta_cfgs[i];
609
610 ret = of_property_read_u32_array(node, "qcom,seta-gpios-dir",
611 (u32 *)seta_cfgs,
612 drvdata->seta_gpiocnt);
613 if (ret)
614 return ret;
615
616 for (i = 0; i < drvdata->seta_gpiocnt; i++)
617 drvdata->seta_cfgs[i].dir = seta_cfgs[i];
618 } else {
619 dev_err(dev, "seta gpios not specified\n");
620 }
621
622 drvdata->setb_gpiocnt = of_gpio_named_count(node, "qcom,setb-gpios");
623 if (drvdata->setb_gpiocnt) {
624 drvdata->setb_gpios = devm_kzalloc(dev,
625 sizeof(*drvdata->setb_gpios) *
626 drvdata->setb_gpiocnt, GFP_KERNEL);
627 if (!drvdata->setb_gpios)
628 return -ENOMEM;
629
630 for (i = 0; i < drvdata->setb_gpiocnt; i++) {
631 gpio = of_get_named_gpio(node, "qcom,setb-gpios", i);
632 if (!gpio_is_valid(gpio))
633 return gpio;
634
635 drvdata->setb_gpios[i] = gpio;
636 }
637
638 drvdata->setb_cfgs = devm_kzalloc(dev,
639 sizeof(*drvdata->setb_cfgs) *
640 drvdata->setb_gpiocnt, GFP_KERNEL);
641 if (!drvdata->setb_cfgs)
642 return -ENOMEM;
643
644 setb_cfgs = devm_kzalloc(dev, sizeof(*setb_cfgs) *
645 drvdata->setb_gpiocnt, GFP_KERNEL);
646 if (!setb_cfgs)
647 return -ENOMEM;
648
649 ret = of_property_read_u32_array(node, "qcom,setb-gpios-func",
650 (u32 *)setb_cfgs,
651 drvdata->setb_gpiocnt);
652 if (ret)
653 return ret;
654
655 for (i = 0; i < drvdata->setb_gpiocnt; i++)
656 drvdata->setb_cfgs[i].func = setb_cfgs[i];
657
658 ret = of_property_read_u32_array(node, "qcom,setb-gpios-drv",
659 (u32 *)setb_cfgs,
660 drvdata->setb_gpiocnt);
661 if (ret)
662 return ret;
663
664 for (i = 0; i < drvdata->setb_gpiocnt; i++)
665 drvdata->setb_cfgs[i].drv = setb_cfgs[i];
666
667 ret = of_property_read_u32_array(node, "qcom,setb-gpios-pull",
668 (u32 *)setb_cfgs,
669 drvdata->setb_gpiocnt);
670 if (ret)
671 return ret;
672
673 for (i = 0; i < drvdata->setb_gpiocnt; i++)
674 drvdata->setb_cfgs[i].pull = setb_cfgs[i];
675
676 ret = of_property_read_u32_array(node, "qcom,setb-gpios-dir",
677 (u32 *)setb_cfgs,
678 drvdata->setb_gpiocnt);
679 if (ret)
680 return ret;
681
682 for (i = 0; i < drvdata->setb_gpiocnt; i++)
683 drvdata->setb_cfgs[i].dir = setb_cfgs[i];
684 } else {
685 dev_err(dev, "setb gpios not specified\n");
686 }
687
688 return 0;
689}
690
Pratik Patel7831c082011-06-08 21:44:37 -0700691static int __devinit tpiu_probe(struct platform_device *pdev)
692{
693 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -0700694 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -0700695 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700696 struct tpiu_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -0700697 struct resource *res;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700698 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -0700699
Pratik Patel5f6d1af2012-06-13 15:48:13 -0700700 if (pdev->dev.of_node) {
701 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
702 if (IS_ERR(pdata))
703 return PTR_ERR(pdata);
704 pdev->dev.platform_data = pdata;
705 }
706
Pratik Patel4a1b2522012-06-17 15:31:15 -0700707 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
708 if (!drvdata)
709 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700710 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700711 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700712
Pratik Patel4a1b2522012-06-17 15:31:15 -0700713 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
714 if (!res)
715 return -ENODEV;
Pratik Patel2c09b762012-07-21 15:54:54 -0700716
Pratik Patel4a1b2522012-06-17 15:31:15 -0700717 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
718 if (!drvdata->base)
719 return -ENOMEM;
Pratik Patelf17b1472012-05-25 22:23:52 -0700720
Pratik Patel9a9313d2013-03-20 12:03:27 -0700721 mutex_init(&drvdata->mutex);
722
Pratik Patel4a1b2522012-06-17 15:31:15 -0700723 drvdata->clk = devm_clk_get(dev, "core_clk");
724 if (IS_ERR(drvdata->clk))
725 return PTR_ERR(drvdata->clk);
Pratik Patel2c09b762012-07-21 15:54:54 -0700726
Pratik Patel6fb38342012-06-03 14:51:38 -0700727 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patelf17b1472012-05-25 22:23:52 -0700728 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -0700729 return ret;
Pratik Patelf17b1472012-05-25 22:23:52 -0700730
Pratik Patelc496b662012-06-17 18:42:44 -0700731 ret = clk_prepare_enable(drvdata->clk);
732 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -0700733 return ret;
Pratik Patel2c09b762012-07-21 15:54:54 -0700734
735 /* Disable tpiu to support older targets that need this */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700736 __tpiu_disable(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -0700737
Pratik Patelc496b662012-06-17 18:42:44 -0700738 clk_disable_unprepare(drvdata->clk);
739
Pratik Patel9a9313d2013-03-20 12:03:27 -0700740 if (pdev->dev.of_node) {
741 ret = tpiu_parse_of_data(pdev, drvdata);
742 if (ret)
743 return ret;
744 }
745
Pratik Patel4a1b2522012-06-17 15:31:15 -0700746 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
747 if (!desc)
748 return -ENOMEM;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700749 desc->type = CORESIGHT_DEV_TYPE_SINK;
750 desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;
751 desc->ops = &tpiu_cs_ops;
752 desc->pdata = pdev->dev.platform_data;
753 desc->dev = &pdev->dev;
Pratik Patel9a9313d2013-03-20 12:03:27 -0700754 desc->groups = tpiu_attr_grps;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700755 desc->owner = THIS_MODULE;
756 drvdata->csdev = coresight_register(desc);
Pratik Patel4a1b2522012-06-17 15:31:15 -0700757 if (IS_ERR(drvdata->csdev))
758 return PTR_ERR(drvdata->csdev);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700759
Pratik Patel4a1b2522012-06-17 15:31:15 -0700760 dev_info(dev, "TPIU initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700761 return 0;
Pratik Patel7831c082011-06-08 21:44:37 -0700762}
763
Pratik Patelf6fe9182012-03-20 14:04:18 -0700764static int __devexit tpiu_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700765{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700766 struct tpiu_drvdata *drvdata = platform_get_drvdata(pdev);
767
768 coresight_unregister(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -0700769 return 0;
770}
771
Pratik Patel9eae4822012-05-14 17:34:53 -0700772static struct of_device_id tpiu_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -0700773 {.compatible = "arm,coresight-tpiu"},
Pratik Patel9eae4822012-05-14 17:34:53 -0700774 {}
775};
776
Pratik Patel7831c082011-06-08 21:44:37 -0700777static struct platform_driver tpiu_driver = {
778 .probe = tpiu_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -0700779 .remove = __devexit_p(tpiu_remove),
Pratik Patel7831c082011-06-08 21:44:37 -0700780 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700781 .name = "coresight-tpiu",
Pratik Patel9eae4822012-05-14 17:34:53 -0700782 .owner = THIS_MODULE,
783 .of_match_table = tpiu_match,
Pratik Patel7831c082011-06-08 21:44:37 -0700784 },
785};
786
Pratik Patelf6fe9182012-03-20 14:04:18 -0700787static int __init tpiu_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700788{
789 return platform_driver_register(&tpiu_driver);
790}
Pratik Patelf6fe9182012-03-20 14:04:18 -0700791module_init(tpiu_init);
Pratik Patel7831c082011-06-08 21:44:37 -0700792
Pratik Patelf6fe9182012-03-20 14:04:18 -0700793static void __exit tpiu_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700794{
795 platform_driver_unregister(&tpiu_driver);
796}
Pratik Patelf6fe9182012-03-20 14:04:18 -0700797module_exit(tpiu_exit);
798
799MODULE_LICENSE("GPL v2");
800MODULE_DESCRIPTION("CoreSight Trace Port Interface Unit driver");