Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] mm: hugetlb: support gigantic surplus pages
From: Huang Shijie @ 2016-11-03  2:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478141499-13825-1-git-send-email-shijie.huang@arm.com>

When testing the gigantic page whose order is too large for the buddy
allocator, the libhugetlbfs test case "counter.sh" will fail.

The failure is caused by:
 1) kernel fails to allocate a gigantic page for the surplus case.
    And the gather_surplus_pages() will return NULL in the end.

 2) The condition checks for "over-commit" is wrong.

This patch adds code to allocate the gigantic page in the
__alloc_huge_page(). After this patch, gather_surplus_pages()
can return a gigantic page for the surplus case.

This patch also changes the condition checks for:
     return_unused_surplus_pages()
     nr_overcommit_hugepages_store()

After this patch, the counter.sh can pass for the gigantic page.

Acked-by: Steve Capper <steve.capper@arm.com>
Signed-off-by: Huang Shijie <shijie.huang@arm.com>
---
 mm/hugetlb.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 0bf4444..2b67aff 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1574,7 +1574,7 @@ static struct page *__alloc_huge_page(struct hstate *h,
 	struct page *page;
 	unsigned int r_nid;
 
-	if (hstate_is_gigantic(h))
+	if (hstate_is_gigantic(h) && !gigantic_page_supported())
 		return NULL;
 
 	/*
@@ -1619,7 +1619,13 @@ static struct page *__alloc_huge_page(struct hstate *h,
 	}
 	spin_unlock(&hugetlb_lock);
 
-	page = __hugetlb_alloc_buddy_huge_page(h, vma, addr, nid);
+	if (hstate_is_gigantic(h))  {
+		page = alloc_gigantic_page(nid, huge_page_order(h));
+		if (page)
+			prep_compound_gigantic_page(page, huge_page_order(h));
+	} else {
+		page = __hugetlb_alloc_buddy_huge_page(h, vma, addr, nid);
+	}
 
 	spin_lock(&hugetlb_lock);
 	if (page) {
@@ -1786,8 +1792,7 @@ static void return_unused_surplus_pages(struct hstate *h,
 	/* Uncommit the reservation */
 	h->resv_huge_pages -= unused_resv_pages;
 
-	/* Cannot return gigantic pages currently */
-	if (hstate_is_gigantic(h))
+	if (hstate_is_gigantic(h) && !gigantic_page_supported())
 		return;
 
 	nr_pages = min(unused_resv_pages, h->surplus_huge_pages);
@@ -2439,7 +2444,7 @@ static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj,
 	unsigned long input;
 	struct hstate *h = kobj_to_hstate(kobj, NULL);
 
-	if (hstate_is_gigantic(h))
+	if (hstate_is_gigantic(h) && !gigantic_page_supported())
 		return -EINVAL;
 
 	err = kstrtoul(buf, 10, &input);
-- 
2.1.4

^ permalink raw reply related

* [PATCH 2/2] mm: hugetlb: support gigantic surplus pages
From: kbuild test robot @ 2016-11-03  3:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478141499-13825-3-git-send-email-shijie.huang@arm.com>

Hi Huang,

[auto build test ERROR on mmotm/master]
[also build test ERROR on v4.9-rc3 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Huang-Shijie/mm-hugetlb-rename-some-allocation-functions/20161103-105611
base:   git://git.cmpxchg.org/linux-mmotm.git master
config: x86_64-randconfig-x011-201644 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   mm/hugetlb.c: In function '__alloc_huge_page':
>> mm/hugetlb.c:1623:10: error: implicit declaration of function 'alloc_gigantic_page' [-Werror=implicit-function-declaration]
      page = alloc_gigantic_page(nid, huge_page_order(h));
             ^~~~~~~~~~~~~~~~~~~
>> mm/hugetlb.c:1623:8: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
      page = alloc_gigantic_page(nid, huge_page_order(h));
           ^
   cc1: some warnings being treated as errors

vim +/alloc_gigantic_page +1623 mm/hugetlb.c

  1617			h->nr_huge_pages++;
  1618			h->surplus_huge_pages++;
  1619		}
  1620		spin_unlock(&hugetlb_lock);
  1621	
  1622		if (hstate_is_gigantic(h))  {
> 1623			page = alloc_gigantic_page(nid, huge_page_order(h));
  1624			if (page)
  1625				prep_compound_gigantic_page(page, huge_page_order(h));
  1626		} else {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 25105 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161103/516fb148/attachment-0001.gz>

^ permalink raw reply

* [PATCH v2] of, numa: Return NUMA_NO_NODE from disable of_node_to_nid() if nid not possible.
From: Rob Herring @ 2016-11-03  3:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477689302-32671-1-git-send-email-ddaney.cavm@gmail.com>

On Fri, Oct 28, 2016 at 4:15 PM, David Daney <ddaney.cavm@gmail.com> wrote:
> From: David Daney <david.daney@cavium.com>
>
> On arm64 NUMA kernels we can pass "numa=off" on the command line to
> disable NUMA.  A side effect of this is that kmalloc_node() calls to
> non-zero nodes will crash the system with an OOPS:
>
> [    0.000000] ITS at 0x0000901000020000: allocated 2097152 Devices @10002000000 (flat, esz 8, psz 64K, shr 1)
> [    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00001680
> [    0.000000] pgd = fffffc0009470000
> [    0.000000] [00001680] *pgd=0000010ffff90003, *pud=0000010ffff90003, *pmd=0000010ffff90003, *pte=0000000000000000
> [    0.000000] Internal error: Oops: 96000006 [#1] SMP
> .
> .
> .
> [    0.000000] [<fffffc00081c8950>] __alloc_pages_nodemask+0xa4/0xe68
> [    0.000000] [<fffffc000821fa70>] new_slab+0xd0/0x564
> [    0.000000] [<fffffc0008221e24>] ___slab_alloc+0x2e4/0x514
> [    0.000000] [<fffffc0008239498>] __slab_alloc+0x48/0x58
> [    0.000000] [<fffffc0008222c20>] __kmalloc_node+0xd0/0x2dc
> [    0.000000] [<fffffc0008115374>] __irq_domain_add+0x7c/0x164
> [    0.000000] [<fffffc0008b461dc>] its_probe+0x784/0x81c
> [    0.000000] [<fffffc0008b462bc>] its_init+0x48/0x1b0
> [    0.000000] [<fffffc0008b4543c>] gic_init_bases+0x228/0x360
> [    0.000000] [<fffffc0008b456bc>] gic_of_init+0x148/0x1cc
> [    0.000000] [<fffffc0008b5aec8>] of_irq_init+0x184/0x298
> [    0.000000] [<fffffc0008b43f9c>] irqchip_init+0x14/0x38
> [    0.000000] [<fffffc0008b12d60>] init_IRQ+0xc/0x30
> [    0.000000] [<fffffc0008b10a3c>] start_kernel+0x240/0x3b8
> [    0.000000] [<fffffc0008b101c4>] __primary_switched+0x30/0x6c
> [    0.000000] Code: 912ec2a0 b9403809 0a0902fb 37b007db (f9400300)
> .
> .
> .
>
> This is caused by code like this in kernel/irq/irqdomain.c
>
>     domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
>                   GFP_KERNEL, of_node_to_nid(of_node));
>
> When NUMA is disabled, the concept of a node is really undefined, so
> of_node_to_nid() should unconditionally return NUMA_NO_NODE.
>
> Fix by returning NUMA_NO_NODE when the nid is not in the set of
> possible nodes.
>
> Reported-by: Gilbert Netzer <noname@pdc.kth.se>
> Signed-off-by: David Daney <david.daney@cavium.com>

Does this need to go in 4.9? stable? If so, since what kernel version?

Rob

^ permalink raw reply

* [PATCH] clk: rockchip: remove more CLK_IGNORE_UNUSED for rk3399 clocktree
From: Jianqun Xu @ 2016-11-03  3:38 UTC (permalink / raw)
  To: linux-arm-kernel

Optimize rk3399 clocktree by removing CLK_IGNORE_UNUSED of some clocks.

clocks will managered by usb:
- clk_usbphy0_480m_src
- clk_usbphy1_480m_src
- clk_usbphy_480m

clocks will be managered by pvtm:
- clk_pvtm_core_l
- clk_pvtm_core_b
- clk_pvtm_ddr

clocks will be managered by dfi:
- pclk_ddr_mon
- clk_dfimon0_timer
- clk_dfimon1_timer
- aclk_dcf
- pclk_dcf

Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com>
---
 drivers/clk/rockchip/clk-rk3399.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index b3df2c6..fc29f99 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -410,11 +410,11 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 	GATE(SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(6), 6, GFLAGS),
 
-	GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", CLK_IGNORE_UNUSED,
+	GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", 0,
 			RK3399_CLKGATE_CON(13), 12, GFLAGS),
-	GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", CLK_IGNORE_UNUSED,
+	GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", 0,
 			RK3399_CLKGATE_CON(13), 12, GFLAGS),
-	MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, CLK_IGNORE_UNUSED,
+	MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, 0,
 			RK3399_CLKSEL_CON(14), 6, 1, MFLAGS),
 
 	MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0,
@@ -498,7 +498,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 			RK3399_CLKGATE_CON(14), 10, GFLAGS),
 	GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_core_adb400_core_l_2_gic", "armclkl", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(14), 11, GFLAGS),
-	GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", 0,
 			RK3399_CLKGATE_CON(0), 7, GFLAGS),
 
 	/* big core */
@@ -539,7 +539,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 	GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(14), 2, GFLAGS),
 
-	GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", 0,
 			RK3399_CLKGATE_CON(1), 7, GFLAGS),
 
 	/* gmac */
@@ -675,18 +675,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 
 	GATE(PCLK_CENTER_MAIN_NOC, "pclk_center_main_noc", "pclk_ddr", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(18), 10, GFLAGS),
-	GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", CLK_IGNORE_UNUSED,
+	GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", 0,
 			RK3399_CLKGATE_CON(18), 12, GFLAGS),
 	GATE(PCLK_CIC, "pclk_cic", "pclk_ddr", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(18), 15, GFLAGS),
 	GATE(PCLK_DDR_SGRF, "pclk_ddr_sgrf", "pclk_ddr", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(19), 2, GFLAGS),
 
-	GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", 0,
 			RK3399_CLKGATE_CON(4), 11, GFLAGS),
-	GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", 0,
 			RK3399_CLKGATE_CON(3), 5, GFLAGS),
-	GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", 0,
 			RK3399_CLKGATE_CON(3), 6, GFLAGS),
 
 	/* cci */
@@ -966,7 +966,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 	GATE(SCLK_INTMEM3, "clk_intmem3", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 5, GFLAGS),
 	GATE(SCLK_INTMEM4, "clk_intmem4", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 6, GFLAGS),
 	GATE(SCLK_INTMEM5, "clk_intmem5", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 7, GFLAGS),
-	GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 8, GFLAGS),
+	GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", 0, RK3399_CLKGATE_CON(23), 8, GFLAGS),
 	GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS),
 	GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS),
 	GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 7, GFLAGS),
@@ -980,7 +980,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 	GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS),
 
 	/* pclk_perilp0 gates */
-	GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 9, GFLAGS),
+	GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", 0, RK3399_CLKGATE_CON(23), 9, GFLAGS),
 
 	/* crypto */
 	COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, 0,
-- 
1.9.1

^ permalink raw reply related

* [PATCH v4 6/8] dt-bindings: Add support for Amlogic GXBB SCPI Interface
From: Rob Herring @ 2016-11-03  3:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161102222050.GA32189@e106835-lin.cambridge.arm.com>

On Wed, Nov 2, 2016 at 5:20 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> On Sat, Oct 29, 2016 at 11:39:05AM -0700, Olof Johansson wrote:
>> Hi,
>>
>>
>> On Wed, Oct 5, 2016 at 12:33 AM, Neil Armstrong <narmstrong@baylibre.com> wrote:
>> > Acked-by: Rob Herring <robh@kernel.org>
>> > Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> > ---
>> >  Documentation/devicetree/bindings/arm/arm,scpi.txt | 8 +++++---
>> >  1 file changed, 5 insertions(+), 3 deletions(-)
>> >
>> > diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt
>> > index faa4b44..04bc171 100644
>> > --- a/Documentation/devicetree/bindings/arm/arm,scpi.txt
>> > +++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt
>> > @@ -7,7 +7,7 @@ by Linux to initiate various system control and power operations.
>> >
>> >  Required properties:
>> >
>> > -- compatible : should be "arm,scpi"
>> > +- compatible : should be "arm,scpi" or "amlogic,meson-gxbb-scpi"
>>
>> This doesn't seem right to document here. If anything you might want
>> to have a table of more-specific-compatibles for specific
>> implementations, but "arm,scpi" should still be the compatible of the
>> node (just not the most specific one).
>>
>
> I completely agree with you and I was pushing for a generic "arm,legacy-scpi"
> compatible until this binding was acked by Rob.

Just because I ack something, that doesn't mean don't review or
comment on it further.

>
> Anyways, I will add the generic compatible and post the changes.
>
>> Also, documenting it here indiciates that non-amlogic implementations
>> can/should use that compatible, which is misleading.
>>
>
> Agreed, it's better to keep them out of this generic binding document.
>
>> >  - mboxes: List of phandle and mailbox channel specifiers
>> >           All the channels reserved by remote SCP firmware for use by
>> >           SCPI message protocol should be specified in any order
>> > @@ -60,7 +60,8 @@ A small area of SRAM is reserved for SCPI communication between application
>> >  processors and SCP.
>> >
>> >  Required properties:
>> > -- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
>> > +- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno,
>> > +               or "amlogic,meson-gxbb-sram" for Amlogic GXBB SoC.
>>
>> Maybe you'd be better of with a meson-specific document that refers to
>> these but with different compatible values.
>>
>> Come to think of it, the Juno-specific one maybe shouldn't be in
>> arm,scpi at all, since that adds confusion here.
>>
>> It's somewhat confusing that ARM is both a platform, architecture and
>> in some cases implementer of specific systems. :)
>>
>
> Sorry for that, I will move all juno specific references in the binding
> out of this document(except the examples, which I assume should be fine)
>
>> >  The rest of the properties should follow the generic mmio-sram description
>> >  found in ../../sram/sram.txt
>> > @@ -70,7 +71,8 @@ Each sub-node represents the reserved area for SCPI.
>> >  Required sub-node properties:
>> >  - reg : The base offset and size of the reserved area with the SRAM
>> >  - compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
>> > -              shared memory on Juno platforms
>> > +              shared memory on Juno platforms or
>> > +              "amlogic,meson-gxbb-scp-shmem" for Amlogic GXBB SoC.
>>
>> Same here. It won't scale if all vendors are expected to add an entry here.
>>
>
> I will rework the patches to address the concerns as I too did share same
> concern.

