Commit | Line | Data |
---|---|---|
ad0dfdfd | 1 | // SPDX-License-Identifier: GPL-2.0 |
bc4bf7fe | 2 | /* Copyright (c) 2012, The Linux Foundation. All rights reserved. |
941943cf PG |
3 | * |
4 | * Description: CoreSight Trace Memory Controller driver | |
bc4bf7fe PP |
5 | */ |
6 | ||
7 | #include <linux/kernel.h> | |
bc4bf7fe PP |
8 | #include <linux/init.h> |
9 | #include <linux/types.h> | |
10 | #include <linux/device.h> | |
c5ff7344 | 11 | #include <linux/idr.h> |
bc4bf7fe PP |
12 | #include <linux/io.h> |
13 | #include <linux/err.h> | |
14 | #include <linux/fs.h> | |
15 | #include <linux/miscdevice.h> | |
c5ff7344 | 16 | #include <linux/mutex.h> |
ed2cfb2b | 17 | #include <linux/property.h> |
bc4bf7fe PP |
18 | #include <linux/uaccess.h> |
19 | #include <linux/slab.h> | |
20 | #include <linux/dma-mapping.h> | |
21 | #include <linux/spinlock.h> | |
32398ef6 | 22 | #include <linux/pm_runtime.h> |
bc4bf7fe PP |
23 | #include <linux/of.h> |
24 | #include <linux/coresight.h> | |
25 | #include <linux/amba/bus.h> | |
26 | ||
27 | #include "coresight-priv.h" | |
4c324b5f | 28 | #include "coresight-tmc.h" |
bc4bf7fe | 29 | |
6c6ed1e2 | 30 | void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata) |
bc4bf7fe PP |
31 | { |
32 | /* Ensure formatter, unformatter and hardware fifo are empty */ | |
33 | if (coresight_timeout(drvdata->base, | |
580ff804 | 34 | TMC_STS, TMC_STS_TMCREADY_BIT, 1)) { |
9dd0a920 | 35 | dev_err(&drvdata->csdev->dev, |
67337e8d | 36 | "timeout while waiting for TMC to be Ready\n"); |
bc4bf7fe PP |
37 | } |
38 | } | |
39 | ||
6c6ed1e2 | 40 | void tmc_flush_and_stop(struct tmc_drvdata *drvdata) |
bc4bf7fe PP |
41 | { |
42 | u32 ffcr; | |
43 | ||
44 | ffcr = readl_relaxed(drvdata->base + TMC_FFCR); | |
45 | ffcr |= TMC_FFCR_STOP_ON_FLUSH; | |
46 | writel_relaxed(ffcr, drvdata->base + TMC_FFCR); | |
a8ab4268 | 47 | ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT); |
bc4bf7fe PP |
48 | writel_relaxed(ffcr, drvdata->base + TMC_FFCR); |
49 | /* Ensure flush completes */ | |
50 | if (coresight_timeout(drvdata->base, | |
51 | TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) { | |
9dd0a920 | 52 | dev_err(&drvdata->csdev->dev, |
67337e8d | 53 | "timeout while waiting for completion of Manual Flush\n"); |
bc4bf7fe PP |
54 | } |
55 | ||
580ff804 | 56 | tmc_wait_for_tmcready(drvdata); |
bc4bf7fe PP |
57 | } |
58 | ||
6c6ed1e2 | 59 | void tmc_enable_hw(struct tmc_drvdata *drvdata) |
bc4bf7fe PP |
60 | { |
61 | writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL); | |
62 | } | |
63 | ||
6c6ed1e2 | 64 | void tmc_disable_hw(struct tmc_drvdata *drvdata) |
bc4bf7fe PP |
65 | { |
66 | writel_relaxed(0x0, drvdata->base + TMC_CTL); | |
67 | } | |
68 | ||
bc4bf7fe PP |
69 | static int tmc_read_prepare(struct tmc_drvdata *drvdata) |
70 | { | |
b1789b79 | 71 | int ret = 0; |
bc4bf7fe | 72 | |
b1789b79 MP |
73 | switch (drvdata->config_type) { |
74 | case TMC_CONFIG_TYPE_ETB: | |
b1789b79 | 75 | case TMC_CONFIG_TYPE_ETF: |
4525412a | 76 | ret = tmc_read_prepare_etb(drvdata); |
b1789b79 MP |
77 | break; |
78 | case TMC_CONFIG_TYPE_ETR: | |
4525412a | 79 | ret = tmc_read_prepare_etr(drvdata); |
b1789b79 MP |
80 | break; |
81 | default: | |
82 | ret = -EINVAL; | |
bc4bf7fe | 83 | } |
b1789b79 | 84 | |
4525412a | 85 | if (!ret) |
9dd0a920 | 86 | dev_dbg(&drvdata->csdev->dev, "TMC read start\n"); |
4525412a | 87 | |
bc4bf7fe PP |
88 | return ret; |
89 | } | |
90 | ||
f74debbe | 91 | static int tmc_read_unprepare(struct tmc_drvdata *drvdata) |
bc4bf7fe | 92 | { |
4525412a | 93 | int ret = 0; |
bc4bf7fe | 94 | |
b1789b79 MP |
95 | switch (drvdata->config_type) { |
96 | case TMC_CONFIG_TYPE_ETB: | |
b1789b79 | 97 | case TMC_CONFIG_TYPE_ETF: |
4525412a | 98 | ret = tmc_read_unprepare_etb(drvdata); |
b1789b79 MP |
99 | break; |
100 | case TMC_CONFIG_TYPE_ETR: | |
4525412a | 101 | ret = tmc_read_unprepare_etr(drvdata); |
b1789b79 MP |
102 | break; |
103 | default: | |
4525412a | 104 | ret = -EINVAL; |
bc4bf7fe | 105 | } |
b1789b79 | 106 | |
4525412a | 107 | if (!ret) |
9dd0a920 | 108 | dev_dbg(&drvdata->csdev->dev, "TMC read end\n"); |
f74debbe MP |
109 | |
110 | return ret; | |
bc4bf7fe PP |
111 | } |
112 | ||
113 | static int tmc_open(struct inode *inode, struct file *file) | |
114 | { | |
f74debbe | 115 | int ret; |
bc4bf7fe PP |
116 | struct tmc_drvdata *drvdata = container_of(file->private_data, |
117 | struct tmc_drvdata, miscdev); | |
bc4bf7fe PP |
118 | |
119 | ret = tmc_read_prepare(drvdata); | |
120 | if (ret) | |
121 | return ret; | |
f74debbe | 122 | |
bc4bf7fe PP |
123 | nonseekable_open(inode, file); |
124 | ||
9dd0a920 | 125 | dev_dbg(&drvdata->csdev->dev, "%s: successfully opened\n", __func__); |
bc4bf7fe PP |
126 | return 0; |
127 | } | |
128 | ||
3495722a SP |
129 | static inline ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, |
130 | loff_t pos, size_t len, char **bufpp) | |
131 | { | |
132 | switch (drvdata->config_type) { | |
133 | case TMC_CONFIG_TYPE_ETB: | |
134 | case TMC_CONFIG_TYPE_ETF: | |
135 | return tmc_etb_get_sysfs_trace(drvdata, pos, len, bufpp); | |
136 | case TMC_CONFIG_TYPE_ETR: | |
137 | return tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp); | |
138 | } | |
139 | ||
140 | return -EINVAL; | |
141 | } | |
142 | ||
bc4bf7fe PP |
143 | static ssize_t tmc_read(struct file *file, char __user *data, size_t len, |
144 | loff_t *ppos) | |
145 | { | |
3495722a SP |
146 | char *bufp; |
147 | ssize_t actual; | |
bc4bf7fe PP |
148 | struct tmc_drvdata *drvdata = container_of(file->private_data, |
149 | struct tmc_drvdata, miscdev); | |
3495722a SP |
150 | actual = tmc_get_sysfs_trace(drvdata, *ppos, len, &bufp); |
151 | if (actual <= 0) | |
152 | return 0; | |
bc4bf7fe | 153 | |
3495722a | 154 | if (copy_to_user(data, bufp, actual)) { |
9dd0a920 SP |
155 | dev_dbg(&drvdata->csdev->dev, |
156 | "%s: copy_to_user failed\n", __func__); | |
bc4bf7fe PP |
157 | return -EFAULT; |
158 | } | |
159 | ||
3495722a | 160 | *ppos += actual; |
9dd0a920 | 161 | dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual); |
bc4bf7fe | 162 | |
3495722a | 163 | return actual; |
bc4bf7fe PP |
164 | } |
165 | ||
166 | static int tmc_release(struct inode *inode, struct file *file) | |
167 | { | |
f74debbe | 168 | int ret; |
bc4bf7fe PP |
169 | struct tmc_drvdata *drvdata = container_of(file->private_data, |
170 | struct tmc_drvdata, miscdev); | |
171 | ||
f74debbe MP |
172 | ret = tmc_read_unprepare(drvdata); |
173 | if (ret) | |
174 | return ret; | |
bc4bf7fe | 175 | |
9dd0a920 | 176 | dev_dbg(&drvdata->csdev->dev, "%s: released\n", __func__); |
bc4bf7fe PP |
177 | return 0; |
178 | } | |
179 | ||
180 | static const struct file_operations tmc_fops = { | |
181 | .owner = THIS_MODULE, | |
182 | .open = tmc_open, | |
183 | .read = tmc_read, | |
184 | .release = tmc_release, | |
185 | .llseek = no_llseek, | |
186 | }; | |
187 | ||
4f1ff3de MP |
188 | static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid) |
189 | { | |
190 | enum tmc_mem_intf_width memwidth; | |
191 | ||
192 | /* | |
193 | * Excerpt from the TRM: | |
194 | * | |
195 | * DEVID::MEMWIDTH[10:8] | |
196 | * 0x2 Memory interface databus is 32 bits wide. | |
197 | * 0x3 Memory interface databus is 64 bits wide. | |
198 | * 0x4 Memory interface databus is 128 bits wide. | |
199 | * 0x5 Memory interface databus is 256 bits wide. | |
200 | */ | |
201 | switch (BMVAL(devid, 8, 10)) { | |
202 | case 0x2: | |
203 | memwidth = TMC_MEM_INTF_WIDTH_32BITS; | |
204 | break; | |
205 | case 0x3: | |
206 | memwidth = TMC_MEM_INTF_WIDTH_64BITS; | |
207 | break; | |
208 | case 0x4: | |
209 | memwidth = TMC_MEM_INTF_WIDTH_128BITS; | |
210 | break; | |
211 | case 0x5: | |
212 | memwidth = TMC_MEM_INTF_WIDTH_256BITS; | |
213 | break; | |
214 | default: | |
215 | memwidth = 0; | |
216 | } | |
217 | ||
218 | return memwidth; | |
219 | } | |
220 | ||
47675f6a SP |
221 | #define coresight_tmc_reg(name, offset) \ |
222 | coresight_simple_reg32(struct tmc_drvdata, name, offset) | |
223 | #define coresight_tmc_reg64(name, lo_off, hi_off) \ | |
224 | coresight_simple_reg64(struct tmc_drvdata, name, lo_off, hi_off) | |
225 | ||
226 | coresight_tmc_reg(rsz, TMC_RSZ); | |
227 | coresight_tmc_reg(sts, TMC_STS); | |
228 | coresight_tmc_reg(trg, TMC_TRG); | |
229 | coresight_tmc_reg(ctl, TMC_CTL); | |
230 | coresight_tmc_reg(ffsr, TMC_FFSR); | |
231 | coresight_tmc_reg(ffcr, TMC_FFCR); | |
232 | coresight_tmc_reg(mode, TMC_MODE); | |
233 | coresight_tmc_reg(pscr, TMC_PSCR); | |
2b455339 | 234 | coresight_tmc_reg(axictl, TMC_AXICTL); |
47675f6a SP |
235 | coresight_tmc_reg(devid, CORESIGHT_DEVID); |
236 | coresight_tmc_reg64(rrp, TMC_RRP, TMC_RRPHI); | |
237 | coresight_tmc_reg64(rwp, TMC_RWP, TMC_RWPHI); | |
2b455339 | 238 | coresight_tmc_reg64(dba, TMC_DBALO, TMC_DBAHI); |
7d83d177 MP |
239 | |
240 | static struct attribute *coresight_tmc_mgmt_attrs[] = { | |
241 | &dev_attr_rsz.attr, | |
242 | &dev_attr_sts.attr, | |
243 | &dev_attr_rrp.attr, | |
244 | &dev_attr_rwp.attr, | |
245 | &dev_attr_trg.attr, | |
246 | &dev_attr_ctl.attr, | |
247 | &dev_attr_ffsr.attr, | |
248 | &dev_attr_ffcr.attr, | |
249 | &dev_attr_mode.attr, | |
250 | &dev_attr_pscr.attr, | |
251 | &dev_attr_devid.attr, | |
2b455339 SP |
252 | &dev_attr_dba.attr, |
253 | &dev_attr_axictl.attr, | |
7d83d177 MP |
254 | NULL, |
255 | }; | |
a2d6e184 | 256 | |
0ef7528d BX |
257 | static ssize_t trigger_cntr_show(struct device *dev, |
258 | struct device_attribute *attr, char *buf) | |
bc4bf7fe PP |
259 | { |
260 | struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); | |
261 | unsigned long val = drvdata->trigger_cntr; | |
262 | ||
263 | return sprintf(buf, "%#lx\n", val); | |
264 | } | |
265 | ||
266 | static ssize_t trigger_cntr_store(struct device *dev, | |
267 | struct device_attribute *attr, | |
268 | const char *buf, size_t size) | |
269 | { | |
270 | int ret; | |
271 | unsigned long val; | |
272 | struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); | |
273 | ||
274 | ret = kstrtoul(buf, 16, &val); | |
275 | if (ret) | |
276 | return ret; | |
277 | ||
278 | drvdata->trigger_cntr = val; | |
279 | return size; | |
280 | } | |
281 | static DEVICE_ATTR_RW(trigger_cntr); | |
282 | ||
c34cc23f SP |
283 | static ssize_t buffer_size_show(struct device *dev, |
284 | struct device_attribute *attr, char *buf) | |
285 | { | |
286 | struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); | |
287 | ||
288 | return sprintf(buf, "%#x\n", drvdata->size); | |
289 | } | |
290 | ||
291 | static ssize_t buffer_size_store(struct device *dev, | |
292 | struct device_attribute *attr, | |
293 | const char *buf, size_t size) | |
294 | { | |
295 | int ret; | |
296 | unsigned long val; | |
297 | struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); | |
298 | ||
299 | /* Only permitted for TMC-ETRs */ | |
300 | if (drvdata->config_type != TMC_CONFIG_TYPE_ETR) | |
301 | return -EPERM; | |
302 | ||
303 | ret = kstrtoul(buf, 0, &val); | |
304 | if (ret) | |
305 | return ret; | |
306 | /* The buffer size should be page aligned */ | |
307 | if (val & (PAGE_SIZE - 1)) | |
308 | return -EINVAL; | |
309 | drvdata->size = val; | |
310 | return size; | |
311 | } | |
312 | ||
313 | static DEVICE_ATTR_RW(buffer_size); | |
314 | ||
7d83d177 | 315 | static struct attribute *coresight_tmc_attrs[] = { |
bc4bf7fe | 316 | &dev_attr_trigger_cntr.attr, |
c34cc23f | 317 | &dev_attr_buffer_size.attr, |
bc4bf7fe PP |
318 | NULL, |
319 | }; | |
bc4bf7fe | 320 | |
7d83d177 MP |
321 | static const struct attribute_group coresight_tmc_group = { |
322 | .attrs = coresight_tmc_attrs, | |
bc4bf7fe | 323 | }; |
bc4bf7fe | 324 | |
7d83d177 MP |
325 | static const struct attribute_group coresight_tmc_mgmt_group = { |
326 | .attrs = coresight_tmc_mgmt_attrs, | |
327 | .name = "mgmt", | |
328 | }; | |
329 | ||
330 | const struct attribute_group *coresight_tmc_groups[] = { | |
331 | &coresight_tmc_group, | |
332 | &coresight_tmc_mgmt_group, | |
bc4bf7fe PP |
333 | NULL, |
334 | }; | |
bc4bf7fe | 335 | |
9dd0a920 | 336 | static inline bool tmc_etr_can_use_sg(struct device *dev) |
ed2cfb2b | 337 | { |
9dd0a920 | 338 | return fwnode_property_present(dev->fwnode, "arm,scatter-gather"); |
ed2cfb2b SP |
339 | } |
340 | ||
2884132a | 341 | /* Detect and initialise the capabilities of a TMC ETR */ |
9dd0a920 | 342 | static int tmc_etr_setup_caps(struct device *parent, u32 devid, void *dev_caps) |
2884132a | 343 | { |
08be8747 | 344 | int rc; |
ff11f5bc | 345 | u32 dma_mask = 0; |
9dd0a920 | 346 | struct tmc_drvdata *drvdata = dev_get_drvdata(parent); |
ff11f5bc | 347 | |
2884132a SP |
348 | /* Set the unadvertised capabilities */ |
349 | tmc_etr_init_caps(drvdata, (u32)(unsigned long)dev_caps); | |
350 | ||
9dd0a920 | 351 | if (!(devid & TMC_DEVID_NOSCAT) && tmc_etr_can_use_sg(parent)) |
2e219345 | 352 | tmc_etr_set_cap(drvdata, TMC_ETR_SG); |
ff11f5bc SP |
353 | |
354 | /* Check if the AXI address width is available */ | |
355 | if (devid & TMC_DEVID_AXIAW_VALID) | |
356 | dma_mask = ((devid >> TMC_DEVID_AXIAW_SHIFT) & | |
357 | TMC_DEVID_AXIAW_MASK); | |
358 | ||
2884132a | 359 | /* |
ff11f5bc SP |
360 | * Unless specified in the device configuration, ETR uses a 40-bit |
361 | * AXI master in place of the embedded SRAM of ETB/ETF. | |
2884132a | 362 | */ |
ff11f5bc SP |
363 | switch (dma_mask) { |
364 | case 32: | |
365 | case 40: | |
366 | case 44: | |
367 | case 48: | |
368 | case 52: | |
9dd0a920 | 369 | dev_info(parent, "Detected dma mask %dbits\n", dma_mask); |
ff11f5bc SP |
370 | break; |
371 | default: | |
372 | dma_mask = 40; | |
373 | } | |
374 | ||
9dd0a920 | 375 | rc = dma_set_mask_and_coherent(parent, DMA_BIT_MASK(dma_mask)); |
08be8747 | 376 | if (rc) |
9dd0a920 | 377 | dev_err(parent, "Failed to setup DMA mask: %d\n", rc); |
08be8747 | 378 | return rc; |
2884132a SP |
379 | } |
380 | ||
538eca25 SP |
381 | static u32 tmc_etr_get_default_buffer_size(struct device *dev) |
382 | { | |
383 | u32 size; | |
384 | ||
385 | if (fwnode_property_read_u32(dev->fwnode, "arm,buffer-size", &size)) | |
386 | size = SZ_1M; | |
387 | return size; | |
388 | } | |
389 | ||
bc4bf7fe PP |
390 | static int tmc_probe(struct amba_device *adev, const struct amba_id *id) |
391 | { | |
392 | int ret = 0; | |
393 | u32 devid; | |
394 | void __iomem *base; | |
395 | struct device *dev = &adev->dev; | |
396 | struct coresight_platform_data *pdata = NULL; | |
397 | struct tmc_drvdata *drvdata; | |
398 | struct resource *res = &adev->res; | |
9486295a | 399 | struct coresight_desc desc = { 0 }; |
bc4bf7fe PP |
400 | struct device_node *np = adev->dev.of_node; |
401 | ||
402 | if (np) { | |
403 | pdata = of_get_coresight_platform_data(dev, np); | |
3afd0634 SP |
404 | if (IS_ERR(pdata)) { |
405 | ret = PTR_ERR(pdata); | |
406 | goto out; | |
407 | } | |
bc4bf7fe PP |
408 | adev->dev.platform_data = pdata; |
409 | } | |
410 | ||
3afd0634 | 411 | ret = -ENOMEM; |
bc4bf7fe PP |
412 | drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); |
413 | if (!drvdata) | |
3afd0634 SP |
414 | goto out; |
415 | ||
bc4bf7fe PP |
416 | dev_set_drvdata(dev, drvdata); |
417 | ||
418 | /* Validity for the resource is already checked by the AMBA core */ | |
419 | base = devm_ioremap_resource(dev, res); | |
3afd0634 SP |
420 | if (IS_ERR(base)) { |
421 | ret = PTR_ERR(base); | |
422 | goto out; | |
423 | } | |
bc4bf7fe PP |
424 | |
425 | drvdata->base = base; | |
426 | ||
427 | spin_lock_init(&drvdata->spinlock); | |
428 | ||
bc4bf7fe PP |
429 | devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); |
430 | drvdata->config_type = BMVAL(devid, 6, 7); | |
4f1ff3de | 431 | drvdata->memwidth = tmc_get_memwidth(devid); |
8d03cfd1 MP |
432 | /* This device is not associated with a session */ |
433 | drvdata->pid = -1; | |
bc4bf7fe | 434 | |
538eca25 SP |
435 | if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) |
436 | drvdata->size = tmc_etr_get_default_buffer_size(dev); | |
437 | else | |
bc4bf7fe | 438 | drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4; |
bc4bf7fe | 439 | |
9486295a SP |
440 | desc.pdata = pdata; |
441 | desc.dev = dev; | |
442 | desc.groups = coresight_tmc_groups; | |
bc4bf7fe | 443 | |
99ac6f12 SP |
444 | switch (drvdata->config_type) { |
445 | case TMC_CONFIG_TYPE_ETB: | |
9486295a SP |
446 | desc.type = CORESIGHT_DEV_TYPE_SINK; |
447 | desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; | |
448 | desc.ops = &tmc_etb_cs_ops; | |
99ac6f12 SP |
449 | break; |
450 | case TMC_CONFIG_TYPE_ETR: | |
9486295a SP |
451 | desc.type = CORESIGHT_DEV_TYPE_SINK; |
452 | desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; | |
453 | desc.ops = &tmc_etr_cs_ops; | |
9dd0a920 | 454 | ret = tmc_etr_setup_caps(dev, devid, |
e85fa28e | 455 | coresight_get_uci_data(id)); |
a3959c50 RM |
456 | if (ret) |
457 | goto out; | |
c5ff7344 MP |
458 | idr_init(&drvdata->idr); |
459 | mutex_init(&drvdata->idr_mutex); | |
99ac6f12 SP |
460 | break; |
461 | case TMC_CONFIG_TYPE_ETF: | |
9486295a SP |
462 | desc.type = CORESIGHT_DEV_TYPE_LINKSINK; |
463 | desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO; | |
464 | desc.ops = &tmc_etf_cs_ops; | |
99ac6f12 SP |
465 | break; |
466 | default: | |
467 | pr_err("%s: Unsupported TMC config\n", pdata->name); | |
468 | ret = -EINVAL; | |
469 | goto out; | |
bc4bf7fe PP |
470 | } |
471 | ||
9486295a | 472 | drvdata->csdev = coresight_register(&desc); |
bc4bf7fe PP |
473 | if (IS_ERR(drvdata->csdev)) { |
474 | ret = PTR_ERR(drvdata->csdev); | |
3afd0634 | 475 | goto out; |
bc4bf7fe PP |
476 | } |
477 | ||
478 | drvdata->miscdev.name = pdata->name; | |
479 | drvdata->miscdev.minor = MISC_DYNAMIC_MINOR; | |
480 | drvdata->miscdev.fops = &tmc_fops; | |
481 | ret = misc_register(&drvdata->miscdev); | |
482 | if (ret) | |
3afd0634 | 483 | coresight_unregister(drvdata->csdev); |
26355695 SP |
484 | else |
485 | pm_runtime_put(&adev->dev); | |
3afd0634 | 486 | out: |
bc4bf7fe PP |
487 | return ret; |
488 | } | |
489 | ||
6f964e7c | 490 | static const struct amba_id tmc_ids[] = { |
e85fa28e ML |
491 | CS_AMBA_ID(0x000bb961), |
492 | /* Coresight SoC 600 TMC-ETR/ETS */ | |
493 | CS_AMBA_ID_DATA(0x000bb9e8, (unsigned long)CORESIGHT_SOC_600_ETR_CAPS), | |
494 | /* Coresight SoC 600 TMC-ETB */ | |
495 | CS_AMBA_ID(0x000bb9e9), | |
496 | /* Coresight SoC 600 TMC-ETF */ | |
497 | CS_AMBA_ID(0x000bb9ea), | |
bc4bf7fe PP |
498 | { 0, 0}, |
499 | }; | |
500 | ||
501 | static struct amba_driver tmc_driver = { | |
502 | .drv = { | |
503 | .name = "coresight-tmc", | |
504 | .owner = THIS_MODULE, | |
b15f0fb6 | 505 | .suppress_bind_attrs = true, |
bc4bf7fe PP |
506 | }, |
507 | .probe = tmc_probe, | |
bc4bf7fe PP |
508 | .id_table = tmc_ids, |
509 | }; | |
941943cf | 510 | builtin_amba_driver(tmc_driver); |