Yes

Working on getting comments updated for other patches as well before I resubmit

-----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