Guess I was optimistic that *every* platform wouldn't be different in
some way. I should know better by now...

Rob

^ permalink raw reply

* [PATCH 1/1] KVM: ARM64: Fix the issues when PMCCFILTR is configured
From: cov at codeaurora.org @ 2016-11-03  4:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478120132-9928-1-git-send-email-wei@redhat.com>

Hi Wei,

On 2016-11-02 14:55, Wei Huang wrote:
> KVM calls kvm_pmu_set_counter_event_type() when PMCCFILTR is 
> configured.
> But this function can't deals with PMCCFILTR correctly because the 
> evtCount
> bit of PMCCFILTR, which is reserved 0, conflits with the SW_INCR event
> type of other PMXEVTYPER<n> registers. To fix it, when eventsel == 0, 
> KVM
> shouldn't return immediately, but instead it needs to check further if
> select_idx is ARMV8_PMU_CYCLE_IDX.
> 
> Another issue is that KVM shouldn't copy the eventsel bits of 
> PMCCFILTER
> directly to attr.config. Istead it shoudl convert the request to
> perf_event of type 0x11 (i.e. the "cpu cycle" event type).
> 
> Signed-off-by: Wei Huang <wei@redhat.com>
> ---
>  virt/kvm/arm/pmu.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
> index 6e9c40e..13cc812 100644
> --- a/virt/kvm/arm/pmu.c
> +++ b/virt/kvm/arm/pmu.c
> @@ -379,7 +379,8 @@ void kvm_pmu_set_counter_event_type(struct
> kvm_vcpu *vcpu, u64 data,
>  	eventsel = data & ARMV8_PMU_EVTYPE_EVENT;
> 
>  	/* Software increment event does't need to be backed by a perf event 
> */
> -	if (eventsel == ARMV8_PMU_EVTYPE_EVENT_SW_INCR)
> +	if (eventsel == ARMV8_PMU_EVTYPE_EVENT_SW_INCR &&
> +	    select_idx != ARMV8_PMU_CYCLE_IDX)
>  		return;
> 
>  	memset(&attr, 0, sizeof(struct perf_event_attr));
> @@ -391,7 +392,7 @@ void kvm_pmu_set_counter_event_type(struct
> kvm_vcpu *vcpu, u64 data,
>  	attr.exclude_kernel = data & ARMV8_PMU_EXCLUDE_EL1 ? 1 : 0;
>  	attr.exclude_hv = 1; /* Don't count EL2 events */
>  	attr.exclude_host = 1; /* Don't count host events */
> -	attr.config = eventsel;
> +	attr.config = (select_idx == ARMV8_PMU_CYCLE_IDX) ? 0x011 : eventsel;

Nit: Is there some way you could use ARMV8_PMUV3_PERFCTR_CPU_CYCLES 
currently
defined in arch/arm64/kernel/perf_event.c?

Thanks,
Cov

^ permalink raw reply

* [PATCH] ARM: davinci: da850: Fix pwm name matching
From: David Lechner @ 2016-11-03  4:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <b5da35a5-de11-0aff-9107-1640f5f164cf@ti.com>

On 11/01/2016 05:31 AM, Sekhar Nori wrote:
> On Monday 31 October 2016 08:18 PM, David Lechner wrote:
>> On 10/31/2016 05:18 AM, Sekhar Nori wrote:
>>> On Tuesday 25 October 2016 11:24 PM, David Lechner wrote:
>>>> This fixes pwm name matching for DA850 familiy devices. When using
>>>> device
>>>> tree, the da850_auxdata_lookup[] table caused pwm devices to have the
>>>> exact
>>>> same name, which caused errors when trying to register the devices.
>>>>
>>>> The names for clock matching in da850_clks[] also have to be updated to
>>>> to exactly match in order for the clock lookup to work correctly.
>>>>
>>>> Signed-off-by: David Lechner <david@lechnology.com>
>>>> ---
>>>>
>>>> Tested working on LEGO MINDSTORMS EV3.
>>>>
>>>>
>>>>  arch/arm/mach-davinci/da850.c    | 10 +++++++---
>>>>  arch/arm/mach-davinci/da8xx-dt.c | 10 +++++-----
>>>>  2 files changed, 12 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/arch/arm/mach-davinci/da850.c
>>>> b/arch/arm/mach-davinci/da850.c
>>>> index ed3d0e9..6b78a8f 100644
>>>> --- a/arch/arm/mach-davinci/da850.c
>>>> +++ b/arch/arm/mach-davinci/da850.c
>>>> @@ -510,9 +510,13 @@ static struct clk_lookup da850_clks[] = {
>>>>      CLK("vpif",        NULL,        &vpif_clk),
>>>>      CLK("ahci_da850",        NULL,        &sata_clk),
>>>>      CLK("davinci-rproc.0",    NULL,        &dsp_clk),
>>>> -    CLK("ehrpwm",        "fck",        &ehrpwm_clk),
>>>> -    CLK("ehrpwm",        "tbclk",    &ehrpwm_tbclk),
>>>> -    CLK("ecap",        "fck",        &ecap_clk),
>>>> +    CLK("ehrpwm.0",        "fck",        &ehrpwm_clk),
>>>> +    CLK("ehrpwm.0",        "tbclk",    &ehrpwm_tbclk),
>>>> +    CLK("ehrpwm.1",        "fck",        &ehrpwm_clk),
>>>> +    CLK("ehrpwm.1",        "tbclk",    &ehrpwm_tbclk),
>>>> +    CLK("ecap.0",        "fck",        &ecap_clk),
>>>> +    CLK("ecap.1",        "fck",        &ecap_clk),
>>>> +    CLK("ecap.2",        "fck",        &ecap_clk),
>>>
>>> This has exposed a limitation of DaVinci clock framework. The struct clk
>>> are stored as a linked list themselves. So a node repeating in the table
>>> above will create a loop in the linked list. This is easily seen on the
>>> LCDK board. davinci_clk_disable_unused() never returns. PWMs are unused
>>> on that board.
>>>
>>> There is no "simple" solution to this AFAICS. One solution is to
>>> separate the iterator from the clock hardware structure and use struct
>>> clk_hw available in struct clk_lookup.
>>>
>>> Or move DaVinci to common clock framework. This is of course preferred
>>> but much more involved as all 6 supported SoCs have to be moved together.
>>>
>>> Thanks,
>>> Sekhar
>>>
>>>
>>
>> The simple solution for now could be to make child clocks for each of
>> these that simply enable the parent clock. e.g. ehrpwm0_clk and
>> ehpwm1_clk are children of ehrpwm_clk, etc.
>
> That sounds good. I saw the v2 patch you sent and it looks good. I
> noticed that aemif clock is repeated in da850.c too. That needs fixing.

Same with emac clock.

>> Looking at da830.c, it looks like the solution was to make multiple
>> clocks that use the same LPSC, but this does not seem right to me.
>
> The PWM clock definitions there are definitely wrong. It should be
> fixed. Looks like its been like that forever.
>
> Thanks,
> Sekhar
>

^ permalink raw reply

* [PATCH v4 6/8] dt-bindings: Add support for Amlogic GXBB SCPI Interface
From: Sudeep Holla @ 2016-11-03  4:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAL_JsqJWABnX1-6SHZL8SOSt4OSPbTyXrCqTYCkXgxuO87gN-A@mail.gmail.com>



On 02/11/16 21:51, Rob Herring wrote:
> On Wed, Nov 2, 2016 at 5:20 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> On Sat, Oct 29, 2016 at 11:39:05AM -0700, Olof Johansson wrote:
>>> Hi,
>>>
>>>
>>> On Wed, Oct 5, 2016 at 12:33 AM, Neil Armstrong <narmstrong@baylibre.com> wrote:
>>>> Acked-by: Rob Herring <robh@kernel.org>
>>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>>>> ---
>>>>  Documentation/devicetree/bindings/arm/arm,scpi.txt | 8 +++++---
>>>>  1 file changed, 5 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt
>>>> index faa4b44..04bc171 100644
>>>> --- a/Documentation/devicetree/bindings/arm/arm,scpi.txt
>>>> +++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt
>>>> @@ -7,7 +7,7 @@ by Linux to initiate various system control and power operations.
>>>>
>>>>  Required properties:
>>>>
>>>> -- compatible : should be "arm,scpi"
>>>> +- compatible : should be "arm,scpi" or "amlogic,meson-gxbb-scpi"
>>>
>>> This doesn't seem right to document here. If anything you might want
>>> to have a table of more-specific-compatibles for specific
>>> implementations, but "arm,scpi" should still be the compatible of the
>>> node (just not the most specific one).
>>>
>>
>> I completely agree with you and I was pushing for a generic "arm,legacy-scpi"
>> compatible until this binding was acked by Rob.
>
> Just because I ack something, that doesn't mean don't review or
> comment on it further.
>

Sorry I didn't mean to say that. I was initially pushing for the generic
binding and since it was reworked many times already, I didn't want to
postpone any further just for sake of that. I completely understand that
component maintainers have to review the bindings too. So clearly it was
my mistake.

>>
>> Anyways, I will add the generic compatible and post the changes.
>>
>>> Also, documenting it here indiciates that non-amlogic implementations
>>> can/should use that compatible, which is misleading.
>>>
>>
>> Agreed, it's better to keep them out of this generic binding document.
>>
>>>>  - mboxes: List of phandle and mailbox channel specifiers
>>>>           All the channels reserved by remote SCP firmware for use by
>>>>           SCPI message protocol should be specified in any order
>>>> @@ -60,7 +60,8 @@ A small area of SRAM is reserved for SCPI communication between application
>>>>  processors and SCP.
>>>>
>>>>  Required properties:
>>>> -- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
>>>> +- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno,
>>>> +               or "amlogic,meson-gxbb-sram" for Amlogic GXBB SoC.
>>>
>>> Maybe you'd be better of with a meson-specific document that refers to
>>> these but with different compatible values.
>>>
>>> Come to think of it, the Juno-specific one maybe shouldn't be in
>>> arm,scpi at all, since that adds confusion here.
>>>
>>> It's somewhat confusing that ARM is both a platform, architecture and
>>> in some cases implementer of specific systems. :)
>>>
>>
>> Sorry for that, I will move all juno specific references in the binding
>> out of this document(except the examples, which I assume should be fine)
>>
>>>>  The rest of the properties should follow the generic mmio-sram description
>>>>  found in ../../sram/sram.txt
>>>> @@ -70,7 +71,8 @@ Each sub-node represents the reserved area for SCPI.
>>>>  Required sub-node properties:
>>>>  - reg : The base offset and size of the reserved area with the SRAM
>>>>  - compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
>>>> -              shared memory on Juno platforms
>>>> +              shared memory on Juno platforms or
>>>> +              "amlogic,meson-gxbb-scp-shmem" for Amlogic GXBB SoC.
>>>
>>> Same here. It won't scale if all vendors are expected to add an entry here.
>>>
>>
>> I will rework the patches to address the concerns as I too did share same
>> concern.
>
> Guess I was optimistic that *every* platform wouldn't be different in
> some way. I should know better by now...

:)

-- 
Regards,
Sudeep

^ permalink raw reply

* [PATCH 0/8] firmware: arm_scpi: add support for legacy SCPI protocol
From: Sudeep Holla @ 2016-11-03  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This is minor rework of the series[1] from Neil Armstrong's to support
legacy SCPI protocol to make DT bindings more generic and move out all
the platform specific bindings out of the generic binding document.

--
Regards,
Sudeep

[1] http://www.spinics.net/lists/arm-kernel/msg534999.html

Neil Armstrong (4):
  firmware: arm_scpi: increase MAX_DVFS_OPPS to 16 entries
  firmware: arm_scpi: add alternative legacy structures, functions and
    macros
  firmware: arm_scpi: allow firmware with get_capabilities not
    implemented
  Documentation: bindings: Add support for Amlogic GXBB SCPI protocol

Sudeep Holla (4):
  firmware: arm_scpi: add command indirection to support legacy commands
  Documentation: bindings: decouple juno specific details from generic
    binding
  Documentation: bindings: add compatible specific to legacy SCPI
    protocol
  firmware: arm_scpi: add support for legacy SCPI compatible

 .../devicetree/bindings/arm/amlogic,scpi.txt       |  20 ++
 Documentation/devicetree/bindings/arm/arm,scpi.txt |  24 +-
 .../devicetree/bindings/arm/juno,scpi.txt          |  26 ++
 drivers/firmware/arm_scpi.c                        | 276 ++++++++++++++++++---
 4 files changed, 300 insertions(+), 46 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/amlogic,scpi.txt
 create mode 100644 Documentation/devicetree/bindings/arm/juno,scpi.txt

-- 
1.9.1

^ permalink raw reply

* [PATCH v5 1/8] firmware: arm_scpi: add command indirection to support legacy commands
From: Sudeep Holla @ 2016-11-03  4:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478148731-11712-1-git-send-email-sudeep.holla@arm.com>

Since the legacy SCPI and the SCPI v1.0 differ in the command values,
it's better to create some sort of command indirection in the driver
to avoid repeated version check at multiple places.

This patch adds the indirection command table to allow different values
of the command across SCPI versions.

[narmstrong at baylibre.com: added cmd check in scpi_send_message]
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scpi.c | 71 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 57 insertions(+), 14 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index ce2bc2a38101..9e9b022450eb 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -99,6 +99,7 @@ enum scpi_error_codes {
 	SCPI_ERR_MAX
 };
 
+/* SCPI Standard commands */
 enum scpi_std_cmd {
 	SCPI_CMD_INVALID		= 0x00,
 	SCPI_CMD_SCPI_READY		= 0x01,
@@ -132,6 +133,38 @@ enum scpi_std_cmd {
 	SCPI_CMD_COUNT
 };
 
+/* List of all commands used by this driver, used as indices */
+enum scpi_drv_cmds {
+	CMD_SCPI_CAPABILITIES = 0,
+	CMD_GET_CLOCK_INFO,
+	CMD_GET_CLOCK_VALUE,
+	CMD_SET_CLOCK_VALUE,
+	CMD_GET_DVFS,
+	CMD_SET_DVFS,
+	CMD_GET_DVFS_INFO,
+	CMD_SENSOR_CAPABILITIES,
+	CMD_SENSOR_INFO,
+	CMD_SENSOR_VALUE,
+	CMD_SET_DEVICE_PWR_STATE,
+	CMD_GET_DEVICE_PWR_STATE,
+	CMD_MAX_COUNT,
+};
+
+static int scpi_std_commands[CMD_MAX_COUNT] = {
+	SCPI_CMD_SCPI_CAPABILITIES,
+	SCPI_CMD_GET_CLOCK_INFO,
+	SCPI_CMD_GET_CLOCK_VALUE,
+	SCPI_CMD_SET_CLOCK_VALUE,
+	SCPI_CMD_GET_DVFS,
+	SCPI_CMD_SET_DVFS,
+	SCPI_CMD_GET_DVFS_INFO,
+	SCPI_CMD_SENSOR_CAPABILITIES,
+	SCPI_CMD_SENSOR_INFO,
+	SCPI_CMD_SENSOR_VALUE,
+	SCPI_CMD_SET_DEVICE_PWR_STATE,
+	SCPI_CMD_GET_DEVICE_PWR_STATE,
+};
+
 struct scpi_xfer {
 	u32 slot; /* has to be first element */
 	u32 cmd;
@@ -161,6 +194,7 @@ struct scpi_drvinfo {
 	u32 protocol_version;
 	u32 firmware_version;
 	int num_chans;
+	int *commands;
 	atomic_t next_chan;
 	struct scpi_ops *scpi_ops;
 	struct scpi_chan *channels;
@@ -344,14 +378,20 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
 	mutex_unlock(&ch->xfers_lock);
 }
 
-static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
 			     void *rx_buf, unsigned int rx_len)
 {
 	int ret;
 	u8 chan;
+	u8 cmd;
 	struct scpi_xfer *msg;
 	struct scpi_chan *scpi_chan;
 
+	if (scpi_info->commands[idx] < 0)
+		return -EOPNOTSUPP;
+
+	cmd = scpi_info->commands[idx];
+
 	chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
 	scpi_chan = scpi_info->channels + chan;
 
@@ -397,7 +437,7 @@ static u32 scpi_get_version(void)
 	struct clk_get_info clk;
 	__le16 le_clk_id = cpu_to_le16(clk_id);
 
-	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
+	ret = scpi_send_message(CMD_GET_CLOCK_INFO, &le_clk_id,
 				sizeof(le_clk_id), &clk, sizeof(clk));
 	if (!ret) {
 		*min = le32_to_cpu(clk.min_rate);
@@ -412,8 +452,9 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
 	struct clk_get_value clk;
 	__le16 le_clk_id = cpu_to_le16(clk_id);
 
-	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
+	ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id,
 				sizeof(le_clk_id), &clk, sizeof(clk));
+
 	return ret ? ret : le32_to_cpu(clk.rate);
 }
 
@@ -425,7 +466,7 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
 		.rate = cpu_to_le32(rate)
 	};
 
-	return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
+	return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
 				 &stat, sizeof(stat));
 }
 
