Bruce,

I am going to resubmit this group of patches less any patch that has to do with 
RIO. This was requested by our customer. This should remove any patches that 
don't have the required comments in the headers. The other patches are all 
updated as per your comments.

Charlie

-----Original Message-----
From: Bruce Ashfield [mailto:bruce.ashfi...@windriver.com] 
Sent: Monday, March 24, 2014 6:09 AM
To: Svennebring, Jonas; Charlie Paul; linux-yocto@yoctoproject.org
Cc: Paul, Charlie
Subject: Re: [PATCH 47/57] Basic perf support for axxia plaform block provided 
by LSI.

On 14-03-24 07:24 AM, Svennebring, Jonas wrote:
> Hi,
>
> The basic support includes:
> * Generic AXXIA SMON (Statistic Monitor) functionality.
>
> * Support for Memory Controllers:
>    - DDRC, DDR Controllers.
>    - ELM, Encryption Memory Controllers .
>
> *Preparation for support of:
>    - PCX, integrated Ethernet switch.
>    - VP, virtual pipeline packet processing engines.
>
> Documentation, VP/PCX support as well as patch alignment with coming ARM L3$ 
> and interconnect is in the workings.
>

Looks good. Thanks for the summary.

Charlie: can we capture this in the log ?

Bruce

> Best Regards,
>
> //Jonas
>
> -----Original Message-----
> From: Bruce Ashfield [mailto:bruce.ashfi...@windriver.com]
> Sent: den 20 mars 2014 09:44
> To: Charlie Paul; linux-yocto@yoctoproject.org
> Cc: charlie.p...@windriver.com; Svennebring, Jonas
> Subject: Re: [PATCH 47/57] Basic perf support for axxia plaform block 
> provided by LSI.
>
> Can we get a short feature listing of what is included in the basic support ?
>
> A summary here is fine, and perhaps a README or other perf documentation 
> update as well.
>
> Bruce
>
> On 14-03-18 12:56 AM, Charlie Paul wrote:
>> From: Jonas Svennebring <jonas.svennebr...@lsi.com>
>>
>> Signed-off-by: Jonas Svennebring <jonas.svennebr...@lsi.com>
>> ---
>>    arch/arm/mach-axxia/perf_event_memc.c     |  130 ++++++++++++++
>>    arch/arm/mach-axxia/perf_event_memc.h     |   62 +++++++
>>    arch/arm/mach-axxia/perf_event_pcx.c      |   46 +++++
>>    arch/arm/mach-axxia/perf_event_platform.c |  270 
>> +++++++++++++++++++++++++++++
>>    arch/arm/mach-axxia/perf_event_platform.h |   10 ++
>>    arch/arm/mach-axxia/perf_event_vp.c       |   51 ++++++
>>    arch/arm/mach-axxia/smon.c                |  200 +++++++++++++++++++++
>>    arch/arm/mach-axxia/smon.h                |   71 ++++++++
>>    8 files changed, 840 insertions(+)
>>    create mode 100644 arch/arm/mach-axxia/perf_event_memc.c
>>    create mode 100644 arch/arm/mach-axxia/perf_event_memc.h
>>    create mode 100644 arch/arm/mach-axxia/perf_event_pcx.c
>>    create mode 100644 arch/arm/mach-axxia/perf_event_platform.c
>>    create mode 100644 arch/arm/mach-axxia/perf_event_platform.h
>>    create mode 100644 arch/arm/mach-axxia/perf_event_vp.c
>>    create mode 100644 arch/arm/mach-axxia/smon.c
>>    create mode 100644 arch/arm/mach-axxia/smon.h
>>
>> diff --git a/arch/arm/mach-axxia/perf_event_memc.c
>> b/arch/arm/mach-axxia/perf_event_memc.c
>> new file mode 100644
>> index 0000000..a20fc8a
>> --- /dev/null
>> +++ b/arch/arm/mach-axxia/perf_event_memc.c
>> @@ -0,0 +1,130 @@
>> +/*
>> + * arch/arm/mach-axxia/perf_event_memc.c
>> + * included from arch/arm/mach-axxia/perf_event_platform.c
>> + *
>> + * Support for the LSI Axxia boards based on ARM cores.
>> + *
>> + * Copyright (C) 2014 LSI
>> + *
>> + * This program is free software; you can redistribute it and/or 
>> +modify
>> + * it under the terms of the GNU General Public License as published 
>> +by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>> +02111-1307  USA  */
>> +
>> +#include "perf_event_memc.h"
>> +
>> +static void memc_startup_init(void)
>> +{
>> +    smon_init_ncp(&ddrc0_smon, DDRC0, DDRC_PERF, DDRC_SMON);
>> +    smon_init_ncp(&ddrc1_smon, DDRC1, DDRC_PERF, DDRC_SMON);
>> +    smon_init_mem(&elm0_smon, ELM0, ELM_SMON);
>> +    smon_init_mem(&elm1_smon, ELM1, ELM_SMON); }
>> +
>> +static uint32_t memc_pmu_event_init(uint32_t event, struct 
>> +perf_event
>> +*pevent) {
>> +    return 0;
>> +}
>> +
>> +static void memc_pmu_event_destroy(uint32_t event, struct perf_event
>> +*pevent) {
>> +    smon_stop_if_unassigned(&ddrc0_smon);
>> +    smon_stop_if_unassigned(&ddrc1_smon);
>> +    smon_stop_if_unassigned(&elm0_smon);
>> +    smon_stop_if_unassigned(&elm1_smon);
>> +}
>> +
>> +static uint32_t memc_pmu_event_add(uint32_t ev, struct perf_event
>> +*pevent) {
>> +    uint32_t ret;
>> +
>> +    if (ev >= DDRC0_OFFSET && ev <= DDRC0_SMON_MAX) {
>> +
>> +            ret = smon_allocate(&ddrc0_smon, ev - DDRC0_OFFSET);
>> +            if (ret != 0)
>> +                    return ret;
>> +
>> +            ret = smon_start(&ddrc0_smon, ev - DDRC0_OFFSET);
>> +            if (ret != 0)
>> +                    return ret;
>> +    } else if (ev >= DDRC1_OFFSET && ev <= DDRC1_SMON_MAX) {
>> +
>> +            ret = smon_allocate(&ddrc1_smon, ev - DDRC1_OFFSET);
>> +            if (ret != 0)
>> +                    return ret;
>> +
>> +            ret = smon_start(&ddrc1_smon, ev - DDRC1_OFFSET);
>> +            if (ret != 0)
>> +                    return ret;
>> +    } else if (ev >= ELM0_OFFSET && ev <= ELM0_SMON_MAX) {
>> +
>> +            ret = smon_allocate(&elm0_smon, ev - ELM0_OFFSET);
>> +            if (ret != 0)
>> +                    return ret;
>> +
>> +            ret = smon_start(&elm0_smon, ev - ELM0_OFFSET);
>> +            if (ret != 0)
>> +                    return ret;
>> +    } else if (ev >= ELM1_OFFSET && ev <= ELM1_SMON_MAX) {
>> +
>> +            ret = smon_allocate(&elm1_smon, ev - ELM1_OFFSET);
>> +            if (ret != 0)
>> +                    return ret;
>> +
>> +            ret = smon_start(&elm1_smon, ev - ELM1_OFFSET);
>> +            if (ret != 0)
>> +                    return ret;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +/*
>> + * Remove event and return counter update.
>> + */
>> +static uint32_t memc_pmu_event_del(uint32_t ev, struct perf_event *pevent,
>> +            int flags)
>> +{
>> +    uint32_t count = 0;
>> +
>> +    if (ev >= DDRC0_OFFSET && ev <= DDRC0_SMON_MAX) {
>> +
>> +            count = smon_read(&ddrc0_smon, ev - DDRC0_OFFSET);
>> +            if (count == -ENOEVENT)
>> +                    count = 0;
>> +
>> +            smon_deallocate(&ddrc0_smon, ev - DDRC0_OFFSET);
>> +    } else if (ev >= DDRC1_OFFSET && ev <= DDRC1_SMON_MAX) {
>> +
>> +            count = smon_read(&ddrc1_smon, ev - DDRC1_OFFSET);
>> +            if (count == -ENOEVENT)
>> +                    count = 0;
>> +
>> +            smon_deallocate(&ddrc1_smon, ev - DDRC1_OFFSET);
>> +    } else if (ev >= ELM0_OFFSET && ev <= ELM0_SMON_MAX) {
>> +            count = smon_read(&elm0_smon, ev - ELM0_OFFSET);
>> +            if (count == -ENOEVENT)
>> +                    count = 0;
>> +
>> +            smon_deallocate(&elm0_smon, ev - ELM0_OFFSET);
>> +    } else if (ev >= ELM1_OFFSET && ev <= ELM1_SMON_MAX) {
>> +
>> +            count = smon_read(&elm1_smon, ev - ELM1_OFFSET);
>> +            if (count == -ENOEVENT)
>> +                    count = 0;
>> +
>> +            smon_deallocate(&elm1_smon, ev - ELM1_OFFSET);
>> +    }
>> +
>> +    return count;
>> +}
>> diff --git a/arch/arm/mach-axxia/perf_event_memc.h
>> b/arch/arm/mach-axxia/perf_event_memc.h
>> new file mode 100644
>> index 0000000..e4a4f7d
>> --- /dev/null
>> +++ b/arch/arm/mach-axxia/perf_event_memc.h
>> @@ -0,0 +1,62 @@
>> +/*
>> + * arch/arm/mach-axxia/perf_event_memc.h
>> + * included from arch/arm/mach-axxia/perf_event_memc.c
>> + *
>> + * Support for the LSI Axxia boards based on ARM cores.
>> + *
>> + * Copyright (C) 2014 LSI
>> + *
>> + * This program is free software; you can redistribute it and/or 
>> +modify
>> + * it under the terms of the GNU General Public License as published 
>> +by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>> +02111-1307  USA  */
>> +
>> +#ifndef __ASM__ARCH_AXXIA_PERF_EVENT_MEMC_H
>> +#define __ASM__ARCH_AXXIA_PERF_EVENT_MEMC_H
>> +
>> +#define DDRC0_OFFSET 0x00
>> +#define DDRC0_SMON_MAX (DDRC0_OFFSET + 22) #define DDRC1_OFFSET 
>> +0x100 #define DDRC1_SMON_MAX (DDRC1_OFFSET + 22)
>> +
>> +#define ELM0_OFFSET 0x200
>> +#define ELM0_SMON_MAX (ELM0_OFFSET + 15) #define ELM1_OFFSET 0x300 
>> +#define ELM1_SMON_MAX (ELM1_OFFSET + 15)
>> +
>> +/* Node */
>> +#define DDRC0 0x0f
>> +#define DDRC1 0x22
>> +/* Target */
>> +#define DDRC_PERF 0x02
>> +
>> +/* Address */
>> +#ifdef AXM55XX_R1
>> +#define DDRC_SMON 0x40
>> +#endif
>> +#ifdef AXM55XX_R2
>> +#define DDRC_SMON 0xA0
>> +#endif
>> +
>> +/* Base Address */
>> +#define ELM0 0x2010060000
>> +#define ELM1 0x2010070000
>> +/* SMON Offset */
>> +#define ELM_SMON (0x300/4)
>> +
>> +struct smon_s ddrc0_smon;
>> +struct smon_s ddrc1_smon;
>> +struct smon_s elm0_smon;
>> +struct smon_s elm1_smon;
>> +
>> +#endif
>> diff --git a/arch/arm/mach-axxia/perf_event_pcx.c
>> b/arch/arm/mach-axxia/perf_event_pcx.c
>> new file mode 100644
>> index 0000000..a419c67
>> --- /dev/null
>> +++ b/arch/arm/mach-axxia/perf_event_pcx.c
>> @@ -0,0 +1,46 @@
>> +/*
>> + * arch/arm/mach-axxia/perf_event_pcx.c
>> + * included from arch/arm/mach-axxia/perf_event_platform.c
>> + *
>> + * Support for the LSI Axxia boards based on ARM cores.
>> + *
>> + * Copyright (C) 2014 LSI
>> + *
>> + * This program is free software; you can redistribute it and/or 
>> +modify
>> + * it under the terms of the GNU General Public License as published 
>> +by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>> +02111-1307  USA  */
>> +
>> +/*
>> + * Generic PCX
>> + */
>> +
>> +static void pcx_startup_init(void)
>> +{
>> +}
>> +
>> +static uint32_t pcx_pmu_event_init(uint32_t ev, struct perf_event
>> +*event) {
>> +    return 0;
>> +}
>> +
>> +static uint32_t pcx_pmu_event_add(uint32_t ev, struct perf_event
>> +*event) {
>> +    return 0;
>> +}
>> +
>> +static uint32_t pcx_pmu_event_del(uint32_t ev, struct perf_event *event,
>> +            int flags)
>> +{
>> +    return 0;
>> +}
>> diff --git a/arch/arm/mach-axxia/perf_event_platform.c
>> b/arch/arm/mach-axxia/perf_event_platform.c
>> new file mode 100644
>> index 0000000..83a221d
>> --- /dev/null
>> +++ b/arch/arm/mach-axxia/perf_event_platform.c
>> @@ -0,0 +1,270 @@
>> +/*
>> + * arch/arm/mach-axxia/perf_event_platform.c
>> + *
>> + * Support for the LSI Axxia boards based on ARM cores.
>> + *
>> + * Copyright (C) 2014 LSI
>> + *
>> + * This program is free software; you can redistribute it and/or 
>> +modify
>> + * it under the terms of the GNU General Public License as published 
>> +by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>> +02111-1307  USA  */
>> +
>> +#include <linux/init.h>
>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <linux/platform_device.h>
>> +
>> +#include <linux/bitmap.h>
>> +#include <linux/cpu_pm.h>
>> +#include <linux/export.h>
>> +#include <linux/of.h>
>> +#include <linux/slab.h>
>> +#include <linux/spinlock.h>
>> +
>> +#include <asm/cputype.h>
>> +#include <asm/irq_regs.h>
>> +#include <asm/pmu.h>
>> +
>> +#include <linux/kthread.h>
>> +#include <linux/sched.h>
>> +
>> +#include <linux/cpu.h>
>> +#include <linux/reboot.h>
>> +#include <linux/syscore_ops.h>
>> +
>> +#include <linux/proc_fs.h>
>> +
>> +#include <linux/io.h>
>> +#include <asm/cacheflush.h>
>> +#include <../../../drivers/misc/lsi-ncr.h>
>> +
>> +#include "perf_event_platform.h"
>> +
>> +#include "smon.h"
>> +
>> +/*
>> + * Include code for individual block support  */
>> +
>> +#include "perf_event_pcx.c"
>> +#include "perf_event_vp.c"
>> +#include "perf_event_memc.c"
>> +
>> +/*
>> + * General platform perf code, muxed out to individual blocks  */
>> +
>> +int platform_pmu_event_idx(struct perf_event *event) {
>> +    return 0;
>> +}
>> +
>> +int platform_pmu_event_init(struct perf_event *event) {
>> +    uint64_t ev = event->attr.config;
>> +
>> +    if (event->attr.type != event->pmu->type)
>> +            return -ENOENT;
>> +
>> +    if ((ev < AXM_55XX_PLATFORM_BASE) || (ev > AXM_55XX_PLATFORM_MAX))
>> +            return -ENOENT;
>> +
>> +    event->hw.config = ev - AXM_55XX_PLATFORM_BASE;
>> +
>> +    event->hw.idx = -1;
>> +    event->hw.config_base = 1;
>> +
>> +/*
>> + if (event->group_leader != event) {
>> +  printk("This is not the group leader!\n");
>> +  printk("event->group_leader 0x%x\n", (unsigned 
>> +int)event->group_leader);  } */
>> +
>> +    if (event->attr.exclude_user)
>> +            return -ENOTSUPP;
>> +    if (event->attr.exclude_kernel)
>> +            return -ENOTSUPP;
>> +    if (event->attr.exclude_idle)
>> +            return -ENOTSUPP;
>> +
>> +    event->hw.last_period = event->hw.sample_period;
>> +    local64_set(&event->hw.period_left, event->hw.last_period);
>> +/*
>> + event->destroy = hw_perf_event_destroy;
>> +*/
>> +    local64_set(&event->count, 0);
>> +
>> +    if (ev >= AXM_55XX_VP_BASE && ev <= AXM_55XX_VP_MAX)
>> +            vp_pmu_event_init(ev - AXM_55XX_VP_BASE, event);
>> +    else if (ev >= AXM_55XX_PCX_BASE && ev <= AXM_55XX_PCX_MAX)
>> +            pcx_pmu_event_init(ev - AXM_55XX_PCX_BASE, event);
>> +    else if (ev >= AXM_55XX_MEMC_BASE && ev <= AXM_55XX_MEMC_MAX)
>> +            memc_pmu_event_init(ev - AXM_55XX_MEMC_BASE, event);
>> +    else
>> +            pr_info("Platform perf, undefined event, %llu\n", ev);
>> +
>> +    return 0;
>> +}
>> +
>> +static int platform_pmu_event_add(struct perf_event *event, int
>> +flags) {
>> +    uint64_t ev = event->attr.config;
>> +
>> +    if (ev >= AXM_55XX_VP_BASE && ev <= AXM_55XX_VP_MAX)
>> +            vp_pmu_event_add(ev - AXM_55XX_VP_BASE, event);
>> +    else if (ev >= AXM_55XX_PCX_BASE && ev <= AXM_55XX_PCX_MAX)
>> +            pcx_pmu_event_add(ev - AXM_55XX_PCX_BASE, event);
>> +    else if (ev >= AXM_55XX_MEMC_BASE && ev <= AXM_55XX_MEMC_MAX)
>> +            memc_pmu_event_add(ev - AXM_55XX_MEMC_BASE, event);
>> +
>> +    return 0;
>> +}
>> +
>> +static void platform_pmu_event_del(struct perf_event *event, int
>> +flags) {
>> +    uint64_t ev = event->attr.config;
>> +    uint32_t n;
>> +
>> +    if (ev >= AXM_55XX_VP_BASE && ev <= AXM_55XX_VP_MAX) {
>> +            n = vp_pmu_event_del(ev - AXM_55XX_VP_BASE, event, flags);
>> +            local64_add(n, &event->count);
>> +    } else if (ev >= AXM_55XX_PCX_BASE && ev <= AXM_55XX_PCX_MAX) {
>> +            n = pcx_pmu_event_del(ev - AXM_55XX_PCX_BASE, event, flags);
>> +            local64_add(n, &event->count);
>> +    } else if (ev >= AXM_55XX_MEMC_BASE && ev <= AXM_55XX_MEMC_MAX) {
>> +            n = memc_pmu_event_del(ev - AXM_55XX_MEMC_BASE, event, flags);
>> +            local64_add(n, &event->count);
>> +    } else {
>> +            local64_set(&event->count, 0);
>> +    }
>> +}
>> +
>> +static void platform_pmu_event_start(struct perf_event *event, int
>> +flags) { }
>> +
>> +static void platform_pmu_event_stop(struct perf_event *event, int
>> +flags) { }
>> +
>> +static void platform_pmu_event_read(struct perf_event *event) {
>> +    uint64_t ev = event->attr.config;
>> +    uint32_t n;
>> +
>> +    if (ev >= AXM_55XX_VP_BASE && ev <= AXM_55XX_VP_MAX) {
>> +            n = vp_pmu_event_del(ev - AXM_55XX_VP_BASE, event, 0);
>> +            local64_add(n, &event->count);
>> +    } else if (ev >= AXM_55XX_PCX_BASE && ev <= AXM_55XX_PCX_MAX) {
>> +            n = pcx_pmu_event_del(ev - AXM_55XX_PCX_BASE, event, 0);
>> +            local64_add(n, &event->count);
>> +    } else if (ev >= AXM_55XX_MEMC_BASE && ev <= AXM_55XX_MEMC_MAX) {
>> +            n = memc_pmu_event_del(ev - AXM_55XX_MEMC_BASE, event, 0);
>> +            local64_add(n, &event->count);
>> +    }
>> +}
>> +
>> +/*
>> + * Device
>> + */
>> +
>> +static void axmperf_device_release(struct device *dev) {
>> +    pr_warn("AXM55xxPlatformPerf release device\n"); }
>> +
>> +static struct platform_device axmperf_device = {
>> +    .name = "AXM55xxPlatformPerf",
>> +    .id = 0,
>> +    .dev = {
>> +            .release = axmperf_device_release,
>> +            },
>> +};
>> +
>> +/*
>> + * Driver
>> + */
>> +
>> +#define PLATFORM_PMU_NAME_LEN 32
>> +
>> +struct lsi_platform_pmu {
>> +    struct pmu pmu;
>> +    char name[PLATFORM_PMU_NAME_LEN];
>> +};
>> +
>> +static int axmperf_probe(struct platform_device *dev) {
>> +    int ret;
>> +    struct lsi_platform_pmu *axm_pmu;
>> +
>> +    axm_pmu = kzalloc(sizeof(struct lsi_platform_pmu), GFP_KERNEL);
>> +    if (!axm_pmu) {
>> +            pr_warn("Failed platform perf memory alloc!\n");
>> +            return -ENOMEM;
>> +    }
>> +
>> +    axm_pmu->pmu = (struct pmu) {
>> +            .attr_groups = 0,
>> +            .event_init = platform_pmu_event_init,
>> +            .add = platform_pmu_event_add,
>> +            .del = platform_pmu_event_del,
>> +            .start = platform_pmu_event_start,
>> +            .stop = platform_pmu_event_stop,
>> +            .read = platform_pmu_event_read,
>> +            .event_idx = platform_pmu_event_idx,
>> +    };
>> +
>> +    sprintf(axm_pmu->name, "LSI AXM55xx Platform");
>> +
>> +    ret = perf_pmu_register(&axm_pmu->pmu, axm_pmu->name, 
>> +PERF_TYPE_RAW);
>> +
>> +    if (ret == 0)
>> +            pr_info("axxia platform perf enabled\n");
>> +    else
>> +            pr_info("axxia platform perf failed\n");
>> +
>> +    vp_startup_init();
>> +    pcx_startup_init();
>> +    memc_startup_init();
>> +
>> +    return ret;
>> +}
>> +
>> +static struct platform_driver axmperf_driver = {
>> +    .driver = {
>> +               .name = "AXM55xxPlatformPerf",
>> +               .owner = THIS_MODULE,
>> +               },
>> +    .probe = axmperf_probe,
>> +};
>> +
>> +static int __init axmperf_init(void) {
>> +    platform_device_register(&axmperf_device);
>> +    platform_driver_register(&axmperf_driver);
>> +
>> +    return 0;
>> +}
>> +
>> +static void __exit axmperf_exit(void) {
>> +    pr_warn("AXM55xx platform perf exit!\n");
>> +    platform_driver_unregister(&axmperf_driver);
>> +    platform_device_unregister(&axmperf_device);
>> +}
>> +
>> +module_init(axmperf_init);
>> +module_exit(axmperf_exit);
>> +MODULE_LICENSE("GPL");
>> diff --git a/arch/arm/mach-axxia/perf_event_platform.h
>> b/arch/arm/mach-axxia/perf_event_platform.h
>> new file mode 100644
>> index 0000000..5446855
>> --- /dev/null
>> +++ b/arch/arm/mach-axxia/perf_event_platform.h
>> @@ -0,0 +1,10 @@
>> + #define AXM55XX_R1
>> +
>> +#define AXM_55XX_PLATFORM_BASE 0x10000 #define AXM_55XX_VP_BASE 
>> +(AXM_55XX_PLATFORM_BASE + 0x00) #define AXM_55XX_VP_MAX 
>> +(AXM_55XX_VP_BASE + 0x1fff) #define AXM_55XX_PCX_BASE 
>> +(AXM_55XX_PLATFORM_BASE + 0x4000) #define AXM_55XX_PCX_MAX 
>> +(AXM_55XX_PCX_BASE + 0x0fff) #define AXM_55XX_MEMC_BASE 
>> +(AXM_55XX_PLATFORM_BASE + 0x8000) #define AXM_55XX_MEMC_MAX 
>> +(AXM_55XX_MEMC_BASE + 0x0fff) #define AXM_55XX_PLATFORM_MAX
>> +(AXM_55XX_MEMC_MAX)
>> diff --git a/arch/arm/mach-axxia/perf_event_vp.c
>> b/arch/arm/mach-axxia/perf_event_vp.c
>> new file mode 100644
>> index 0000000..3993f24
>> --- /dev/null
>> +++ b/arch/arm/mach-axxia/perf_event_vp.c
>> @@ -0,0 +1,51 @@
>> +/*
>> + * arch/arm/mach-axxia/perf_event_vp.c
>> + * included from arch/arm/mach-axxia/perf_event_platform.c
>> + *
>> + * Support for the LSI Axxia boards based on ARM cores.
>> + *
>> + * Copyright (C) 2014 LSI
>> + *
>> + * This program is free software; you can redistribute it and/or 
>> +modify
>> + * it under the terms of the GNU General Public License as published 
>> +by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>> +02111-1307  USA  */
>> +
>> +
>> +/*
>> + * Generic VP
>> + */
>> +
>> +static void vp_startup_init(void)
>> +{
>> +}
>> +
>> +static uint32_t vp_pmu_event_init(uint32_t event, struct perf_event
>> +*pevent) {
>> +    return 0;
>> +}
>> +
>> +static uint32_t vp_pmu_event_add(uint32_t event, struct perf_event
>> +*pevent) {
>> +    return 0;
>> +}
>> +
>> +static uint32_t vp_pmu_event_del(uint32_t event, struct perf_event *pevent,
>> +            int flags)
>> +{
>> +    return 0;
>> +}
>> +
>> +static void vp_pmu_event_destroy(uint32_t event, struct perf_event
>> +*pevent) { }
>> diff --git a/arch/arm/mach-axxia/smon.c b/arch/arm/mach-axxia/smon.c 
>> new file mode 100644 index 0000000..b2f0a56
>> --- /dev/null
>> +++ b/arch/arm/mach-axxia/smon.c
>> @@ -0,0 +1,200 @@
>> +/*
>> + * linux/arch/arm/mach-axxia/smon.c
>> + *
>> + * Platform perf helper module for generic VP statistical monitor
>> + *
>> + * Copyright (C) 2013 LSI Corporation.
>> + *
>> + * 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.
>> + *
>> + * This program is distributed in the hope that it will be useful, 
>> +but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
>> + * 02110-1301 USA
>> + *
>> + */
>> +#include <linux/io.h>
>> +
>> +#include <../../../drivers/misc/lsi-ncr.h>
>> +
>> +#include "smon.h"
>> +
>> +static void memcpy32_fromio(uint32_t *dest, uint32_t *src, uint32_t
>> +len) {
>> +    uint32_t i;
>> +
>> +    for (i = 0; i < len; i++)
>> +            dest[i] = ioread32(src + i);
>> +}
>> +
>> +static void memcpy32_toio(uint32_t *dest, uint32_t *src, uint32_t
>> +len) {
>> +    uint32_t i;
>> +
>> +    for (i = 0; i < len; i++)
>> +            iowrite32(src[i], dest + i);
>> +}
>> +
>> +void smon_init_ncp(struct smon_s *smon, uint32_t node, uint32_t target,
>> +    uint32_t offset)
>> +{
>> +    smon->assigned[0] = UNASSIGNED;
>> +    smon->assigned[1] = UNASSIGNED;
>> +    smon->type = NCP_SMON;
>> +    smon->node = node;
>> +    smon->target = target;
>> +    smon->offset = offset;
>> +}
>> +
>> +void smon_init_mem(struct smon_s *smon, uint64_t addr, uint32_t
>> +offset) {
>> +    smon->assigned[0] = UNASSIGNED;
>> +    smon->assigned[1] = UNASSIGNED;
>> +    smon->type = MEM_SMON;
>> +    smon->addr = ioremap(addr, SZ_4K);
>> +    smon->offset = offset;
>> +
>> +    if (smon->addr == NULL)
>> +            pr_err("axxia perf, smon can't remap memory %lld\n", addr); }
>> +
>> +void smon_stop_if_unassigned(struct smon_s *smon) {
>> +    uint32_t control = 0;
>> +
>> +    if (smon->assigned[0] == UNASSIGNED &&
>> +        smon->assigned[1] == UNASSIGNED) {
>> +            ncr_write(NCP_REGION_ID(smon->node, smon->target), smon->offset,
>> +                      1 * REG_SZ, &control);
>> +    }
>> +}
>> +
>> +uint32_t smon_allocate(struct smon_s *smon, uint8_t event) {
>> +    if (smon->assigned[0] == UNASSIGNED) {
>> +            smon->events[0] = event;
>> +            smon->assigned[0] = ASSIGNED;
>> +    } else if (smon->assigned[1] == UNASSIGNED) {
>> +            smon->events[1] = event;
>> +            smon->assigned[1] = ASSIGNED;
>> +    } else {
>> +            pr_warn("smon_allocate, no counter availible\n");
>> +            return -ENOCOUNTER;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +uint32_t smon_deallocate(struct smon_s *smon, uint8_t event) {
>> +    if ((smon->assigned[0] == ASSIGNED) && (smon->events[0] == event))
>> +            smon->assigned[0] = UNASSIGNED;
>> +    else if ((smon->assigned[1] == ASSIGNED) && (smon->events[1] == event))
>> +            smon->assigned[1] = UNASSIGNED;
>> +    else
>> +            return -ENOCOUNTER;
>> +
>> +    return 0;
>> +}
>> +
>> +uint32_t smon_event_active(struct smon_s *smon, uint8_t event) {
>> +    if ((smon->assigned[0] == ASSIGNED) && (smon->events[0] == event))
>> +            return 0;
>> +    else if ((smon->assigned[1] == ASSIGNED) && (smon->events[1] == event))
>> +            return 0;
>> +
>> +    return -ENOCOUNTER;
>> +}
>> +
>> +uint32_t smon_read(struct smon_s *smon, uint8_t event) {
>> +    if (smon->type == NCP_SMON)
>> +            ncr_read(NCP_REGION_ID(smon->node, smon->target), smon->offset,
>> +                     8 * REG_SZ, &smon->regs);
>> +    else if (smon->type == MEM_SMON)
>> +            memcpy32_fromio((uint32_t *)&smon->regs,
>> +                    (uint32_t *)smon->addr + smon->offset, 8);
>> +
>> +    if ((smon->assigned[0] == ASSIGNED) && (smon->events[0] == event))
>> +            return smon->regs.count0;
>> +    else if ((smon->assigned[1] == ASSIGNED) && (smon->events[1] == event))
>> +            return smon->regs.count1;
>> +
>> +    return -ENOEVENT;
>> +}
>> +
>> +uint32_t smon_start(struct smon_s *smon, uint8_t event) {
>> +    /* get currect configuration */
>> +    if (smon->type == NCP_SMON)
>> +            ncr_read(NCP_REGION_ID(smon->node, smon->target), smon->offset,
>> +                     8 * REG_SZ, &smon->regs);
>> +    else if (smon->type == MEM_SMON)
>> +            memcpy32_fromio((uint32_t *)&smon->regs,
>> +                    (uint32_t *)smon->addr + smon->offset, 8);
>> +
>> +    smon->regs.control = 1; /* run counters */
>> +
>> +    if ((smon->assigned[0] == ASSIGNED) && (smon->events[0] == event)) {
>> +            smon->regs.event0 = event;
>> +            smon->regs.count0 = 0;
>> +
>> +            if (smon->type == NCP_SMON) {
>> +                    /* write configuration, but do not change count reg */
>> +                    ncr_write(NCP_REGION_ID(smon->node, smon->target),
>> +                            smon->offset, 2 * REG_SZ, &smon->regs);
>> +
>> +                    /* clear this events counter register */
>> +                    ncr_write(NCP_REGION_ID(smon->node, smon->target),
>> +                            smon->offset + 4 * REG_SZ, 1 * REG_SZ,
>> +                            &smon->regs.count0);
>> +            } else if (smon->type == MEM_SMON) {
>> +                    /* write configuration, but do not change count reg */
>> +                    memcpy32_toio((uint32_t *)smon->addr + smon->offset,
>> +                            (uint32_t *)&smon->regs, 2);
>> +
>> +                    /* clear this events counter register */
>> +                    memcpy32_toio((uint32_t *)smon->addr + smon->offset + 4,
>> +                            (uint32_t *)&smon->regs.count0, 1);
>> +
>> +            }
>> +
>> +    } else if ((smon->assigned[1] == ASSIGNED)
>> +            && (smon->events[1] == event)) {
>> +            smon->regs.event1 = event;
>> +            smon->regs.count1 = 0;
>> +
>> +            if (smon->type == NCP_SMON) {
>> +                    /* write configuration, but do not change count reg */
>> +                    ncr_write(NCP_REGION_ID(smon->node, smon->target),
>> +                            smon->offset, 2 * REG_SZ, &smon->regs);
>> +
>> +                    /* clear this events counter register */
>> +                    ncr_write(NCP_REGION_ID(smon->node, smon->target),
>> +                              smon->offset + 5 * REG_SZ, 1 * REG_SZ,
>> +                              &smon->regs.count1);
>> +            } else if (smon->type == MEM_SMON) {
>> +                    /* write configuration, but do not change count reg */
>> +                    memcpy32_toio((uint32_t *)smon->addr + smon->offset,
>> +                            (uint32_t *)&smon->regs, 2);
>> +
>> +                    /* clear this events counter register */
>> +                    memcpy32_toio((uint32_t *)smon->addr + smon->offset + 5,
>> +                            (uint32_t *)&smon->regs.count1, 1);
>> +            }
>> +
>> +    } else {
>> +            pr_warn("smon_start, no counter availible\n");
>> +            return -ENOCOUNTER;
>> +    }
>> +
>> +    return 0;
>> +}
>> diff --git a/arch/arm/mach-axxia/smon.h b/arch/arm/mach-axxia/smon.h 
>> new file mode 100644 index 0000000..bcdf39f
>> --- /dev/null
>> +++ b/arch/arm/mach-axxia/smon.h
>> @@ -0,0 +1,71 @@
>> +/*
>> + * Helper module for board specific I2C bus registration
>> + *
>> + * Copyright (C) 2014 LSI Corporation.
>> + *
>> + * 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.
>> + *
>> + * This program is distributed in the hope that it will be useful, 
>> +but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
>> + * 02110-1301 USA
>> + *
>> + */
>> +#ifndef __ASM__ARCH_AXXIA_SMON_H
>> +#define __ASM__ARCH_AXXIA_SMON_H
>> +
>> +#include <linux/kernel.h>
>> +
>> +struct smon_reg_s {
>> +    uint32_t control;
>> +    uint8_t event0;
>> +    uint8_t event1;
>> +    uint16_t reserved;
>> +    uint32_t compare0;
>> +    uint32_t compare1;
>> +    uint32_t count0;
>> +    uint32_t count1;
>> +    uint32_t time;
>> +    uint32_t maxtime;
>> +};
>> +
>> +struct smon_s {
>> +    struct smon_reg_s regs;
>> +    uint32_t type; /* NCP_SMON or MEM_SMON */
>> +    uint32_t *addr; /* MEM_SMON */
>> +    uint32_t node; /* NCP_SMON */
>> +    uint32_t target; /* " */
>> +    uint32_t offset;
>> +    uint8_t assigned[2];
>> +    uint8_t events[2];
>> +};
>> +
>> +#define REG_SZ 4
>> +
>> +#define MEM_SMON 0
>> +#define NCP_SMON 1
>> +
>> +#define UNASSIGNED 0
>> +#define ASSIGNED 1
>> +
>> +#define ENOCOUNTER 1
>> +#define ENOEVENT 2
>> +
>> +void smon_init_ncp(struct smon_s *smon, uint32_t node, uint32_t target,
>> +    uint32_t offset);
>> +void smon_init_mem(struct smon_s *smon, uint64_t addr, uint32_t 
>> +offset); void smon_stop_if_unassigned(struct smon_s *smon); uint32_t 
>> +smon_allocate(struct smon_s *smon, uint8_t event); uint32_t 
>> +smon_deallocate(struct smon_s *smon, uint8_t event); uint32_t 
>> +smon_event_active(struct smon_s *smon, uint8_t event); uint32_t 
>> +smon_read(struct smon_s *smon, uint8_t event); uint32_t 
>> +smon_start(struct smon_s *smon, uint8_t event);
>> +
>> +#endif /* __ASM__ARCH_AXXIA_SMON_H */
>>
>
>

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to