2 * raspberrypi_axi_monitor.c
4 * Author: james.hughes@raspberrypi.org
6 * Raspberry Pi AXI performance counters.
8 * Copyright (C) 2017 Raspberry Pi Trading Ltd.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 #include <linux/debugfs.h>
16 #include <linux/devcoredump.h>
17 #include <linux/device.h>
18 #include <linux/kthread.h>
19 #include <linux/module.h>
20 #include <linux/netdevice.h>
21 #include <linux/mutex.h>
23 #include <linux/platform_device.h>
25 #include <soc/bcm2835/raspberrypi-firmware.h>
27 #define NUM_MONITORS 2
28 #define NUM_BUS_WATCHERS_PER_MONITOR 3
30 #define SYSTEM_MONITOR 0
34 #define DEFAULT_SAMPLE_TIME 100
36 #define NUM_BUS_WATCHER_RESULTS 9
38 struct bus_watcher_data {
40 u32 results[NUM_BUS_WATCHER_RESULTS];
57 struct platform_device *dev;
58 struct dentry *root_folder;
60 struct task_struct *monitor_thread;
63 struct rpi_firmware *firmware;
65 /* Sample time spent on for each bus */
68 /* Now storage for the per monitor settings and the resulting
72 /* Bit field of buses we want to monitor */
74 /* Bit field of buses to filter by */
76 /* The current buses being monitored on this monitor */
77 int current_bus[NUM_BUS_WATCHERS_PER_MONITOR];
78 /* The last bus monitored on this monitor */
81 /* Set true if this mailbox must use the mailbox interface
82 * rather than access registers directly.
84 int use_mailbox_interface;
86 /* Current result values */
87 struct bus_watcher_data results[MAX_BUSES];
89 struct dentry *debugfs_entry;
90 void __iomem *base_address;
92 } monitor[NUM_MONITORS];
96 static struct rpi_axiperf *state;
98 /* Two monitors, System and VPU, each with the following register sets.
99 * Each monitor can only monitor one bus at a time, so we time share them,
100 * giving each bus 100ms (default, settable via debugfs) of time on its
102 * Record results from the three Bus watchers per monitor and push to the sysfs
105 /* general registers */
108 const int GEN_CTL_ENABLE_BIT = BIT(0);
109 const int GEN_CTL_RESET_BIT = BIT(1);
111 /* Bus watcher registers */
112 const int BW_PITCH = 0x40;
114 const int BW0_CTRL = 0x40;
115 const int BW1_CTRL = 0x80;
116 const int BW2_CTRL = 0xc0;
118 const int BW_ATRANS_OFFSET = 0x04;
119 const int BW_ATWAIT_OFFSET = 0x08;
120 const int BW_AMAX_OFFSET = 0x0c;
121 const int BW_WTRANS_OFFSET = 0x10;
122 const int BW_WTWAIT_OFFSET = 0x14;
123 const int BW_WMAX_OFFSET = 0x18;
124 const int BW_RTRANS_OFFSET = 0x1c;
125 const int BW_RTWAIT_OFFSET = 0x20;
126 const int BW_RMAX_OFFSET = 0x24;
128 const int BW_CTRL_RESET_BIT = BIT(31);
129 const int BW_CTRL_ENABLE_BIT = BIT(30);
130 const int BW_CTRL_ENABLE_ID_FILTER_BIT = BIT(29);
131 const int BW_CTRL_LIMIT_HALT_BIT = BIT(28);
133 const int BW_CTRL_SOURCE_SHIFT = 8;
134 const int BW_CTRL_SOURCE_MASK = GENMASK(12, 8); // 5 bits
135 const int BW_CTRL_BUS_WATCH_SHIFT;
136 const int BW_CTRL_BUS_WATCH_MASK = GENMASK(5, 0); // 6 bits
137 const int BW_CTRL_BUS_FILTER_SHIFT = 8;
139 const static char *bus_filter_strings[] = {
174 const int num_bus_filters = ARRAY_SIZE(bus_filter_strings);
176 const static char *system_bus_string[] = {
195 const int num_system_buses = ARRAY_SIZE(system_bus_string);
197 const static char *vpu_bus_string[] = {
216 const int num_vpu_buses = ARRAY_SIZE(vpu_bus_string);
218 const static char *monitor_name[] = {
223 static inline void write_reg(int monitor, int reg, u32 value)
225 writel(value, state->monitor[monitor].base_address + reg);
228 static inline u32 read_reg(int monitor, u32 reg)
230 return readl(state->monitor[monitor].base_address + reg);
233 static void read_bus_watcher(int monitor, int watcher, u32 *results)
235 if (state->monitor[monitor].use_mailbox_interface) {
236 /* We have 9 results, plus the overheads of start address and
237 * length So 11 u32 to define
242 tmp[0] = (u32)(uintptr_t)(state->monitor[monitor].base_address + watcher
244 tmp[1] = NUM_BUS_WATCHER_RESULTS;
246 err = rpi_firmware_property(state->firmware,
247 RPI_FIRMWARE_GET_PERIPH_REG,
250 if (err < 0 || tmp[1] != NUM_BUS_WATCHER_RESULTS)
251 dev_err_once(&state->dev->dev,
252 "Failed to read bus watcher");
254 memcpy(results, &tmp[2],
255 NUM_BUS_WATCHER_RESULTS * sizeof(u32));
258 void __iomem *addr = state->monitor[monitor].base_address
259 + watcher + BW_ATRANS_OFFSET;
260 for (i = 0; i < NUM_BUS_WATCHER_RESULTS; i++, addr += 4)
261 *results++ = readl(addr);
265 static void set_monitor_control(int monitor, u32 set)
267 if (state->monitor[monitor].use_mailbox_interface) {
268 u32 tmp[3] = {(u32)(uintptr_t)(state->monitor[monitor].base_address +
270 int err = rpi_firmware_property(state->firmware,
271 RPI_FIRMWARE_SET_PERIPH_REG,
274 if (err < 0 || tmp[1] != 1)
275 dev_err_once(&state->dev->dev,
276 "Failed to set monitor control");
278 write_reg(monitor, GEN_CTRL, set);
281 static void set_bus_watcher_control(int monitor, int watcher, u32 set)
283 if (state->monitor[monitor].use_mailbox_interface) {
284 u32 tmp[3] = {(u32)(uintptr_t)(state->monitor[monitor].base_address +
286 int err = rpi_firmware_property(state->firmware,
287 RPI_FIRMWARE_SET_PERIPH_REG,
289 if (err < 0 || tmp[1] != 1)
290 dev_err_once(&state->dev->dev,
291 "Failed to set bus watcher control");
293 write_reg(monitor, watcher, set);
296 static void monitor(struct rpi_axiperf *state)
298 int monitor, num_buses[NUM_MONITORS];
300 mutex_lock(&state->lock);
302 for (monitor = 0; monitor < NUM_MONITORS; monitor++) {
303 typeof(state->monitor[0]) *mon = &(state->monitor[monitor]);
305 /* Anything enabled? */
306 if (mon->bus_enabled == 0) {
307 /* No, disable all monitoring for this monitor */
308 set_monitor_control(monitor, GEN_CTL_RESET_BIT);
312 /* Find out how many busses we want to monitor, and
313 * spread our 3 actual monitors over them
315 num_buses[monitor] = hweight32(mon->bus_enabled);
316 num_buses[monitor] = min(num_buses[monitor],
317 NUM_BUS_WATCHERS_PER_MONITOR);
319 for (i = 0; i < num_buses[monitor]; i++) {
323 mon->last_monitored++;
324 mon->last_monitored &= 0xf;
325 } while ((mon->bus_enabled &
326 (1 << mon->last_monitored)) == 0);
328 mon->current_bus[i] = mon->last_monitored;
330 /* Reset the counters */
331 set_bus_watcher_control(monitor,
336 bus_control = BW_CTRL_ENABLE_BIT |
339 if (mon->bus_filter) {
341 BW_CTRL_ENABLE_ID_FILTER_BIT;
343 ((mon->bus_filter & 0x1f)
344 << BW_CTRL_BUS_FILTER_SHIFT);
348 set_bus_watcher_control(monitor,
349 BW0_CTRL + i*BW_PITCH,
354 /* start monitoring */
355 set_monitor_control(monitor, GEN_CTL_ENABLE_BIT);
358 mutex_unlock(&state->lock);
360 msleep(state->sample_time);
362 /* Now read the results */
364 mutex_lock(&state->lock);
365 for (monitor = 0; monitor < NUM_MONITORS; monitor++) {
366 typeof(state->monitor[0]) *mon = &(state->monitor[monitor]);
368 /* Anything enabled? */
369 if (mon->bus_enabled == 0) {
370 /* No, disable all monitoring for this monitor */
371 set_monitor_control(monitor, 0);
375 for (i = 0; i < num_buses[monitor]; i++) {
376 int bus = mon->current_bus[i];
378 read_bus_watcher(monitor,
379 BW0_CTRL + i*BW_PITCH,
380 (u32 *)&mon->results[bus].results);
384 mutex_unlock(&state->lock);
387 static int monitor_thread(void *data)
389 struct rpi_axiperf *state = data;
394 if (kthread_should_stop())
400 static ssize_t myreader(struct file *fp, char __user *user_buffer,
401 size_t count, loff_t *position)
403 #define INIT_BUFF_SIZE 2048
406 int idx = (int)(uintptr_t)(fp->private_data);
409 int buff_size = INIT_BUFF_SIZE;
411 typeof(state->monitor[0]) *mon = &(state->monitor[idx]);
413 if (idx < 0 || idx > NUM_MONITORS)
416 num_buses = idx == SYSTEM_MONITOR ? num_system_buses : num_vpu_buses;
418 string_buffer = kmalloc(buff_size, GFP_KERNEL);
420 if (!string_buffer) {
421 dev_err(&state->dev->dev,
422 "Failed temporary string allocation\n");
428 mutex_lock(&state->lock);
430 if (mon->bus_filter) {
431 int filt = min(mon->bus_filter & 0x1f, num_bus_filters);
433 cnt = snprintf(p, buff_size,
434 "\nMonitoring transactions from %s only\n",
435 bus_filter_strings[filt]);
440 cnt = snprintf(p, buff_size, " Bus | Atrans Atwait AMax Wtrans Wtwait WMax Rtrans Rtwait RMax\n"
441 "======================================================================================================\n");
443 if (cnt >= buff_size)
449 for (i = 0; i < num_buses; i++) {
450 if (mon->bus_enabled & (1 << i)) {
451 #define DIVIDER (1024)
452 typeof(mon->results[0]) *res = &(mon->results[i]);
454 cnt = snprintf(p, buff_size,
455 "%10s | %8uK %8uK %8uK %8uK %8uK %8uK %8uK %8uK %8uK\n",
456 idx == SYSTEM_MONITOR ?
457 system_bus_string[i] :
469 if (cnt >= buff_size)
477 mutex_unlock(&state->lock);
481 /* did the last string entry exceeed our buffer size? ie out of string
482 * buffer space. Null terminate, use what we have.
484 if (cnt >= buff_size) {
486 string_buffer[INIT_BUFF_SIZE] = 0;
489 cnt = simple_read_from_buffer(user_buffer, count, position,
491 INIT_BUFF_SIZE - buff_size);
493 kfree(string_buffer);
498 static ssize_t mywriter(struct file *fp, const char __user *user_buffer,
499 size_t count, loff_t *position)
501 int idx = (int)(uintptr_t)(fp->private_data);
503 if (idx < 0 || idx > NUM_MONITORS)
506 /* At the moment, this does nothing, but in the future it could be
507 * used to reset counters etc
512 static const struct file_operations fops_debug = {
518 static int rpi_axiperf_probe(struct platform_device *pdev)
521 struct device *dev = &pdev->dev;
522 struct device_node *np = dev->of_node;
523 struct device_node *fw_node;
525 state = kzalloc(sizeof(struct rpi_axiperf), GFP_KERNEL);
529 /* Get the firmware handle for future rpi-firmware-xxx calls */
530 fw_node = of_parse_phandle(np, "firmware", 0);
532 dev_err(dev, "Missing firmware node\n");
536 state->firmware = rpi_firmware_get(fw_node);
537 if (!state->firmware)
538 return -EPROBE_DEFER;
540 /* Special case for the VPU monitor, we must use the mailbox interface
541 * as it is not accessible from the ARM address space.
543 state->monitor[VPU_MONITOR].use_mailbox_interface = 1;
544 state->monitor[SYSTEM_MONITOR].use_mailbox_interface = 0;
546 for (i = 0; i < NUM_MONITORS; i++) {
547 if (state->monitor[i].use_mailbox_interface) {
548 of_property_read_u32_index(np, "reg", i*2,
549 (u32 *)(&state->monitor[i].base_address));
551 struct resource *resource =
552 platform_get_resource(pdev, IORESOURCE_MEM, i);
554 state->monitor[i].base_address =
555 devm_ioremap_resource(&pdev->dev, resource);
558 if (IS_ERR(state->monitor[i].base_address))
559 return PTR_ERR(state->monitor[i].base_address);
561 /* Enable all buses by default */
562 state->monitor[i].bus_enabled = 0xffff;
566 platform_set_drvdata(pdev, state);
568 state->sample_time = DEFAULT_SAMPLE_TIME;
570 /* Set up all the debugfs stuff */
571 state->root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
573 for (i = 0; i < NUM_MONITORS; i++) {
574 state->monitor[i].debugfs_entry =
575 debugfs_create_dir(monitor_name[i], state->root_folder);
576 if (IS_ERR(state->monitor[i].debugfs_entry))
577 state->monitor[i].debugfs_entry = NULL;
579 debugfs_create_file("data", 0444,
580 state->monitor[i].debugfs_entry,
581 (void *)(uintptr_t)i, &fops_debug);
582 debugfs_create_u32("enable", 0644,
583 state->monitor[i].debugfs_entry,
584 &state->monitor[i].bus_enabled);
585 debugfs_create_u32("filter", 0644,
586 state->monitor[i].debugfs_entry,
587 &state->monitor[i].bus_filter);
588 debugfs_create_u32("sample_time", 0644,
589 state->monitor[i].debugfs_entry,
590 &state->sample_time);
593 mutex_init(&state->lock);
595 state->monitor_thread = kthread_run(monitor_thread, state,
602 static int rpi_axiperf_remove(struct platform_device *dev)
606 kthread_stop(state->monitor_thread);
608 debugfs_remove_recursive(state->root_folder);
609 state->root_folder = NULL;
614 static const struct of_device_id rpi_axiperf_match[] = {
616 .compatible = "brcm,bcm2835-axiperf",
620 MODULE_DEVICE_TABLE(of, rpi_axiperf_match);
622 static struct platform_driver rpi_axiperf_driver = {
623 .probe = rpi_axiperf_probe,
624 .remove = rpi_axiperf_remove,
626 .name = "rpi-bcm2835-axiperf",
627 .of_match_table = of_match_ptr(rpi_axiperf_match),
631 module_platform_driver(rpi_axiperf_driver);
633 /* Module information */
634 MODULE_AUTHOR("James Hughes <james.hughes@raspberrypi.org>");
635 MODULE_DESCRIPTION("RPI AXI Performance monitor driver");
636 MODULE_LICENSE("GPL");