Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
[sfrench/cifs-2.6.git] / arch / arc / plat-eznps / mtm.c
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
29 static int mtm_hs_ctr = MT_HS_CNT_MAX;
30
31 #ifdef CONFIG_EZNPS_MEM_ERROR_ALIGN
32 int 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
40 static 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
61 static 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
93 int 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
108 void 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 */
158 static 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 }
175 early_param("nps_mtm_hs_ctr", set_mtm_hs_ctr);