@@ -434,8 +475,9 @@ static int scpi_dvfs_get_idx(u8 domain)
 	int ret;
 	u8 dvfs_idx;
 
-	ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
+	ret = scpi_send_message(CMD_GET_DVFS, &domain, sizeof(domain),
 				&dvfs_idx, sizeof(dvfs_idx));
+
 	return ret ? ret : dvfs_idx;
 }
 
@@ -444,7 +486,7 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index)
 	int stat;
 	struct dvfs_set dvfs = {domain, index};
 
-	return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
+	return scpi_send_message(CMD_SET_DVFS, &dvfs, sizeof(dvfs),
 				 &stat, sizeof(stat));
 }
 
@@ -468,9 +510,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
 	if (scpi_info->dvfs[domain])	/* data already populated */
 		return scpi_info->dvfs[domain];
 
-	ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
+	ret = scpi_send_message(CMD_GET_DVFS_INFO, &domain, sizeof(domain),
 				&buf, sizeof(buf));
-
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -503,7 +544,7 @@ static int scpi_sensor_get_capability(u16 *sensors)
 	struct sensor_capabilities cap_buf;
 	int ret;
 
-	ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
+	ret = scpi_send_message(CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
 				sizeof(cap_buf));
 	if (!ret)
 		*sensors = le16_to_cpu(cap_buf.sensors);
@@ -517,7 +558,7 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
 	struct _scpi_sensor_info _info;
 	int ret;
 
-	ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
+	ret = scpi_send_message(CMD_SENSOR_INFO, &id, sizeof(id),
 				&_info, sizeof(_info));
 	if (!ret) {
 		memcpy(info, &_info, sizeof(*info));
@@ -533,7 +574,7 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
 	struct sensor_value buf;
 	int ret;
 
-	ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
+	ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id),
 				&buf, sizeof(buf));
 	if (!ret)
 		*val = (u64)le32_to_cpu(buf.hi_val) << 32 |
@@ -548,7 +589,7 @@ static int scpi_device_get_power_state(u16 dev_id)
 	u8 pstate;
 	__le16 id = cpu_to_le16(dev_id);
 
-	ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
+	ret = scpi_send_message(CMD_GET_DEVICE_PWR_STATE, &id,
 				sizeof(id), &pstate, sizeof(pstate));
 	return ret ? ret : pstate;
 }
@@ -561,7 +602,7 @@ static int scpi_device_set_power_state(u16 dev_id, u8 pstate)
 		.pstate = pstate,
 	};
 
-	return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
+	return scpi_send_message(CMD_SET_DEVICE_PWR_STATE, &dev_set,
 				 sizeof(dev_set), &stat, sizeof(stat));
 }
 
@@ -591,7 +632,7 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
 	int ret;
 	struct scp_capabilities caps;
 
-	ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
+	ret = scpi_send_message(CMD_SCPI_CAPABILITIES, NULL, 0,
 				&caps, sizeof(caps));
 	if (!ret) {
 		info->protocol_version = le32_to_cpu(caps.protocol_version);
@@ -755,6 +796,8 @@ static int scpi_probe(struct platform_device *pdev)
 
 	scpi_info->channels = scpi_chan;
 	scpi_info->num_chans = count;
+	scpi_info->commands = scpi_std_commands;
+
 	platform_set_drvdata(pdev, scpi_info);
 
 	ret = scpi_init_versions(scpi_info);
-- 
1.9.1

^ permalink raw reply related

* [PATCH v5 2/8] firmware: arm_scpi: increase MAX_DVFS_OPPS to 16 entries
From: Sudeep Holla @ 2016-11-03  4:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478148731-11712-1-git-send-email-sudeep.holla@arm.com>

From: Neil Armstrong <narmstrong@baylibre.com>

Since Amlogic SoCs supports more than 8 OPPs per domains, we need increase
the OPP structure size.

This patch increases the MAX_DVFS_OPPS to 16.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scpi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 9e9b022450eb..21542a32ad9f 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -63,7 +63,7 @@
 #define SCPI_SLOT		0
 
 #define MAX_DVFS_DOMAINS	8
-#define MAX_DVFS_OPPS		8
+#define MAX_DVFS_OPPS		16
 #define DVFS_LATENCY(hdr)	(le32_to_cpu(hdr) >> 16)
 #define DVFS_OPP_COUNT(hdr)	((le32_to_cpu(hdr) >> 8) & 0xff)
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH v5 3/8] firmware: arm_scpi: add alternative legacy structures, functions and macros
From: Sudeep Holla @ 2016-11-03  4:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478148731-11712-1-git-send-email-sudeep.holla@arm.com>

From: Neil Armstrong <narmstrong@baylibre.com>

This patch adds support for the Legacy SCPI protocol that is available
in very early JUNO versions and shipped Amlogic ARMv8 based SoCs. Some
Rockchip SoC are also known to use this version of protocol with
extended vendor commands.

In order to support the legacy SCPI protocol variant, we need to add the
structures and macros definitions that varies against the final SCPI v1.0
specification.

We add the indirection table for legacy commands set so that it can
co-exist with the standard v1.0 command set. It also adds bitmap field
for channel selection since the legacy protocol mandates to send only
selected subset of the commands on the high priority channel.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
[sudeep.holla at arm.com: Updated the changelog]
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scpi.c | 192 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 174 insertions(+), 18 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 21542a32ad9f..2982bc7b8c33 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -50,13 +50,20 @@
 #define CMD_TOKEN_ID_MASK	0xff
 #define CMD_DATA_SIZE_SHIFT	16
 #define CMD_DATA_SIZE_MASK	0x1ff
+#define CMD_LEGACY_DATA_SIZE_SHIFT	20
+#define CMD_LEGACY_DATA_SIZE_MASK	0x1ff
 #define PACK_SCPI_CMD(cmd_id, tx_sz)			\
 	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
 	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
 #define ADD_SCPI_TOKEN(cmd, token)			\
 	((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
+#define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz)				\
+	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |			       \
+	(((tx_sz) & CMD_LEGACY_DATA_SIZE_MASK) << CMD_LEGACY_DATA_SIZE_SHIFT))
 
 #define CMD_SIZE(cmd)	(((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
+#define CMD_LEGACY_SIZE(cmd)	(((cmd) >> CMD_LEGACY_DATA_SIZE_SHIFT) & \
+					CMD_LEGACY_DATA_SIZE_MASK)
 #define CMD_UNIQ_MASK	(CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
 #define CMD_XTRACT_UNIQ(cmd)	((cmd) & CMD_UNIQ_MASK)
 
@@ -133,7 +140,62 @@ enum scpi_std_cmd {
 	SCPI_CMD_COUNT
 };
 
