From 7b49b7c6c1ea3644358a38ba56eab9c89d2a41d7 Mon Sep 17 00:00:00 2001 From: Bingxing Wang Date: Fri, 3 Sep 2021 13:10:31 +0300 Subject: [PATCH] MSM8916Pkg: Implement Bam Signed-off-by: Ivaylo Ivanov --- MSM8916Pkg/Drivers/BamDxe/BamDxe.inf | 30 ++ MSM8916Pkg/Drivers/BamDxe/Driver.c | 40 +++ MSM8916Pkg/Drivers/BamDxe/Source.txt | 2 + MSM8916Pkg/Drivers/BamDxe/bam.c | 471 ++++++++++++++++++++++++++ MSM8916Pkg/Drivers/BamDxe/bam_p.h | 31 ++ MSM8916Pkg/Include/Chipset/bam.h | 222 ++++++++++++ MSM8916Pkg/Include/Library/Pow2Lib.h | 58 ++++ MSM8916Pkg/Include/Protocol/QcomBam.h | 35 ++ MSM8916Pkg/MSM8916Pkg.dec | 1 + MSM8916Pkg/MSM8916Pkg.dsc | 1 + MSM8916Pkg/MSM8916Pkg.fdf | 1 + 11 files changed, 892 insertions(+) create mode 100644 MSM8916Pkg/Drivers/BamDxe/BamDxe.inf create mode 100644 MSM8916Pkg/Drivers/BamDxe/Driver.c create mode 100644 MSM8916Pkg/Drivers/BamDxe/Source.txt create mode 100644 MSM8916Pkg/Drivers/BamDxe/bam.c create mode 100644 MSM8916Pkg/Drivers/BamDxe/bam_p.h create mode 100644 MSM8916Pkg/Include/Chipset/bam.h create mode 100644 MSM8916Pkg/Include/Library/Pow2Lib.h create mode 100644 MSM8916Pkg/Include/Protocol/QcomBam.h diff --git a/MSM8916Pkg/Drivers/BamDxe/BamDxe.inf b/MSM8916Pkg/Drivers/BamDxe/BamDxe.inf new file mode 100644 index 0000000..db78b89 --- /dev/null +++ b/MSM8916Pkg/Drivers/BamDxe/BamDxe.inf @@ -0,0 +1,30 @@ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BamDxe + FILE_GUID = 6914BF99-1BAB-4042-A266-B206374E0239 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = BamDxeInitialize + +[Sources.common] + Driver.c + bam.c + +[BuildOptions.AARCH64] + GCC:*_*_*_CC_FLAGS = -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + MSM8916Pkg/MSM8916Pkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + IoLib + +[Protocols] + gQcomBamProtocolGuid + +[Depex] + TRUE diff --git a/MSM8916Pkg/Drivers/BamDxe/Driver.c b/MSM8916Pkg/Drivers/BamDxe/Driver.c new file mode 100644 index 0000000..ae4dab9 --- /dev/null +++ b/MSM8916Pkg/Drivers/BamDxe/Driver.c @@ -0,0 +1,40 @@ +#include + +#include +#include +#include + +#include "bam_p.h" + +STATIC QCOM_BAM_PROTOCOL mBam = { + bam_init, + bam_sys_pipe_init, + bam_pipe_fifo_init, + bam_add_cmd_element, + bam_add_desc, + bam_add_one_desc, + bam_sys_gen_event, + bam_wait_for_interrupt, + bam_read_offset_update, +}; + +EFI_STATUS +EFIAPI +BamDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE Handle = NULL; + EFI_STATUS Status; + + Status = gBS->InstallMultipleProtocolInterfaces( + &Handle, + &gQcomBamProtocolGuid, + &mBam, + NULL + ); + ASSERT_EFI_ERROR(Status); + + return Status; +} diff --git a/MSM8916Pkg/Drivers/BamDxe/Source.txt b/MSM8916Pkg/Drivers/BamDxe/Source.txt new file mode 100644 index 0000000..31aca1c --- /dev/null +++ b/MSM8916Pkg/Drivers/BamDxe/Source.txt @@ -0,0 +1,2 @@ +URL: https://source.codeaurora.org/quic/la/kernel/lk +BRANCH: LA.AF.1.1-02810-8064.0 diff --git a/MSM8916Pkg/Drivers/BamDxe/bam.c b/MSM8916Pkg/Drivers/BamDxe/bam.c new file mode 100644 index 0000000..f98ea58 --- /dev/null +++ b/MSM8916Pkg/Drivers/BamDxe/bam.c @@ -0,0 +1,471 @@ +/* Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "bam_p.h" + +#define HLOS_EE_INDEX 0 + +/* Reset BAM registers and pipes */ +static void bam_reset(struct bam_instance *bam) +{ + /* Initiate SW reset */ + writel(BAM_SW_RST_BIT_MASK, BAM_CTRL_REG(bam->base)); + + /* No delay required */ + + /* Disable SW reset */ + writel(~BAM_SW_RST_BIT_MASK, BAM_CTRL_REG(bam->base)); +} + +/* Resets pipe registers and state machines */ +static void bam_pipe_reset(struct bam_instance *bam, + uint8_t pipe_num) +{ + /* Start sw reset of the pipe to be allocated */ + writel(1, BAM_P_RSTn(bam->pipe[pipe_num].pipe_num, bam->base)); + + /* No delay required */ + + /* Stop sw reset of the pipe to be allocated */ + writel(0, BAM_P_RSTn(bam->pipe[pipe_num].pipe_num, bam->base)); +} + +/* A blocking function that waits till an interrupt is signalled. + * bam : BAM instance for the descriptors to be queued. + * pipe_num : pipe number for the descriptors to be queued. + * interrupt: interrupt to wait for. + */ +int bam_wait_for_interrupt(struct bam_instance *bam, + uint8_t pipe_num, + enum p_int_type interrupt) +{ + uint32_t val; + + while (1) + { + /* Wait for a interrupt on the right pipe */ + do{ + /* Determine the pipe causing the interrupt */ + val = readl(BAM_IRQ_SRCS(bam->base)); + /* Flush out the right most global interrupt bit */ + } while (!((val & 0x7FFF) & (1 << bam->pipe[pipe_num].pipe_num))); + + /* Check the reason for this BAM interrupt */ + if (readl(BAM_IRQ_STTS(bam->base))) + goto bam_wait_int_error; + + /* Check the interrupt type */ + /* Read interrupt status register */ + val = readl(BAM_P_IRQ_STTSn(bam->pipe[pipe_num].pipe_num, bam->base)); + + /* Check for error */ + if (val & P_ERR_EN_MASK) + goto bam_wait_int_error; + + if (val & interrupt) + { + /* Correct interrupt was fired. */ + /* Clear the other interrupts */ + val = P_OUT_OF_DESC_EN_MASK | P_PRCSD_DESC_EN_MASK | P_TRNSFR_END_EN_MASK; + writel (val, BAM_P_IRQ_CLRn(bam->pipe[pipe_num].pipe_num, bam->base)); + return BAM_RESULT_SUCCESS; + } + else if (val & P_TRNSFR_END_EN_MASK) + { + dprintf(CRITICAL, + "Trasfer end signalled before the last descc was processed\n"); + goto bam_wait_int_error; + } + } + +bam_wait_int_error: + + dprintf(CRITICAL, "Unexpected interrupt\n"); + return BAM_RESULT_FAILURE; +} + +/* Enable BAM and pipe level interrupts */ +void bam_enable_interrupts(struct bam_instance *bam, uint8_t pipe_num) +{ + + uint32_t int_mask = P_ERR_EN_MASK | P_OUT_OF_DESC_EN_MASK | + P_PRCSD_DESC_EN_MASK | P_TRNSFR_END_EN_MASK; + uint32_t val; + + /* Enable BAM error interrupts */ + writel(BAM_ERROR_EN_MASK, BAM_IRQ_EN_REG(bam->base)); + + /* Enable the interrupts for the pipe by enabling the relevant bits + * in the BAM_PIPE_INTERRUPT_ENABLE register. + */ + writel(int_mask, + BAM_P_IRQ_ENn(bam->pipe[pipe_num].pipe_num, bam->base)); + + /* Enable pipe interrups */ + /* Do read-modify-write */ + val = readl(BAM_IRQ_SRCS_MSK(bam->base)); + writel((1 << bam->pipe[pipe_num].pipe_num) | val, + BAM_IRQ_SRCS_MSK(bam->base)); +} + +/* Reset and initialize the bam module */ +void bam_init(struct bam_instance *bam) +{ + uint32_t val = 0; + + bam_reset(bam); + + /* Check for only one pipe's direction. + * The other is assumed to be the opposite system + * transaction. + */ + if (bam->pipe[0].trans_type == SYS2BAM || + bam->pipe[0].trans_type == BAM2SYS) + { + /* Program the threshold count */ + writel(bam->threshold, BAM_DESC_CNT_TRSHLD_REG(bam->base)); + } + + /* Program config register for H/W bug fixes */ + val = 0xffffffff & ~(1 << 11); + writel(val, BAM_CNFG_BITS(bam->base)); + + /* Write the EE index to control the mapping of interrupts to EE */ + val = HLOS_EE_INDEX & BAM_EE_MASK; + writel(val, BAM_TRUST_REG(bam->base)); + + /* Enable the BAM */ + writel(BAM_ENABLE_BIT_MASK, BAM_CTRL_REG(bam->base)); +} + +/* Funtion to setup a simple fifo structure. + * Note: Addr should be 8 byte aligned. + * bam : BAM instance for the descriptors to be queued. + * pipe_num : pipe number for the descriptors to be queued. + */ +int bam_pipe_fifo_init(struct bam_instance *bam, + uint8_t pipe_num) +{ + if (bam->pipe[pipe_num].fifo.size > 0x7FFF) + { + dprintf(CRITICAL, + "Size exceeds max size for a descriptor(0x7FFF)\n"); + return BAM_RESULT_FAILURE; + } + + /* Check if fifo start is 8-byte alligned */ + ASSERT(!((uint32_t)bam->pipe[pipe_num].fifo.head & 0x7)); + + /* Check if fifo size is a power of 2. + * The circular fifo logic in lk expects this. + */ + ASSERT(ispow2(bam->pipe[pipe_num].fifo.size)); + + bam->pipe[pipe_num].fifo.current = bam->pipe[pipe_num].fifo.head; + + /* Set the descriptor buffer size. Must be a multiple of 8 */ + writel(bam->pipe[pipe_num].fifo.size * BAM_DESC_SIZE, + BAM_P_FIFO_SIZESn(bam->pipe[pipe_num].pipe_num, bam->base)); + + /* Write descriptors FIFO base addr must be 8-byte aligned */ + /* Needs a physical address conversion as we are setting up + * the base of the FIFO for the BAM state machine. + */ + writel((uint32_t)bam->pipe[pipe_num].fifo.head, + BAM_P_DESC_FIFO_ADDRn(bam->pipe[pipe_num].pipe_num, bam->base)); + + /* Initialize FIFO offset for the first read */ + bam->pipe[pipe_num].fifo.offset = BAM_DESC_SIZE; + + /* Everything is set. + * Flag pipe init done. + */ + bam->pipe[pipe_num].initialized = 1; + + return BAM_RESULT_SUCCESS; +} + +void bam_sys_pipe_init(struct bam_instance *bam, + uint8_t pipe_num) +{ + uint32_t val = 0; + + /* Reset the pipe to be allocated */ + bam_pipe_reset(bam, pipe_num); + + /* Enable minimal interrupts */ + bam_enable_interrupts(bam, pipe_num); + + /* Pipe event threshold register is not relevant in sys modes */ + + /* Enable pipe in system mode and set the direction */ + writel(P_SYS_MODE_MASK | P_ENABLE | + (bam->pipe[pipe_num].trans_type << P_DIRECTION_SHIFT), + BAM_P_CTRLn(bam->pipe[pipe_num].pipe_num, bam->base)); + + /* Write the EE index to control the mapping of pipe interrupts to EE */ + val = HLOS_EE_INDEX & BAM_EE_MASK; + writel(val, BAM_P_TRUST_REGn(bam->pipe[pipe_num].pipe_num, bam->base)); + + /* Mark the pipe FIFO as uninitialized. */ + bam->pipe[pipe_num].initialized = 0; +} + +/* Function to notify written descriptors to BAM. + * bam : BAM instance for the descriptors to be queued. + * pipe_num : pipe number for the descriptors to be queued. + * num_desc : number of the descriptors. + * fifo : Circular FIFO used for the descriptors. + */ +void bam_sys_gen_event(struct bam_instance *bam, + uint8_t pipe_num, + unsigned int num_desc) +{ + uint32_t val = 0; + + if (num_desc >= bam->pipe[pipe_num].fifo.size) { + dprintf(CRITICAL, + "Max allowed desc is one less than the fifo length\n"); + return; + } + + /* Update the fifo peer offset */ + val = (num_desc - 1) * BAM_DESC_SIZE; + val += bam->pipe[pipe_num].fifo.offset; + val &= (bam->pipe[pipe_num].fifo.size * BAM_DESC_SIZE - 1); + + writel(val, BAM_P_EVNT_REGn(bam->pipe[pipe_num].pipe_num, bam->base)); +} + +/* Function to read the updates for FIFO offsets. + * bam : BAM that uses the FIFO. + * pipe : BAM pipe that uses the FIFO. + * return : FIFO offset where the next descriptor should be written. + * Note : S/W maintains the circular properties of the FIFO and updates + * the offsets accordingly. + */ +void bam_read_offset_update(struct bam_instance *bam, unsigned int pipe_num) +{ + uint32_t offset; + + offset = readl(BAM_P_SW_OFSTSn(bam->pipe[pipe_num].pipe_num, bam->base)); + offset &= 0xFFFF; + + dprintf(INFO, "Offset value is %d \n", offset); + + /* Save the next offset to be written to. */ + bam->pipe[pipe_num].fifo.current = (struct bam_desc*) + ((uint32_t)bam->pipe[pipe_num].fifo.head + offset); + + bam->pipe[pipe_num].fifo.offset = offset + BAM_DESC_SIZE ; +} + +/* Function to get the next desc address. + * Keeps track of circular properties of the FIFO + * and returns the appropriate address. + */ +static struct bam_desc* fifo_getnext(struct bam_desc_fifo *fifo, + struct bam_desc* desc) +{ + uint16_t offset; + + offset = desc - fifo->head; + + if (offset == (fifo->size - 1)) + return fifo->head; + else + return desc + 1; +} + +/* Function to add BAM descriptors for a given fifo. + * bam : BAM instance to be used. + * data_ptr : Memory address for data transfer. + * data_len : Length of the data_ptr. + * flags : Flags to be set on the last desc added. + * + * Note: This function also notifies the BAM about the added descriptors. + */ +int bam_add_desc(struct bam_instance *bam, + unsigned int pipe_num, + unsigned char *data_ptr, + unsigned int data_len, + unsigned flags) +{ + int bam_ret = BAM_RESULT_SUCCESS; + unsigned int len = data_len; + unsigned int desc_len; + unsigned int n = 0; + unsigned int desc_flags; + + dprintf(INFO, "Data length for BAM transfer is %u\n", data_len); + + if (data_ptr == NULL || len == 0) + { + dprintf(CRITICAL, "Wrong params for BAM transfer \n"); + bam_ret = BAM_RESULT_FAILURE; + goto bam_add_desc_error; + } + + /* Check if we have enough space in FIFO */ + if (len > (unsigned)bam->pipe[pipe_num].fifo.size * BAM_MAX_DESC_DATA_LEN) + { + dprintf(CRITICAL, "Data transfer exceeds desc fifo length.\n"); + bam_ret = BAM_RESULT_FAILURE; + goto bam_add_desc_error; + } + + while (len) + { + + /* There are only 16 bits to write data length. + * If more bits are needed, create more + * descriptors. + */ + if (len > BAM_MAX_DESC_DATA_LEN) + { + desc_len = BAM_MAX_DESC_DATA_LEN; + len -= BAM_MAX_DESC_DATA_LEN; + desc_flags = 0; + } + else + { + desc_len = len; + len = 0; + /* Set correct flags on the last desc. */ + desc_flags = flags; + } + + /* Write descriptor */ + bam_add_one_desc(bam, pipe_num, data_ptr, desc_len, desc_flags); + + data_ptr += BAM_MAX_DESC_DATA_LEN; + n++; + } + + + /* Create a read/write event to notify the periperal of the added desc. */ + bam_sys_gen_event(bam, pipe_num, n); + +bam_add_desc_error: + + return bam_ret; +} + +/* Function to add a BAM descriptor for a given fifo. + * bam : BAM instance to be used. + * data_ptr : Memory address for data transfer. + * data_len : Length of the data_ptr. + * flags : Flags to be set on the desc added. + * + * Note: This function does not notify the BAM about the added descriptor. + */ +int bam_add_one_desc(struct bam_instance *bam, + unsigned int pipe_num, + unsigned char* data_ptr, + uint32_t len, + uint8_t flags) +{ + + struct bam_desc *desc = bam->pipe[pipe_num].fifo.current; + int bam_ret = BAM_RESULT_SUCCESS; + + if (data_ptr == NULL || len == 0) + { + dprintf(CRITICAL, "Wrong params for BAM transfer \n"); + bam_ret = BAM_RESULT_FAILURE; + goto bam_add_one_desc_error; + } + + /* Check if the FIFO is allocated for the pipe */ + if (!bam->pipe[pipe_num].initialized) + { + dprintf(CRITICAL, "Please allocate the FIFO for the BAM pipe %d\n", + bam->pipe[pipe_num].pipe_num); + bam_ret = BAM_RESULT_FAILURE; + goto bam_add_one_desc_error; + } + + if ((flags & BAM_DESC_LOCK_FLAG) && (flags & BAM_DESC_UNLOCK_FLAG)) + { + dprintf(CRITICAL, "Can't lock and unlock in the same desc\n"); + bam_ret = BAM_RESULT_FAILURE; + goto bam_add_one_desc_error; + } + + /* Setting EOT flag on a CMD desc is not valid */ + if ((flags & BAM_DESC_EOT_FLAG) && (flags & BAM_DESC_CMD_FLAG)) + { + dprintf(CRITICAL, "EOT flag set on the CMD desc\n"); + bam_ret = BAM_RESULT_FAILURE; + goto bam_add_one_desc_error; + } + + /* Check for the length of the desc. */ + if (len > BAM_MAX_DESC_DATA_LEN) + { + dprintf(CRITICAL, "len of the desc exceeds max length" + " %d > %d\n", len, BAM_MAX_DESC_DATA_LEN); + bam_ret = BAM_RESULT_FAILURE; + goto bam_add_one_desc_error; + } + + desc->flags = flags; + desc->addr = (uint32_t)data_ptr; + desc->size = (uint16_t)len; + desc->reserved = 0; + + /* Update the FIFO to point to the head */ + bam->pipe[pipe_num].fifo.current = fifo_getnext(&bam->pipe[pipe_num].fifo, desc); + +bam_add_one_desc_error: + return bam_ret; +} + +struct cmd_element* bam_add_cmd_element(struct cmd_element *ptr, + uint32_t reg_addr, + uint32_t value, + enum bam_ce_cmd_t cmd_type) +{ + /* Write cmd type. + * Also, write the register address. + */ + ptr->addr_n_cmd = (reg_addr & ~(0xFF000000)) | (cmd_type << 24); + + /* Do not mask any of the addr bits by default */ + ptr->reg_mask = 0xFFFFFFFF; + + /* Write the value to be written */ + ptr->reg_data = value; + + /* Return the address to add the next element to */ + return ptr + 1; +} diff --git a/MSM8916Pkg/Drivers/BamDxe/bam_p.h b/MSM8916Pkg/Drivers/BamDxe/bam_p.h new file mode 100644 index 0000000..da98a65 --- /dev/null +++ b/MSM8916Pkg/Drivers/BamDxe/bam_p.h @@ -0,0 +1,31 @@ +#ifndef _BAM_PRIVATE_H +#define _BAM_PRIVATE_H + +void bam_init(struct bam_instance *bam); +void bam_sys_pipe_init(struct bam_instance *bam, + uint8_t pipe_num); +int bam_pipe_fifo_init(struct bam_instance *bam, + uint8_t pipe_num); +struct cmd_element* bam_add_cmd_element(struct cmd_element *ptr, + uint32_t addr, + uint32_t data, + enum bam_ce_cmd_t cmd_type); +int bam_add_desc(struct bam_instance *bam, + unsigned int pipe_num, + unsigned char *data_ptr, + unsigned int data_len, + unsigned flags); +int bam_add_one_desc(struct bam_instance *bam, + unsigned int pipe_num, + unsigned char*, + uint32_t len, + uint8_t flags); +void bam_sys_gen_event(struct bam_instance *bam, + uint8_t pipe_num, + unsigned int num_desc); +int bam_wait_for_interrupt(struct bam_instance *bam, + uint8_t pipe_num, + enum p_int_type interrupt); +void bam_read_offset_update(struct bam_instance *bam, unsigned int pipe_num); + +#endif // _BAM_PRIVATE_H diff --git a/MSM8916Pkg/Include/Chipset/bam.h b/MSM8916Pkg/Include/Chipset/bam.h new file mode 100644 index 0000000..41d1014 --- /dev/null +++ b/MSM8916Pkg/Include/Chipset/bam.h @@ -0,0 +1,222 @@ +/* Copyright (c) 2012, The Linux Foundation. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PLATFORM_MSM_SHARED_BAM_H +#define __PLATFORM_MSM_SHARED_BAM_H + +#include + +#define BAM_DESC_SIZE 8 +#define BAM_CE_SIZE 16 +#define BAM_MAX_DESC_DATA_LEN 0xFFFF +#define BAM_DATA_READ 0 +#define BAM_DATA_WRITE 1 + +#define BAM_CTRL_REG(x) (0x0000 + (x)) +#define BAM_SW_RST_BIT_MASK 1 +#define BAM_ENABLE_BIT_MASK (1 << 1) + +#define BAM_DESC_CNT_TRSHLD_REG(x) (0x0008 + (x)) +#define COUNT_TRESHOLD_MASK 0xFF +#define BAM_IRQ_SRCS(x) (0x0000000C + (x)) +#define BAM_IRQ_SRCS_MSK(x) (0x00000010 + (x)) +#define BAM_IRQ_MASK (1 << 31) +#define P_IRQ_MASK (1) + +/* Pipe Interrupt masks */ +enum p_int_type +{ + P_PRCSD_DESC_EN_MASK = 1, + P_OUT_OF_DESC_EN_MASK = (1 << 3), + P_ERR_EN_MASK = (1 << 4), + P_TRNSFR_END_EN_MASK = (1 << 5) +}; + +#define BAM_IRQ_STTS(x) (0x00000014 + (x)) +#define BAM_IRQ_SRCS_UNMASKED(x) (0x00000030 + (x)) + +#define BAM_IRQ_EN_REG(x) (0x001C + (x)) +#define BAM_TIMER_EN_MASK (1 << 4) +/* Available only in BAM-Lite */ +#define BAM_EMPTY_EN_MASK (1 << 3) +#define BAM_ERROR_EN_MASK (1 << 2) +/* Available only in BAM */ +#define BAM_HRESP_ERR_EN_MASK (1 << 1) + +#define BAM_TRUST_REG(x) (0x00000070 + (x)) +#define BAM_EE_MASK (7 << 0) +#define BAM_RESET_BLK_MASK (1 << 7) +#define BAM_LOCK_EE_CTRL_MASK (1 << 13) + +#define BAM_CNFG_BITS(x) (0x0000007C + (x)) + +#define BAM_P_CTRLn(n, x) (0x00001000 + 0x1000 * (n) + (x)) +#define P_SYS_MODE_MASK (1 << 5) +/* 1: Producer mode 0: Consumer mode */ +#define P_DIRECTION_SHIFT 3 +#define P_ENABLE (1 << 1) + +#define BAM_P_RSTn(n, x) (0x00001000 + 0x4 + 0x1000 * (n) + (x)) +#define BAM_P_IRQ_STTSn(n, x) (0x00001000 + 0x10 + 0x1000 * (n) + (x)) +#define BAM_P_IRQ_CLRn(n, x) (0x00001000 + 0x14 + 0x1000 * (n) + (x)) +#define BAM_P_IRQ_ENn(n, x) (0x00001000 + 0x18 + 0x1000 * (n) + (x)) +#define BAM_P_TRUST_REGn(n, x) (0x00001000 + 0x30 + 0x1000 * (n) + (x)) +#define BAM_P_SW_OFSTSn(n, x) (0x00001800 + 0x1000 * (n) + (x)) +#define BAM_P_EVNT_REGn(n, x) (0x00001818 + 0x1000 * (n) + (x)) +#define P_DESC_FIFO_PEER_OFST_MASK 0xFF + +#define BAM_P_DESC_FIFO_ADDRn(n, x) (0x0000181C + 0x1000 * (n) + (x)) +#define BAM_P_FIFO_SIZESn(n, x) (0x00001820 + 0x1000 * (n) + (x)) + +/* Flags for descriptors */ +#define BAM_DESC_INT_FLAG (1 << 7) +#define BAM_DESC_EOT_FLAG (1 << 6) +#define BAM_DESC_EOB_FLAG (1 << 5) +#define BAM_DESC_NWD_FLAG (1 << 4) +#define BAM_DESC_CMD_FLAG (1 << 3) +#define BAM_DESC_LOCK_FLAG (1 << 2) +#define BAM_DESC_UNLOCK_FLAG (1 << 1) + +enum bam_ce_cmd_t{ + CE_WRITE_TYPE = 0, + CE_READ_TYPE = 1 +}; + +/* result type */ +typedef enum { + BAM_RESULT_SUCCESS = 0, + BAM_RESULT_FAILURE = 1, + BAM_RESULT_TIMEOUT = 2 +} bam_result_t; + + +/* Enum to define the BAM type: + * BAM2BAM:Producer BAM to Consumer BAM. + * SYS2BAM:Producer System to Consumer BAM. + * BAM2SYS:Producer BAM to Consumer System. + */ +enum bam_transaction_type { + SYS2BAM, + BAM2SYS, + BAM2BAM, +}; + +/* Enum to define BAM mode: + * SPS:Use BAM pipes. + * DIRECT:Pipes are disabled. + * LEGACY:BAM is not used. + */ +enum bam_mode { + SPS, + DIRECT, + LEGACY, +}; + +/* Enum to define BAM pipe states: + * ENABLED:Producer and Consumer pipes are enabled. + * HALT:Consumer pipe is halted. (Preferred type) + * FULL_HALT:Both Producer and Consumer pipes are halted. + */ +enum bam_pipe_state { + ENABLED, + HALT, + FULL_HALT, +}; + +enum bam_type { + BAM_LITE, + BAM, +}; + +/* Structure to define BAM descriptors that describe the data + * descriptors written to the data FIFO. + * addr:Descriptor address. + * size:Each descriptor is 8 bytes. Size of the descriptor fifo must + * contain an integer number of Descriptors. + */ +struct bam_desc { + uint32_t addr; + uint16_t size; + uint8_t reserved; + uint8_t flags; +} __PACKED; + +struct bam_desc_fifo { + struct bam_desc *head; + struct bam_desc *current; + uint16_t size; + uint16_t offset; +}; + +/* Structure to define BAM pipes + * pipe_state: BAM pipe states. + * trans_type: BAM tranaction type. + * evt_gen_threshold: This register configures the threshold value for + * Read/Write event generation by the BAM + * towards another BAM. + * fifo: Circular fifo associated with this pipe. + * num_pipe: Number of pipes used in this bam. + * pipe: Pipe number for this pipe. + */ +struct bam_pipe { + enum bam_pipe_state state; + enum bam_transaction_type trans_type; + struct bam_desc_fifo fifo; + uint16_t evt_gen_threshold; + uint8_t pipe_num; + uint8_t initialized; +}; + +/* Structure to define a BAM instance being used + * base:Base address for the BAM. + * type:BAM type. + * mode:BAM mode. + * pipe_pair:The pipe pairs to be used to access the BAM. + * threshold:This Register holds a threshold value for the + * counter summing the Size of the Descriptors Provided. + * init:Pipe initialization status for the BAM. + */ +struct bam_instance { + uint32_t base; + enum bam_type type; + enum bam_mode mode; + uint8_t num_of_pipes; + struct bam_pipe pipe[3]; + uint16_t threshold; + void (*callback)(int); +}; + +/* Command element(CE) structure*/ +struct cmd_element { + uint32_t addr_n_cmd; + uint32_t reg_data; + uint32_t reg_mask; + uint32_t reserve; +} __PACKED; + +#endif diff --git a/MSM8916Pkg/Include/Library/Pow2Lib.h b/MSM8916Pkg/Include/Library/Pow2Lib.h new file mode 100644 index 0000000..651ce28 --- /dev/null +++ b/MSM8916Pkg/Include/Library/Pow2Lib.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2008 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __LIBRARY_POW2_H +#define __LIBRARY_POW2_H + +#include + +/* routines for dealing with power of 2 values for efficiency */ +STATIC inline __ALWAYS_INLINE BOOLEAN ispow2(UINTN val) +{ + return ((val - 1) & val) == 0; +} + +STATIC inline __ALWAYS_INLINE UINTN log2(UINTN val) +{ + if (!ispow2(val)) + return 0; // undefined + + return __builtin_ctz(val); +} + +STATIC inline __ALWAYS_INLINE UINTN valpow2(UINTN valp2) +{ + return 1 << valp2; +} + +STATIC inline __ALWAYS_INLINE UINTN divpow2(UINTN val, UINTN divp2) +{ + return val >> divp2; +} + +STATIC inline __ALWAYS_INLINE UINTN modpow2(UINTN val, UINTN modp2) +{ + return val & ((1UL << modp2) - 1); +} + + +#endif diff --git a/MSM8916Pkg/Include/Protocol/QcomBam.h b/MSM8916Pkg/Include/Protocol/QcomBam.h new file mode 100644 index 0000000..9575a93 --- /dev/null +++ b/MSM8916Pkg/Include/Protocol/QcomBam.h @@ -0,0 +1,35 @@ +#ifndef __QCOM_PROTOCOL_BAM_H__ +#define __QCOM_PROTOCOL_BAM_H__ + +#include + +#define QCOM_BAM_PROTOCOL_GUID \ + { 0xacdd545a, 0xf1f6, 0x4272, { 0x81, 0xc5, 0x04, 0x93, 0xe3, 0x58, 0x05, 0x32 } } + +typedef struct _QCOM_BAM_PROTOCOL QCOM_BAM_PROTOCOL; + +typedef void (EFIAPI *bam_init_t)(struct bam_instance *bam); +typedef void (EFIAPI *bam_sys_pipe_init_t)(struct bam_instance *bam, uint8_t pipe_num); +typedef int (EFIAPI *bam_pipe_fifo_init_t)(struct bam_instance *bam, uint8_t pipe_num); +typedef struct cmd_element* (EFIAPI *bam_add_cmd_element_t)(struct cmd_element *ptr, uint32_t addr, uint32_t data, enum bam_ce_cmd_t cmd_type); +typedef int (EFIAPI *bam_add_desc_t)(struct bam_instance *bam, unsigned int pipe_num, unsigned char *data_ptr, unsigned int data_len, unsigned flags); +typedef int (EFIAPI *bam_add_one_desc_t)(struct bam_instance *bam, unsigned int pipe_num, unsigned char*, uint32_t len, uint8_t flags); +typedef void (EFIAPI *bam_sys_gen_event_t)(struct bam_instance *bam, uint8_t pipe_num, unsigned int num_desc); +typedef int (EFIAPI *bam_wait_for_interrupt_t)(struct bam_instance *bam, uint8_t pipe_num, enum p_int_type interrupt); +typedef void (EFIAPI *bam_read_offset_update_t)(struct bam_instance *bam, unsigned int pipe_num); + +struct _QCOM_BAM_PROTOCOL { + bam_init_t bam_init; + bam_sys_pipe_init_t bam_sys_pipe_init; + bam_pipe_fifo_init_t bam_pipe_fifo_init; + bam_add_cmd_element_t bam_add_cmd_element; + bam_add_desc_t bam_add_desc; + bam_add_one_desc_t bam_add_one_desc; + bam_sys_gen_event_t bam_sys_gen_event; + bam_wait_for_interrupt_t bam_wait_for_interrupt; + bam_read_offset_update_t bam_read_offset_update; +}; + +extern EFI_GUID gQcomBamProtocolGuid; + +#endif diff --git a/MSM8916Pkg/MSM8916Pkg.dec b/MSM8916Pkg/MSM8916Pkg.dec index f87feff..09cd2d4 100644 --- a/MSM8916Pkg/MSM8916Pkg.dec +++ b/MSM8916Pkg/MSM8916Pkg.dec @@ -34,6 +34,7 @@ [Protocols] gEFIDroidKeypadDeviceProtocolGuid = { 0xb27625b5, 0x0b6c, 0x4614, { 0xaa, 0x3c, 0x33, 0x13, 0xb5, 0x1d, 0x36, 0x46 } } gQcomClockProtocolGuid = { 0x4fcc91c2, 0x9c4f, 0x4e3c, { 0xa6, 0x73, 0xc6, 0xdf, 0x62, 0xe0, 0x41, 0xd5 } } + gQcomBamProtocolGuid = { 0xacdd545a, 0xf1f6, 0x4272, { 0x81, 0xc5, 0x04, 0x93, 0xe3, 0x58, 0x05, 0x32 } } [PcdsFixedAtBuild.common] # Simple FrameBuffer diff --git a/MSM8916Pkg/MSM8916Pkg.dsc b/MSM8916Pkg/MSM8916Pkg.dsc index 21f5064..a95901b 100644 --- a/MSM8916Pkg/MSM8916Pkg.dsc +++ b/MSM8916Pkg/MSM8916Pkg.dsc @@ -203,6 +203,7 @@ # MSM8916Pkg/Drivers/ClockDxe/ClockDxe.inf + MSM8916Pkg/Drivers/BamDxe/BamDxe.inf # # Virtual Keyboard diff --git a/MSM8916Pkg/MSM8916Pkg.fdf b/MSM8916Pkg/MSM8916Pkg.fdf index 4053ee3..baa2237 100644 --- a/MSM8916Pkg/MSM8916Pkg.fdf +++ b/MSM8916Pkg/MSM8916Pkg.fdf @@ -157,6 +157,7 @@ READ_LOCK_STATUS = TRUE # SoC Drivers # INF MSM8916Pkg/Drivers/ClockDxe/ClockDxe.inf + INF MSM8916Pkg/Drivers/BamDxe/BamDxe.inf # # USB Host Support