Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754842AbbGFKMZ (ORCPT ); Mon, 6 Jul 2015 06:12:25 -0400 Received: from mga11.intel.com ([192.55.52.93]:4030 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754821AbbGFKMV (ORCPT ); Mon, 6 Jul 2015 06:12:21 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,414,1432623600"; d="scan'208";a="519501611" From: Alexander Shishkin To: Greg Kroah-Hartman Cc: linux-kernel@vger.kernel.org, mathieu.poirier@linaro.org, peter.lachner@intel.com, norbert.schulz@intel.com, keven.boell@intel.com, yann.fouassier@intel.com, laurent.fert@intel.com, Alexander Shishkin Subject: [PATCH v3 10/11] intel_th: Add PTI output driver Date: Mon, 6 Jul 2015 13:09:03 +0300 Message-Id: <1436177344-16751-11-git-send-email-alexander.shishkin@linux.intel.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1436177344-16751-1-git-send-email-alexander.shishkin@linux.intel.com> References: <1436177344-16751-1-git-send-email-alexander.shishkin@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10377 Lines: 380 Parallel Trace Interface (PTI) unit is a trace output device that sends data over a PTI port. The driver provides interfaces to configure bus width, bus clock divider and mode. Tracing is enabled via output device's "active" attribute. Signed-off-by: Alexander Shishkin --- .../ABI/testing/sysfs-bus-intel_th-devices-pti | 24 ++ drivers/hwtracing/intel_th/Kconfig | 9 + drivers/hwtracing/intel_th/Makefile | 3 + drivers/hwtracing/intel_th/pti.c | 252 +++++++++++++++++++++ drivers/hwtracing/intel_th/pti.h | 29 +++ 5 files changed, 317 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-intel_th-devices-pti create mode 100644 drivers/hwtracing/intel_th/pti.c create mode 100644 drivers/hwtracing/intel_th/pti.h diff --git a/Documentation/ABI/testing/sysfs-bus-intel_th-devices-pti b/Documentation/ABI/testing/sysfs-bus-intel_th-devices-pti new file mode 100644 index 0000000000..df0b24fd02 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-intel_th-devices-pti @@ -0,0 +1,24 @@ +What: /sys/bus/intel_th/devices/-pti/mode +Date: June 2015 +KernelVersion: 4.3 +Contact: Alexander Shishkin +Description: (RW) Configure PTI output width. Currently supported values + are 4, 8, 12, 16. + +What: /sys/bus/intel_th/devices/-pti/freerunning_clock +Date: June 2015 +KernelVersion: 4.3 +Contact: Alexander Shishkin +Description: (RW) 0: PTI trace clock acts as a strobe which only toggles + when there is trace data to send. 1: PTI trace clock is a + free-running clock. + +What: /sys/bus/intel_th/devices/-pti/clock_divider +Date: June 2015 +KernelVersion: 4.3 +Contact: Alexander Shishkin +Description: (RW) Configure PTI port clock divider: + - 0: Intel TH clock rate, + - 1: 1/2 Intel TH clock rate, + - 2: 1/4 Intel TH clock rate, + - 3: 1/8 Intel TH clock rate. diff --git a/drivers/hwtracing/intel_th/Kconfig b/drivers/hwtracing/intel_th/Kconfig index e3de779ff5..9c9a82287c 100644 --- a/drivers/hwtracing/intel_th/Kconfig +++ b/drivers/hwtracing/intel_th/Kconfig @@ -54,6 +54,15 @@ config INTEL_TH_MSU Say Y here to enable MSU output device for Intel TH. +config INTEL_TH_PTI + tristate "Intel Trace Hub PTI output" + help + Parallel Trace Interface unit (PTI) is a trace output device + of Intel TH architecture that facilitates STP trace output via + a PTI port. + + Say Y to enable PTI output of Intel TH data. + config INTEL_TH_DEBUG bool "Intel Trace Hub debugging" depends on DEBUG_FS diff --git a/drivers/hwtracing/intel_th/Makefile b/drivers/hwtracing/intel_th/Makefile index 4636757df2..81d42fe918 100644 --- a/drivers/hwtracing/intel_th/Makefile +++ b/drivers/hwtracing/intel_th/Makefile @@ -13,3 +13,6 @@ intel_th_sth-y := sth.o obj-$(CONFIG_INTEL_TH_MSU) += intel_th_msu.o intel_th_msu-y := msu.o + +obj-$(CONFIG_INTEL_TH_PTI) += intel_th_pti.o +intel_th_pti-y := pti.o diff --git a/drivers/hwtracing/intel_th/pti.c b/drivers/hwtracing/intel_th/pti.c new file mode 100644 index 0000000000..599689fe69 --- /dev/null +++ b/drivers/hwtracing/intel_th/pti.c @@ -0,0 +1,252 @@ +/* + * Intel Trace Hub PTI output driver + * + * Copyright (C) 2014-2015 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "intel_th.h" +#include "pti.h" + +struct pti_device { + void __iomem *base; + struct intel_th_device *thdev; + unsigned int mode; + unsigned int freeclk; + unsigned int clkdiv; + unsigned int patgen; +}; + +/* map PTI widths to MODE settings of PTI_CTL register */ +static const unsigned int pti_mode[] = { + 0, 4, 8, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, +}; + +static int pti_width_mode(unsigned int width) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pti_mode); i++) + if (pti_mode[i] == width) + return i; + + return -EINVAL; +} + +static ssize_t mode_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pti_device *pti = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", pti_mode[pti->mode]); +} + +static ssize_t mode_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pti_device *pti = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + ret = pti_width_mode(val); + if (ret < 0) + return ret; + + pti->mode = ret; + + return size; +} + +static DEVICE_ATTR_RW(mode); + +static ssize_t +freerunning_clock_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pti_device *pti = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", pti->freeclk); +} + +static ssize_t +freerunning_clock_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pti_device *pti = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + pti->freeclk = !!val; + + return size; +} + +static DEVICE_ATTR_RW(freerunning_clock); + +static ssize_t +clock_divider_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pti_device *pti = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", 1u << pti->clkdiv); +} + +static ssize_t +clock_divider_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pti_device *pti = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + if (!is_power_of_2(val) || val > 8 || !val) + return -EINVAL; + + pti->clkdiv = val; + + return size; +} + +static DEVICE_ATTR_RW(clock_divider); + +static struct attribute *pti_output_attrs[] = { + &dev_attr_mode.attr, + &dev_attr_freerunning_clock.attr, + &dev_attr_clock_divider.attr, + NULL, +}; + +static struct attribute_group pti_output_group = { + .attrs = pti_output_attrs, +}; + +static int intel_th_pti_activate(struct intel_th_device *thdev) +{ + struct pti_device *pti = dev_get_drvdata(&thdev->dev); + u32 ctl = PTI_EN; + + if (pti->patgen) + ctl |= pti->patgen << __ffs(PTI_PATGENMODE); + if (pti->freeclk) + ctl |= PTI_FCEN; + ctl |= pti->mode << __ffs(PTI_MODE); + ctl |= pti->clkdiv << __ffs(PTI_CLKDIV); + + iowrite32(ctl, pti->base + REG_PTI_CTL); + + intel_th_trace_enable(thdev); + + return 0; +} + +static void intel_th_pti_deactivate(struct intel_th_device *thdev) +{ + struct pti_device *pti = dev_get_drvdata(&thdev->dev); + + intel_th_trace_disable(thdev); + + iowrite32(0, pti->base + REG_PTI_CTL); +} + +static void read_hw_config(struct pti_device *pti) +{ + u32 ctl = ioread32(pti->base + REG_PTI_CTL); + + pti->mode = (ctl & PTI_MODE) >> __ffs(PTI_MODE); + pti->clkdiv = (ctl & PTI_CLKDIV) >> __ffs(PTI_CLKDIV); + pti->freeclk = !!(ctl & PTI_FCEN); + + if (!pti_mode[pti->mode]) + pti->mode = pti_width_mode(4); + if (!pti->clkdiv) + pti->clkdiv = 1; +} + +static int intel_th_pti_probe(struct intel_th_device *thdev) +{ + struct device *dev = &thdev->dev; + struct resource *res; + struct pti_device *pti; + void __iomem *base; + int ret; + + res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + base = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(base)) + return PTR_ERR(base); + + pti = devm_kzalloc(dev, sizeof(*pti), GFP_KERNEL); + if (!pti) + return -ENOMEM; + + pti->thdev = thdev; + pti->base = base; + + read_hw_config(pti); + + ret = sysfs_create_group(&dev->kobj, &pti_output_group); + if (ret) + return ret; + + dev_set_drvdata(dev, pti); + + return 0; +} + +static void intel_th_pti_remove(struct intel_th_device *thdev) +{ +} + +static struct intel_th_driver intel_th_pti_driver = { + .probe = intel_th_pti_probe, + .remove = intel_th_pti_remove, + .activate = intel_th_pti_activate, + .deactivate = intel_th_pti_deactivate, + .driver = { + .name = "pti", + .owner = THIS_MODULE, + }, +}; + +module_driver(intel_th_pti_driver, + intel_th_driver_register, + intel_th_driver_unregister); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel Trace Hub PTI output driver"); +MODULE_AUTHOR("Alexander Shishkin "); diff --git a/drivers/hwtracing/intel_th/pti.h b/drivers/hwtracing/intel_th/pti.h new file mode 100644 index 0000000000..3084064731 --- /dev/null +++ b/drivers/hwtracing/intel_th/pti.h @@ -0,0 +1,29 @@ +/* + * Intel Trace Hub PTI output data structures + * + * Copyright (C) 2014-2015 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __INTEL_TH_STH_H__ +#define __INTEL_TH_STH_H__ + +enum { + REG_PTI_CTL = 0x1c00, +}; + +#define PTI_EN BIT(0) +#define PTI_FCEN BIT(1) +#define PTI_MODE 0xf0 +#define PTI_CLKDIV 0x000f0000 +#define PTI_PATGENMODE 0x00f00000 + +#endif /* __INTEL_TH_STH_H__ */ -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/