-/* List of all commands used by this driver, used as indices */
+/* SCPI Legacy Commands */
+enum legacy_scpi_std_cmd {
+	LEGACY_SCPI_CMD_INVALID			= 0x00,
+	LEGACY_SCPI_CMD_SCPI_READY		= 0x01,
+	LEGACY_SCPI_CMD_SCPI_CAPABILITIES	= 0x02,
+	LEGACY_SCPI_CMD_EVENT			= 0x03,
+	LEGACY_SCPI_CMD_SET_CSS_PWR_STATE	= 0x04,
+	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE	= 0x05,
+	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT	= 0x06,
+	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT	= 0x07,
+	LEGACY_SCPI_CMD_SYS_PWR_STATE		= 0x08,
+	LEGACY_SCPI_CMD_L2_READY		= 0x09,
+	LEGACY_SCPI_CMD_SET_AP_TIMER		= 0x0a,
+	LEGACY_SCPI_CMD_CANCEL_AP_TIME		= 0x0b,
+	LEGACY_SCPI_CMD_DVFS_CAPABILITIES	= 0x0c,
+	LEGACY_SCPI_CMD_GET_DVFS_INFO		= 0x0d,
+	LEGACY_SCPI_CMD_SET_DVFS		= 0x0e,
+	LEGACY_SCPI_CMD_GET_DVFS		= 0x0f,
+	LEGACY_SCPI_CMD_GET_DVFS_STAT		= 0x10,
+	LEGACY_SCPI_CMD_SET_RTC			= 0x11,
+	LEGACY_SCPI_CMD_GET_RTC			= 0x12,
+	LEGACY_SCPI_CMD_CLOCK_CAPABILITIES	= 0x13,
+	LEGACY_SCPI_CMD_SET_CLOCK_INDEX		= 0x14,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE		= 0x15,
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE		= 0x16,
+	LEGACY_SCPI_CMD_PSU_CAPABILITIES	= 0x17,
+	LEGACY_SCPI_CMD_SET_PSU			= 0x18,
+	LEGACY_SCPI_CMD_GET_PSU			= 0x19,
+	LEGACY_SCPI_CMD_SENSOR_CAPABILITIES	= 0x1a,
+	LEGACY_SCPI_CMD_SENSOR_INFO		= 0x1b,
+	LEGACY_SCPI_CMD_SENSOR_VALUE		= 0x1c,
+	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC	= 0x1d,
+	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS	= 0x1e,
+	LEGACY_SCPI_CMD_SENSOR_ASYNC_VALUE	= 0x1f,
+	LEGACY_SCPI_CMD_COUNT
+};
+
+/* List all commands that are required to go through the high priority link */
+static int legacy_hpriority_cmds[] = {
+	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
+	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
+	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT,
+	LEGACY_SCPI_CMD_SET_DVFS,
+	LEGACY_SCPI_CMD_GET_DVFS,
+	LEGACY_SCPI_CMD_SET_RTC,
+	LEGACY_SCPI_CMD_GET_RTC,
+	LEGACY_SCPI_CMD_SET_CLOCK_INDEX,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_SET_PSU,
+	LEGACY_SCPI_CMD_GET_PSU,
+	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC,
+	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS,
+};
+
+/* List all commands used by this driver, used as indexes */
 enum scpi_drv_cmds {
 	CMD_SCPI_CAPABILITIES = 0,
 	CMD_GET_CLOCK_INFO,
@@ -165,6 +227,21 @@ enum scpi_drv_cmds {
 	SCPI_CMD_GET_DEVICE_PWR_STATE,
 };
 
+static int scpi_legacy_commands[CMD_MAX_COUNT] = {
+	LEGACY_SCPI_CMD_SCPI_CAPABILITIES,
+	-1, /* GET_CLOCK_INFO */
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_GET_DVFS,
+	LEGACY_SCPI_CMD_SET_DVFS,
+	LEGACY_SCPI_CMD_GET_DVFS_INFO,
+	LEGACY_SCPI_CMD_SENSOR_CAPABILITIES,
+	LEGACY_SCPI_CMD_SENSOR_INFO,
+	LEGACY_SCPI_CMD_SENSOR_VALUE,
+	-1, /* SET_DEVICE_PWR_STATE */
+	-1, /* GET_DEVICE_PWR_STATE */
+};
+
 struct scpi_xfer {
 	u32 slot; /* has to be first element */
 	u32 cmd;
@@ -193,8 +270,10 @@ struct scpi_chan {
 struct scpi_drvinfo {
 	u32 protocol_version;
 	u32 firmware_version;
+	bool is_legacy;
 	int num_chans;
 	int *commands;
+	DECLARE_BITMAP(cmd_priority, LEGACY_SCPI_CMD_COUNT);
 	atomic_t next_chan;
 	struct scpi_ops *scpi_ops;
 	struct scpi_chan *channels;
@@ -211,6 +290,11 @@ struct scpi_shared_mem {
 	u8 payload[0];
 } __packed;
 
+struct legacy_scpi_shared_mem {
+	__le32 status;
+	u8 payload[0];
+} __packed;
+
 struct scp_capabilities {
 	__le32 protocol_version;
 	__le32 event_version;
@@ -236,6 +320,12 @@ struct clk_set_value {
 	__le32 rate;
 } __packed;
 
+struct legacy_clk_set_value {
+	__le32 rate;
+	__le16 id;
+	__le16 reserved;
+} __packed;
+
 struct dvfs_info {
 	__le32 header;
 	struct {
@@ -307,19 +397,43 @@ static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd)
 		return;
 	}
 
-	list_for_each_entry(t, &ch->rx_pending, node)
-		if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
-			list_del(&t->node);
-			match = t;
-			break;
-		}
+	/* Command type is not replied by the SCP Firmware in legacy Mode
+	 * We should consider that command is the head of pending RX commands
+	 * if the list is not empty. In TX only mode, the list would be empty.
+	 */
+	if (scpi_info->is_legacy) {
+		match = list_first_entry(&ch->rx_pending, struct scpi_xfer,
+					 node);
+		list_del(&match->node);
+	} else {
+		list_for_each_entry(t, &ch->rx_pending, node)
+			if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
+				list_del(&t->node);
+				match = t;
+				break;
+			}
+	}
 	/* check if wait_for_completion is in progress or timed-out */
 	if (match && !completion_done(&match->done)) {
-		struct scpi_shared_mem *mem = ch->rx_payload;
-		unsigned int len = min(match->rx_len, CMD_SIZE(cmd));
+		unsigned int len;
+
+		if (scpi_info->is_legacy) {
+			struct legacy_scpi_shared_mem *mem = ch->rx_payload;
+
+			/* RX Length is not replied by the legacy Firmware */
+			len = match->rx_len;
+
+			match->status = le32_to_cpu(mem->status);
+			memcpy_fromio(match->rx_buf, mem->payload, len);
+		} else {
+			struct scpi_shared_mem *mem = ch->rx_payload;
+
+			len = min(match->rx_len, CMD_SIZE(cmd));
+
+			match->status = le32_to_cpu(mem->status);
+			memcpy_fromio(match->rx_buf, mem->payload, len);
+		}
 
-		match->status = le32_to_cpu(mem->status);
-		memcpy_fromio(match->rx_buf, mem->payload, len);
 		if (match->rx_len > len)
 			memset(match->rx_buf + len, 0, match->rx_len - len);
 		complete(&match->done);
@@ -331,7 +445,10 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
 {
 	struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
 	struct scpi_shared_mem *mem = ch->rx_payload;
-	u32 cmd = le32_to_cpu(mem->command);
+	u32 cmd = 0;
+
+	if (!scpi_info->is_legacy)
+		cmd = le32_to_cpu(mem->command);
 
 	scpi_process_cmd(ch, cmd);
 }
@@ -343,8 +460,13 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
 	struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
 	struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload;
 
-	if (t->tx_buf)
-		memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
+	if (t->tx_buf) {
+		if (scpi_info->is_legacy)
+			memcpy_toio(ch->tx_payload, t->tx_buf, t->tx_len);
+		else
+			memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
+	}
+
 	if (t->rx_buf) {
 		if (!(++ch->token))
 			++ch->token;
@@ -353,7 +475,9 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
 		list_add_tail(&t->node, &ch->rx_pending);
 		spin_unlock_irqrestore(&ch->rx_lock, flags);
 	}
-	mem->command = cpu_to_le32(t->cmd);
+
+	if (!scpi_info->is_legacy)
+		mem->command = cpu_to_le32(t->cmd);
 }
 
 static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
@@ -392,15 +516,24 @@ static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
 
 	cmd = scpi_info->commands[idx];
 
-	chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
+	if (scpi_info->is_legacy)
+		chan = test_bit(cmd, scpi_info->cmd_priority) ? 1 : 0;
+	else
+		chan = atomic_inc_return(&scpi_info->next_chan) %
+			scpi_info->num_chans;
 	scpi_chan = scpi_info->channels + chan;
 
 	msg = get_scpi_xfer(scpi_chan);
 	if (!msg)
 		return -ENOMEM;
 
-	msg->slot = BIT(SCPI_SLOT);
-	msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+	if (scpi_info->is_legacy) {
+		msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
+		msg->slot = msg->cmd;
+	} else {
+		msg->slot = BIT(SCPI_SLOT);
+		msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+	}
 	msg->tx_buf = tx_buf;
 	msg->tx_len = tx_len;
 	msg->rx_buf = rx_buf;
@@ -470,6 +603,18 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
 				 &stat, sizeof(stat));
 }
 
+static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
+{
+	int stat;
+	struct legacy_clk_set_value clk = {
+		.id = cpu_to_le16(clk_id),
+		.rate = cpu_to_le32(rate)
+	};
+
+	return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
+				 &stat, sizeof(stat));
+}
+
 static int scpi_dvfs_get_idx(u8 domain)
 {
 	int ret;
@@ -800,6 +945,17 @@ static int scpi_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, scpi_info);
 
+	if (scpi_info->is_legacy) {
+		/* Replace with legacy variants */
+		scpi_ops.clk_set_val = legacy_scpi_clk_set_val;
+		scpi_info->commands = scpi_legacy_commands;
+
+		/* Fill priority bitmap */
+		for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++)
+			set_bit(legacy_hpriority_cmds[idx],
+				scpi_info->cmd_priority);
+	}
+
 	ret = scpi_init_versions(scpi_info);
 	if (ret) {
 		dev_err(dev, "incorrect or no SCP firmware found\n");
-- 
1.9.1

^ permalink raw reply related

* [PATCH v5 4/8] firmware: arm_scpi: allow firmware with get_capabilities not implemented
From: Sudeep Holla @ 2016-11-03  4:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478148731-11712-1-git-send-email-sudeep.holla@arm.com>

From: Neil Armstrong <narmstrong@baylibre.com>

On Amlogic SCPI legacy implementation, the GET_CAPABILITIES command is
not supported, failover by using 0.0.0 version.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
[sudeep.holla at arm.com: changed the subject]
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scpi.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 2982bc7b8c33..902233642bd3 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -783,6 +783,10 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
 		info->protocol_version = le32_to_cpu(caps.protocol_version);
 		info->firmware_version = le32_to_cpu(caps.platform_version);
 	}
+	/* Ignore error if not implemented */
+	if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
+		return 0;
+
 	return ret;
 }
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH v5 5/8] Documentation: bindings: decouple juno specific details from generic binding
From: Sudeep Holla @ 2016-11-03  4:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478148731-11712-1-git-send-email-sudeep.holla@arm.com>

Since SCPI is a generic protocol and the bindings are intended to be
generic, we need to decouple all the platform specific binding details
out of the generic bindings.

This patch moves are the Juno platform specific details into a separate
binding document.

Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 Documentation/devicetree/bindings/arm/arm,scpi.txt | 20 ++++++-----------
 .../devicetree/bindings/arm/juno,scpi.txt          | 26 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/juno,scpi.txt

diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt
index faa4b44572e3..d1882c4540d0 100644
--- a/Documentation/devicetree/bindings/arm/arm,scpi.txt
+++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt
@@ -59,18 +59,14 @@ SRAM and Shared Memory for SCPI
 A small area of SRAM is reserved for SCPI communication between application
 processors and SCP.
 
-Required properties:
-- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
-
-The rest of the properties should follow the generic mmio-sram description
-found in ../../sram/sram.txt
+The properties should follow the generic mmio-sram description found in [3]
 
 Each sub-node represents the reserved area for SCPI.
 
 Required sub-node properties:
 - reg : The base offset and size of the reserved area with the SRAM
-- compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
-	       shared memory on Juno platforms
+- compatible : should be "arm,scp-shmem" for Non-secure SRAM based
+	       shared memory
 
 Sensor bindings for the sensors based on SCPI Message Protocol
 --------------------------------------------------------------
@@ -81,11 +77,9 @@ SCPI provides an API to access the various sensors on the SoC.
 - #thermal-sensor-cells: should be set to 1. This property follows the
 			 thermal device tree bindings[2].
 
-			 Valid cell values are raw identifiers (Sensor
-			 ID) as used by the firmware. Refer to
-			 platform documentation for your
-			 implementation for the IDs to use. For Juno
-			 R0 and Juno R1 refer to [3].
+			 Valid cell values are raw identifiers (Sensor ID)
+			 as used by the firmware. Refer to  platform details
+			 for your implementation for the IDs to use.
 
 Power domain bindings for the power domains based on SCPI Message Protocol
 ------------------------------------------------------------
