/**************************************************************************** * drivers/coresight/coresight_common.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include "coresight_common.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define CORESIGHT_UNLOCK 0xc5acce55 #define CORESIGHT_LOCK 0x0 #define CORESIGHT_CLAIM_SELF_HOSTED BIT(1) #define CORESIGHT_SOURCE_BITMAP_SIZE 32 #define CORESIGHT_ETM_PMU_SEED 0x10 /**************************************************************************** * Private Data ****************************************************************************/ static DECLARE_BITMAP(g_coresight_trace_id_bitmap, CORESIGHT_SOURCE_BITMAP_SIZE); static spinlock_t g_coresight_trace_id_lock = SP_UNLOCKED; static const uint32_t g_coresight_barrier_pkt[4] = { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff }; /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: coresight_lock * * Description: * To ensure that the software being debugged can never access an unlocked * CoreSight component, a software monitor that accesses debug registers * must unlock the component before accessing any registers, and lock the * component again before exiting the monitor. * * Input Parameters: * addr - Base addr of the coresight device. * ****************************************************************************/ void coresight_lock(uintptr_t addr) { coresight_put32(CORESIGHT_LOCK, addr + CORESIGHT_LAR); } /**************************************************************************** * Name: coresight_unlock ****************************************************************************/ void coresight_unlock(uintptr_t addr) { coresight_put32(CORESIGHT_UNLOCK, addr + CORESIGHT_LAR); } /**************************************************************************** * Name: coresight_claim_device * * Description: * Claim the device for self-hosted usage to prevent an external tool from * touching this device.Use Protocol 3: Set private bit and check for race. * * Input Parameters: * addr - Base addr of the coresight device. * * Returned Value: * Zero on success; a negative value on failure. * ****************************************************************************/ int coresight_claim_device(uintptr_t addr) { int ret = -EBUSY; coresight_unlock(addr); if (coresight_get32(addr + CORESIGHT_CLAIMCLR) != 0) { goto out; } coresight_put32(CORESIGHT_CLAIM_SELF_HOSTED, addr + CORESIGHT_CLAIMSET); if (coresight_get32(addr + CORESIGHT_CLAIMCLR) == CORESIGHT_CLAIM_SELF_HOSTED) { ret = 0; } else { /* There was a race setting the tags, clean up and fail */ coresight_put32(CORESIGHT_CLAIM_SELF_HOSTED, addr + CORESIGHT_CLAIMCLR); } out: coresight_lock(addr); return ret; } /**************************************************************************** * Name: coresight_disclaim_device * * Description: * Disclaim the device, then an external tool can touch the device. * * Input Parameters: * addr - Base addr of the coresight device. * ****************************************************************************/ void coresight_disclaim_device(uintptr_t addr) { coresight_unlock(addr); if (coresight_get32(addr + CORESIGHT_CLAIMCLR) == CORESIGHT_CLAIM_SELF_HOSTED) { coresight_put32(CORESIGHT_CLAIM_SELF_HOSTED, addr + CORESIGHT_CLAIMCLR); } else { cserr("current device is not claimed or something wrong happend\n"); } coresight_lock(addr); } /**************************************************************************** * Name: coresight_get_cpu_trace_id * * Description: * Used to get an unique trace id associated with cpu id of an ETM * coresight device. * * Input Parameters: * cpu - CPU index to generate an unique trace id. * * Returned Value: * Unique trace id on success; a negative value on failure. * ****************************************************************************/ int coresight_get_cpu_trace_id(int cpu) { int traceid = CORESIGHT_ETM_PMU_SEED + cpu * 2; if (traceid >= CORESIGHT_SOURCE_BITMAP_SIZE) { cserr("trace id is out of bounds\n"); return -EINVAL; } return traceid; } /**************************************************************************** * Name: coresight_get_system_trace_id * * Description: * Used to get an unique trace id of a STM coresight device. The trace ID * value for *ETM* tracers start at CPU_ID * 2 + 0x10, and Trace ID 0x00 * and anything equal to or higher than 0x70 is reserved. * * Returned Value: * Unique trace id on success; a negative value on failure. * ****************************************************************************/ int coresight_get_system_trace_id(void) { int max = CORESIGHT_SOURCE_BITMAP_SIZE / 2; irqstate_t flags; int traceid = 0; int i; flags = spin_lock_irqsave(&g_coresight_trace_id_lock); for (i = 0; i < max - 1; i++) { if (test_bit(1 + 2 * i, g_coresight_trace_id_bitmap) == 0) { traceid = 1 + 2 * i; break; } } if (traceid == 0) { cserr("get system trace id failed\n"); spin_unlock_irqrestore(&g_coresight_trace_id_lock, flags); return -EINVAL; } set_bit(traceid, g_coresight_trace_id_bitmap); spin_unlock_irqrestore(&g_coresight_trace_id_lock, flags); return traceid; } /**************************************************************************** * Name: coresight_put_system_trace_id * * Description: * Release an allocated system trace ID. * * Input Parameters: * traceid - Traceid to be released. * ****************************************************************************/ void coresight_put_system_trace_id(int traceid) { irqstate_t flags; flags = spin_lock_irqsave(&g_coresight_trace_id_lock); clear_bit(traceid, g_coresight_trace_id_bitmap); spin_unlock_irqrestore(&g_coresight_trace_id_lock, flags); } /**************************************************************************** * Name: coresight_timeout * * Description: * Loop until a bitmask of register has changed to a specific value. * * Input Parameters: * addr - Base addr of the coresight device. * off - Register offset of the coresight device. * bitmask - Bitmask to be checked. * val - Value to be matched. * * Returned Value: * Zero on success; a negative value on failure. * ****************************************************************************/ int coresight_timeout(uint32_t val, uint32_t mask, uintptr_t addr) { int i; for (i = CONFIG_CORESIGHT_TIMEOUT; i > 0; i--) { uint32_t value = coresight_get32(addr); if ((value & mask) == val) { return 0; } up_udelay(1); } return -EAGAIN; } /**************************************************************************** * Name: coresight_insert_barrier_packet * * Description: * When losing synchronisation a new barrier packet needs to be inserted at * the beginning of the data collected in a buffer. That way the decoder * knows that it needs to look for another sync sequence. * * Input Parameters: * buf - buffer that a new barrier packet inserts to. * ****************************************************************************/ void coresight_insert_barrier_packet(FAR void *buf) { if (buf != NULL) { memcpy(buf, g_coresight_barrier_pkt, sizeof(g_coresight_barrier_pkt)); } }