Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751706AbcDOFOC (ORCPT ); Fri, 15 Apr 2016 01:14:02 -0400 Received: from mailout3.samsung.com ([203.254.224.33]:58505 "EHLO mailout3.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751157AbcDOFN7 (ORCPT ); Fri, 15 Apr 2016 01:13:59 -0400 MIME-version: 1.0 Content-type: text/plain; charset=UTF-8 X-AuditID: cbfee68d-f79e86d0000012da-ad-57107891c3b3 Content-transfer-encoding: 8BIT Message-id: <57107890.7080705@samsung.com> Date: Fri, 15 Apr 2016 14:13:52 +0900 From: Chanwoo Choi User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 To: Krzysztof Kozlowski , myungjoo.ham@samsung.com, kyungmin.park@samsung.com, kgene@kernel.org, s.nawrocki@samsung.com, tomasz.figa@gmail.com Cc: rjw@rjwysocki.net, robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com, ijc+devicetree@hellion.org.uk, galak@codeaurora.org, linux@arm.linux.org.uk, linux.amoon@gmail.com, m.reichl@fivetechno.de, tjakobi@math.uni-bielefeld.de, inki.dae@samsung.com, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org Subject: Re: [PATCH 1/7] PM / devfreq: event: Add new Exynos NoC probe driver References: <1460091646-28701-1-git-send-email-cw00.choi@samsung.com> <1460091646-28701-2-git-send-email-cw00.choi@samsung.com> <570CACB6.40405@samsung.com> In-reply-to: <570CACB6.40405@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA02Se0hTURzHO7uPXZeD43x0FLIS7CFpmo+OVKIUcakEI8oKopZdVJxz3Kkp CLnMRPOV2muGaWTq1B4r6IU650Wq+ShHJS4fIdR89bKiaEm7jqj/vnx+39853y/8GEJRTPkx qepMjlcrVQG0jGzziuCDz+XAxNCZm4H4qjBA4YrZBgoPTLcAXDVeSeIZexiumJwhcP+pWSk2 Tr6isPXRFRrPlwkAXxrslOCbd0ak2GaV4ynhB8CNr19IsE3XTOPKi+0k7rMMUbiwQ5Dintki Cp9p/URhwyMHiPVh2+raAHu6oJRmreVlEnbkzUn2oX5UyrY0faVZo6GYZu9eP8ku9ErZey+L SLb8ngGw80b/BPdDsi3HOVVqNsdviDkqSxl8PUhq5lJz3vb/ovOBbV8JcGMQjEBPP38gXdoH PR+7RZcAGaOAzQDV/DZRf00XuoYo16ARIEdPx+KGHHqgH9VjTs0wBFyBhKE0ERNwDaqqu0aI WgEnAKpt2OuyB6HhX4+lop2EgcghbBMx7cRd9mFaxN7wADr7JFfEXrAVoPHeg+KvBGwn0HSR bjGOJ4xHDl076Xq+HqDOa9tF7QbXoabmLxJxAcFPDGptMdHigIQQfa82L8ZEcDkymghXLV/U 3TxMVgIf/X9l9P/K6P8rUw8IA/DmNEka7bFkPixEq0zXZqmTQ5Iy0o3AeSGWhXdlD4DNtNkM IAMC3OUTh2GiglJma3PTzSDSGeIc4eedlOE8KnXmkbDwqI04MiIyfOOm6KiAZfJVfj/3KmCy MpNL4zgNxx/hs1Sc1gwkjJtfPmj/eL5LY+7MqFpfVHFfLSSWWrbScUHBS7X71+aNdus87LdX ddaaTNaG80n8cJlVP5A5VkDyeZuM8d/mojOGuMuBa3YY7M9mYooV3yd8V3N5sTWDlj5P3927 ekIP3N+z1Ov6yqkO07ZCSbyC8rfd2OnJfItbEneij0h4XymomvQBpDZFGRZE8FrlHyluDgcc AwAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrGKsWRmVeSWpSXmKPExsVy+t9jAd2JFQLhBp++S1vMP3KO1aL/zUJW i3OvVjJaTLo/gcXi9QtDi/7Hr5ktzja9YbfY9Pgaq8XlXXPYLD73HmG0mHF+H5PFuo232C1u X+a1eHnkB6PF0usXmSxuN65gs5gwfS2LxZnTl1gtWvceYbc4/Kad1aJt9QdWi1W7/jA6iHms mbeG0aOluYfN43JfL5PHrTv1Hjtn3WX3WLn8C5vHplWdbB6bl9R7/DvG7rHlajuLR9+WVYwe nzfJBfBENTDaZKQmpqQWKaTmJeenZOal2yp5B8c7x5uaGRjqGlpamCsp5CXmptoqufgE6Lpl 5gA9rKRQlphTChQKSCwuVtK3wzQhNMRN1wKmMULXNyQIrsfIAA0krGHMOH/9PEvB28yKh2d/ szUw3g7tYuTkkBAwkZi2/xIrhC0mceHeerYuRi4OIYGljBJ/Du9lAUnwCghK/Jh8D8jm4GAW kJc4cikbJMwsoC4xad4iZhBbSOABo8TshcEQ5VoSN37vZgcpZxFQlfhzxBkkzAYU3v/iBhtI WFQgQqL7RCVIWERgNaPE/WORIFuZBdYyS7xqbwQ7R1jAV+JP41oWiPELGCX2LXIBsTkFNCWW r/jENIFRYBaS42YhHDcLyXELGJlXMUqkFiQXFCel5xrmpZbrFSfmFpfmpesl5+duYgSnqWdS OxgP7nI/xCjAwajEw/sgViBciDWxrLgy9xCjBAezkghvSjlQiDclsbIqtSg/vqg0J7X4EKMp 0HsTmaVEk/OBKTSvJN7Q2MTMyNLI3NDCyNhcSZz38f91YUIC6YklqdmpqQWpRTB9TBycUg2M mtHftvQ8u3ZvTQN7zfrt9YZyxYu2Z2bul8/in3U567FrQWnAxGzz/dXSV7/qy25MnbTe7r0T 59/H9/6/26B6MPvRJZXOwL6/r4/PlrU89v1GxKSQwzUPbprtWhzlIXX6beXrqRd61mzxP//4 Vt39m+V8+bO8Us8xmgesOiPP9Ot096H07VpK3kosxRmJhlrMRcWJAHMGLe1pAwAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 13145 Lines: 404 On 2016년 04월 12일 17:07, Krzysztof Kozlowski wrote: > On 04/08/2016 07:00 AM, Chanwoo Choi wrote: >> This patch adds NoC (Network on Chip) Probe driver which provides >> the primitive values to get the performance data. The packets that the Network >> on Chip (NoC) probes detects are transported over the network infrastructure. >> Exynos542x bus has multiple NoC probes to provide bandwidth information about >> behavior of the SoC that you can use while analyzing system performance. >> >> Signed-off-by: Chanwoo Choi >> --- >> .../bindings/devfreq/event/exynos-nocp.txt | 86 +++++++ >> drivers/devfreq/event/Kconfig | 8 + >> drivers/devfreq/event/Makefile | 2 + >> drivers/devfreq/event/exynos-nocp.c | 247 +++++++++++++++++++++ >> drivers/devfreq/event/exynos-nocp.h | 78 +++++++ >> 5 files changed, 421 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt >> create mode 100644 drivers/devfreq/event/exynos-nocp.c >> create mode 100644 drivers/devfreq/event/exynos-nocp.h >> >> diff --git a/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt b/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt >> new file mode 100644 >> index 000000000000..03b74fed034c >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt >> @@ -0,0 +1,86 @@ >> + >> +* Samsung Exynos NoC (Network on Chip) Probe device >> + >> +The Samsung Exynos542x SoC has NoC (Network on Chip) Probe for NoC bus. >> +NoC provides the primitive values to get the performance data. The packets >> +that the Network on Chip (NoC) probes detects are transported over >> +the network infrastructure to observer units. You can configure probes to >> +capture packets with header or data on the data request response network, >> +or as traffic debug or statistic collectors. Exynos542x bus has multiple >> +NoC probes to provide bandwidth information about behavior of the SoC >> +that you can use while analyzing system performance. >> + >> +Required properties: >> +- compatible: Should be "samsung,exynos5420-nocp" >> +- reg: physical base address of each NoC Probe and length of memory mapped region. >> + >> +Optional properties: >> +- clock-names : the name of clock used by the NoC Probe, "nocp" >> +- clocks : phandles for clock specified in "clock-names" property >> + >> +Example1 : NoC Probe nodes in exynos5420.dtsi are listed below. >> + >> + nocp_mem0_0: nocp_mem0_0@10CA1000 { >> + compatible = "samsung,exynos5420-nocp"; >> + reg = <0x10CA1000 0x200>; >> + status = "disabled"; >> + }; >> + >> + nocp_mem0_1: nocp_mem0_1@10CA1400 { >> + compatible = "samsung,exynos5420-nocp"; >> + reg = <0x10CA1400 0x200>; >> + status = "disabled"; >> + }; >> + >> + nocp_mem0_2: nocp_mem0_2@10CA1800 { >> + compatible = "samsung,exynos5420-nocp"; >> + reg = <0x10CA1800 0x200>; >> + status = "disabled"; >> + }; >> + >> + nocp_mem0_3: nocp_mem0_0@10CA1C00 { >> + compatible = "samsung,exynos5420-nocp"; >> + reg = <0x10CA1C00 0x200>; >> + status = "disabled"; >> + }; >> + >> + nocp_g3d_0: nocp_g3d_0@11A51000 { >> + compatible = "samsung,exynos5420-nocp"; >> + reg = <0x11A51000 0x200>; >> + status = "disabled"; >> + }; >> + >> + nocp_g3d_1: nocp_g3d_1@11A51400 { >> + compatible = "samsung,exynos5420-nocp"; >> + reg = <0x11A51400 0x200>; >> + status = "disabled"; >> + }; >> + >> + >> +Example2 : Events of each NoC Probe node in exynos5422-odroidxu3-common.dtsi >> + are listed below. >> + >> + >> + &nocp_mem0_0 { >> + status = "okay"; >> + }; >> + >> + &nocp_mem0_1 { >> + status = "okay"; >> + }; >> + >> + &nocp_mem0_2 { >> + status = "okay"; >> + }; >> + >> + &nocp_mem0_3 { >> + status = "okay"; >> + }; >> + >> + &nocp_g3d_0 { >> + status = "okay"; >> + }; >> + >> + &nocp_g3d_1 { >> + status = "okay"; >> + }; > > I think this split in documentation between DTSI and DTS is not needed > for example. Just add one example without the status and it should be > sufficient to get the idea. I'll modify it as following: Example1 : NoC Probe nodes in Device Tree are listed below. nocp_mem0_0: nocp@10CA1000 { compatible = "samsung,exynos5420-nocp"; reg = <0x10CA1000 0x200>; }; > >> diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig >> index a11720affc31..1e8b4f469f38 100644 >> --- a/drivers/devfreq/event/Kconfig >> +++ b/drivers/devfreq/event/Kconfig >> @@ -13,6 +13,14 @@ menuconfig PM_DEVFREQ_EVENT >> >> if PM_DEVFREQ_EVENT >> >> +config DEVFREQ_EVENT_EXYNOS_NOCP >> + bool "EXYNOS NoC (Network On Chip) Probe DEVFREQ event Driver" >> + depends on ARCH_EXYNOS >> + select PM_OPP >> + help >> + This add the devfreq-event driver for Exynos SoC. It provides NoC >> + (Network on Chip) Probe counters to measure the bandwidth of AXI bus. >> + >> config DEVFREQ_EVENT_EXYNOS_PPMU >> bool "EXYNOS PPMU (Platform Performance Monitoring Unit) DEVFREQ event Driver" >> depends on ARCH_EXYNOS >> diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile >> index be146ead79cf..3d6afd352253 100644 >> --- a/drivers/devfreq/event/Makefile >> +++ b/drivers/devfreq/event/Makefile >> @@ -1,2 +1,4 @@ >> # Exynos DEVFREQ Event Drivers >> + >> +obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o >> obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o >> diff --git a/drivers/devfreq/event/exynos-nocp.c b/drivers/devfreq/event/exynos-nocp.c >> new file mode 100644 >> index 000000000000..b9468a6143f6 >> --- /dev/null >> +++ b/drivers/devfreq/event/exynos-nocp.c >> @@ -0,0 +1,247 @@ >> +/* >> + * exynos-nocp.c - EXYNOS NoC (Network On Chip) Probe support >> + * >> + * Copyright (c) 2016 Samsung Electronics Co., Ltd. >> + * Author : Chanwoo Choi >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "exynos-nocp.h" >> + >> +struct exynos_nocp { >> + struct devfreq_event_dev *edev; >> + struct devfreq_event_desc desc; >> + >> + struct device *dev; >> + >> + struct regmap *regmap; >> + struct clk *clk; >> +}; >> + >> +/* >> + * The devfreq-event ops structure for nocp probe. >> + */ >> +static int exynos_nocp_set_event(struct devfreq_event_dev *edev) >> +{ >> + struct exynos_nocp *nocp = devfreq_event_get_drvdata(edev); >> + >> + /* Disable NoC probe */ >> + regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL, >> + NOCP_MAIN_CTL_STATEN_MASK, 0); >> + >> + /* Set a statistics dump period to 0 */ >> + regmap_write(nocp->regmap, NOCP_STAT_PERIOD, 0x0); >> + >> + /* Set the IntEvent fields of *_SRC */ >> + regmap_update_bits(nocp->regmap, NOCP_COUNTERS_0_SRC, >> + NOCP_CNT_SRC_INTEVENT_MASK, >> + NOCP_CNT_SRC_INTEVENT_BYTE_MASK); >> + >> + regmap_update_bits(nocp->regmap, NOCP_COUNTERS_1_SRC, >> + NOCP_CNT_SRC_INTEVENT_MASK, >> + NOCP_CNT_SRC_INTEVENT_CHAIN_MASK); >> + >> + regmap_update_bits(nocp->regmap, NOCP_COUNTERS_2_SRC, >> + NOCP_CNT_SRC_INTEVENT_MASK, >> + NOCP_CNT_SRC_INTEVENT_CYCLE_MASK); >> + >> + regmap_update_bits(nocp->regmap, NOCP_COUNTERS_3_SRC, >> + NOCP_CNT_SRC_INTEVENT_MASK, >> + NOCP_CNT_SRC_INTEVENT_CHAIN_MASK); >> + >> + >> + /* Set an alarm with a max/min value of 0 to generate StatALARM */ >> + regmap_write(nocp->regmap, NOCP_STAT_ALARM_MIN, 0x0); >> + regmap_write(nocp->regmap, NOCP_STAT_ALARM_MAX, 0x0); >> + >> + /* Set AlarmMode */ >> + regmap_update_bits(nocp->regmap, NOCP_COUNTERS_0_ALARM_MODE, >> + NOCP_CNT_ALARM_MODE_MASK, >> + NOCP_CNT_ALARM_MODE_MIN_MAX_MASK); >> + regmap_update_bits(nocp->regmap, NOCP_COUNTERS_1_ALARM_MODE, >> + NOCP_CNT_ALARM_MODE_MASK, >> + NOCP_CNT_ALARM_MODE_MIN_MAX_MASK); >> + regmap_update_bits(nocp->regmap, NOCP_COUNTERS_2_ALARM_MODE, >> + NOCP_CNT_ALARM_MODE_MASK, >> + NOCP_CNT_ALARM_MODE_MIN_MAX_MASK); >> + regmap_update_bits(nocp->regmap, NOCP_COUNTERS_3_ALARM_MODE, >> + NOCP_CNT_ALARM_MODE_MASK, >> + NOCP_CNT_ALARM_MODE_MIN_MAX_MASK); >> + >> + /* Enable the measurements by setting AlarmEn and StatEn */ >> + regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL, >> + NOCP_MAIN_CTL_STATEN_MASK | NOCP_MAIN_CTL_ALARMEN_MASK, >> + NOCP_MAIN_CTL_STATEN_MASK | NOCP_MAIN_CTL_ALARMEN_MASK); >> + >> + /* Set GlobalEN */ >> + regmap_update_bits(nocp->regmap, NOCP_CFG_CTL, >> + NOCP_CFG_CTL_GLOBALEN_MASK, >> + NOCP_CFG_CTL_GLOBALEN_MASK); >> + >> + /* Enable NoC probe */ >> + regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL, >> + NOCP_MAIN_CTL_STATEN_MASK, >> + NOCP_MAIN_CTL_STATEN_MASK); > > In all these regmap_update_bits() calls you are ignoring the return > value. This does not look right. OK. I'll check the return value of regmap function. > >> + >> + return 0; >> +} >> + >> +static int exynos_nocp_get_event(struct devfreq_event_dev *edev, >> + struct devfreq_event_data *edata) >> +{ >> + struct exynos_nocp *nocp = devfreq_event_get_drvdata(edev); >> + unsigned int counter[4]; >> + >> + /* Read cycle count */ >> + regmap_read(nocp->regmap, NOCP_COUNTERS_0_VAL, &counter[0]); >> + regmap_read(nocp->regmap, NOCP_COUNTERS_1_VAL, &counter[1]); >> + regmap_read(nocp->regmap, NOCP_COUNTERS_2_VAL, &counter[2]); >> + regmap_read(nocp->regmap, NOCP_COUNTERS_3_VAL, &counter[3]); > > Ditto. If read fails, the data in counter should not be trusted (not > initialized) so the devfreq_event_get_event() should not use it. The > simplest would be to return error on each failure. ditto. > >> + >> + edata->load_count = ((counter[1] << 16) | counter[0]); >> + edata->total_count = ((counter[3] << 16) | counter[2]); >> + >> + dev_dbg(&edev->dev, "%s (event: %ld/%ld)\n", edev->desc->name, >> + edata->load_count, edata->total_count); >> + >> + return 0; >> +} >> + >> +static const struct devfreq_event_ops exynos_nocp_ops = { >> + .set_event = exynos_nocp_set_event, >> + .get_event = exynos_nocp_get_event, >> +}; >> + >> +static const struct of_device_id exynos_nocp_id_match[] = { >> + { .compatible = "samsung,exynos5420-nocp", }, >> + { /* sentinel */ }, >> +}; >> + >> +static struct regmap_config exynos_nocp_regmap_config = { >> + .reg_bits = 32, >> + .val_bits = 32, >> + .reg_stride = 4, >> + .max_register = NOCP_COUNTERS_3_VAL, >> +}; >> + >> +static int exynos_nocp_parse_dt(struct platform_device *pdev, >> + struct exynos_nocp *nocp) >> +{ >> + struct device *dev = nocp->dev; >> + struct device_node *np = dev->of_node; >> + struct resource *res; >> + void __iomem *base; >> + int ret = 0; >> + >> + if (!np) { >> + dev_err(dev, "failed to find devicetree node\n"); >> + return -EINVAL; >> + } >> + >> + nocp->clk = devm_clk_get(dev, "nocp"); >> + if (IS_ERR(nocp->clk)) >> + nocp->clk = NULL; >> + >> + /* Maps the memory mapped IO to control nocp register */ >> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); >> + if (IS_ERR(res)) >> + return PTR_ERR(res); >> + >> + base = devm_ioremap_resource(dev, res); >> + if (IS_ERR(base)) >> + return PTR_ERR(base); >> + exynos_nocp_regmap_config.max_register = resource_size(res) - 4; >> + >> + nocp->regmap = devm_regmap_init_mmio(dev, base, >> + &exynos_nocp_regmap_config); >> + if (IS_ERR(nocp->regmap)) { >> + dev_err(dev, "failed to initialize regmap\n"); >> + ret = PTR_ERR(nocp->regmap); >> + goto err; >> + } >> + >> + return 0; >> + >> +err: >> + devm_iounmap(dev, base); > > Why you need this? This is obtained by devm-like() interface so it > should be released by the core. I'll remove it. > >> + >> + return ret; >> +} >> + >> +static int exynos_nocp_probe(struct platform_device *pdev) >> +{ >> + struct device *dev = &pdev->dev; >> + struct device_node *np = dev->of_node; >> + struct exynos_nocp *nocp; >> + int ret; >> + >> + nocp = devm_kzalloc(&pdev->dev, sizeof(*nocp), GFP_KERNEL); >> + if (!nocp) >> + return -ENOMEM; >> + >> + nocp->dev = &pdev->dev; >> + >> + /* Parse dt data to get resource */ >> + ret = exynos_nocp_parse_dt(pdev, nocp); >> + if (ret < 0) { >> + dev_err(&pdev->dev, >> + "failed to parse devicetree for resource\n"); >> + return ret; >> + } >> + >> + /* Add devfreq-event device to measure the bandwidth of NoC */ >> + nocp->desc.ops = &exynos_nocp_ops; >> + nocp->desc.driver_data = nocp; >> + nocp->desc.name = np->name; >> + nocp->edev = devm_devfreq_event_add_edev(&pdev->dev, &nocp->desc); >> + if (IS_ERR(nocp->edev)) { >> + ret = PTR_ERR(nocp->edev); >> + dev_err(&pdev->dev, >> + "failed to add devfreq-event device\n"); >> + goto err; > > This looks not needed and does not improve readability to me. Just > 'return ret' always. At this point (before this if() statement) 'ret' > equals to 0. Then you could remove the 'err' label and always 'return ret'. OK. Best Regards, Chanwoo Choi