@@ -112,7 +106,7 @@ PM domain consumers
 [0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 [2] Documentation/devicetree/bindings/thermal/thermal.txt
-[3] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0922b/apas03s22.html
+[3] Documentation/devicetree/bindings/sram/sram.txt
 [4] Documentation/devicetree/bindings/power/power_domain.txt
 
 Example:
diff --git a/Documentation/devicetree/bindings/arm/juno,scpi.txt b/Documentation/devicetree/bindings/arm/juno,scpi.txt
new file mode 100644
index 000000000000..2ace8696bbee
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/juno,scpi.txt
@@ -0,0 +1,26 @@
+System Control and Power Interface (SCPI) Message Protocol
+(in addition to the standard binding in [0])
+
+Juno SRAM and Shared Memory for SCPI
+------------------------------------
+
+Required properties:
+- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM
+
+Each sub-node represents the reserved area for SCPI.
+
+Required sub-node properties:
+- reg : The base offset and size of the reserved area with the SRAM
+- compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
+	       shared memory on Juno platforms
+
+Sensor bindings for the sensors based on SCPI Message Protocol
+--------------------------------------------------------------
+Required properties:
+- compatible : should be "arm,scpi-sensors".
+- #thermal-sensor-cells: should be set to 1.
+			 For Juno R0 and Juno R1 refer to [1] for the
+			 sensor identifiers
+
+[0] Documentation/devicetree/bindings/arm/arm,scpi.txt
+[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0922b/apas03s22.html
-- 
1.9.1

^ permalink raw reply related

* [PATCH v5 6/8] Documentation: bindings: add compatible specific to legacy SCPI protocol
From: Sudeep Holla @ 2016-11-03  4:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478148731-11712-1-git-send-email-sudeep.holla@arm.com>

This patch adds specific compatible to support legacy SCPI protocol.

Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 Documentation/devicetree/bindings/arm/arm,scpi.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt
index d1882c4540d0..ebd03fc93135 100644
--- a/Documentation/devicetree/bindings/arm/arm,scpi.txt
+++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt
@@ -7,7 +7,9 @@ by Linux to initiate various system control and power operations.
 
 Required properties:
 
-- compatible : should be "arm,scpi"
+- compatible : should be
+	* "arm,scpi" : For implementations complying to SCPI v1.0 or above
+	* "arm,legacy-scpi" : For implementations complying pre SCPI v1.0
 - mboxes: List of phandle and mailbox channel specifiers
 	  All the channels reserved by remote SCP firmware for use by
 	  SCPI message protocol should be specified in any order
-- 
1.9.1

^ permalink raw reply related

* [PATCH v5 7/8] Documentation: bindings: Add support for Amlogic GXBB SCPI protocol
From: Sudeep Holla @ 2016-11-03  4:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478148731-11712-1-git-send-email-sudeep.holla@arm.com>

From: Neil Armstrong <narmstrong@baylibre.com>

Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
(decoupled from the generic scpi binding)
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 .../devicetree/bindings/arm/amlogic,scpi.txt         | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/amlogic,scpi.txt

diff --git a/Documentation/devicetree/bindings/arm/amlogic,scpi.txt b/Documentation/devicetree/bindings/arm/amlogic,scpi.txt
new file mode 100644
index 000000000000..7b9a861e9306
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/amlogic,scpi.txt
@@ -0,0 +1,20 @@
+System Control and Power Interface (SCPI) Message Protocol
+(in addition to the standard binding in [0])
+----------------------------------------------------------
+Required properties
+
+- compatible : should be "amlogic,meson-gxbb-scpi"
+
+AMLOGIC SRAM and Shared Memory for SCPI
+------------------------------------
+
+Required properties:
+- compatible : should be "amlogic,meson-gxbb-sram"
+
+Each sub-node represents the reserved area for SCPI.
+
+Required sub-node properties:
+- compatible : should be "amlogic,meson-gxbb-scp-shmem" for SRAM based shared
+		memory on Amlogic GXBB SoC.
+
+[0] Documentation/devicetree/bindings/arm/arm,scpi.txt
-- 
1.9.1

^ permalink raw reply related

* [PATCH v5 8/8] firmware: arm_scpi: add support for legacy SCPI compatible
From: Sudeep Holla @ 2016-11-03  4:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478148731-11712-1-git-send-email-sudeep.holla@arm.com>

This patch adds new DT match table to setup the support for legacy SCPI
protocol. It aldo adds "arm,legacy-scpi" to the legacy match entry.

Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scpi.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 902233642bd3..a38e1537fb8e 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -871,6 +871,11 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
 	return 0;
 }
 
+static const struct of_device_id legacy_scpi_of_match[] = {
+	{.compatible = "arm,legacy-scpi"},
+	{},
+};
+
 static int scpi_probe(struct platform_device *pdev)
 {
 	int count, idx, ret;
@@ -883,6 +888,9 @@ static int scpi_probe(struct platform_device *pdev)
 	if (!scpi_info)
 		return -ENOMEM;
 
+	if (of_match_device(legacy_scpi_of_match, &pdev->dev))
+		scpi_info->is_legacy = true;
+
 	count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
 	if (count < 0) {
 		dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
@@ -984,6 +992,7 @@ static int scpi_probe(struct platform_device *pdev)
 
 static const struct of_device_id scpi_of_match[] = {
 	{.compatible = "arm,scpi"},
+	{.compatible = "arm,legacy-scpi"},
 	{},
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH v7 REPOST 8/9] arm: add sysfs cpu_capacity attribute
From: Juri Lelli @ 2016-11-03  5:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161030204551.GM1041@n2100.armlinux.org.uk>

Hi,

apologies for the delay in replying, but I'm attending Linux Plumbers
this week.

On 30/10/16 20:45, Russell King - ARM Linux wrote:
> On Mon, Oct 17, 2016 at 04:46:49PM +0100, Juri Lelli wrote:
> > +#ifdef CONFIG_PROC_SYSCTL
> > +#include <asm/cpu.h>
> > +#include <linux/string.h>
> 
> Include files at the top of the file please.  No need to ifdef them.
> They're sorted alphabetically, so new additions should be alphabetical.
> (That's a general rule - if something is already alphabetical, do not
> make it non-alphabetical.)
> 
> > +static ssize_t show_cpu_capacity(struct device *dev,
> > +				 struct device_attribute *attr,
> > +				 char *buf)
> > +{
> > +	struct cpu *cpu = container_of(dev, struct cpu, dev);
> > +	ssize_t rc;
> > +	int cpunum = cpu->dev.id;
> > +	unsigned long capacity = arch_scale_cpu_capacity(NULL, cpunum);
> > +
> > +	rc = sprintf(buf, "%lu\n", capacity);
> > +
> > +	return rc;
> 
> Way too many lines for such a simple function.  This can be simplified
> to just:
> 
> 	struct cpu *cpu = container_of(dev, struct cpu, dev);
> 
> 	return sprintf(buf, "%lu\n", arch_scale_cpu_capacity(NULL, cpu->dev.id);
> 
> If you don't like the last line ending on column 79, then feel free to
> break it across two lines after the format string.
> 
> > +}
> > +
> > +static ssize_t store_cpu_capacity(struct device *dev,
> > +				  struct device_attribute *attr,
> > +				  const char *buf,
> > +				  size_t count)
> > +{
> > +	struct cpu *cpu = container_of(dev, struct cpu, dev);
> > +	int this_cpu = cpu->dev.id, i;
> > +	unsigned long new_capacity;
> > +	ssize_t ret;
> > +
> > +	if (count) {
> > +		char *p = (char *) buf;
> > +
> > +		ret = kstrtoul(p, 0, &new_capacity);
> 
> Unnecessary cast - kstrtoul takes a const char pointer, and in any case
> it's really bad form to cast away the "const-ness" of any pointer.  So,
> just:
> 
> 	if (count) {
> 		ret = kstrtoul(buf, 0, &new_capacity);
> 
> should work just fine.
> 
> > +		if (ret)
> > +			return ret;
> > +		if (new_capacity > SCHED_CAPACITY_SCALE)
> > +			return -EINVAL;
> > +
> > +		mutex_lock(&cpu_scale_mutex);
> > +		for_each_cpu(i, &cpu_topology[this_cpu].core_sibling)
> > +			set_capacity_scale(i, new_capacity);
> > +		mutex_unlock(&cpu_scale_mutex);
> > +	}
> > +
> > +	return count;
> > +}
> > +
> > +static DEVICE_ATTR(cpu_capacity,
> > +		   0644,
> > +		   show_cpu_capacity,
> > +		   store_cpu_capacity);
> 
> There's a move to use the named DEVICE_ATTR_RW() for this kind of thing,
> it'll want the functions named xxx_show() and xxx_store().  I see
> there's some recent patches to do this conversion across the kernel, so
> this should probably be done before submission.
> 
> > +
> > +static int register_cpu_capacity_sysctl(void)
> > +{
> > +	int i;
> > +	struct device *cpu;
> > +
> > +	for_each_possible_cpu(i) {
> > +		cpu = get_cpu_device(i);
> > +		if (!cpu) {
> > +			pr_err("%s: too early to get CPU%d device!\n",
> > +			       __func__, i);
> > +			continue;
> > +		}
> > +		device_create_file(cpu, &dev_attr_cpu_capacity);
> > +	}
> > +
> > +	return 0;
> > +}
> > +late_initcall(register_cpu_capacity_sysctl);
> 
> Hmm, this is really weird.  topology_init() in arch/arm/kernel/setup.c
> is where these devices get created, and they're created at
> subsys_initcall() time.  By that point, the list of possible CPUs has
> to be static, it's not going to change.  I don't see why this has to be
> done at late_initcall() - and since topology.c will be linked after
> setup.c, I don't see why it shouldn't be at subsys_initcall() level to
> follow on after topology_init().
> 

I should have addressed your comments with the updated version below. If
it looks good to you I'll superseed the old version with this new one.

Best,

- Juri

--->8---
>From 14c0f21d403ad47843896eecc042334d4e0ed8dd Mon Sep 17 00:00:00 2001
From: Juri Lelli <juri.lelli@arm.com>
Date: Thu, 15 Oct 2015 13:53:37 +0100
Subject: [PATCH v7.1 8/9] arm: add sysfs cpu_capacity attribute

Add a sysfs cpu_capacity attribute with which it is possible to read and
write (thus over-writing default values) CPUs capacity. This might be
useful in situations where values needs changing after boot.

The new attribute shows up as:

 /sys/devices/system/cpu/cpu*/cpu_capacity

Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---

Changes from v5:
  - add mutex to protect cpu_scale (as pointed out by Morten off-line)

Changes from v7:
  - include files moved at top of file
  - show_cpu_capacity simplified to less lines of code
  - unnecessary cast removed in store_cpu_capacity
  - use DEVICE_ATTR_RW() instead of DEVICE_ATTR()
  - use subsys_initcall instead of late_initcall
---
 arch/arm/kernel/topology.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index aa63287d9a10..ebf47d91b804 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -22,7 +22,9 @@
 #include <linux/of.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 
+#include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/topology.h>
 
@@ -42,6 +44,7 @@
  * updated during this sequence.
  */
 static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
+static DEFINE_MUTEX(cpu_scale_mutex);
 
 unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
 {
@@ -53,6 +56,65 @@ static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
 	per_cpu(cpu_scale, cpu) = capacity;
 }
 
+#ifdef CONFIG_PROC_SYSCTL
+static ssize_t cpu_capacity_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, dev);
+
+	return sprintf(buf, "%lu\n",
+			arch_scale_cpu_capacity(NULL, cpu->dev.id));
+}
+
+static ssize_t cpu_capacity_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf,
+				  size_t count)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, dev);
+	int this_cpu = cpu->dev.id, i;
+	unsigned long new_capacity;
+	ssize_t ret;
+
+	if (count) {
+		ret = kstrtoul(buf, 0, &new_capacity);
+		if (ret)
+			return ret;
+		if (new_capacity > SCHED_CAPACITY_SCALE)
+			return -EINVAL;
+
+		mutex_lock(&cpu_scale_mutex);
+		for_each_cpu(i, &cpu_topology[this_cpu].core_sibling)
+			set_capacity_scale(i, new_capacity);
+		mutex_unlock(&cpu_scale_mutex);
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(cpu_capacity);
+
+static int register_cpu_capacity_sysctl(void)
+{
+	int i;
+	struct device *cpu;
+
+	for_each_possible_cpu(i) {
+		cpu = get_cpu_device(i);
+		if (!cpu) {
+			pr_err("%s: too early to get CPU%d device!\n",
+			       __func__, i);
+			continue;
+		}
+		device_create_file(cpu, &dev_attr_cpu_capacity);
+	}
+
+	return 0;
+}
+subsys_initcall(register_cpu_capacity_sysctl);
+#endif
+
 #ifdef CONFIG_OF
 struct cpu_efficiency {
 	const char *compatible;
@@ -132,6 +194,7 @@ static void normalize_cpu_capacity(void)
 		return;
 
 	pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale);
+	mutex_lock(&cpu_scale_mutex);
 	for_each_possible_cpu(cpu) {
 		capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT)
 			/ capacity_scale;
@@ -139,6 +202,7 @@ static void normalize_cpu_capacity(void)
 		pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n",
 			cpu, arch_scale_cpu_capacity(NULL, cpu));
 	}
+	mutex_unlock(&cpu_scale_mutex);
 }
 
 #ifdef CONFIG_CPU_FREQ
-- 
2.10.0

^ permalink raw reply related

* [PATCH v7 REPOST 0/9] CPUs capacity information for heterogeneous systems
From: Juri Lelli @ 2016-11-03  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161030142246.od5skjzegyp62hma@localhost>

Hi Catalin,

On 30/10/16 14:22, Catalin Marinas wrote:
> On Mon, Oct 17, 2016 at 04:46:41PM +0100, Juri Lelli wrote:
> > I'm thus now assuming that everybody is OK with the patches and that they can
> > be queued for 4.10 (we certainly need this plumbing at this point). Please
> > speak if my assumption is wrong (and provide feedback! :).
> > Otherwise I'm going to:
> > 
> >  - use Russell's patching system for patches 2 and 8
> >  - ask Sudeep to pull patches 3,5,6 and 7
> >  - ask Catalin/Will to pull patches 1,4 and 9
> 
> I'm happy to queue patches 1, 4 and 9 for 4.10 (though it might have
> been easier for the whole series to go through arm-soc).
> 
> > Do you think we might get into trouble splitting the merge process this way?
> 
> Probably not. The only minor downside is that I have to grab a new DT
> for Juno from Sudeep to test the patches. Not an issue, though.
> 

Thanks and apologies if merging through different trees generates some
confusion.

I updated arm patches to address Russell's comments. I did the same for
arm64. I'll reply with the updated version, so you can see if it looks
good to you as well. In case it is OK, I already updated the for-arm64
branch with the new version:
 
 git://linux-arm.org/linux-jl.git upstream/default_caps_for-arm64 

Best,

- Juri

^ permalink raw reply

* [PATCH v7 REPOST 9/9] arm64: add sysfs cpu_capacity attribute
From: Juri Lelli @ 2016-11-03  5:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161017154650.18779-10-juri.lelli@arm.com>

Hi,

small update to be in sync with Russell's comments on arm correspoding
patch.

On 17/10/16 16:46, Juri Lelli wrote:
> Add a sysfs cpu_capacity attribute with which it is possible to read and
> write (thus over-writing default values) CPUs capacity. This might be
> useful in situations where values needs changing after boot.
> 
> The new attribute shows up as:
> 
>  /sys/devices/system/cpu/cpu*/cpu_capacity
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Brown <broonie@kernel.org>
> Cc: Sudeep Holla <sudeep.holla@arm.com>
> Signed-off-by: Juri Lelli <juri.lelli@arm.com>
> ---
> 
> Changes from v5:
>   - add mutex to protect cpu_scale (as pointed out by Morten off-line)

--->8---
>From 17684f3db6d74342da424997badcb3714a1a9e63 Mon Sep 17 00:00:00 2001
From: Juri Lelli <juri.lelli@arm.com>
Date: Wed, 14 Oct 2015 12:02:05 +0100
Subject: [PATCH v7.1 9/9] arm64: add sysfs cpu_capacity attribute

Add a sysfs cpu_capacity attribute with which it is possible to read and
write (thus over-writing default values) CPUs capacity. This might be
useful in situations where values needs changing after boot.

The new attribute shows up as:

 /sys/devices/system/cpu/cpu*/cpu_capacity

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---

Changes from v5:
  - add mutex to protect cpu_scale (as pointed out by Morten off-line)

Changes from v7:
  - include files moved at top of file
  - show_cpu_capacity simplified to less lines of code
  - unnecessary cast removed in store_cpu_capacity
  - use DEVICE_ATTR_RW() instead of DEVICE_ATTR()
  - use subsys_initcall instead of late_initcall
---
 arch/arm64/kernel/topology.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index b75b0ba2e113..23e9e13bd2aa 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -20,12 +20,15 @@
 #include <linux/of.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/cpufreq.h>
 
+#include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/topology.h>
 
 static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
+static DEFINE_MUTEX(cpu_scale_mutex);
 
 unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
 {
@@ -37,6 +40,65 @@ static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
 	per_cpu(cpu_scale, cpu) = capacity;
 }
 
