blob: 53df0f9dc0f48004d67cfb843be3d4093e543e8b [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
Pratik Patela60feab2013-04-12 11:38:58 -0700221static int tpiu_reg_set_optimum_mode(struct regulator *reg,
222 unsigned int reg_hpm)
223{
224 if (regulator_count_voltages(reg) <= 0)
225 return 0;
226
227 return regulator_set_optimum_mode(reg, reg_hpm);
228}
229
230static int tpiu_reg_set_voltage(struct regulator *reg, unsigned int reg_low,
231 unsigned int reg_high)
232{
233 if (regulator_count_voltages(reg) <= 0)
234 return 0;
235
236 return regulator_set_voltage(reg, reg_low, reg_high);
237}
238
Pratik Patel9a9313d2013-03-20 12:03:27 -0700239static int __tpiu_enable_to_sdc(struct tpiu_drvdata *drvdata)
240{
241 int ret;
242
243 if (!drvdata->reg)
244 return -EINVAL;
245
Pratik Patela60feab2013-04-12 11:38:58 -0700246 ret = tpiu_reg_set_optimum_mode(drvdata->reg, drvdata->reg_hpm);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700247 if (ret < 0)
248 return ret;
Pratik Patela60feab2013-04-12 11:38:58 -0700249 ret = tpiu_reg_set_voltage(drvdata->reg, drvdata->reg_low,
250 drvdata->reg_high);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700251 if (ret)
252 goto err0;
253 ret = regulator_enable(drvdata->reg);
254 if (ret)
255 goto err1;
256
257 msm_tlmm_misc_reg_write(TLMM_SDC2_HDRV_PULL_CTL, 0x16D);
258 msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 1);
259
260 TPIU_UNLOCK(drvdata);
261
262 tpiu_writel(drvdata, 0x8, TPIU_CURR_PORTSZ);
263 tpiu_writel(drvdata, 0x103, TPIU_FFCR);
264
265 TPIU_LOCK(drvdata);
266
267 return 0;
268err1:
Pratik Patela60feab2013-04-12 11:38:58 -0700269 tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700270err0:
Pratik Patela60feab2013-04-12 11:38:58 -0700271 tpiu_reg_set_optimum_mode(drvdata->reg, 0);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700272 return ret;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700273}
274
275static int tpiu_enable(struct coresight_device *csdev)
276{
277 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
278 int ret;
279
280 ret = clk_prepare_enable(drvdata->clk);
281 if (ret)
282 return ret;
283
Pratik Patel9a9313d2013-03-20 12:03:27 -0700284 mutex_lock(&drvdata->mutex);
285
286 if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
287 ret = __tpiu_enable_to_mictor(drvdata);
288 else
289 ret = __tpiu_enable_to_sdc(drvdata);
290 if (ret)
291 goto err;
292 drvdata->enable = true;
293
294 mutex_unlock(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700295
296 dev_info(drvdata->dev, "TPIU enabled\n");
297 return 0;
Pratik Patel9a9313d2013-03-20 12:03:27 -0700298err:
299 mutex_unlock(&drvdata->mutex);
300 clk_disable_unprepare(drvdata->clk);
301 return ret;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700302}
303
304static void __tpiu_disable(struct tpiu_drvdata *drvdata)
305{
306 TPIU_UNLOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700307
Pratik Patel9a9313d2013-03-20 12:03:27 -0700308 tpiu_flush_and_stop(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700309
Pratik Patel3b0ca882012-06-01 16:54:14 -0700310 TPIU_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700311}
312
Pratik Patel9a9313d2013-03-20 12:03:27 -0700313static void __tpiu_disable_seta(struct tpiu_drvdata *drvdata)
314{
315 int i;
316
317 for (i = 0; i < drvdata->seta_gpiocnt; i++)
318 gpio_free(drvdata->seta_gpios[i]);
319}
320
321static void __tpiu_disable_setb(struct tpiu_drvdata *drvdata)
322{
323 int i;
324
325 for (i = 0; i < drvdata->setb_gpiocnt; i++)
326 gpio_free(drvdata->setb_gpios[i]);
327}
328
329static void __tpiu_disable_to_mictor(struct tpiu_drvdata *drvdata)
330{
331 __tpiu_disable(drvdata);
332
333 if (drvdata->set == TPIU_SET_A)
334 __tpiu_disable_seta(drvdata);
335 else if (drvdata->set == TPIU_SET_B)
336 __tpiu_disable_setb(drvdata);
337}
338
339static void __tpiu_disable_to_sdc(struct tpiu_drvdata *drvdata)
340{
341 __tpiu_disable(drvdata);
342
343 msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 0);
344
345 regulator_disable(drvdata->reg);
Pratik Patela60feab2013-04-12 11:38:58 -0700346 tpiu_reg_set_optimum_mode(drvdata->reg, 0);
347 tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700348}
349
Pratik Patel3b0ca882012-06-01 16:54:14 -0700350static void tpiu_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700351{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700352 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
353
Pratik Patel9a9313d2013-03-20 12:03:27 -0700354 mutex_lock(&drvdata->mutex);
355
356 if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
357 __tpiu_disable_to_mictor(drvdata);
358 else
359 __tpiu_disable_to_sdc(drvdata);
360 drvdata->enable = false;
361
362 mutex_unlock(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700363
364 clk_disable_unprepare(drvdata->clk);
365
Pratik Patel16aefdb2012-05-30 10:41:23 -0700366 dev_info(drvdata->dev, "TPIU disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700367}
368
Pratik Patelcf7d0452012-07-02 13:57:20 -0700369static void tpiu_abort(struct coresight_device *csdev)
370{
371 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
372
373 __tpiu_disable(drvdata);
374
375 dev_info(drvdata->dev, "TPIU aborted\n");
376}
377
Pratik Patel3b0ca882012-06-01 16:54:14 -0700378static const struct coresight_ops_sink tpiu_sink_ops = {
379 .enable = tpiu_enable,
380 .disable = tpiu_disable,
Pratik Patelcf7d0452012-07-02 13:57:20 -0700381 .abort = tpiu_abort,
Pratik Patel3b0ca882012-06-01 16:54:14 -0700382};
383
Pratik Patel9a9313d2013-03-20 12:03:27 -0700384static ssize_t tpiu_show_out_mode(struct device *dev,
385 struct device_attribute *attr, char *buf)
386{
387 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
388
389 return scnprintf(buf, PAGE_SIZE, "%s\n",
390 drvdata->out_mode == TPIU_OUT_MODE_MICTOR ?
391 "mictor" : "sdc");
392}
393
394static ssize_t tpiu_store_out_mode(struct device *dev,
395 struct device_attribute *attr,
396 const char *buf, size_t size)
397{
398 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
399 char str[10] = "";
400 int ret;
401
402 if (strlen(buf) >= 10)
403 return -EINVAL;
404 if (sscanf(buf, "%s", str) != 1)
405 return -EINVAL;
406
407 mutex_lock(&drvdata->mutex);
408 if (!strcmp(str, "mictor")) {
409 if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
410 goto out;
411
412 if (!drvdata->enable) {
413 drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
414 goto out;
415 }
416 __tpiu_disable_to_sdc(drvdata);
417 ret = __tpiu_enable_to_mictor(drvdata);
418 if (ret) {
419 dev_err(drvdata->dev, "failed to enable mictor\n");
420 goto err;
421 }
422 drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
423 } else if (!strcmp(str, "sdc")) {
424 if (drvdata->out_mode == TPIU_OUT_MODE_SDC)
425 goto out;
426
427 if (!drvdata->enable) {
428 drvdata->out_mode = TPIU_OUT_MODE_SDC;
429 goto out;
430 }
431 __tpiu_disable_to_mictor(drvdata);
432 ret = __tpiu_enable_to_sdc(drvdata);
433 if (ret) {
434 dev_err(drvdata->dev, "failed to enable sdc\n");
435 goto err;
436 }
437 drvdata->out_mode = TPIU_OUT_MODE_SDC;
438 }
439out:
440 mutex_unlock(&drvdata->mutex);
441 return size;
442err:
443 mutex_unlock(&drvdata->mutex);
444 return ret;
445}
446static DEVICE_ATTR(out_mode, S_IRUGO | S_IWUSR, tpiu_show_out_mode,
447 tpiu_store_out_mode);
448
Pratik Patel3b0ca882012-06-01 16:54:14 -0700449static const struct coresight_ops tpiu_cs_ops = {
450 .sink_ops = &tpiu_sink_ops,
451};
452
Pratik Patel9a9313d2013-03-20 12:03:27 -0700453static ssize_t tpiu_show_set(struct device *dev,
454 struct device_attribute *attr, char *buf)
455{
456 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
457
458 return scnprintf(buf, PAGE_SIZE, "%s\n",
459 drvdata->set == TPIU_SET_A ?
460 "a" : "b");
461}
462
463static ssize_t tpiu_store_set(struct device *dev, struct device_attribute *attr,
464 const char *buf, size_t size)
465{
466 struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
467 char str[10] = "";
468 int ret;
469
470 if (strlen(buf) >= 10)
471 return -EINVAL;
472 if (sscanf(buf, "%s", str) != 1)
473 return -EINVAL;
474
475 mutex_lock(&drvdata->mutex);
476 if (!strcmp(str, "a")) {
477 if (drvdata->set == TPIU_SET_A)
478 goto out;
479
480 if (!drvdata->enable || drvdata->out_mode !=
481 TPIU_OUT_MODE_MICTOR) {
482 drvdata->set = TPIU_SET_A;
483 goto out;
484 }
485 __tpiu_disable_setb(drvdata);
486 ret = __tpiu_enable_seta(drvdata);
487 if (ret) {
488 dev_err(drvdata->dev, "failed to enable set A\n");
489 goto err;
490 }
491 drvdata->set = TPIU_SET_A;
492 } else if (!strcmp(str, "b")) {
493 if (drvdata->set == TPIU_SET_B)
494 goto out;
495
496 if (!drvdata->enable || drvdata->out_mode !=
497 TPIU_OUT_MODE_MICTOR) {
498 drvdata->set = TPIU_SET_B;
499 goto out;
500 }
501 __tpiu_disable_seta(drvdata);
502 ret = __tpiu_enable_setb(drvdata);
503 if (ret) {
504 dev_err(drvdata->dev, "failed to enable set B\n");
505 goto err;
506 }
507 drvdata->set = TPIU_SET_B;
508 }
509out:
510 mutex_unlock(&drvdata->mutex);
511 return size;
512err:
513 mutex_unlock(&drvdata->mutex);
514 return ret;
515}
516static DEVICE_ATTR(set, S_IRUGO | S_IWUSR, tpiu_show_set, tpiu_store_set);
517
518static struct attribute *tpiu_attrs[] = {
519 &dev_attr_out_mode.attr,
520 &dev_attr_set.attr,
521 NULL,
522};
523
524static struct attribute_group tpiu_attr_grp = {
525 .attrs = tpiu_attrs,
526};
527
528static const struct attribute_group *tpiu_attr_grps[] = {
529 &tpiu_attr_grp,
530 NULL,
531};
532
533static int __devinit tpiu_parse_of_data(struct platform_device *pdev,
534 struct tpiu_drvdata *drvdata)
535{
536 struct device_node *node = pdev->dev.of_node;
537 struct device_node *reg_node = NULL;
538 struct device *dev = &pdev->dev;
539 const __be32 *prop;
540 int i, len, gpio, ret;
541 uint32_t *seta_cfgs, *setb_cfgs;
542
543 reg_node = of_parse_phandle(node, "vdd-supply", 0);
544 if (reg_node) {
545 drvdata->reg = devm_regulator_get(dev, "vdd");
546 if (IS_ERR(drvdata->reg))
547 return PTR_ERR(drvdata->reg);
548
549 prop = of_get_property(node, "qcom,vdd-voltage-level", &len);
550 if (!prop || (len != (2 * sizeof(__be32)))) {
Pratik Patela60feab2013-04-12 11:38:58 -0700551 dev_err(dev, "sdc voltage levels not specified\n");
Pratik Patel9a9313d2013-03-20 12:03:27 -0700552 } else {
553 drvdata->reg_low = be32_to_cpup(&prop[0]);
554 drvdata->reg_high = be32_to_cpup(&prop[1]);
555 }
556
557 prop = of_get_property(node, "qcom,vdd-current-level", &len);
558 if (!prop || (len != (2 * sizeof(__be32)))) {
Pratik Patela60feab2013-04-12 11:38:58 -0700559 dev_err(dev, "sdc current levels not specified\n");
Pratik Patel9a9313d2013-03-20 12:03:27 -0700560 } else {
561 drvdata->reg_lpm = be32_to_cpup(&prop[0]);
562 drvdata->reg_hpm = be32_to_cpup(&prop[1]);
563 }
564 of_node_put(reg_node);
565 } else {
566 dev_err(dev, "sdc voltage supply not specified or available\n");
567 }
568
569 drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
570 drvdata->set = TPIU_SET_B;
571
572 drvdata->seta_gpiocnt = of_gpio_named_count(node, "qcom,seta-gpios");
573 if (drvdata->seta_gpiocnt) {
574 drvdata->seta_gpios = devm_kzalloc(dev,
575 sizeof(*drvdata->seta_gpios) *
576 drvdata->seta_gpiocnt, GFP_KERNEL);
577 if (!drvdata->seta_gpios)
578 return -ENOMEM;
579
580 for (i = 0; i < drvdata->seta_gpiocnt; i++) {
581 gpio = of_get_named_gpio(node, "qcom,seta-gpios", i);
582 if (!gpio_is_valid(gpio))
583 return gpio;
584
585 drvdata->seta_gpios[i] = gpio;
586 }
587
588 drvdata->seta_cfgs = devm_kzalloc(dev,
589 sizeof(*drvdata->seta_cfgs) *
590 drvdata->seta_gpiocnt, GFP_KERNEL);
591 if (!drvdata->seta_cfgs)
592 return -ENOMEM;
593
594 seta_cfgs = devm_kzalloc(dev, sizeof(*seta_cfgs) *
595 drvdata->seta_gpiocnt, GFP_KERNEL);
596 if (!seta_cfgs)
597 return -ENOMEM;
598
599 ret = of_property_read_u32_array(node, "qcom,seta-gpios-func",
600 (u32 *)seta_cfgs,
601 drvdata->seta_gpiocnt);
602 if (ret)
603 return ret;
604
605 for (i = 0; i < drvdata->seta_gpiocnt; i++)
606 drvdata->seta_cfgs[i].func = seta_cfgs[i];
607
608 ret = of_property_read_u32_array(node, "qcom,seta-gpios-drv",
609 (u32 *)seta_cfgs,
610 drvdata->seta_gpiocnt);
611 if (ret)
612 return ret;
613
614 for (i = 0; i < drvdata->seta_gpiocnt; i++)
615 drvdata->seta_cfgs[i].drv = seta_cfgs[i];
616
617 ret = of_property_read_u32_array(node, "qcom,seta-gpios-pull",
618 (u32 *)seta_cfgs,
619 drvdata->seta_gpiocnt);
620 if (ret)
621 return ret;
622
623 for (i = 0; i < drvdata->seta_gpiocnt; i++)
624 drvdata->seta_cfgs[i].pull = seta_cfgs[i];
625
626 ret = of_property_read_u32_array(node, "qcom,seta-gpios-dir",
627 (u32 *)seta_cfgs,
628 drvdata->seta_gpiocnt);
629 if (ret)
630 return ret;
631
632 for (i = 0; i < drvdata->seta_gpiocnt; i++)
633 drvdata->seta_cfgs[i].dir = seta_cfgs[i];
Pratik Patel4b2cb3b2013-05-13 12:29:41 -0700634
635 devm_kfree(dev, seta_cfgs);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700636 } else {
637 dev_err(dev, "seta gpios not specified\n");
638 }
639
640 drvdata->setb_gpiocnt = of_gpio_named_count(node, "qcom,setb-gpios");
641 if (drvdata->setb_gpiocnt) {
642 drvdata->setb_gpios = devm_kzalloc(dev,
643 sizeof(*drvdata->setb_gpios) *
644 drvdata->setb_gpiocnt, GFP_KERNEL);
645 if (!drvdata->setb_gpios)
646 return -ENOMEM;
647
648 for (i = 0; i < drvdata->setb_gpiocnt; i++) {
649 gpio = of_get_named_gpio(node, "qcom,setb-gpios", i);
650 if (!gpio_is_valid(gpio))
651 return gpio;
652
653 drvdata->setb_gpios[i] = gpio;
654 }
655
656 drvdata->setb_cfgs = devm_kzalloc(dev,
657 sizeof(*drvdata->setb_cfgs) *
658 drvdata->setb_gpiocnt, GFP_KERNEL);
659 if (!drvdata->setb_cfgs)
660 return -ENOMEM;
661
662 setb_cfgs = devm_kzalloc(dev, sizeof(*setb_cfgs) *
663 drvdata->setb_gpiocnt, GFP_KERNEL);
664 if (!setb_cfgs)
665 return -ENOMEM;
666
667 ret = of_property_read_u32_array(node, "qcom,setb-gpios-func",
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].func = setb_cfgs[i];
675
676 ret = of_property_read_u32_array(node, "qcom,setb-gpios-drv",
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].drv = setb_cfgs[i];
684
685 ret = of_property_read_u32_array(node, "qcom,setb-gpios-pull",
686 (u32 *)setb_cfgs,
687 drvdata->setb_gpiocnt);
688 if (ret)
689 return ret;
690
691 for (i = 0; i < drvdata->setb_gpiocnt; i++)
692 drvdata->setb_cfgs[i].pull = setb_cfgs[i];
693
694 ret = of_property_read_u32_array(node, "qcom,setb-gpios-dir",
695 (u32 *)setb_cfgs,
696 drvdata->setb_gpiocnt);
697 if (ret)
698 return ret;
699
700 for (i = 0; i < drvdata->setb_gpiocnt; i++)
701 drvdata->setb_cfgs[i].dir = setb_cfgs[i];
Pratik Patel4b2cb3b2013-05-13 12:29:41 -0700702
703 devm_kfree(dev, setb_cfgs);
Pratik Patel9a9313d2013-03-20 12:03:27 -0700704 } else {
705 dev_err(dev, "setb gpios not specified\n");
706 }
707
708 return 0;
709}
710
Pratik Patel7831c082011-06-08 21:44:37 -0700711static int __devinit tpiu_probe(struct platform_device *pdev)
712{
713 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -0700714 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -0700715 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700716 struct tpiu_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -0700717 struct resource *res;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700718 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -0700719
Pratik Patel5f6d1af2012-06-13 15:48:13 -0700720 if (pdev->dev.of_node) {
721 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
722 if (IS_ERR(pdata))
723 return PTR_ERR(pdata);
724 pdev->dev.platform_data = pdata;
725 }
726
Pratik Patel4a1b2522012-06-17 15:31:15 -0700727 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
728 if (!drvdata)
729 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700730 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700731 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700732
Aparna Dasc9907512013-03-08 10:20:52 -0800733 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpiu-base");
Pratik Patel4a1b2522012-06-17 15:31:15 -0700734 if (!res)
735 return -ENODEV;
Pratik Patel2c09b762012-07-21 15:54:54 -0700736
Pratik Patel4a1b2522012-06-17 15:31:15 -0700737 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
738 if (!drvdata->base)
739 return -ENOMEM;
Pratik Patelf17b1472012-05-25 22:23:52 -0700740
Pratik Patel9a9313d2013-03-20 12:03:27 -0700741 mutex_init(&drvdata->mutex);
742
Pratik Patel4a1b2522012-06-17 15:31:15 -0700743 drvdata->clk = devm_clk_get(dev, "core_clk");
744 if (IS_ERR(drvdata->clk))
745 return PTR_ERR(drvdata->clk);
Pratik Patel2c09b762012-07-21 15:54:54 -0700746
Pratik Patel6fb38342012-06-03 14:51:38 -0700747 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patelf17b1472012-05-25 22:23:52 -0700748 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -0700749 return ret;
Pratik Patelf17b1472012-05-25 22:23:52 -0700750
Pratik Patelc496b662012-06-17 18:42:44 -0700751 ret = clk_prepare_enable(drvdata->clk);
752 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -0700753 return ret;
Pratik Patel2c09b762012-07-21 15:54:54 -0700754
755 /* Disable tpiu to support older targets that need this */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700756 __tpiu_disable(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -0700757
Pratik Patelc496b662012-06-17 18:42:44 -0700758 clk_disable_unprepare(drvdata->clk);
759
Pratik Patel9a9313d2013-03-20 12:03:27 -0700760 if (pdev->dev.of_node) {
761 ret = tpiu_parse_of_data(pdev, drvdata);
762 if (ret)
763 return ret;
764 }
765
Pratik Patel4a1b2522012-06-17 15:31:15 -0700766 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
767 if (!desc)
768 return -ENOMEM;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700769 desc->type = CORESIGHT_DEV_TYPE_SINK;
770 desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;
771 desc->ops = &tpiu_cs_ops;
772 desc->pdata = pdev->dev.platform_data;
773 desc->dev = &pdev->dev;
Pratik Patel9a9313d2013-03-20 12:03:27 -0700774 desc->groups = tpiu_attr_grps;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700775 desc->owner = THIS_MODULE;
776 drvdata->csdev = coresight_register(desc);
Pratik Patel4a1b2522012-06-17 15:31:15 -0700777 if (IS_ERR(drvdata->csdev))
778 return PTR_ERR(drvdata->csdev);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700779
Pratik Patel4a1b2522012-06-17 15:31:15 -0700780 dev_info(dev, "TPIU initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700781 return 0;
Pratik Patel7831c082011-06-08 21:44:37 -0700782}
783
Pratik Patelf6fe9182012-03-20 14:04:18 -0700784static int __devexit tpiu_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700785{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700786 struct tpiu_drvdata *drvdata = platform_get_drvdata(pdev);
787
788 coresight_unregister(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -0700789 return 0;
790}
791
Pratik Patel9eae4822012-05-14 17:34:53 -0700792static struct of_device_id tpiu_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -0700793 {.compatible = "arm,coresight-tpiu"},
Pratik Patel9eae4822012-05-14 17:34:53 -0700794 {}
795};
796
Pratik Patel7831c082011-06-08 21:44:37 -0700797static struct platform_driver tpiu_driver = {
798 .probe = tpiu_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -0700799 .remove = __devexit_p(tpiu_remove),
Pratik Patel7831c082011-06-08 21:44:37 -0700800 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700801 .name = "coresight-tpiu",
Pratik Patel9eae4822012-05-14 17:34:53 -0700802 .owner = THIS_MODULE,
803 .of_match_table = tpiu_match,
Pratik Patel7831c082011-06-08 21:44:37 -0700804 },
805};
806
Pratik Patelf6fe9182012-03-20 14:04:18 -0700807static int __init tpiu_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700808{
809 return platform_driver_register(&tpiu_driver);
810}
Pratik Patelf6fe9182012-03-20 14:04:18 -0700811module_init(tpiu_init);
Pratik Patel7831c082011-06-08 21:44:37 -0700812
Pratik Patelf6fe9182012-03-20 14:04:18 -0700813static void __exit tpiu_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700814{
815 platform_driver_unregister(&tpiu_driver);
816}
Pratik Patelf6fe9182012-03-20 14:04:18 -0700817module_exit(tpiu_exit);
818
819MODULE_LICENSE("GPL v2");
820MODULE_DESCRIPTION("CoreSight Trace Port Interface Unit driver");