/* * netip_subsystem_config.c * * GPL LICENSE SUMMARY * * Copyright(c) 2015-2018 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License 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. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * 2200 Mission College Blvd. * Santa Clara, CA 97052 * */ #include #include #include #include #include "netip_subsystem_defs.h" #include "netip_subsystem_config.h" #define NETSS_SILICON_STEPPING 0xFFFF3FF4 #define MAX_DOMAIN_REGS (38) #define LOCK_REG1_OFF (0x007c) #define LOCK_REG2_OFF (0x0080) #define DOMAIN_BASE_REG_OFF (0x028c) #define SECURITY_MODULE_REG_OFF (0x0268) #define ENABLE_SNOOPED_MODE (0x00008000) #define UNLOCK1_VALUE (0x20406080) #define UNLOCK2_VALUE (0x10305070) #define LOCK1_VALUE (0x0204060f) static bool snooped_en = false; unsigned int netss_subsystem_get_silicon_step(void) { unsigned int siliconStep; unsigned int *siliconStepReg; siliconStepReg = netip_mmio_to_virtual(NETSS_SILICON_STEPPING); siliconStep = be32_to_cpu(*siliconStepReg); return siliconStep; } EXPORT_SYMBOL(netss_subsystem_get_silicon_step); void netss_enable_snooped_mode(void) { int i; unsigned long *lock1; unsigned long *lock2; unsigned long *domain_base; unsigned int reg_val; if (snooped_en) return; lock1 = netip_mmio_to_virtual(NETSS_DEV_BOOTCFG_BASE + LOCK_REG1_OFF); lock2 = netip_mmio_to_virtual(NETSS_DEV_BOOTCFG_BASE + LOCK_REG2_OFF); domain_base = netip_mmio_to_virtual(NETSS_DEV_BOOTCFG_BASE + DOMAIN_BASE_REG_OFF); *lock1 = cpu_to_be32(UNLOCK1_VALUE); *lock2 = cpu_to_be32(UNLOCK2_VALUE); for (i=0; i < MAX_DOMAIN_REGS; i++) { reg_val = be32_to_cpu(*domain_base); reg_val |= ENABLE_SNOOPED_MODE; *domain_base = cpu_to_be32(reg_val); domain_base++; } domain_base = netip_mmio_to_virtual(NETSS_DEV_BOOTCFG_BASE + SECURITY_MODULE_REG_OFF); reg_val = be32_to_cpu(*domain_base); reg_val |= ENABLE_SNOOPED_MODE; *domain_base = cpu_to_be32(reg_val); *lock1 = cpu_to_be32(LOCK1_VALUE); snooped_en = true; pr_info("netip snooped mode enabled!\n"); } /* SATT configuration*/ #define SATT_HOST_INDEX_MIN (5) #define SATT_HOST_INDEX_MAX (8) #define SATT_BASE_OFF (0x1000) #define SATT_SAP_SIZE_MAX (32 << 21) #define SATT_N_ENTRY_OFF (0x20) #define SATT2_CTRL_BRG_BA_MSB_SHIFT (8) #define SATT2_CTRL_BRG_BA_MSB_MASK (0xF) /* target field in SATT_N ctrl register, shift, mask and val */ #define SATT_NTARGET_IOSF_PRIMARY_VAL (0x4) #define SATT_N_CTRL_TARGET_SHIFT (0x1) #define SATT_N_CTRL_TARGET_MASK (0x7) /* SATT_N register offsets */ #define SATT_N_CTRL_OFF (0x0) #define SATT_N_SAP_BA_OFF (0x4) #define SATT_N_SAP_SIZE_OFF (0x8) #define SATT_N_BRG_BA_OFF (0xC) /* SATT_N register addresses */ #define SATT_N_BASE(idx) (SATT_BASE_OFF + ((idx) * SATT_N_ENTRY_OFF)) #define SATT_N_CTRL(idx) (SATT_N_BASE(idx) + SATT_N_CTRL_OFF) #define SATT_N_SAP_BA(idx) (SATT_N_BASE(idx) + SATT_N_SAP_BA_OFF) #define SATT_N_SAP_SIZE(idx) (SATT_N_BASE(idx) + SATT_N_SAP_SIZE_OFF) #define SATT_N_BRG_BA(idx) (SATT_N_BASE(idx) + SATT_N_BRG_BA_OFF) void netss_sattn_reg_write(unsigned long off, uint32_t val) { __raw_writel(val, pnetss_drv_data->bridge_reg_base + off); } uint32_t netss_sattn_reg_read(unsigned long off) { return __raw_readl(pnetss_drv_data->bridge_reg_base + off); } int netss_sattn_iosf_prim_set(int idx, phys_addr_t brg_ba, uint32_t sap_size) { uint32_t lo32 = lower_32_bits(brg_ba); uint32_t hi32 = upper_32_bits(brg_ba); uint32_t ctrl; if (!pnetss_drv_data->netss_driver_initialized) return -EBUSY; /* ATOM cpu controls 4 entries */ if ((idx < SATT_HOST_INDEX_MIN) || (idx > SATT_HOST_INDEX_MAX)) return -EINVAL; /* SATT is limited to 36 Bits */ if (hi32 & ~0xF) return -EINVAL; /* SATT has to be 16Byte aligned */ if (lo32 & 0xF) return -EINVAL; /* SATT range has to be 4Bytes aligned */ if (sap_size & 0x3) return -EINVAL; /* SATT is limited to 64 MB range*/ if (sap_size > SATT_SAP_SIZE_MAX) return -EINVAL; ctrl = netss_sattn_reg_read(SATT_N_CTRL(idx)); ctrl &= ~(SATT2_CTRL_BRG_BA_MSB_MASK << SATT2_CTRL_BRG_BA_MSB_SHIFT); ctrl |= hi32 << SATT2_CTRL_BRG_BA_MSB_SHIFT; ctrl &= ~(SATT_N_CTRL_TARGET_MASK << SATT_N_CTRL_TARGET_SHIFT); ctrl |= (SATT_NTARGET_IOSF_PRIMARY_VAL << SATT_N_CTRL_TARGET_SHIFT); netss_sattn_reg_write(SATT_N_SAP_SIZE(idx), sap_size); netss_sattn_reg_write(SATT_N_BRG_BA(idx), lo32); netss_sattn_reg_write(SATT_N_CTRL(idx), ctrl); return 0; } EXPORT_SYMBOL(netss_sattn_iosf_prim_set); void netss_sattn_get(int idx, uint32_t *ctrl, uint32_t *sap_ba, uint32_t *sap_size, uint32_t *brg_ba) { BUG_ON(!ctrl || !sap_ba || !sap_size || !brg_ba); *ctrl = netss_sattn_reg_read(SATT_N_CTRL(idx)); *sap_ba = netss_sattn_reg_read(SATT_N_SAP_BA(idx)); *sap_size = netss_sattn_reg_read(SATT_N_SAP_SIZE(idx)); *brg_ba = netss_sattn_reg_read(SATT_N_BRG_BA(idx)); } EXPORT_SYMBOL(netss_sattn_get);