coresight:add stm device

Signed-off-by: liaoao <liaoao@xiaomi.com>
This commit is contained in:
liaoao 2023-09-21 10:32:42 +08:00 committed by Xiang Xiao
parent c0e40fc19f
commit e3e23f7eaf
7 changed files with 738 additions and 0 deletions

View File

@ -29,6 +29,10 @@ if(CONFIG_CORESIGHT)
list(APPEND SRCS coresight_replicator.c)
endif()
if(CONFIG_CORESIGHT_STM)
list(APPEND SRCS coresight_stm.c)
endif()
if(CONFIG_CORESIGHT_TPIU)
list(APPEND SRCS coresight_tpiu.c)
endif()

View File

@ -27,6 +27,10 @@ config CORESIGHT_REPLICATOR
bool "Replicator coresight device support"
default n
config CORESIGHT_STM
bool "STM coresight device support"
default n
config CORESIGHT_TPIU
bool "TPIU coresight device support"
default n

View File

@ -32,6 +32,10 @@ ifeq ($(CONFIG_CORESIGHT_REPLICATOR),y)
CSRCS += coresight_replicator.c
endif
ifeq ($(CONFIG_CORESIGHT_STM),y)
CSRCS += coresight_stm.c
endif
ifeq ($(CONFIG_CORESIGHT_TPIU),y)
CSRCS += coresight_tpiu.c
endif

View File