+#ifdef CONFIG_PROC_SYSCTL
+static ssize_t cpu_capacity_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, dev);
+
+	return sprintf(buf, "%lu\n",
+			arch_scale_cpu_capacity(NULL, cpu->dev.id));
+}
+
+static ssize_t cpu_capacity_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf,
+				  size_t count)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, dev);
+	int this_cpu = cpu->dev.id, i;
+	unsigned long new_capacity;
+	ssize_t ret;
+
+	if (count) {
+		ret = kstrtoul(buf, 0, &new_capacity);
+		if (ret)
+			return ret;
+		if (new_capacity > SCHED_CAPACITY_SCALE)
+			return -EINVAL;
+
+		mutex_lock(&cpu_scale_mutex);
+		for_each_cpu(i, &cpu_topology[this_cpu].core_sibling)
+			set_capacity_scale(i, new_capacity);
+		mutex_unlock(&cpu_scale_mutex);
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(cpu_capacity);
+
+static int register_cpu_capacity_sysctl(void)
+{
+	int i;
+	struct device *cpu;
+
+	for_each_possible_cpu(i) {
+		cpu = get_cpu_device(i);
+		if (!cpu) {
+			pr_err("%s: too early to get CPU%d device!\n",
+			       __func__, i);
+			continue;
+		}
+		device_create_file(cpu, &dev_attr_cpu_capacity);
+	}
+
+	return 0;
+}
+subsys_initcall(register_cpu_capacity_sysctl);
+#endif
+
 static u32 capacity_scale;
 static u32 *raw_capacity;
 static bool cap_parsing_failed;
@@ -87,6 +149,7 @@ static void normalize_cpu_capacity(void)
 		return;
 
 	pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale);
+	mutex_lock(&cpu_scale_mutex);
 	for_each_possible_cpu(cpu) {
 		pr_debug("cpu_capacity: cpu=%d raw_capacity=%u\n",
 			 cpu, raw_capacity[cpu]);
@@ -96,6 +159,7 @@ static void normalize_cpu_capacity(void)
 		pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n",
 			cpu, arch_scale_cpu_capacity(NULL, cpu));
 	}
+	mutex_unlock(&cpu_scale_mutex);
 }
 
 #ifdef CONFIG_CPU_FREQ
-- 
2.10.0

^ permalink raw reply related

* [RESEND PATCH v1 00/11] perf: arm64: Support for Hisilicon SoC Hardware event counters
From: Anurup M @ 2016-11-03  5:41 UTC (permalink / raw)
  To: linux-arm-kernel

[Resending after adding maintainers in --to]

Provide Support for Hisilicon SoC(Hip05/06/07) Hardware event counters.
The Hisilicon SoC Hip0x series has many uncore or non-CPU performance
events and counters units.

This initial patch series is implemented refering to arm-cci, Intel/AMD uncore and
also the cavium thunderX and xgene uncore pmu patches.

Support for Hisilicon L3 cache(L3C), MN and DDR hardware events and
counters are added in this implementation.

The Hisilicon uncore PMUs can be found under /sys/bus/event_source/devices.
The counters are exported via sysfs in the corresponding events files
under the PMU directory so the perf tool can list the event names.

ToDo:
	1) The counter overflow handling is currently unsupported in this
	   patch series.
	2) ACPI support.

Anurup M (8):
  arm64: MAINTAINERS: hisi: Add hisilicon SoC PMU support
  Documentation: perf: hisi: Documentation for HIP05/06/07 PMU event
    counting.
  dt-bindings: perf: hisi: Add Devicetree bindings for Hisilicon SoC PMU
  perf: hisi: Update Kconfig for Hisilicon PMU support
  perf: hisi: Add support for Hisilicon SoC event counters
  perf: hisi: Add sysfs attributes for L3 cache(L3C) PMU
  perf: hisi: Support for Hisilicon DDRC PMU.
  dts: arm64: hip06: Add Hisilicon SoC PMU support

Shaokun Zhang (1):
  perf: hisi: Miscellanous node(MN) event counting in perf

Tan Xiaojun (2):
  dt-bindings: hisi: Add Hisilicon HiP05/06/07 Sysctrl and Djtag dts
    bindings
  drivers: soc: hisi: Add support for Hisilicon Djtag driver

 .../bindings/arm/hisilicon/hisilicon.txt           |  82 +++
 .../devicetree/bindings/arm/hisilicon/pmu.txt      | 127 ++++
 Documentation/perf/hisi-pmu.txt                    |  80 +++
 MAINTAINERS                                        |  10 +
 arch/arm64/boot/dts/hisilicon/hip06.dtsi           | 116 ++++
 drivers/perf/Kconfig                               |   9 +
 drivers/perf/Makefile                              |   1 +
 drivers/perf/hisilicon/Makefile                    |   1 +
 drivers/perf/hisilicon/hisi_uncore_ddrc.c          | 444 ++++++++++++++
 drivers/perf/hisilicon/hisi_uncore_ddrc.h          |  73 +++
 drivers/perf/hisilicon/hisi_uncore_l3c.c           | 628 ++++++++++++++++++++
 drivers/perf/hisilicon/hisi_uncore_l3c.h           |  67 +++
 drivers/perf/hisilicon/hisi_uncore_mn.c            | 571 ++++++++++++++++++
 drivers/perf/hisilicon/hisi_uncore_mn.h            |  68 +++
 drivers/perf/hisilicon/hisi_uncore_pmu.c           | 371 ++++++++++++
 drivers/perf/hisilicon/hisi_uncore_pmu.h           | 130 +++++
 drivers/soc/Kconfig                                |   1 +
 drivers/soc/Makefile                               |   1 +
 drivers/soc/hisilicon/Kconfig                      |  12 +
 drivers/soc/hisilicon/Makefile                     |   1 +
 drivers/soc/hisilicon/djtag.c                      | 639 +++++++++++++++++++++
 include/linux/soc/hisilicon/djtag.h                |  38 ++
 22 files changed, 3470 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/pmu.txt
 create mode 100644 Documentation/perf/hisi-pmu.txt
 create mode 100644 drivers/perf/hisilicon/Makefile
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_ddrc.c
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_ddrc.h
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_l3c.c
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_l3c.h
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_mn.c
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_mn.h
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_pmu.c
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_pmu.h
 create mode 100644 drivers/soc/hisilicon/Kconfig
 create mode 100644 drivers/soc/hisilicon/Makefile
 create mode 100644 drivers/soc/hisilicon/djtag.c
 create mode 100644 include/linux/soc/hisilicon/djtag.h

-- 
2.1.4

^ permalink raw reply

* [RESEND PATCH v1 01/11] arm64: MAINTAINERS: hisi: Add hisilicon SoC PMU support
From: Anurup M @ 2016-11-03  5:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478151727-20250-1-git-send-email-anurup.m@huawei.com>

	Add support for Hisilicon SoC hardware event counters
	for HIP05/06/07 chip versions.

Signed-off-by: Anurup M <anurup.m@huawei.com>
---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b224caa..839abc8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5725,6 +5725,16 @@ S:	Maintained
 F:	drivers/net/ethernet/hisilicon/
 F:	Documentation/devicetree/bindings/net/hisilicon*.txt
 
+HISILICON SOC PMU
+M:	Anurup M <anurup.m@huawei.com>
+W:	http://www.hisilicon.com
+S:	Supported
+F:	drivers/perf/hisilicon/*
+F:	drivers/soc/hisilicon/djtag.c
+F:	include/linux/soc/hisilicon/djtag.h
+F:	Documentation/perf/hisi-pmu.txt
+F:	Documentation/devicetree/bindings/arm/hisilicon/pmu.txt
+
 HISILICON ROCE DRIVER
 M:	Lijun Ou <oulijun@huawei.com>
 M:	Wei Hu(Xavier) <xavier.huwei@huawei.com>
-- 
2.1.4

^ permalink raw reply related

* [RESEND PATCH v1 02/11] dt-bindings: hisi: Add Hisilicon HiP05/06/07 Sysctrl and Djtag dts bindings
From: Anurup M @ 2016-11-03  5:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478151727-20250-1-git-send-email-anurup.m@huawei.com>

From: Tan Xiaojun <tanxiaojun@huawei.com>

	1) Add Hisilicon HiP05/06/07 CPU and ALGSUB system controller dts
	   bindings.
	2) Add Hisilicon Djtag dts binding.

Signed-off-by: Tan Xiaojun <tanxiaojun@huawei.com>
Signed-off-by: Anurup M <anurup.m@huawei.com>
---
 .../bindings/arm/hisilicon/hisilicon.txt           | 82 ++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 7df79a7..341cbb9 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -270,3 +270,85 @@ Required Properties:
   [1]: bootwrapper size
   [2]: relocation physical address
   [3]: relocation size
+
+-----------------------------------------------------------------------
+The Hisilicon Djtag in CPU die is an independent component which connects with
+some other components in the SoC by Debug Bus. This driver can be configured
+to access the registers of connecting components (like L3 cache, l3 cache PMU
+ etc.) during real time debugging by sysctrl. These components appear as child
+nodes of djtag.
+
+The Hip05/06/07 CPU system controller(sysctrl) support to manage some important
+components (such as clock, reset, soft reset, secure debugger, etc.).
+The CPU sysctrl registers in hip05/06/07 doesnot use syscon but will be mapped
+by djtag driver for use by connecting components.
+
+Hisilicon HiP05 CPU system controller
+Required properties:
+  - compatible : "hisilicon,hip05-cpu-djtag-v1"
+  - reg : Register address and size
+
+Hisilicon HiP06 djtag for CPU sysctrl
+Required properties:
+- compatible : "hisilicon,hip06-sysctrl", "syscon", "simple-mfd";
+- reg : Register address and size
+- djtag :
+  - compatible : "hisilicon,hip06-cpu-djtag-v1"
+  - reg : Register address and size
+
+Hisilicon HiP07 djtag for CPU sysctrl
+Required properties:
+  - compatible : "hisilicon,hip07-cpu-djtag-v2"
+  - reg : Register address and size
+
+Example:
+	/* for Hisilicon HiP05 djtag for CPU sysctrl */
+	djtag0: djtag at 80010000 {
+		compatible = "hisilicon,hip05-cpu-djtag-v1";
+		reg = <0x0 0x80010000 0x0 0x10000>;
+
+		/* For L3 cache PMU */
+		pmul3c0 {
+			compatible = "hisilicon,hisi-pmu-l3c-v1";
+			scl-id = <0x02>;
+			num-events = <0x16>;
+			num-counters = <0x08>;
+			module-id = <0x04>;
+			num-banks = <0x04>;
+			cfgen-map = <0x02 0x04 0x01 0x08>;
+			counter-reg = <0x170>;
+			evctrl-reg = <0x04>;
+			event-en = <0x1000000>;
+			evtype-reg = <0x140>;
+		};
+	};
+
+-----------------------------------------------------------------------
+The Hisilicon HiP05/06/07 ALGSUB system controller(sysctrl) is in IO die
+of SoC. It has a similar function as the Hisilicon HiP05/06/07 CPU system
+controller in CPU die and it manage different components, like RSA, etc.
+The Hisilicon Djtag in IO die has a similar function as in CPU die and maps
+the sysctrl registers for use by connecting components.
+All connecting components shall appear as child nodes of djtag.
+
+Hisilicon HiP05 djtag for ALGSUB sysctrl
+Required properties:
+  - compatible : "hisilicon,hip05-io-djtag-v1"
+  - reg : Register address and size
+
+Hisilicon HiP06 djtag for ALGSUB sysctrl
+Required properties:
+  - compatible : "hisilicon,hip06-io-djtag-v2"
+  - reg : Register address and size
+
+Hisilicon HiP07 djtag for ALGSUB sysctrl
+Required properties:
+  - compatible : "hisilicon,hip07-io-djtag-v2"
+  - reg : Register address and size
+
+Example:
+	/* for Hisilicon HiP05 djtag for alg sysctrl */
+	djtag0: djtag at d0000000 {
+	       compatible = "hisilicon,hip05-io-djtag-v1";
+		reg = <0x0 0xd0000000 0x0 0x10000>;
+	};
-- 
2.1.4

^ permalink raw reply related

* [RESEND PATCH v1 03/11] drivers: soc: hisi: Add support for Hisilicon Djtag driver
From: Anurup M @ 2016-11-03  5:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478151727-20250-1-git-send-email-anurup.m@huawei.com>

From: Tan Xiaojun <tanxiaojun@huawei.com>

	The Hisilicon Djtag is an independent component which connects
	with some other components in the SoC by Debug Bus. This driver
	can be configured to access the registers of connecting components
	(like L3 cache) during real time debugging.

Signed-off-by: Tan Xiaojun <tanxiaojun@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Anurup M <anurup.m@huawei.com>
---
 drivers/soc/Kconfig                 |   1 +
 drivers/soc/Makefile                |   1 +
 drivers/soc/hisilicon/Kconfig       |  12 +
 drivers/soc/hisilicon/Makefile      |   1 +
 drivers/soc/hisilicon/djtag.c       | 639 ++++++++++++++++++++++++++++++++++++
 include/linux/soc/hisilicon/djtag.h |  38 +++
 6 files changed, 692 insertions(+)
 create mode 100644 drivers/soc/hisilicon/Kconfig
 create mode 100644 drivers/soc/hisilicon/Makefile
 create mode 100644 drivers/soc/hisilicon/djtag.c
 create mode 100644 include/linux/soc/hisilicon/djtag.h

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index e6e90e8..89ecd42 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -3,6 +3,7 @@ menu "SOC (System On Chip) specific Drivers"
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/fsl/qbman/Kconfig"
 source "drivers/soc/fsl/qe/Kconfig"
+source "drivers/soc/hisilicon/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 50c23d0..ce2beb5 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -6,6 +6,7 @@ obj-y				+= bcm/
 obj-$(CONFIG_ARCH_DOVE)		+= dove/
 obj-$(CONFIG_MACH_DOVE)		+= dove/
 obj-y				+= fsl/
+obj-$(CONFIG_ARCH_HISI)		+= hisilicon/
 obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-$(CONFIG_ARCH_RENESAS)	+= renesas/
