| /* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 and |
| * only version 2 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. |
| */ |
| |
| /** |
| * Smart-Peripheral-Switch (SPS) internal API. |
| */ |
| |
| #ifndef _SPSI_H_ |
| #define _SPSI_H_ |
| |
| #include <linux/types.h> /* u32 */ |
| #include <linux/list.h> /* list_head */ |
| #include <linux/kernel.h> /* pr_info() */ |
| #include <linux/compiler.h> |
| #include <linux/ratelimit.h> |
| #include <linux/ipc_logging.h> |
| |
| #include <linux/msm-sps.h> |
| |
| #include "sps_map.h" |
| |
| #if defined(CONFIG_PHYS_ADDR_T_64BIT) || defined(CONFIG_ARM_LPAE) |
| #define SPS_LPAE (true) |
| #else |
| #define SPS_LPAE (false) |
| #endif |
| |
| #define BAM_MAX_PIPES 31 |
| #define BAM_MAX_P_LOCK_GROUP_NUM 31 |
| |
| /* Adjust for offset of struct sps_q_event */ |
| #define SPS_EVENT_INDEX(e) ((e) - 1) |
| #define SPS_ERROR -1 |
| |
| /* BAM identifier used in log messages */ |
| #define BAM_ID(dev) (&(dev)->props.phys_addr) |
| |
| /* "Clear" value for the connection parameter struct */ |
| #define SPSRM_CLEAR 0xccccccccUL |
| #define SPSRM_ADDR_CLR \ |
| ((sizeof(int) == sizeof(long)) ? 0 : (SPSRM_CLEAR << 32)) |
| |
| #define MAX_MSG_LEN 80 |
| #define SPS_IPC_LOGPAGES 10 |
| #define SPS_IPC_REG_DUMP_FACTOR 3 |
| #define SPS_IPC_DEFAULT_LOGLEVEL 3 |
| #define SPS_IPC_MAX_LOGLEVEL 4 |
| |
| /* Connection mapping control struct */ |
| struct sps_rm { |
| struct list_head connections_q; |
| struct mutex lock; |
| }; |
| |
| /* SPS driver state struct */ |
| struct sps_drv { |
| struct class *dev_class; |
| dev_t dev_num; |
| struct device *dev; |
| struct clk *pmem_clk; |
| struct clk *bamdma_clk; |
| struct clk *dfab_clk; |
| |
| int is_ready; |
| |
| /* Platform data */ |
| phys_addr_t pipemem_phys_base; |
| u32 pipemem_size; |
| phys_addr_t bamdma_bam_phys_base; |
| u32 bamdma_bam_size; |
| phys_addr_t bamdma_dma_phys_base; |
| u32 bamdma_dma_size; |
| u32 bamdma_irq; |
| u32 bamdma_restricted_pipes; |
| |
| /* Driver options bitflags (see SPS_OPT_*) */ |
| u32 options; |
| |
| /* Mutex to protect BAM and connection queues */ |
| struct mutex lock; |
| |
| /* BAM devices */ |
| struct list_head bams_q; |
| |
| char *hal_bam_version; |
| |
| /* Connection control state */ |
| struct sps_rm connection_ctrl; |
| |
| void *ipc_log0; |
| void *ipc_log1; |
| void *ipc_log2; |
| void *ipc_log3; |
| void *ipc_log4; |
| |
| u32 ipc_loglevel; |
| }; |
| |
| extern struct sps_drv *sps; |
| extern u32 d_type; |
| extern bool enhd_pipe; |
| extern bool imem; |
| extern enum sps_bam_type bam_type; |
| |
| #ifdef CONFIG_DEBUG_FS |
| extern u8 debugfs_record_enabled; |
| extern u8 logging_option; |
| extern u8 debug_level_option; |
| extern u8 print_limit_option; |
| |
| #define SPS_IPC(idx, dev, msg, args...) do { \ |
| if (dev) { \ |
| if ((idx == 0) && (dev)->ipc_log0) \ |
| ipc_log_string((dev)->ipc_log0, \ |
| "%s: " msg, __func__, args); \ |
| else if ((idx == 1) && (dev)->ipc_log1) \ |
| ipc_log_string((dev)->ipc_log1, \ |
| "%s: " msg, __func__, args); \ |
| else if ((idx == 2) && (dev)->ipc_log2) \ |
| ipc_log_string((dev)->ipc_log2, \ |
| "%s: " msg, __func__, args); \ |
| else if ((idx == 3) && (dev)->ipc_log3) \ |
| ipc_log_string((dev)->ipc_log3, \ |
| "%s: " msg, __func__, args); \ |
| else if ((idx == 4) && (dev)->ipc_log4) \ |
| ipc_log_string((dev)->ipc_log4, \ |
| "%s: " msg, __func__, args); \ |
| else \ |
| pr_debug("sps: no such IPC logging index!\n"); \ |
| } \ |
| } while (0) |
| #define SPS_DUMP(msg, args...) do { \ |
| SPS_IPC(4, sps, msg, args); \ |
| if (sps) { \ |
| if (sps->ipc_log4 == NULL) \ |
| pr_info(msg, ##args); \ |
| } \ |
| } while (0) |
| #define SPS_ERR(dev, msg, args...) do { \ |
| if (logging_option != 1) { \ |
| if (unlikely(print_limit_option > 2)) \ |
| pr_err_ratelimited(msg, ##args); \ |
| else \ |
| pr_err(msg, ##args); \ |
| } \ |
| SPS_IPC(3, dev, msg, args); \ |
| } while (0) |
| #define SPS_INFO(dev, msg, args...) do { \ |
| if (logging_option != 1) { \ |
| if (unlikely(print_limit_option > 1)) \ |
| pr_info_ratelimited(msg, ##args); \ |
| else \ |
| pr_info(msg, ##args); \ |
| } \ |
| SPS_IPC(3, dev, msg, args); \ |
| } while (0) |
| #define SPS_DBG(dev, msg, args...) do { \ |
| if ((unlikely(logging_option > 1)) \ |
| && (unlikely(debug_level_option > 3))) {\ |
| if (unlikely(print_limit_option > 0)) \ |
| pr_info_ratelimited(msg, ##args); \ |
| else \ |
| pr_info(msg, ##args); \ |
| } else \ |
| pr_debug(msg, ##args); \ |
| if (dev) { \ |
| if ((dev)->ipc_loglevel <= 0) \ |
| SPS_IPC(0, dev, msg, args); \ |
| } \ |
| } while (0) |
| #define SPS_DBG1(dev, msg, args...) do { \ |
| if ((unlikely(logging_option > 1)) \ |
| && (unlikely(debug_level_option > 2))) {\ |
| if (unlikely(print_limit_option > 0)) \ |
| pr_info_ratelimited(msg, ##args); \ |
| else \ |
| pr_info(msg, ##args); \ |
| } else \ |
| pr_debug(msg, ##args); \ |
| if (dev) { \ |
| if ((dev)->ipc_loglevel <= 1) \ |
| SPS_IPC(1, dev, msg, args); \ |
| } \ |
| } while (0) |
| #define SPS_DBG2(dev, msg, args...) do { \ |
| if ((unlikely(logging_option > 1)) \ |
| && (unlikely(debug_level_option > 1))) {\ |
| if (unlikely(print_limit_option > 0)) \ |
| pr_info_ratelimited(msg, ##args); \ |
| else \ |
| pr_info(msg, ##args); \ |
| } else \ |
| pr_debug(msg, ##args); \ |
| if (dev) { \ |
| if ((dev)->ipc_loglevel <= 2) \ |
| SPS_IPC(2, dev, msg, args); \ |
| } \ |
| } while (0) |
| #define SPS_DBG3(dev, msg, args...) do { \ |
| if ((unlikely(logging_option > 1)) \ |
| && (unlikely(debug_level_option > 0))) {\ |
| if (unlikely(print_limit_option > 0)) \ |
| pr_info_ratelimited(msg, ##args); \ |
| else \ |
| pr_info(msg, ##args); \ |
| } else \ |
| pr_debug(msg, ##args); \ |
| if (dev) { \ |
| if ((dev)->ipc_loglevel <= 3) \ |
| SPS_IPC(3, dev, msg, args); \ |
| } \ |
| } while (0) |
| #else |
| #define SPS_DBG3(x...) pr_debug(x) |
| #define SPS_DBG2(x...) pr_debug(x) |
| #define SPS_DBG1(x...) pr_debug(x) |
| #define SPS_DBG(x...) pr_debug(x) |
| #define SPS_INFO(x...) pr_info(x) |
| #define SPS_ERR(x...) pr_err(x) |
| #define SPS_DUMP(x...) pr_info(x) |
| #endif |
| |
| /* End point parameters */ |
| struct sps_conn_end_pt { |
| unsigned long dev; /* Device handle of BAM */ |
| phys_addr_t bam_phys; /* Physical address of BAM. */ |
| u32 pipe_index; /* Pipe index */ |
| u32 event_threshold; /* Pipe event threshold */ |
| u32 lock_group; /* The lock group this pipe belongs to */ |
| void *bam; |
| }; |
| |
| /* Connection bookkeeping descriptor struct */ |
| struct sps_connection { |
| struct list_head list; |
| |
| /* Source end point parameters */ |
| struct sps_conn_end_pt src; |
| |
| /* Destination end point parameters */ |
| struct sps_conn_end_pt dest; |
| |
| /* Resource parameters */ |
| struct sps_mem_buffer desc; /* Descriptor FIFO */ |
| struct sps_mem_buffer data; /* Data FIFO (BAM-to-BAM mode only) */ |
| u32 config; /* Client specified connection configuration */ |
| |
| /* Connection state */ |
| void *client_src; |
| void *client_dest; |
| int refs; /* Reference counter */ |
| |
| /* Dynamically allocated resources, if required */ |
| u32 alloc_src_pipe; /* Source pipe index */ |
| u32 alloc_dest_pipe; /* Destination pipe index */ |
| /* Physical address of descriptor FIFO */ |
| phys_addr_t alloc_desc_base; |
| phys_addr_t alloc_data_base; /* Physical address of data FIFO */ |
| }; |
| |
| /* Event bookkeeping descriptor struct */ |
| struct sps_q_event { |
| struct list_head list; |
| /* Event payload data */ |
| struct sps_event_notify notify; |
| }; |
| |
| /* Memory heap statistics */ |
| struct sps_mem_stats { |
| u32 base_addr; |
| u32 size; |
| u32 blocks_used; |
| u32 bytes_used; |
| u32 max_bytes_used; |
| }; |
| |
| enum sps_bam_type { |
| SPS_BAM_LEGACY, |
| SPS_BAM_NDP, |
| SPS_BAM_NDP_4K |
| }; |
| |
| #ifdef CONFIG_DEBUG_FS |
| /* record debug info for debugfs */ |
| void sps_debugfs_record(const char *msg); |
| #endif |
| |
| /* output the content of BAM-level registers */ |
| void print_bam_reg(void *virt_addr); |
| |
| /* output the content of BAM pipe registers */ |
| void print_bam_pipe_reg(void *virt_addr, u32 pipe_index); |
| |
| /* output the content of selected BAM-level registers */ |
| void print_bam_selected_reg(void *virt_addr, u32 pipe_index); |
| |
| /* output the content of selected BAM pipe registers */ |
| void print_bam_pipe_selected_reg(void *virt_addr, u32 pipe_index); |
| |
| /* output descriptor FIFO of a pipe */ |
| void print_bam_pipe_desc_fifo(void *virt_addr, u32 pipe_index, u32 option); |
| |
| /* output BAM_TEST_BUS_REG */ |
| void print_bam_test_bus_reg(void *base, u32 tb_sel); |
| |
| /* halt and un-halt a pipe */ |
| void bam_pipe_halt(void *base, u32 pipe, bool halt); |
| |
| /** |
| * Translate physical to virtual address |
| * |
| * This Function translates physical to virtual address. |
| * |
| * @phys_addr - physical address to translate |
| * |
| * @return virtual memory pointer |
| * |
| */ |
| void *spsi_get_mem_ptr(phys_addr_t phys_addr); |
| |
| /** |
| * Allocate I/O (pipe) memory |
| * |
| * This function allocates target I/O (pipe) memory. |
| * |
| * @bytes - number of bytes to allocate |
| * |
| * @return physical address of allocated memory, or SPS_ADDR_INVALID on error |
| */ |
| phys_addr_t sps_mem_alloc_io(u32 bytes); |
| |
| /** |
| * Free I/O (pipe) memory |
| * |
| * This function frees target I/O (pipe) memory. |
| * |
| * @phys_addr - physical address of memory to free |
| * |
| * @bytes - number of bytes to free. |
| */ |
| void sps_mem_free_io(phys_addr_t phys_addr, u32 bytes); |
| |
| /** |
| * Find matching connection mapping |
| * |
| * This function searches for a connection mapping that matches the |
| * parameters supplied by the client. If a match is found, the client's |
| * parameter struct is updated with the values specified in the mapping. |
| * |
| * @connect - pointer to client connection parameters |
| * |
| * @return 0 if match is found, negative value otherwise |
| * |
| */ |
| int sps_map_find(struct sps_connect *connect); |
| |
| /** |
| * Allocate a BAM DMA pipe |
| * |
| * This function allocates a BAM DMA pipe, and is intended to be called |
| * internally from the BAM resource manager. Allocation implies that |
| * the pipe has been referenced by a client Connect() and is in use. |
| * |
| * BAM DMA is permissive with activations, and allows a pipe to be allocated |
| * with or without a client-initiated allocation. This allows the client to |
| * specify exactly which pipe should be used directly through the Connect() API. |
| * sps_dma_alloc_chan() does not allow the client to specify the pipes/channel. |
| * |
| * @bam - pointer to BAM device descriptor |
| * |
| * @pipe_index - pipe index |
| * |
| * @dir - pipe direction |
| * |
| * @return 0 on success, negative value on error |
| */ |
| int sps_dma_pipe_alloc(void *bam, u32 pipe_index, enum sps_mode dir); |
| |
| /** |
| * Enable a BAM DMA pipe |
| * |
| * This function enables the channel associated with a BAM DMA pipe, and |
| * is intended to be called internally from the BAM resource manager. |
| * Enable must occur *after* the pipe has been enabled so that proper |
| * sequencing between pipe and DMA channel enables can be enforced. |
| * |
| * @bam - pointer to BAM device descriptor |
| * |
| * @pipe_index - pipe index |
| * |
| * @return 0 on success, negative value on error |
| * |
| */ |
| int sps_dma_pipe_enable(void *bam, u32 pipe_index); |
| |
| /** |
| * Free a BAM DMA pipe |
| * |
| * This function disables and frees a BAM DMA pipe, and is intended to be |
| * called internally from the BAM resource manager. This must occur *after* |
| * the pipe has been disabled/reset so that proper sequencing between pipe and |
| * DMA channel resets can be enforced. |
| * |
| * @bam_arg - pointer to BAM device descriptor |
| * |
| * @pipe_index - pipe index |
| * |
| * @return 0 on success, negative value on error |
| * |
| */ |
| int sps_dma_pipe_free(void *bam, u32 pipe_index); |
| |
| /** |
| * Initialize driver memory module |
| * |
| * This function initializes the driver memory module. |
| * |
| * @pipemem_phys_base - Pipe-Memory physical base. |
| * |
| * @pipemem_size - Pipe-Memory size. |
| * |
| * @return 0 on success, negative value on error |
| * |
| */ |
| int sps_mem_init(phys_addr_t pipemem_phys_base, u32 pipemem_size); |
| |
| /** |
| * De-initialize driver memory module |
| * |
| * This function de-initializes the driver memory module. |
| * |
| * @return 0 on success, negative value on error |
| * |
| */ |
| int sps_mem_de_init(void); |
| |
| /** |
| * Initialize BAM DMA module |
| * |
| * This function initializes the BAM DMA module. |
| * |
| * @bam_props - pointer to BAM DMA devices BSP configuration properties |
| * |
| * @return 0 on success, negative value on error |
| * |
| */ |
| int sps_dma_init(const struct sps_bam_props *bam_props); |
| |
| /** |
| * De-initialize BAM DMA module |
| * |
| * This function de-initializes the SPS BAM DMA module. |
| * |
| */ |
| void sps_dma_de_init(void); |
| |
| /** |
| * Initialize BAM DMA device |
| * |
| * This function initializes a BAM DMA device. |
| * |
| * @h - BAM handle |
| * |
| * @return 0 on success, negative value on error |
| * |
| */ |
| int sps_dma_device_init(unsigned long h); |
| |
| /** |
| * De-initialize BAM DMA device |
| * |
| * This function de-initializes a BAM DMA device. |
| * |
| * @h - BAM handle |
| * |
| * @return 0 on success, negative value on error |
| * |
| */ |
| int sps_dma_device_de_init(unsigned long h); |
| |
| /** |
| * Initialize connection mapping module |
| * |
| * This function initializes the SPS connection mapping module. |
| * |
| * @map_props - pointer to connection mapping BSP configuration properties |
| * |
| * @options - driver options bitflags (see SPS_OPT_*) |
| * |
| * @return 0 on success, negative value on error |
| * |
| */ |
| |
| int sps_map_init(const struct sps_map *map_props, u32 options); |
| |
| /** |
| * De-initialize connection mapping module |
| * |
| * This function de-initializes the SPS connection mapping module. |
| * |
| */ |
| void sps_map_de_init(void); |
| |
| /* |
| * bam_pipe_reset - reset a BAM pipe. |
| * @base: BAM virtual address |
| * @pipe: pipe index |
| * |
| * This function resets a BAM pipe. |
| */ |
| void bam_pipe_reset(void *base, u32 pipe); |
| |
| /* |
| * bam_disable_pipe - disable a BAM pipe. |
| * @base: BAM virtual address |
| * @pipe: pipe index |
| * |
| * This function disables a BAM pipe. |
| */ |
| void bam_disable_pipe(void *base, u32 pipe); |
| #endif /* _SPSI_H_ */ |