linux/arch/arc/plat-eznps/mtm.c
<<
>>
Prefs
   1/*
   2 * Copyright(c) 2015 EZchip Technologies.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * The full GNU General Public License is included in this distribution in
  14 * the file called "COPYING".
  15 */
  16
  17#include <linux/smp.h>
  18#include <linux/io.h>
  19#include <linux/log2.h>
  20#include <asm/arcregs.h>
  21#include <plat/mtm.h>
  22#include <plat/smp.h>
  23
  24#define MT_HS_CNT_MIN           0x01
  25#define MT_HS_CNT_MAX           0xFF
  26#define MT_CTRL_ST_CNT          0xF
  27#define NPS_NUM_HW_THREADS      0x10
  28
  29static int mtm_hs_ctr = MT_HS_CNT_MAX;
  30
  31#ifdef CONFIG_EZNPS_MEM_ERROR_ALIGN
  32int do_memory_error(unsigned long address, struct pt_regs *regs)
  33{
  34        die("Invalid Mem Access", regs, address);
  35
  36        return 1;
  37}
  38#endif
  39
  40static void mtm_init_nat(int cpu)
  41{
  42        struct nps_host_reg_mtm_cfg mtm_cfg;
  43        struct nps_host_reg_aux_udmc udmc;
  44        int log_nat, nat = 0, i, t;
  45
  46        /* Iterate core threads and update nat */
  47        for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
  48                nat += test_bit(t, cpumask_bits(cpu_possible_mask));
  49
  50        log_nat = ilog2(nat);
  51
  52        udmc.value = read_aux_reg(CTOP_AUX_UDMC);
  53        udmc.nat = log_nat;
  54        write_aux_reg(CTOP_AUX_UDMC, udmc.value);
  55
  56        mtm_cfg.value = ioread32be(MTM_CFG(cpu));
  57        mtm_cfg.nat = log_nat;
  58        iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
  59}
  60
  61static void mtm_init_thread(int cpu)
  62{
  63        int i, tries = 5;
  64        struct nps_host_reg_thr_init thr_init;
  65        struct nps_host_reg_thr_init_sts thr_init_sts;
  66
  67        /* Set thread init register */
  68        thr_init.value = 0;
  69        iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
  70        thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
  71        thr_init.str = 1;
  72        iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
  73
  74        /* Poll till thread init is done */
  75        for (i = 0; i < tries; i++) {
  76                thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
  77                if (thr_init_sts.thr_id == thr_init.thr_id) {
  78                        if (thr_init_sts.bsy)
  79                                continue;
  80                        else if (thr_init_sts.err)
  81                                pr_warn("Failed to thread init cpu %u\n", cpu);
  82                        break;
  83                }
  84
  85                pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
  86                break;
  87        }
  88
  89        if (i == tries)
  90                pr_warn("Got thread init timeout for cpu %u\n", cpu);
  91}
  92
  93int mtm_enable_thread(int cpu)
  94{
  95        struct nps_host_reg_mtm_cfg mtm_cfg;
  96
  97        if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
  98                return 1;
  99
 100        /* Enable thread in mtm */
 101        mtm_cfg.value = ioread32be(MTM_CFG(cpu));
 102        mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
 103        iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
 104
 105        return 0;
 106}
 107
 108void mtm_enable_core(unsigned int cpu)
 109{
 110        int i;
 111        struct nps_host_reg_aux_mt_ctrl mt_ctrl;
 112        struct nps_host_reg_mtm_cfg mtm_cfg;
 113        struct nps_host_reg_aux_dpc dpc;
 114
 115        /*
 116         * Initializing dpc register in each CPU.
 117         * Overwriting the init value of the DPC
 118         * register so that CMEM and FMT virtual address
 119         * spaces are accessible, and Data Plane HW
 120         * facilities are enabled.
 121         */
 122        dpc.ien = 1;
 123        dpc.men = 1;
 124        write_aux_reg(CTOP_AUX_DPC, dpc.value);
 125
 126        if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
 127                return;
 128
 129        /* Initialize Number of Active Threads */
 130        mtm_init_nat(cpu);
 131
 132        /* Initialize mtm_cfg */
 133        mtm_cfg.value = ioread32be(MTM_CFG(cpu));
 134        mtm_cfg.ten = 1;
 135        iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
 136
 137        /* Initialize all other threads in core */
 138        for (i = 1; i < NPS_NUM_HW_THREADS; i++)
 139                mtm_init_thread(cpu + i);
 140
 141
 142        /* Enable HW schedule, stall counter, mtm */
 143        mt_ctrl.value = 0;
 144        mt_ctrl.hsen = 1;
 145        mt_ctrl.hs_cnt = mtm_hs_ctr;
 146        mt_ctrl.mten = 1;
 147        write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
 148
 149        /*
 150         * HW scheduling mechanism will start working
 151         * Only after call to instruction "schd.rw".
 152         * cpu_relax() calls "schd.rw" instruction.
 153         */
 154        cpu_relax();
 155}
 156
 157/* Verify and set the value of the mtm hs counter */
 158static int __init set_mtm_hs_ctr(char *ctr_str)
 159{
 160        long hs_ctr;
 161        int ret;
 162
 163        ret = kstrtol(ctr_str, 0, &hs_ctr);
 164
 165        if (ret || hs_ctr > MT_HS_CNT_MAX || hs_ctr < MT_HS_CNT_MIN) {
 166                pr_err("** Invalid @nps_mtm_hs_ctr [%d] needs to be [%d:%d] (incl)\n",
 167                       hs_ctr, MT_HS_CNT_MIN, MT_HS_CNT_MAX);
 168                return -EINVAL;
 169        }
 170
 171        mtm_hs_ctr = hs_ctr;
 172
 173        return 0;
 174}
 175early_param("nps_mtm_hs_ctr", set_mtm_hs_ctr);
 176