diff --git a/drivers/soc/hisilicon/Kconfig b/drivers/soc/hisilicon/Kconfig
new file mode 100644
index 0000000..6dd4ba0
--- /dev/null
+++ b/drivers/soc/hisilicon/Kconfig
@@ -0,0 +1,12 @@
+#
+# Hisilicon SoC drivers
+#
+config HISI_DJTAG
+	bool "Hisilicon Djtag Support"
+	depends on ARCH_HISI || COMPILE_TEST
+	help
+	  Say y here to enable the Hisilicon Djtag support. It is
+	  an independent component which connects with some other
+	  components in the SoC by Debug Bus. This driver can be
+	  configured to access the registers of connecting
+	  components during real time debugging.
diff --git a/drivers/soc/hisilicon/Makefile b/drivers/soc/hisilicon/Makefile
new file mode 100644
index 0000000..35a7b4b
--- /dev/null
+++ b/drivers/soc/hisilicon/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_HISI_DJTAG)	+= djtag.o
diff --git a/drivers/soc/hisilicon/djtag.c b/drivers/soc/hisilicon/djtag.c
new file mode 100644
index 0000000..a87c8b6
--- /dev/null
+++ b/drivers/soc/hisilicon/djtag.c
@@ -0,0 +1,639 @@
+/*
+ * Driver for Hisilicon Djtag r/w via System Controller.
+ *
+ * Copyright (C) 2016 Hisilicon Ltd.
+ *
+ * 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 <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm-generic/delay.h>
+#include <linux/soc/hisilicon/djtag.h>
+
+#define SC_DJTAG_TIMEOUT		100000	/* 100ms */
+
+/* for djtag v1 */
+#define SC_DJTAG_MSTR_EN		0x6800
+#define DJTAG_NOR_CFG			BIT(1)	/* accelerate R,W */
+#define DJTAG_MSTR_EN			BIT(0)
+#define SC_DJTAG_MSTR_START_EN		0x6804
+#define DJTAG_MSTR_START_EN		0x1
+#define SC_DJTAG_DEBUG_MODULE_SEL	0x680c
+#define SC_DJTAG_MSTR_WR		0x6810
+#define DJTAG_MSTR_W			0x1
+#define DJTAG_MSTR_R			0x0
+#define SC_DJTAG_CHAIN_UNIT_CFG_EN	0x6814
+#define CHAIN_UNIT_CFG_EN		0xFFFF
+#define SC_DJTAG_MSTR_ADDR		0x6818
+#define SC_DJTAG_MSTR_DATA		0x681c
+#define SC_DJTAG_RD_DATA_BASE		0xe800
+
+/* for djtag v2 */
+#define SC_DJTAG_SEC_ACC_EN_EX		0xd800
+#define DJTAG_SEC_ACC_EN_EX		0x1
+#define SC_DJTAG_MSTR_CFG_EX		0xd818
+#define DJTAG_MSTR_RW_SHIFT_EX		29
+#define DJTAG_MSTR_RD_EX		(0x0 << DJTAG_MSTR_RW_SHIFT_EX)
+#define DJTAG_MSTR_WR_EX		(0x1 << DJTAG_MSTR_RW_SHIFT_EX)
+#define DEBUG_MODULE_SEL_SHIFT_EX	16
+#define CHAIN_UNIT_CFG_EN_EX		0xFFFF
+#define SC_DJTAG_MSTR_ADDR_EX		0xd810
+#define SC_DJTAG_MSTR_DATA_EX		0xd814
+#define SC_DJTAG_MSTR_START_EN_EX	0xd81c
+#define DJTAG_MSTR_START_EN_EX		0x1
+#define SC_DJTAG_RD_DATA_BASE_EX	0xe800
+#define SC_DJTAG_OP_ST_EX		0xe828
+#define DJTAG_OP_DONE_EX		BIT(8)
+
+#define DJTAG_PREFIX "hisi-djtag-dev-"
+
+DEFINE_IDR(djtag_hosts_idr);
+
+struct hisi_djtag_host {
+	spinlock_t lock;
+	int id;
+	struct device dev;
+	struct list_head client_list;
+	void __iomem *sysctl_reg_map;
+	struct device_node *of_node;
+	int (*djtag_readwrite)(void __iomem *regs_base, u32 offset,
+			u32 mod_sel, u32 mod_mask, bool is_w,
+			u32 wval, int chain_id, u32 *rval);
+};
+
+#define to_hisi_djtag_client(d) container_of(d, struct hisi_djtag_client, dev)
+#define to_hisi_djtag_driver(d) container_of(d, struct hisi_djtag_driver, \
+								 driver)
+#define MODULE_PREFIX "hisi_djtag:"
+
+static void djtag_read32_relaxed(void __iomem *regs_base, u32 off, u32 *value)
+{
+	void __iomem *reg_addr = regs_base + off;
+
+	*value = readl_relaxed(reg_addr);
+}
+
+static void djtag_write32(void __iomem *regs_base, u32 off, u32 val)
+{
+	void __iomem *reg_addr = regs_base + off;
+
+	writel(val, reg_addr);
+}
+
+/*
+ * djtag_readwrite_v1/v2: djtag read/write interface
+ * @reg_base:	djtag register base address
+ * @offset:	register's offset
+ * @mod_sel:	module selection
+ * @mod_mask:	mask to select specific modules for write
+ * @is_w:	write -> true, read -> false
+ * @wval:	value to register for write
+ * @chain_id:	which sub module for read
+ * @rval:	value in register for read
+ *
+ * Return non-zero if error, else return 0.
+ */
+static int djtag_readwrite_v1(void __iomem *regs_base, u32 offset, u32 mod_sel,
+		u32 mod_mask, bool is_w, u32 wval, int chain_id, u32 *rval)
+{
+	u32 rd;
+	int timeout = SC_DJTAG_TIMEOUT;
+
+	if (!(mod_mask & CHAIN_UNIT_CFG_EN)) {
+		pr_warn("djtag: do nothing.\n");
+		return 0;
+	}
+
+	/* djtag mster enable & accelerate R,W */
+	djtag_write32(regs_base, SC_DJTAG_MSTR_EN,
+			DJTAG_NOR_CFG | DJTAG_MSTR_EN);
+
+	/* select module */
+	djtag_write32(regs_base, SC_DJTAG_DEBUG_MODULE_SEL, mod_sel);
+	djtag_write32(regs_base, SC_DJTAG_CHAIN_UNIT_CFG_EN,
+				mod_mask & CHAIN_UNIT_CFG_EN);
+
+	if (is_w) {
+		djtag_write32(regs_base, SC_DJTAG_MSTR_WR, DJTAG_MSTR_W);
+		djtag_write32(regs_base, SC_DJTAG_MSTR_DATA, wval);
+	} else
+		djtag_write32(regs_base, SC_DJTAG_MSTR_WR, DJTAG_MSTR_R);
+
+	/* address offset */
+	djtag_write32(regs_base, SC_DJTAG_MSTR_ADDR, offset);
+
+	/* start to write to djtag register */
+	djtag_write32(regs_base, SC_DJTAG_MSTR_START_EN, DJTAG_MSTR_START_EN);
+
+	/* ensure the djtag operation is done */
+	do {
+		djtag_read32_relaxed(regs_base, SC_DJTAG_MSTR_START_EN, &rd);
+		if (!(rd & DJTAG_MSTR_EN))
+			break;
+
+		udelay(1);
+	} while (timeout--);
+
+	if (timeout < 0) {
+		pr_err("djtag: %s timeout!\n", is_w ? "write" : "read");
+		return -EBUSY;
+	}
+
+	if (!is_w)
+		djtag_read32_relaxed(regs_base,
+			SC_DJTAG_RD_DATA_BASE + chain_id * 0x4, rval);
+
+	return 0;
+}
+
+static int djtag_readwrite_v2(void __iomem *regs_base, u32 offset, u32 mod_sel,
+		u32 mod_mask, bool is_w, u32 wval, int chain_id, u32 *rval)
+{
+	u32 rd;
+	int timeout = SC_DJTAG_TIMEOUT;
+
+	if (!(mod_mask & CHAIN_UNIT_CFG_EN_EX)) {
+		pr_warn("djtag: do nothing.\n");
+		return 0;
+	}
+
+	/* djtag mster enable */
+	djtag_write32(regs_base, SC_DJTAG_SEC_ACC_EN_EX, DJTAG_SEC_ACC_EN_EX);
+
+	if (is_w) {
+		djtag_write32(regs_base, SC_DJTAG_MSTR_CFG_EX, DJTAG_MSTR_WR_EX
+				| (mod_sel << DEBUG_MODULE_SEL_SHIFT_EX)
+				| (mod_mask & CHAIN_UNIT_CFG_EN_EX));
+		djtag_write32(regs_base, SC_DJTAG_MSTR_DATA_EX, wval);
+	} else
+		djtag_write32(regs_base, SC_DJTAG_MSTR_CFG_EX, DJTAG_MSTR_RD_EX
+				| (mod_sel << DEBUG_MODULE_SEL_SHIFT_EX)
+				| (mod_mask & CHAIN_UNIT_CFG_EN_EX));
+
+	/* address offset */
+	djtag_write32(regs_base, SC_DJTAG_MSTR_ADDR_EX, offset);
+
+	/* start to write to djtag register */
+	djtag_write32(regs_base,
+		      SC_DJTAG_MSTR_START_EN_EX, DJTAG_MSTR_START_EN_EX);
+
+	/* ensure the djtag operation is done */
+	do {
+		djtag_read32_relaxed(regs_base, SC_DJTAG_MSTR_START_EN_EX, &rd);
+
+		if (!(rd & DJTAG_MSTR_START_EN_EX))
+			break;
+
+		udelay(1);
+	} while (timeout--);
+
+	if (timeout < 0)
+		goto timeout;
+
+	timeout = SC_DJTAG_TIMEOUT;
+	do {
+		djtag_read32_relaxed(regs_base, SC_DJTAG_OP_ST_EX, &rd);
+
+		if (rd & DJTAG_OP_DONE_EX)
+			break;
+
+		udelay(1);
+	} while (timeout--);
+
+	if (timeout < 0)
+		goto timeout;
+
+	if (!is_w)
+		djtag_read32_relaxed(regs_base,
+				     SC_DJTAG_RD_DATA_BASE_EX + chain_id * 0x4,
+									rval);
+
+	return 0;
+
+timeout:
+	pr_err("djtag: %s timeout!\n", is_w ? "write" : "read");
+	return -EBUSY;
+}
+
+
+/**
+ * djtag_writel - write registers via djtag
+ * @node:	djtag node
+ * @offset:	register's offset
+ * @mod_sel:	module selection
+ * @mod_mask:	mask to select specific modules
+ * @val:	value to write to register
+ *
+ * If error return errno, otherwise return 0.
+ */
+int hisi_djtag_writel(struct hisi_djtag_client *client, u32 offset, u32 mod_sel,
+							u32 mod_mask, u32 val)
+{
+	void __iomem *reg_map = client->host->sysctl_reg_map;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&client->host->lock, flags);
+	ret = client->host->djtag_readwrite(reg_map, offset, mod_sel, mod_mask,
+					true, val, 0, NULL);
+	if (ret)
+		pr_err("djtag_writel: error! ret=%d\n", ret);
+	spin_unlock_irqrestore(&client->host->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hisi_djtag_writel);
+
+/**
+ * djtag_readl - read registers via djtag
+ * @node:	djtag node
+ * @offset:	register's offset
+ * @mod_sel:	module type selection
+ * @chain_id:	chain_id number, mostly is 0
+ * @val:	register's value
+ *
+ * If error return errno, otherwise return 0.
+ */
+int hisi_djtag_readl(struct hisi_djtag_client *client, u32 offset, u32 mod_sel,
+							int chain_id, u32 *val)
+{
+	void __iomem *reg_map = client->host->sysctl_reg_map;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&client->host->lock, flags);
+	ret = client->host->djtag_readwrite(reg_map, offset, mod_sel,
+			0xffff, false, 0, chain_id, val);
+	if (ret)
+		pr_err("djtag_readl: error! ret=%d\n", ret);
+	spin_unlock_irqrestore(&client->host->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hisi_djtag_readl);
+
+static const struct of_device_id djtag_of_match[] = {
+	/* for hip05(D02) cpu die */
+	{ .compatible = "hisilicon,hip05-cpu-djtag-v1",
+		.data = (void *)djtag_readwrite_v1 },
+	/* for hip05(D02) io die */
+	{ .compatible = "hisilicon,hip05-io-djtag-v1",
+		.data = (void *)djtag_readwrite_v1 },
+	/* for hip06(D03) cpu die */
+	{ .compatible = "hisilicon,hip06-cpu-djtag-v1",
+		.data = (void *)djtag_readwrite_v1 },
+	/* for hip06(D03) io die */
+	{ .compatible = "hisilicon,hip06-io-djtag-v2",
+		.data = (void *)djtag_readwrite_v2 },
+	/* for hip07(D05) cpu die */
+	{ .compatible = "hisilicon,hip07-cpu-djtag-v2",
+		.data = (void *)djtag_readwrite_v2 },
+	/* for hip07(D05) io die */
+	{ .compatible = "hisilicon,hip07-io-djtag-v2",
+		.data = (void *)djtag_readwrite_v2 },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, djtag_of_match);
+
+static ssize_t
+show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hisi_djtag_client *client = to_hisi_djtag_client(dev);
+
+	return sprintf(buf, "%s%s\n", MODULE_PREFIX, client->name);
+}
+static DEVICE_ATTR(modalias, 0444, show_modalias, NULL);
+
+static struct attribute *hisi_djtag_dev_attrs[] = {
+	NULL,
+	/* modalias helps coldplug:  modprobe $(cat .../modalias) */
+	&dev_attr_modalias.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(hisi_djtag_dev);
+
+static struct device_type hisi_djtag_client_type = {
+	.groups		= hisi_djtag_dev_groups,
+};
+
+struct hisi_djtag_client *hisi_djtag_verify_client(struct device *dev)
+{
+	return (dev->type == &hisi_djtag_client_type)
+			? to_hisi_djtag_client(dev)
+			: NULL;
+}
+
+static int hisi_djtag_device_probe(struct device *dev)
+{
+	struct hisi_djtag_driver *driver;
+	struct hisi_djtag_client *client;
+	int rc;
+
+	client = hisi_djtag_verify_client(dev);
+	if (!client) {
+		dev_err(dev, "could not find client\n");
+		return -ENODEV;
+	}
+
+	driver = to_hisi_djtag_driver(dev->driver);
+	if (!driver) {
+		dev_err(dev, "could not find driver\n");
+		return -ENODEV;
+	}
+
+	rc = driver->probe(client);
+	if (rc < 0) {
+		dev_err(dev, "client probe failed\n");
+		return rc;
+	}
+
+	return 0;
+}
+
+static int hisi_djtag_device_remove(struct device *dev)
+{
+	struct hisi_djtag_driver *driver;
+	struct hisi_djtag_client *client;
+	int rc;
+
+	client = hisi_djtag_verify_client(dev);
+	if (!client) {
+		dev_err(dev, "could not find client\n");
+		return -ENODEV;
+	}
+
+	driver = to_hisi_djtag_driver(dev->driver);
+	if (!driver) {
+		dev_err(dev, "could not find driver\n");
+		return -ENODEV;
+	}
+
+	rc = driver->remove(client);
+	if (rc < 0) {
+		dev_err(dev, "client probe failed\n");
+		return rc;
+	}
+
+	return 0;
+}
+
+static int hisi_djtag_device_match(struct device *dev,
+					struct device_driver *drv)
+{
+	const struct of_device_id *p;
+	struct hisi_djtag_client *client = hisi_djtag_verify_client(dev);
+
+	if (!client)
+		return false;
+
+	if (of_driver_match_device(dev, drv))
+		return true;
+
+	p = of_match_device(drv->of_match_table, dev);
+	if (!p)
+		return false;
+
+	return true;
+}
+
+struct bus_type hisi_djtag_bus = {
+	.name		= "hisi-djtag",
+	.match		= hisi_djtag_device_match,
+	.probe		= hisi_djtag_device_probe,
+	.remove		= hisi_djtag_device_remove,
+};
+
+struct hisi_djtag_client *hisi_djtag_new_device(struct hisi_djtag_host *host,
+						struct device_node *node)
+{
+	struct hisi_djtag_client *client;
+	int status;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (!client)
+		return NULL;
+
+	client->host = host;
+
+	client->dev.parent = &client->host->dev;
+	client->dev.bus = &hisi_djtag_bus;
+	client->dev.type = &hisi_djtag_client_type;
+	client->dev.of_node = node;
+	snprintf(client->name, DJTAG_CLIENT_NAME_LEN, "%s%s",
+					DJTAG_PREFIX, node->name);
+	dev_set_name(&client->dev, "%s", client->name);
+
+	status = device_register(&client->dev);
+	if (status < 0) {
+		pr_err("error adding new device, status=%d\n", status);
+		kfree(client);
+		return NULL;
+	}
+
+	return client;
+}
+
+static struct hisi_djtag_client *hisi_djtag_of_register_device(
+						struct hisi_djtag_host *host,
+						struct device_node *node)
+{
+	struct hisi_djtag_client *client;
+
+	client = hisi_djtag_new_device(host, node);
+	if (client == NULL) {
+		dev_err(&host->dev, "error registering device %s\n",
+			node->full_name);
+		of_node_put(node);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return client;
+}
+
+static void djtag_register_devices(struct hisi_djtag_host *host)
+{
+	struct device_node *node;
+	struct hisi_djtag_client *client;
+
+	if (!host->of_node)
+		return;
+
+	for_each_available_child_of_node(host->of_node, node) {
+		if (of_node_test_and_set_flag(node, OF_POPULATED))
+			continue;
+		client = hisi_djtag_of_register_device(host, node);
+		list_add(&client->next, &host->client_list);
+	}
+}
+
+static int hisi_djtag_add_host(struct hisi_djtag_host *host)
+{
+	int rc;
+
+	host->dev.bus = &hisi_djtag_bus;
+
+	rc = idr_alloc(&djtag_hosts_idr, host, 0, 0, GFP_KERNEL);
+	if (rc < 0) {
+		dev_err(&host->dev, "No available djtag host ID'!s\n");
+		return rc;
+	}
+	host->id = rc;
+
+	/* Suffix the unique ID and set djtag hostname */
+	dev_set_name(&host->dev, "djtag-host-%d", host->id);
+
+	rc = device_register(&host->dev);
+	if (rc < 0) {
+		dev_err(&host->dev, "add_host dev register failed, rc=%d\n",
+									rc);
+		idr_remove(&djtag_hosts_idr, host->id);
+		return rc;
+	}
+
+	djtag_register_devices(host);
+
+	return 0;
+}
+
+static int djtag_host_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct hisi_djtag_host *host;
+	const struct of_device_id *of_id;
+	struct resource *res;
+	int rc;
+
+	of_id = of_match_device(djtag_of_match, dev);
+	if (!of_id)
+		return -EINVAL;
+
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENOMEM;
+
+	host->of_node = dev->of_node;
+	host->djtag_readwrite = of_id->data;
+	spin_lock_init(&host->lock);
+
+	INIT_LIST_HEAD(&host->client_list);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "No reg resorces!\n");
+		kfree(host);
+		return -EINVAL;
+	}
+
+	if (!resource_size(res)) {
+		dev_err(&pdev->dev, "Zero reg entry!\n");
+		kfree(host);
+		return -EINVAL;
+	}
+
+	host->sysctl_reg_map = devm_ioremap_resource(dev, res);
+	if (IS_ERR(host->sysctl_reg_map)) {
+		dev_warn(dev, "Unable to map sysctl registers.\n");
+		kfree(host);
+		return -EINVAL;
+	}
+
+	platform_set_drvdata(pdev, host);
+
+	rc = hisi_djtag_add_host(host);
+	if (rc) {
+		dev_err(dev, "add host failed, rc=%d\n", rc);
+		kfree(host);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int djtag_host_remove(struct platform_device *pdev)
+{
+	struct hisi_djtag_host *host;
+	struct hisi_djtag_client *client, *tmp;
+	struct list_head *client_list;
+
+	host = platform_get_drvdata(pdev);
+	client_list = &host->client_list;
+
+	list_for_each_entry_safe(client, tmp, client_list, next) {
+		list_del(&client->next);
+		kfree(client);
+	}
+
+	device_unregister(&host->dev);
+	idr_remove(&djtag_hosts_idr, host->id);
+	kfree(host);
+
+	return 0;
+}
+
+static struct platform_driver djtag_dev_driver = {
+	.driver = {
+		.name = "hisi-djtag",
+		.of_match_table = djtag_of_match,
+	},
+	.probe = djtag_host_probe,
+	.remove = djtag_host_remove,
+};
+module_platform_driver(djtag_dev_driver);
+
+int hisi_djtag_register_driver(struct module *owner,
+				struct hisi_djtag_driver *driver)
+{
+	int rc;
+
+	driver->driver.owner = owner;
+	driver->driver.bus = &hisi_djtag_bus;
+
+	rc = driver_register(&driver->driver);
+	if (rc < 0)
+		pr_err("%s register failed, rc=%d\n", __func__, rc);
+
+	return rc;
+}
+
+void hisi_djtag_unregister_driver(struct hisi_djtag_driver *driver)
+{
+	driver->driver.bus = &hisi_djtag_bus;
+	driver_unregister(&driver->driver);
+}
+
+static int __init hisi_djtag_init(void)
+{
+	int rc;
+
+	rc = bus_register(&hisi_djtag_bus);
+	if (rc) {
+		pr_err("hisi  djtag init failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+module_init(hisi_djtag_init);
+
+static void __exit hisi_djtag_exit(void)
+{
+	bus_unregister(&hisi_djtag_bus);
+}
+module_exit(hisi_djtag_exit);
+
+MODULE_DESCRIPTION("Hisilicon djtag driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
diff --git a/include/linux/soc/hisilicon/djtag.h b/include/linux/soc/hisilicon/djtag.h
new file mode 100644
index 0000000..aae3bca
--- /dev/null
+++ b/include/linux/soc/hisilicon/djtag.h
@@ -0,0 +1,38 @@
+/*
+ * Driver for Hisilicon djtag r/w via System Controller.
+ *
+ * Copyright (C) 2016-2017 Hisilicon Ltd.
+ *
+ * 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.
+ */
+
+#ifndef __HISI_DJTAG_H
+#define __HISI_DJTAG_H
+
+#define DJTAG_CLIENT_NAME_LEN 24
+
+struct hisi_djtag_client {
+	struct hisi_djtag_host *host;
+	struct list_head next;
+	char name[DJTAG_CLIENT_NAME_LEN];
+	struct device dev;
+};
+
+struct hisi_djtag_driver {
+	struct device_driver driver;
+	int (*probe)(struct hisi_djtag_client *);
+	int (*remove)(struct hisi_djtag_client *);
+};
+
+extern struct bus_type hisi_djtag_bus;
+
+int hisi_djtag_register_driver(struct module *owner,
+				struct hisi_djtag_driver *driver);
+void hisi_djtag_unregister_driver(struct hisi_djtag_driver *driver);
+int hisi_djtag_readl(struct hisi_djtag_client *client, u32 offset,
+					u32 mod_sel, int chain_id, u32 *val);
+int hisi_djtag_writel(struct hisi_djtag_client *client, u32 offset,
+					u32 mod_sel, u32 mod_mask, u32 val);
+#endif /* __HISI_DJTAG_H */
-- 
2.1.4

^ permalink raw reply related

* [RESEND PATCH v1 04/11] Documentation: perf: hisi: Documentation for HIP05/06/07 PMU event counting.
From: Anurup M @ 2016-11-03  5:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478151727-20250-1-git-send-email-anurup.m@huawei.com>

	Documentation for perf usage and Hisilicon SoC PMU uncore events.
	The Hisilicon SOC has event counters for hardware modules like
	L3 cache, Miscellaneous node, DDR cntroller etc. These events are
	all uncore.

Signed-off-by: Anurup M <anurup.m@huawei.com>
Signed-off-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
---
 Documentation/perf/hisi-pmu.txt | 80 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
 create mode 100644 Documentation/perf/hisi-pmu.txt

diff --git a/Documentation/perf/hisi-pmu.txt b/Documentation/perf/hisi-pmu.txt
new file mode 100644
index 0000000..670a9df
--- /dev/null
+++ b/Documentation/perf/hisi-pmu.txt
@@ -0,0 +1,80 @@
+Hisilicon SoC PMU (Performance Monitoring Unit)
+================================================
+The Hisilicon SoC hip05/06/07 chips consist of varous independent system
+device PMU's such as L3 cache(L3C), Miscellaneous Nodes(MN) and DDR
+controllers. These PMU devices are independent and have hardware logic to
+gather statistics and performance information.
+
+Hip0x chips are encapsulated by multiple CPU and IO die's. The CPU die is
+called as Super CPU cluster (SCCL) which includes 16 cpu-cores. Every SCCL
+is further grouped as CPU clusters (CCL) which includes 4 cpu-cores each.
+Each SCCL has 1 L3 cache and 1 MN units.
+
+The L3 cache is shared by all CPU cores in a CPU die. The L3C has four banks
+(or instances). Each bank or instance of L3C has Eight 32-bit counter
+registers. The hip05/06 chip L3 cache has 22 statistics events. The hip07
+chip has 66 statistics events. These events are very useful for debugging.
+
+The MN module is also shared by all CPU cores in a CPU die. It receives
+barriers and DVM(Distributed Virtual Memory) messages from cpu or smmu, and
+perform the required actions and return response messages. These events are
+very useful for debugging. The MN has total 9 statistics events and support
+four 32-bit counter registers in hip05/06/07 chips.
+
+The DDR conroller supports various statistics events. Every SCCL has fot 2
+DDR channels and hence 2 DDR controllers. The Hip05/06/07 has support for a
+total of 13 statistics events.
+
+There is no memory mapping for L3 cache and MN registers. It can be accessed
+by using the Hisilicon djtag interface. The Djtag in a SCCL is an independent
+module which connects with some modules in the SoC by Debug Bus.
+
+Hisilicon SoC (hip05/06/07) PMU driver
+--------------------------------------
+The hip0x PMU driver shall register perf PMU drivers like L3 cache, MN, DDRC
+etc.
+Separate PMU shall be registered for L3 cache and MN for each Super CPU
+cluster.
+For DRR controller separate PMU shall be registered for each channel in a
+Super CPU cluster.
+
+The available events and configuration options shall be described in the sysfs.
+The "perf list" shall list the available events from sysfs.
+eg. hisi_l3c2/read_allocate/ [kernel PMU event]
+
+The Super Cluster ID will be the number suffix to PMU name
+e.g. hisi_l3c2. Here Super cluster ID is 2 and so hisi_l3c2/read_allocate
+is the event for read_allocate of SCCL #2.
+
+For DDRC the channel number will be suffix at the end.
+eg: hisi_ddrc2_0/flux_read/. Here Super cluster ID is 2 and the channel number
+is 0 for the event flux_read.
+
+The event code is represented by 12 bits.
+	i) event 0-11
+		The event code will be represented using the LSB 12 bits.
+
+The driver also provides a "cpumask" sysfs attribute, which shows the CPU core
+ID used to count the uncore PMU event.
+
+Example usage of perf:
+$# perf list
+hisi_l3c2/read_hit/ [kernel PMU event]
+hisi_l3c2/write_hit/ [kernel PMU event]
+------------------------------------------
+hisi_l3c1/read_hit/ [kernel PMU event]
+hisi_l3c1/write_hit/ [kernel PMU event]
+------------------------------------------
+hisi_mn2/read_req/ [kernel PMU event]
+hisi_mn2/write_req/ [kernel PMU event]
+------------------------------------------
+hisi_ddrc2_0/flux_read/ [kernel PMU event]
+------------------------------------------
+
+$# perf stat -a -e hisi_l3c2/read_allocate/ sleep 5
+
+The current driver doesnot support sampling. so "perf record" is unsupported.
+Also attach to a task is unsupported as the events are all uncore.
+
+Note: Please contact the maintainer for a complete list of events supported for
+the PMU devices in the SoC and its information if needed.
-- 
2.1.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox