ARC: [plat-eznps] Add eznps platform
This platform include boards: Hardware Emulator (HE) Simulator based upon nSIM. Signed-off-by: Noam Camus <noamc@ezchip.com>
This commit is contained in:
parent
845033be00
commit
4a66d3fecf
|
@ -4379,6 +4379,12 @@ S: Maintained
|
||||||
F: drivers/video/fbdev/exynos/exynos_mipi*
|
F: drivers/video/fbdev/exynos/exynos_mipi*
|
||||||
F: include/video/exynos_mipi*
|
F: include/video/exynos_mipi*
|
||||||
|
|
||||||
|
EZchip NPS platform support
|
||||||
|
M: Noam Camus <noamc@ezchip.com>
|
||||||
|
S: Supported
|
||||||
|
F: arch/arc/plat-eznps
|
||||||
|
F: arch/arc/boot/dts/eznps.dts
|
||||||
|
|
||||||
F71805F HARDWARE MONITORING DRIVER
|
F71805F HARDWARE MONITORING DRIVER
|
||||||
M: Jean Delvare <jdelvare@suse.com>
|
M: Jean Delvare <jdelvare@suse.com>
|
||||||
L: linux-hwmon@vger.kernel.org
|
L: linux-hwmon@vger.kernel.org
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
#
|
||||||
|
# For a description of the syntax of this configuration file,
|
||||||
|
# see Documentation/kbuild/kconfig-language.txt.
|
||||||
|
#
|
||||||
|
|
||||||
|
menuconfig ARC_PLAT_EZNPS
|
||||||
|
bool "\"EZchip\" ARC dev platform"
|
||||||
|
select ARC_HAS_COH_CACHES if SMP
|
||||||
|
select CPU_BIG_ENDIAN
|
||||||
|
select CLKSRC_NPS
|
||||||
|
select EZNPS_GIC
|
||||||
|
select EZCHIP_NPS_MANAGEMENT_ENET if ETHERNET
|
||||||
|
help
|
||||||
|
Support for EZchip development platforms,
|
||||||
|
based on ARC700 cores.
|
||||||
|
We handle few flavours:
|
||||||
|
- Hardware Emulator AKA HE which is FPGA based chasis
|
||||||
|
- Simulator based on MetaWare nSIM
|
||||||
|
- NPS400 chip based on ASIC
|
||||||
|
|
||||||
|
config EZNPS_MTM_EXT
|
||||||
|
bool "ARC-EZchip MTM Extensions"
|
||||||
|
select CPUMASK_OFFSTACK
|
||||||
|
depends on ARC_PLAT_EZNPS && SMP
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Here we add new hierarchy for CPUs topology.
|
||||||
|
We got:
|
||||||
|
Core
|
||||||
|
Thread
|
||||||
|
At the new thread level each CPU represent one HW thread.
|
||||||
|
At highest hierarchy each core contain 16 threads,
|
||||||
|
any of them seem like CPU from Linux point of view.
|
||||||
|
All threads within same core share the execution unit of the
|
||||||
|
core and HW scheduler round robin between them.
|
|
@ -0,0 +1,7 @@
|
||||||
|
#
|
||||||
|
# Makefile for the linux kernel.
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-y := entry.o platform.o
|
||||||
|
obj-$(CONFIG_SMP) += smp.o
|
||||||
|
obj-$(CONFIG_EZNPS_MTM_EXT) += mtm.o
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
EZNPS CPU startup Code
|
||||||
|
Copyright(c) 2012 EZchip Technologies.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms and conditions of the GNU General Public License,
|
||||||
|
version 2, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope 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.
|
||||||
|
|
||||||
|
The full GNU General Public License is included in this distribution in
|
||||||
|
the file called "COPYING".
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
#include <asm/entry.h>
|
||||||
|
#include <asm/cache.h>
|
||||||
|
#include <plat/ctop.h>
|
||||||
|
|
||||||
|
.cpu A7
|
||||||
|
|
||||||
|
.section .init.text, "ax",@progbits
|
||||||
|
.align 1024 ; HW requierment for restart first PC
|
||||||
|
|
||||||
|
ENTRY(res_service)
|
||||||
|
#ifdef CONFIG_EZNPS_MTM_EXT
|
||||||
|
; There is no work for HW thread id != 0
|
||||||
|
lr r3, [CTOP_AUX_THREAD_ID]
|
||||||
|
cmp r3, 0
|
||||||
|
jne stext
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARC_HAS_DCACHE
|
||||||
|
; With no cache coherency mechanism D$ need to be used very carefully.
|
||||||
|
; Address space:
|
||||||
|
; 0G-2G: We disable CONFIG_ARC_CACHE_PAGES.
|
||||||
|
; 2G-3G: We disable D$ by setting this bit.
|
||||||
|
; 3G-4G: D$ is disabled by architecture.
|
||||||
|
; FMT are huge pages for user application reside at 0-2G.
|
||||||
|
; Only FMT left as one who can use D$ where each such page got
|
||||||
|
; disable/enable bit for cachability.
|
||||||
|
; Programmer will use FMT pages for private data so cache coherency
|
||||||
|
; would not be a problem.
|
||||||
|
; First thing we invalidate D$
|
||||||
|
sr 1, [ARC_REG_DC_IVDC]
|
||||||
|
sr HW_COMPLY_KRN_NOT_D_CACHED, [CTOP_AUX_HW_COMPLY]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
; We set logical cpuid to be used by GET_CPUID
|
||||||
|
; We do not use physical cpuid since we want ids to be continious when
|
||||||
|
; it comes to cpus on the same quad cluster.
|
||||||
|
; This is useful for applications that used shared resources of a quad
|
||||||
|
; cluster such SRAMS.
|
||||||
|
lr r3, [CTOP_AUX_CORE_ID]
|
||||||
|
sr r3, [CTOP_AUX_LOGIC_CORE_ID]
|
||||||
|
lr r3, [CTOP_AUX_CLUSTER_ID]
|
||||||
|
; Set logical is acheived by swap of 2 middle bits of cluster id (4 bit)
|
||||||
|
; r3 is used since we use short instruction and we need q-class reg
|
||||||
|
.short CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST
|
||||||
|
.word CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM
|
||||||
|
sr r3, [CTOP_AUX_LOGIC_CLUSTER_ID]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
j stext
|
||||||
|
END(res_service)
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2015 EZchip Technologies.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* The full GNU General Public License is included in this distribution in
|
||||||
|
* the file called "COPYING".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAT_EZNPS_CTOP_H
|
||||||
|
#define _PLAT_EZNPS_CTOP_H
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARC_PLAT_EZNPS
|
||||||
|
#error "Incorrect ctop.h include"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <soc/nps/common.h>
|
||||||
|
|
||||||
|
/* core auxiliary registers */
|
||||||
|
#ifdef __ASSEMBLY__
|
||||||
|
#define CTOP_AUX_BASE (-0x800)
|
||||||
|
#else
|
||||||
|
#define CTOP_AUX_BASE 0xFFFFF800
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CTOP_AUX_GLOBAL_ID (CTOP_AUX_BASE + 0x000)
|
||||||
|
#define CTOP_AUX_CLUSTER_ID (CTOP_AUX_BASE + 0x004)
|
||||||
|
#define CTOP_AUX_CORE_ID (CTOP_AUX_BASE + 0x008)
|
||||||
|
#define CTOP_AUX_THREAD_ID (CTOP_AUX_BASE + 0x00C)
|
||||||
|
#define CTOP_AUX_LOGIC_GLOBAL_ID (CTOP_AUX_BASE + 0x010)
|
||||||
|
#define CTOP_AUX_LOGIC_CLUSTER_ID (CTOP_AUX_BASE + 0x014)
|
||||||
|
#define CTOP_AUX_LOGIC_CORE_ID (CTOP_AUX_BASE + 0x018)
|
||||||
|
#define CTOP_AUX_MT_CTRL (CTOP_AUX_BASE + 0x020)
|
||||||
|
#define CTOP_AUX_HW_COMPLY (CTOP_AUX_BASE + 0x024)
|
||||||
|
#define CTOP_AUX_LPC (CTOP_AUX_BASE + 0x030)
|
||||||
|
#define CTOP_AUX_EFLAGS (CTOP_AUX_BASE + 0x080)
|
||||||
|
#define CTOP_AUX_IACK (CTOP_AUX_BASE + 0x088)
|
||||||
|
#define CTOP_AUX_GPA1 (CTOP_AUX_BASE + 0x08C)
|
||||||
|
#define CTOP_AUX_UDMC (CTOP_AUX_BASE + 0x300)
|
||||||
|
|
||||||
|
/* EZchip core instructions */
|
||||||
|
#define CTOP_INST_HWSCHD_OFF_R3 0x3B6F00BF
|
||||||
|
#define CTOP_INST_HWSCHD_OFF_R4 0x3C6F00BF
|
||||||
|
#define CTOP_INST_HWSCHD_RESTORE_R3 0x3E6F70C3
|
||||||
|
#define CTOP_INST_HWSCHD_RESTORE_R4 0x3E6F7103
|
||||||
|
#define CTOP_INST_SCHD_RW 0x3E6F7004
|
||||||
|
#define CTOP_INST_SCHD_RD 0x3E6F7084
|
||||||
|
#define CTOP_INST_ASRI_0_R3 0x3B56003E
|
||||||
|
#define CTOP_INST_XEX_DI_R2_R2_R3 0x4A664C00
|
||||||
|
#define CTOP_INST_EXC_DI_R2_R2_R3 0x4A664C01
|
||||||
|
#define CTOP_INST_AADD_DI_R2_R2_R3 0x4A664C02
|
||||||
|
#define CTOP_INST_AAND_DI_R2_R2_R3 0x4A664C04
|
||||||
|
#define CTOP_INST_AOR_DI_R2_R2_R3 0x4A664C05
|
||||||
|
#define CTOP_INST_AXOR_DI_R2_R2_R3 0x4A664C06
|
||||||
|
|
||||||
|
/* Do not use D$ for address in 2G-3G */
|
||||||
|
#define HW_COMPLY_KRN_NOT_D_CACHED _BITUL(28)
|
||||||
|
|
||||||
|
#define NPS_MSU_EN_CFG 0x80
|
||||||
|
#define NPS_CRG_BLKID 0x480
|
||||||
|
#define NPS_CRG_SYNC_BIT _BITUL(0)
|
||||||
|
#define NPS_GIM_BLKID 0x5C0
|
||||||
|
|
||||||
|
/* GIM registers and fields*/
|
||||||
|
#define NPS_GIM_UART_LINE _BITUL(7)
|
||||||
|
#define NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE _BITUL(10)
|
||||||
|
#define NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE _BITUL(11)
|
||||||
|
#define NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE _BITUL(25)
|
||||||
|
#define NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE _BITUL(26)
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
/* Functional registers definition */
|
||||||
|
struct nps_host_reg_mtm_cfg {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 gen:1, gdis:1, clk_gate_dis:1, asb:1,
|
||||||
|
__reserved:9, nat:3, ten:16;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nps_host_reg_mtm_cpu_cfg {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 csa:22, dmsid:6, __reserved:3, cs:1;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nps_host_reg_thr_init {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 str:1, __reserved:27, thr_id:4;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nps_host_reg_thr_init_sts {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 bsy:1, err:1, __reserved:26, thr_id:4;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nps_host_reg_msu_en_cfg {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 __reserved1:11,
|
||||||
|
rtc_en:1, ipc_en:1, gim_1_en:1,
|
||||||
|
gim_0_en:1, ipi_en:1, buff_e_rls_bmuw:1,
|
||||||
|
buff_e_alc_bmuw:1, buff_i_rls_bmuw:1, buff_i_alc_bmuw:1,
|
||||||
|
buff_e_rls_bmue:1, buff_e_alc_bmue:1, buff_i_rls_bmue:1,
|
||||||
|
buff_i_alc_bmue:1, __reserved2:1, buff_e_pre_en:1,
|
||||||
|
buff_i_pre_en:1, pmuw_ja_en:1, pmue_ja_en:1,
|
||||||
|
pmuw_nj_en:1, pmue_nj_en:1, msu_en:1;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nps_host_reg_gim_p_int_dst {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 int_out_en:1, __reserved1:4,
|
||||||
|
is:1, intm:2, __reserved2:4,
|
||||||
|
nid:4, __reserved3:4, cid:4,
|
||||||
|
__reserved4:4, tid:4;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* AUX registers definition */
|
||||||
|
struct nps_host_reg_aux_udmc {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 dcp:1, cme:1, __reserved:19, nat:3,
|
||||||
|
__reserved2:5, dcas:3;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nps_host_reg_aux_mt_ctrl {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 mten:1, hsen:1, scd:1, sten:1,
|
||||||
|
st_cnt:8, __reserved:8,
|
||||||
|
hs_cnt:8, __reserved1:4;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nps_host_reg_aux_hw_comply {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 me:1, le:1, te:1, knc:1, __reserved:28;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nps_host_reg_aux_lpc {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 mep:1, __reserved:31;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* CRG registers */
|
||||||
|
#define REG_GEN_PURP_0 nps_host_reg_non_cl(NPS_CRG_BLKID, 0x1BF)
|
||||||
|
|
||||||
|
/* GIM registers */
|
||||||
|
#define REG_GIM_P_INT_EN_0 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x100)
|
||||||
|
#define REG_GIM_P_INT_POL_0 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x110)
|
||||||
|
#define REG_GIM_P_INT_SENS_0 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x114)
|
||||||
|
#define REG_GIM_P_INT_BLK_0 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x118)
|
||||||
|
#define REG_GIM_P_INT_DST_10 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13A)
|
||||||
|
#define REG_GIM_P_INT_DST_11 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13B)
|
||||||
|
#define REG_GIM_P_INT_DST_25 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x149)
|
||||||
|
#define REG_GIM_P_INT_DST_26 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x14A)
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
#endif /* _PLAT_EZNPS_CTOP_H */
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2015 EZchip Technologies.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* The full GNU General Public License is included in this distribution in
|
||||||
|
* the file called "COPYING".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAT_EZNPS_MTM_H
|
||||||
|
#define _PLAT_EZNPS_MTM_H
|
||||||
|
|
||||||
|
#include <plat/ctop.h>
|
||||||
|
|
||||||
|
static inline void *nps_mtm_reg_addr(u32 cpu, u32 reg)
|
||||||
|
{
|
||||||
|
struct global_id gid;
|
||||||
|
u32 core, blkid;
|
||||||
|
|
||||||
|
gid.value = cpu;
|
||||||
|
core = gid.core;
|
||||||
|
blkid = (((core & 0x0C) << 2) | (core & 0x03));
|
||||||
|
|
||||||
|
return nps_host_reg(cpu, blkid, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_EZNPS_MTM_EXT
|
||||||
|
#define NPS_CPU_TO_THREAD_NUM(cpu) \
|
||||||
|
({ struct global_id gid; gid.value = cpu; gid.thread; })
|
||||||
|
|
||||||
|
/* MTM registers */
|
||||||
|
#define MTM_CFG(cpu) nps_mtm_reg_addr(cpu, 0x81)
|
||||||
|
#define MTM_THR_INIT(cpu) nps_mtm_reg_addr(cpu, 0x92)
|
||||||
|
#define MTM_THR_INIT_STS(cpu) nps_mtm_reg_addr(cpu, 0x93)
|
||||||
|
|
||||||
|
#define get_thread(map) map.thread
|
||||||
|
#define eznps_max_cpus 4096
|
||||||
|
#define eznps_cpus_per_cluster 256
|
||||||
|
|
||||||
|
void mtm_enable_core(unsigned int cpu);
|
||||||
|
int mtm_enable_thread(int cpu);
|
||||||
|
#else /* !CONFIG_EZNPS_MTM_EXT */
|
||||||
|
|
||||||
|
#define get_thread(map) 0
|
||||||
|
#define eznps_max_cpus 256
|
||||||
|
#define eznps_cpus_per_cluster 16
|
||||||
|
#define mtm_enable_core(cpu)
|
||||||
|
#define mtm_enable_thread(cpu) 1
|
||||||
|
#define NPS_CPU_TO_THREAD_NUM(cpu) 0
|
||||||
|
|
||||||
|
#endif /* CONFIG_EZNPS_MTM_EXT */
|
||||||
|
|
||||||
|
#endif /* _PLAT_EZNPS_MTM_H */
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2015 EZchip Technologies.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* The full GNU General Public License is included in this distribution in
|
||||||
|
* the file called "COPYING".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PLAT_EZNPS_SMP_H
|
||||||
|
#define __PLAT_EZNPS_SMP_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
|
||||||
|
extern void res_service(void);
|
||||||
|
|
||||||
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2015 EZchip Technologies.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* The full GNU General Public License is included in this distribution in
|
||||||
|
* the file called "COPYING".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/smp.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/log2.h>
|
||||||
|
#include <asm/arcregs.h>
|
||||||
|
#include <plat/mtm.h>
|
||||||
|
#include <plat/smp.h>
|
||||||
|
|
||||||
|
#define MT_CTRL_HS_CNT 0xFF
|
||||||
|
#define MT_CTRL_ST_CNT 0xF
|
||||||
|
#define NPS_NUM_HW_THREADS 0x10
|
||||||
|
|
||||||
|
static void mtm_init_nat(int cpu)
|
||||||
|
{
|
||||||
|
struct nps_host_reg_mtm_cfg mtm_cfg;
|
||||||
|
struct nps_host_reg_aux_udmc udmc;
|
||||||
|
int log_nat, nat = 0, i, t;
|
||||||
|
|
||||||
|
/* Iterate core threads and update nat */
|
||||||
|
for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
|
||||||
|
nat += test_bit(t, cpumask_bits(cpu_possible_mask));
|
||||||
|
|
||||||
|
log_nat = ilog2(nat);
|
||||||
|
|
||||||
|
udmc.value = read_aux_reg(CTOP_AUX_UDMC);
|
||||||
|
udmc.nat = log_nat;
|
||||||
|
write_aux_reg(CTOP_AUX_UDMC, udmc.value);
|
||||||
|
|
||||||
|
mtm_cfg.value = ioread32be(MTM_CFG(cpu));
|
||||||
|
mtm_cfg.nat = log_nat;
|
||||||
|
iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mtm_init_thread(int cpu)
|
||||||
|
{
|
||||||
|
int i, tries = 5;
|
||||||
|
struct nps_host_reg_thr_init thr_init;
|
||||||
|
struct nps_host_reg_thr_init_sts thr_init_sts;
|
||||||
|
|
||||||
|
/* Set thread init register */
|
||||||
|
thr_init.value = 0;
|
||||||
|
iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
|
||||||
|
thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
|
||||||
|
thr_init.str = 1;
|
||||||
|
iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
|
||||||
|
|
||||||
|
/* Poll till thread init is done */
|
||||||
|
for (i = 0; i < tries; i++) {
|
||||||
|
thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
|
||||||
|
if (thr_init_sts.thr_id == thr_init.thr_id) {
|
||||||
|
if (thr_init_sts.bsy)
|
||||||
|
continue;
|
||||||
|
else if (thr_init_sts.err)
|
||||||
|
pr_warn("Failed to thread init cpu %u\n", cpu);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == tries)
|
||||||
|
pr_warn("Got thread init timeout for cpu %u\n", cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mtm_enable_thread(int cpu)
|
||||||
|
{
|
||||||
|
struct nps_host_reg_mtm_cfg mtm_cfg;
|
||||||
|
|
||||||
|
if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Enable thread in mtm */
|
||||||
|
mtm_cfg.value = ioread32be(MTM_CFG(cpu));
|
||||||
|
mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
|
||||||
|
iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtm_enable_core(unsigned int cpu)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct nps_host_reg_aux_mt_ctrl mt_ctrl;
|
||||||
|
struct nps_host_reg_mtm_cfg mtm_cfg;
|
||||||
|
|
||||||
|
if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Initialize Number of Active Threads */
|
||||||
|
mtm_init_nat(cpu);
|
||||||
|
|
||||||
|
/* Initialize mtm_cfg */
|
||||||
|
mtm_cfg.value = ioread32be(MTM_CFG(cpu));
|
||||||
|
mtm_cfg.ten = 1;
|
||||||
|
iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
|
||||||
|
|
||||||
|
/* Initialize all other threads in core */
|
||||||
|
for (i = 1; i < NPS_NUM_HW_THREADS; i++)
|
||||||
|
mtm_init_thread(cpu + i);
|
||||||
|
|
||||||
|
|
||||||
|
/* Enable HW schedule, stall counter, mtm */
|
||||||
|
mt_ctrl.value = 0;
|
||||||
|
mt_ctrl.hsen = 1;
|
||||||
|
mt_ctrl.hs_cnt = MT_CTRL_HS_CNT;
|
||||||
|
mt_ctrl.sten = 1;
|
||||||
|
mt_ctrl.st_cnt = MT_CTRL_ST_CNT;
|
||||||
|
mt_ctrl.mten = 1;
|
||||||
|
write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HW scheduling mechanism will start working
|
||||||
|
* Only after call to instruction "schd.rw".
|
||||||
|
* cpu_relax() calls "schd.rw" instruction.
|
||||||
|
*/
|
||||||
|
cpu_relax();
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2015 EZchip Technologies.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* The full GNU General Public License is included in this distribution in
|
||||||
|
* the file called "COPYING".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <asm/mach_desc.h>
|
||||||
|
#include <plat/mtm.h>
|
||||||
|
|
||||||
|
static void __init eznps_configure_msu(void)
|
||||||
|
{
|
||||||
|
int cpu;
|
||||||
|
struct nps_host_reg_msu_en_cfg msu_en_cfg = {.value = 0};
|
||||||
|
|
||||||
|
msu_en_cfg.msu_en = 1;
|
||||||
|
msu_en_cfg.ipi_en = 1;
|
||||||
|
msu_en_cfg.gim_0_en = 1;
|
||||||
|
msu_en_cfg.gim_1_en = 1;
|
||||||
|
|
||||||
|
/* enable IPI and GIM messages on all clusters */
|
||||||
|
for (cpu = 0 ; cpu < eznps_max_cpus; cpu += eznps_cpus_per_cluster)
|
||||||
|
iowrite32be(msu_en_cfg.value,
|
||||||
|
nps_host_reg(cpu, NPS_MSU_BLKID, NPS_MSU_EN_CFG));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init eznps_configure_gim(void)
|
||||||
|
{
|
||||||
|
u32 reg_value;
|
||||||
|
u32 gim_int_lines;
|
||||||
|
struct nps_host_reg_gim_p_int_dst gim_p_int_dst = {.value = 0};
|
||||||
|
|
||||||
|
gim_int_lines = NPS_GIM_UART_LINE;
|
||||||
|
gim_int_lines |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
|
||||||
|
gim_int_lines |= NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE;
|
||||||
|
gim_int_lines |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
|
||||||
|
gim_int_lines |= NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IRQ polarity
|
||||||
|
* low or high level
|
||||||
|
* negative or positive edge
|
||||||
|
*/
|
||||||
|
reg_value = ioread32be(REG_GIM_P_INT_POL_0);
|
||||||
|
reg_value &= ~gim_int_lines;
|
||||||
|
iowrite32be(reg_value, REG_GIM_P_INT_POL_0);
|
||||||
|
|
||||||
|
/* IRQ type level or edge */
|
||||||
|
reg_value = ioread32be(REG_GIM_P_INT_SENS_0);
|
||||||
|
reg_value |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
|
||||||
|
reg_value |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
|
||||||
|
iowrite32be(reg_value, REG_GIM_P_INT_SENS_0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GIM interrupt select type for
|
||||||
|
* dbg_lan TX and RX interrupts
|
||||||
|
* should be type 1
|
||||||
|
* type 0 = IRQ line 6
|
||||||
|
* type 1 = IRQ line 7
|
||||||
|
*/
|
||||||
|
gim_p_int_dst.is = 1;
|
||||||
|
iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_10);
|
||||||
|
iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_11);
|
||||||
|
iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_25);
|
||||||
|
iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_26);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CTOP IRQ lines should be defined
|
||||||
|
* as blocking in GIM
|
||||||
|
*/
|
||||||
|
iowrite32be(gim_int_lines, REG_GIM_P_INT_BLK_0);
|
||||||
|
|
||||||
|
/* enable CTOP IRQ lines in GIM */
|
||||||
|
iowrite32be(gim_int_lines, REG_GIM_P_INT_EN_0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init eznps_early_init(void)
|
||||||
|
{
|
||||||
|
eznps_configure_msu();
|
||||||
|
eznps_configure_gim();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *eznps_compat[] __initconst = {
|
||||||
|
"ezchip,arc-nps",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
MACHINE_START(NPS, "nps")
|
||||||
|
.dt_compat = eznps_compat,
|
||||||
|
.init_early = eznps_early_init,
|
||||||
|
MACHINE_END
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2015 EZchip Technologies.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* The full GNU General Public License is included in this distribution in
|
||||||
|
* the file called "COPYING".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/smp.h>
|
||||||
|
#include <linux/of_fdt.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/irqdomain.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <plat/ctop.h>
|
||||||
|
#include <plat/smp.h>
|
||||||
|
#include <plat/mtm.h>
|
||||||
|
|
||||||
|
#define NPS_DEFAULT_MSID 0x34
|
||||||
|
#define NPS_MTM_CPU_CFG 0x90
|
||||||
|
|
||||||
|
static char smp_cpuinfo_buf[128] = {"Extn [EZNPS-SMP]\t: On\n"};
|
||||||
|
|
||||||
|
/* Get cpu map from device tree */
|
||||||
|
static int __init eznps_get_map(const char *name, struct cpumask *cpumask)
|
||||||
|
{
|
||||||
|
unsigned long dt_root = of_get_flat_dt_root();
|
||||||
|
const char *buf;
|
||||||
|
|
||||||
|
buf = of_get_flat_dt_prop(dt_root, name, NULL);
|
||||||
|
if (!buf)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
cpulist_parse(buf, cpumask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update board cpu maps */
|
||||||
|
static void __init eznps_init_cpumasks(void)
|
||||||
|
{
|
||||||
|
struct cpumask cpumask;
|
||||||
|
|
||||||
|
if (eznps_get_map("present-cpus", &cpumask)) {
|
||||||
|
pr_err("Failed to get present-cpus from dtb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
init_cpu_present(&cpumask);
|
||||||
|
|
||||||
|
if (eznps_get_map("possible-cpus", &cpumask)) {
|
||||||
|
pr_err("Failed to get possible-cpus from dtb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
init_cpu_possible(&cpumask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eznps_init_core(unsigned int cpu)
|
||||||
|
{
|
||||||
|
u32 sync_value;
|
||||||
|
struct nps_host_reg_aux_hw_comply hw_comply;
|
||||||
|
struct nps_host_reg_aux_lpc lpc;
|
||||||
|
|
||||||
|
if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hw_comply.value = read_aux_reg(CTOP_AUX_HW_COMPLY);
|
||||||
|
hw_comply.me = 1;
|
||||||
|
hw_comply.le = 1;
|
||||||
|
hw_comply.te = 1;
|
||||||
|
write_aux_reg(CTOP_AUX_HW_COMPLY, hw_comply.value);
|
||||||
|
|
||||||
|
/* Enable MMU clock */
|
||||||
|
lpc.mep = 1;
|
||||||
|
write_aux_reg(CTOP_AUX_LPC, lpc.value);
|
||||||
|
|
||||||
|
/* Boot CPU only */
|
||||||
|
if (!cpu) {
|
||||||
|
/* Write to general purpose register in CRG */
|
||||||
|
sync_value = ioread32be(REG_GEN_PURP_0);
|
||||||
|
sync_value |= NPS_CRG_SYNC_BIT;
|
||||||
|
iowrite32be(sync_value, REG_GEN_PURP_0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Master kick starting another CPU
|
||||||
|
*/
|
||||||
|
static void __init eznps_smp_wakeup_cpu(int cpu, unsigned long pc)
|
||||||
|
{
|
||||||
|
struct nps_host_reg_mtm_cpu_cfg cpu_cfg;
|
||||||
|
|
||||||
|
if (mtm_enable_thread(cpu) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* set PC, dmsid, and start CPU */
|
||||||
|
cpu_cfg.value = (u32)res_service;
|
||||||
|
cpu_cfg.dmsid = NPS_DEFAULT_MSID;
|
||||||
|
cpu_cfg.cs = 1;
|
||||||
|
iowrite32be(cpu_cfg.value, nps_mtm_reg_addr(cpu, NPS_MTM_CPU_CFG));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eznps_ipi_send(int cpu)
|
||||||
|
{
|
||||||
|
struct global_id gid;
|
||||||
|
struct {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 num:8, cluster:8, core:8, thread:8;
|
||||||
|
};
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
} ipi;
|
||||||
|
|
||||||
|
gid.value = cpu;
|
||||||
|
ipi.thread = get_thread(gid);
|
||||||
|
ipi.core = gid.core;
|
||||||
|
ipi.cluster = nps_cluster_logic_to_phys(gid.cluster);
|
||||||
|
ipi.num = NPS_IPI_IRQ;
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
" mov r3, %0\n"
|
||||||
|
" .word %1\n"
|
||||||
|
:
|
||||||
|
: "r"(ipi.value), "i"(CTOP_INST_ASRI_0_R3)
|
||||||
|
: "r3");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eznps_init_per_cpu(int cpu)
|
||||||
|
{
|
||||||
|
smp_ipi_irq_setup(cpu, NPS_IPI_IRQ);
|
||||||
|
|
||||||
|
eznps_init_core(cpu);
|
||||||
|
mtm_enable_core(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eznps_ipi_clear(int irq)
|
||||||
|
{
|
||||||
|
write_aux_reg(CTOP_AUX_IACK, 1 << irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct plat_smp_ops plat_smp_ops = {
|
||||||
|
.info = smp_cpuinfo_buf,
|
||||||
|
.init_early_smp = eznps_init_cpumasks,
|
||||||
|
.cpu_kick = eznps_smp_wakeup_cpu,
|
||||||
|
.ipi_send = eznps_ipi_send,
|
||||||
|
.init_per_cpu = eznps_init_per_cpu,
|
||||||
|
.ipi_clear = eznps_ipi_clear,
|
||||||
|
};
|
Loading…
Reference in New Issue