@ -56,8 +56,14 @@
(*(FAR volatile uint16_t *)(addr) = (val))
#define coresight_put32(val, addr) \
(*(FAR volatile uint32_t *)(addr) = (val))
#define coresight_put64(val, addr) \
(*(FAR volatile uint64_t *)(addr) = (val))
#define coresight_get32(addr) \
(*(FAR volatile uint32_t *)(addr))
#define coresight_modify32(val, mask, addr) \
coresight_put32((coresight_get32(addr) & ~(mask)) | \
((val) & (mask)), (addr))
/****************************************************************************
* Public Function Prototypes

View File

@ -0,0 +1,533 @@
/****************************************************************************
* drivers/coresight/coresight_stm.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 <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/list.h>
#include <nuttx/bits.h>
#include <nuttx/coresight/coresight_stm.h>
#include "coresight_common.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* STM registers */
#define STM_DMASTARTR 0xc04
#define STM_DMASTOPR 0xc08
#define STM_DMASTATR 0xc0c
#define STM_DMACTLR 0xc10
#define STM_DMAIDR 0xcfc
#define STM_HEER 0xd00
#define STM_HETER 0xd20
#define STM_HEBSR 0xd60
#define STM_HEMCR 0xd64
#define STM_HEMASTR 0xdf4
#define STM_HEFEAT1R 0xdf8
#define STM_HEIDR 0xdfc
#define STM_SPER 0xe00
#define STM_SPTER 0xe20
#define STM_PRIVMASKR 0xe40
#define STM_SPSCR 0xe60
#define STM_SPMSCR 0xe64
#define STM_SPOVERRIDER 0xe68
#define STM_SPMOVERRIDER 0xe6c
#define STM_SPTRIGCSR 0xe70
#define STM_TCSR 0xe80
#define STM_TSSTIMR 0xe84
#define STM_TSFREQR 0xe8c
#define STM_SYNCR 0xe90
#define STM_AUXCR 0xe94
#define STM_SPFEAT1R 0xea0
#define STM_SPFEAT2R 0xea4
#define STM_SPFEAT3R 0xea8
#define STM_ITTRIGGER 0xee8
#define STM_ITATBDATA0 0xeec
#define STM_ITATBCTR2 0xef0
#define STM_ITATBID 0xef4
#define STM_ITATBCTR0 0xef8
#define STM_DEFAULT_CHANNELS 32
#define STM_BYTES_PER_CHANNEL 256
/* Register bit definition */
#define STM_EN BIT(0)
#define STM_TIMESTAMPED_EN BIT(1)
#define STM_TCSR_BUSY BIT(23)
#define STM_ATBTRIGEN_DIR BIT(4)
#define STM_HE_EN BIT(0)
#define STM_HE_ERRDETECT_EN BIT(2)
/* Channel offset bit definition */
#define STM_NO_TIMESTAMPED BIT(3)
#define STM_NO_MARKED BIT(4)
#define STM_NO_GUARANTEED BIT(7)
/* Bit operation */
#define rounddown_pow_of_two(n) (1 << (fls(n) - 1))
/****************************************************************************
* Private Types
****************************************************************************/
/* Address offset of different data type. */
enum stm_pkt_type_e
{
STM_PKT_TYPE_DATA = 0x00,
STM_PKT_TYPE_FLAG = 0x60,
STM_PKT_TYPE_TRIG = 0x70,
};
/****************************************************************************
* Private Functions Prototypes
****************************************************************************/
static int stm_enable(FAR struct coresight_dev_s *csdev);
static void stm_disable(FAR struct coresight_dev_s *csdev);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct coresight_source_ops_s g_stm_source_ops =
{
.enable = stm_enable,
.disable = stm_disable,
};
static const struct coresight_ops_s g_stm_ops =
{
.source_ops = &g_stm_source_ops,
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: stm_hw_disable
****************************************************************************/
static void stm_hw_disable(FAR struct coresight_stm_dev_s *stmdev)
{
coresight_unlock(stmdev->csdev.addr);
coresight_modify32(0x0, STM_EN, stmdev->csdev.addr + STM_TCSR);
coresight_put32(0x0, stmdev->csdev.addr + STM_SPER);
coresight_put32(0x0, stmdev->csdev.addr + STM_SPTRIGCSR);
coresight_put32(0x0, stmdev->csdev.addr + STM_HEMCR);
coresight_put32(0x0, stmdev->csdev.addr + STM_HEER);
coresight_put32(0x0, stmdev->csdev.addr + STM_HETER);
if (coresight_timeout(stmdev->csdev.addr, STM_TCSR,
STM_TCSR_BUSY, 0) < 0)
{
cserr("timeout waiting for STM stopped\n");
}
coresight_lock(stmdev->csdev.addr);
coresight_disclaim_device(stmdev->csdev.addr);
}
/****************************************************************************
* Name: stm_hw_enable
****************************************************************************/
static int stm_hw_enable(FAR struct coresight_stm_dev_s *stmdev)
{
int ret;
ret = coresight_claim_device(stmdev->csdev.addr);
if (ret < 0)
{
cserr("stm %s claim failed\n", stmdev->csdev.name);
return ret;
}
coresight_unlock(stmdev->csdev.addr);
if (stmdev->stmheer != 0)
{
coresight_put32(stmdev->stmhebsr, stmdev->csdev.addr + STM_HEBSR);
coresight_put32(stmdev->stmheter, stmdev->csdev.addr + STM_HETER);
coresight_put32(stmdev->stmheer, stmdev->csdev.addr + STM_HEER);
coresight_put32(STM_HE_EN | STM_HE_ERRDETECT_EN,
stmdev->csdev.addr + STM_HEMCR);
}
coresight_put32(STM_ATBTRIGEN_DIR, stmdev->csdev.addr + STM_SPTRIGCSR);
coresight_put32(stmdev->stmspscr, stmdev->csdev.addr + STM_SPSCR);
coresight_put32(stmdev->stmsper, stmdev->csdev.addr + STM_SPER);
/* 4096 byte between synchronisation packets */
coresight_put32(0xfff, stmdev->csdev.addr + STM_SYNCR);
coresight_put32((stmdev->traceid << 16) | STM_TIMESTAMPED_EN | STM_EN,
stmdev->csdev.addr + STM_TCSR);
coresight_lock(stmdev->csdev.addr);
return ret;
}
/****************************************************************************
* Name: stm_hw_disable
****************************************************************************/
static void stm_disable(FAR struct coresight_dev_s *csdev)
{
FAR struct coresight_stm_dev_s *stmdev =
(FAR struct coresight_stm_dev_s *)csdev;
if (--stmdev->refcnt == 0)
{
stm_hw_disable(stmdev);
csinfo("%s disabled\n", csdev->name);
}
}
/****************************************************************************
* Name: stm_enable
****************************************************************************/
static int stm_enable(FAR struct coresight_dev_s *csdev)
{
FAR struct coresight_stm_dev_s *stmdev =
(FAR struct coresight_stm_dev_s *)csdev;
int ret = 0;
if (stmdev->refcnt++ == 0)
{
ret = stm_hw_enable(stmdev);
if (ret < 0)
{
stmdev->refcnt--;
cserr("%s enabled failed\n", csdev->name);
}
}
return ret;
}
/****************************************************************************
* Name: stm_get_stimulus_port_num
****************************************************************************/
static uint32_t stm_get_stimulus_port_num(uintptr_t addr)
{
uint32_t numsp;
coresight_unlock(addr);
numsp = coresight_get32(addr + CORESIGHT_DEVID);
if ((numsp & 0x1ffff) == 0)
{
numsp = STM_DEFAULT_CHANNELS;
}
coresight_lock(addr);
return numsp;
}
/****************************************************************************
* Name: stm_get_fundamental_data_size
****************************************************************************/
static uint8_t stm_get_fundamental_data_size(uintptr_t addr)
{
uint32_t stmspfeat2r;
if (sizeof(uintptr_t) == 4)
{
return 4;
}
coresight_unlock(addr);
stmspfeat2r = coresight_get32(addr + STM_SPFEAT2R);
coresight_lock(addr);
return BMVAL(stmspfeat2r, 12, 15) ? 8 : 4;
}
/****************************************************************************
* Name: stm_init_default_data
****************************************************************************/
static void stm_init_default_data(FAR struct coresight_stm_dev_s *stmdev)
{
/* Do not use port selection, and enable all channels. */
stmdev->stmspscr = 0x0;
stmdev->stmsper = ~0x0;
/* Disable hardware event tracing. */
stmdev->stmheer = 0x0;
/* Set invariant transaction timing on all channels. */
memset(stmdev->guaranteed, 0,
sizeof(unsigned long) * BITS_TO_LONGS(stmdev->numsp));
}
/****************************************************************************
* Name: stm_send
****************************************************************************/
static void stm_send(uintptr_t addr, const void *data,
uint32_t size, uint8_t write_bytes)
{
uint64_t payload[1];
/* Check data address whether write_bytes aligned. */
if ((unsigned long)data & (write_bytes - 1))
{
memcpy(payload, data, size);
data = payload;
}
switch (size)
{
case 8:
DEBUGASSERT(sizeof(uintptr_t) == 8);
coresight_put64(*(uint64_t *)data, addr);
break;
case 4:
coresight_put32(*(uint32_t *)data, addr);
break;
case 2:
coresight_put16(*(uint16_t *)data, addr);
break;
case 1:
coresight_put8(*(uint8_t *)data, addr);
break;
default:
break;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stm_set_channel_options
*
* Description:
* Set a channel's trace mode.
*
* Input Parameters:
* stmdev - Pointer to STM device.
* channel - Channels to configure.
* options - If this channel's trace mode is guaranteed(blocking)
* or invariant(noblocking).
*
* Returned Value:
* Zero on success; a negative value on failure.
*
****************************************************************************/
int stm_set_channel_options(FAR struct coresight_stm_dev_s *stmdev,
uint32_t channel, uint32_t options)
{
if (channel >= stmdev->numsp)
{
return -EINVAL;
}
switch (options)
{
case STM_OPTION_GUARANTEED:
__set_bit(channel, stmdev->guaranteed);
break;
case STM_OPTION_INVARIANT:
__clear_bit(channel, stmdev->guaranteed);
break;
default:
return -EINVAL;
}
return 0;
}
/****************************************************************************
* Name: stm_sendpacket
*
* Description:
* Write data to STM device.
*
* Input Parameters:
* stmdev - Pointer to STM device.
* type - Data type.
* flag - Data flags (or attributes).
* channel - Channels this data from.
* data - Pointer to the data buffer.
* size - Data size.
*
* Returned Value:
* Size of data written to STM device; a negative value on failure.
*
****************************************************************************/
ssize_t stm_sendpacket(FAR struct coresight_stm_dev_s *stmdev,
enum stp_packet_type_e type,
enum stp_packet_flags_e flag, uint32_t channel,
FAR const void *data, size_t size)
{
uintptr_t chaddr;
uint32_t offset;
if (channel >= stmdev->numsp)
{
return -EINVAL;
}
/* Aligned to STM fundamental data size. */
if (size > stmdev->write_bytes)
{
size = stmdev->write_bytes;
}
else
{
size = rounddown_pow_of_two(size);
}
/* Write data to corresponding channel offset according to data flags. */
chaddr = stmdev->stimulus_port_addr + channel * STM_BYTES_PER_CHANNEL;
offset = (flag & STP_PACKET_TIMESTAMPED) ? 0 : STM_NO_TIMESTAMPED;
offset |= test_bit(channel, stmdev->guaranteed) ? 0 : STM_NO_GUARANTEED;
switch (type)
{
case STP_PACKET_FLAG:
chaddr += offset | STM_PKT_TYPE_FLAG;
stm_send(chaddr, data, 1, stmdev->write_bytes);
size = 1;
break;
case STP_PACKET_DATA:
offset |= (flag & STP_PACKET_MARKED) ? 0 : STM_NO_MARKED;
chaddr += offset | STM_PKT_TYPE_DATA;
stm_send(chaddr, data, size, stmdev->write_bytes);
break;
default:
return -EOPNOTSUPP;
}
return size;
}
/****************************************************************************
* Name: stm_register
*
* Description:
* Register a STM devices.
*
* Input Parameters:
* desc - A description of this coresight device.
*
* Returned Value:
* Pointer to a STM device on success; NULL on failure.
*
****************************************************************************/
FAR struct coresight_stm_dev_s *
stm_register(FAR const struct coresight_desc_s *desc)
{
FAR struct coresight_stm_dev_s *stmdev;
FAR struct coresight_dev_s *csdev;
uint32_t numsp = stm_get_stimulus_port_num(desc->addr);
int ret;
stmdev = kmm_zalloc(sizeof(struct coresight_stm_dev_s) +
sizeof(unsigned long) * BITS_TO_LONGS(numsp));
if (stmdev == NULL)
{
cserr("%s:malloc failed!\n", desc->name);
return NULL;
}
stmdev->numsp = numsp;
stmdev->write_bytes = stm_get_fundamental_data_size(desc->addr);
stmdev->stimulus_port_addr = desc->stimulus_port_addr;
stmdev->traceid = coresight_get_system_trace_id();
if (stmdev->traceid < 0)
{
kmm_free(stmdev);
cserr("%s:get unique traceid failed!\n", desc->name);
return NULL;
}
stm_init_default_data(stmdev);
csdev = &stmdev->csdev;
csdev->ops = &g_stm_ops;
ret = coresight_register(csdev, desc);
if (ret < 0)
{
coresight_put_system_trace_id(stmdev->traceid);
kmm_free(stmdev);
cserr("%s:register failed\n", desc->name);
return NULL;
}
return stmdev;
}
/****************************************************************************
* Name: stm_unregister
*
* Description:
* Unregister a STM devices.
*
* Input Parameters:
* stmdev - Pointer to the STM device.
*
****************************************************************************/
void stm_unregister(FAR struct coresight_stm_dev_s *stmdev)
{
coresight_unregister(&stmdev->csdev);
coresight_put_system_trace_id(stmdev->traceid);
kmm_free(stmdev);
}

View File

@ -126,6 +126,13 @@ struct coresight_desc_s
int inport_num;
/* Used in STM device: start address of extend stimulus port, this memory
* should be reserved for stm use.
* Size of this prealloced memory equals to (256 x number of ports).
*/
uintptr_t stimulus_port_addr;
/* Description of outports of current device. */
int outport_num;

View File

@ -0,0 +1,180 @@
/****************************************************************************
* include/nuttx/coresight/coresight_stm.h
*
* 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.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_CORESIGHT_CORESIGHT_STM_H
#define __INCLUDE_NUTTX_CORESIGHT_CORESIGHT_STM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/coresight/coresight.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
enum stm_trans_type_e
{
STM_OPTION_GUARANTEED = 0, /* Blocking, may stall the bus when fifio is full. */
STM_OPTION_INVARIANT, /* No-blocking, may lost trace data when fifo is full. */
};
/* enum stp_packet_type - STP packets that an STM driver sends. */
enum stp_packet_type_e
{
STP_PACKET_DATA = 0,
STP_PACKET_FLAG,
STP_PACKET_USER,
STP_PACKET_MERR,
STP_PACKET_GERR,
STP_PACKET_TRIG,
STP_PACKET_XSYNC,
};
enum stp_packet_flags_e
{
STP_PACKET_MARKED = 0x1,
STP_PACKET_TIMESTAMPED = 0x2,
};
struct coresight_stm_dev_s
{
struct coresight_dev_s csdev;
uint8_t refcnt;
int traceid; /* Trace id. */
/* Used in STM device: start address of extend stimulus port, this memory
* should be reserved for stm use.
* Size of this reserved memory equals to (256 x number of ports).
*/
uintptr_t stimulus_port_addr;
/* The total number of stimulus port support by this STM. */
uint32_t numsp;
/* Maximus bytes this STM can write at a time. */
uint8_t write_bytes;
/* Port enable and select register. */
uint32_t stmsper;
uint32_t stmspscr;
/* Hardware Event Tracing. */
uint32_t stmheer;
uint32_t stmheter;
uint32_t stmhebsr;
/* Bitmap used to indicate whether corresponding stimulus port is
* guaranteed transactions or invariant timing transactions.
*/
unsigned long guaranteed[0];
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: stm_set_channel_options
*
* Description:
* Set a channel's trace mode.
*
* Input Parameters:
* stmdev - Pointer to STM device.
* channel - Channels to configure.
* options - If this channel's trace mode is guaranteed(blocking)
* or invariant(noblocking).
*
* Returned Value:
* Zero on success; a negative value on failure.
*
****************************************************************************/
int stm_set_channel_options(FAR struct coresight_stm_dev_s *stmdev,
uint32_t channel, uint32_t options);
/****************************************************************************
* Name: stm_sendpacket
*
* Description:
* Write data to STM device.
*
* Input Parameters:
* stmdev - Pointer to STM device.
* type - Data type.
* flag - Data flags (or attributes).
* channel - Channels this data from.
* data - Pointer to the data buffer.
* size - Data size.
*
* Returned Value:
* Size of data written to STM device; a negative value on failure.
*
****************************************************************************/
ssize_t stm_sendpacket(FAR struct coresight_stm_dev_s *stmdev,
enum stp_packet_type_e type,
enum stp_packet_flags_e flag, uint32_t channel,
FAR const void *data, size_t size);
/****************************************************************************
* Name: stm_register
*
* Description:
* Register a STM devices.
*
* Input Parameters:
* desc - A description of this coresight device.
*
* Returned Value:
* Pointer to a STM device on success; NULL on failure.
*
****************************************************************************/
FAR struct coresight_stm_dev_s *
stm_register(FAR const struct coresight_desc_s *desc);
/****************************************************************************
* Name: stm_unregister
*
* Description:
* Unregister a STM devices.
*
* Input Parameters:
* stmdev - Pointer to the STM device.
*
****************************************************************************/
void stm_unregister(FAR struct coresight_stm_dev_s *stmdev);
#endif //__INCLUDE_NUTTX_CORESIGHT_CORESIGHT_STM_H