/* 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. */ /* * Function and data structure declarations for SPS BAM handling. */ #ifndef _SPSBAM_H_ #define _SPSBAM_H_ #include #include #include #include #include #include "spsi.h" #define BAM_HANDLE_INVALID 0 #define to_sps_bam_dev(x) \ container_of((x), struct sps_bam, base) enum bam_irq { BAM_DEV_IRQ_RDY_TO_SLEEP = 0x00000001, BAM_DEV_IRQ_HRESP_ERROR = 0x00000002, BAM_DEV_IRQ_ERROR = 0x00000004, BAM_DEV_IRQ_TIMER = 0x00000010, }; /* Pipe interrupt mask */ enum bam_pipe_irq { /* BAM finishes descriptor which has INT bit selected */ BAM_PIPE_IRQ_DESC_INT = 0x00000001, /* Inactivity timer Expires */ BAM_PIPE_IRQ_TIMER = 0x00000002, /* Wakeup peripheral (i.e. USB) */ BAM_PIPE_IRQ_WAKE = 0x00000004, /* Producer - no free space for adding a descriptor */ /* Consumer - no descriptors for processing */ BAM_PIPE_IRQ_OUT_OF_DESC = 0x00000008, /* Pipe Error interrupt */ BAM_PIPE_IRQ_ERROR = 0x00000010, /* End-Of-Transfer */ BAM_PIPE_IRQ_EOT = 0x00000020, /* Pipe RESET unsuccessful */ BAM_PIPE_IRQ_RST_ERROR = 0x00000040, /* Errorneous Hresponse by AHB MASTER */ BAM_PIPE_IRQ_HRESP_ERROR = 0x00000080, }; /* Halt Type */ enum bam_halt { BAM_HALT_OFF = 0, BAM_HALT_ON = 1, }; /* Threshold values of the DMA channels */ enum bam_dma_thresh_dma { BAM_DMA_THRESH_512 = 0x3, BAM_DMA_THRESH_256 = 0x2, BAM_DMA_THRESH_128 = 0x1, BAM_DMA_THRESH_64 = 0x0, }; /* Weight values of the DMA channels */ enum bam_dma_weight_dma { BAM_DMA_WEIGHT_HIGH = 7, BAM_DMA_WEIGHT_MED = 3, BAM_DMA_WEIGHT_LOW = 1, BAM_DMA_WEIGHT_DEFAULT = BAM_DMA_WEIGHT_LOW, BAM_DMA_WEIGHT_DISABLE = 0, }; /* Invalid pipe index value */ #define SPS_BAM_PIPE_INVALID ((u32)(-1)) /* Parameters for sps_bam_pipe_connect() */ struct sps_bam_connect_param { /* which end point must be initialized */ enum sps_mode mode; /* OR'd connection end point options (see SPS_O defines) */ u32 options; /* SETPEND/MTI interrupt generation parameters */ u32 irq_gen_addr; u32 irq_gen_data; }; /* Event registration struct */ struct sps_bam_event_reg { /* Client's event object handle */ struct completion *xfer_done; void (*callback)(struct sps_event_notify *notify); /* Event trigger mode */ enum sps_trigger mode; /* User pointer that will be provided in event payload data */ void *user; }; /* Descriptor FIFO cache entry */ struct sps_bam_desc_cache { struct sps_iovec iovec; void *user; /* User pointer registered with this transfer */ }; /* Forward declaration */ struct sps_bam; /* System mode control */ struct sps_bam_sys_mode { /* Descriptor FIFO control */ u8 *desc_buf; /* Descriptor FIFO for BAM pipe */ u32 desc_offset; /* Next new descriptor to be written to hardware */ u32 acked_offset; /* Next descriptor to be retired by software */ /* Descriptor cache control (!no_queue only) */ u8 *desc_cache; /* Software cache of descriptor FIFO contents */ u32 cache_offset; /* Next descriptor to be cached (ack_xfers only) */ /* User pointers associated with cached descriptors */ void **user_ptrs; /* Event handling */ struct sps_bam_event_reg event_regs[SPS_EVENT_INDEX(SPS_EVENT_MAX)]; struct list_head events_q; struct sps_q_event event; /* Temp storage for event creation */ int no_queue; /* Whether events are queued */ int ack_xfers; /* Whether client must ACK all descriptors */ int handler_eot; /* Whether EOT handling is in progress (debug) */ /* Statistics */ #ifdef SPS_BAM_STATISTICS u32 desc_wr_count; u32 desc_rd_count; u32 user_ptrs_count; u32 user_found; u32 int_flags; u32 eot_flags; u32 callback_events; u32 wait_events; u32 queued_events; u32 get_events; u32 get_iovecs; #endif /* SPS_BAM_STATISTICS */ }; /* BAM pipe descriptor */ struct sps_pipe { struct list_head list; /* Client state */ u32 client_state; struct sps_bam *bam; struct sps_connect connect; const struct sps_connection *map; /* Pipe parameters */ u32 state; u32 pipe_index; u32 pipe_index_mask; u32 irq_mask; int polled; int hybrid; bool late_eot; u32 irq_gen_addr; enum sps_mode mode; u32 num_descs; /* Size (number of elements) of descriptor FIFO */ u32 desc_size; /* Size (bytes) of descriptor FIFO */ int wake_up_is_one_shot; /* Whether WAKEUP event is a one-shot or not */ /* System mode control */ struct sps_bam_sys_mode sys; bool disconnecting; }; /* BAM device descriptor */ struct sps_bam { struct list_head list; /* BAM device properties, including connection defaults */ struct sps_bam_props props; /* BAM device state */ u32 state; struct mutex lock; void __iomem *base; /* BAM virtual base address */ u32 version; spinlock_t isr_lock; spinlock_t connection_lock; unsigned long irqsave_flags; /* Pipe state */ u32 pipe_active_mask; u32 pipe_remote_mask; struct sps_pipe *pipes[BAM_MAX_PIPES]; struct list_head pipes_q; /* Statistics */ u32 irq_from_disabled_pipe; u32 event_trigger_failures; void *ipc_log0; void *ipc_log1; void *ipc_log2; void *ipc_log3; void *ipc_log4; u32 ipc_loglevel; /* Desc cache pointers */ u8 *desc_cache_pointers[BAM_MAX_PIPES]; }; /** * BAM driver initialization * * This function initializes the BAM driver. * * @options - driver options bitflags (see SPS_OPT_*) * * @return 0 on success, negative value on error * */ int sps_bam_driver_init(u32 options); /** * BAM device initialization * * This function initializes a BAM device. * * @dev - pointer to BAM device descriptor * * @return 0 on success, negative value on error * */ int sps_bam_device_init(struct sps_bam *dev); /** * BAM device de-initialization * * This function de-initializes a BAM device. * * @dev - pointer to BAM device descriptor * * @return 0 on success, negative value on error * */ int sps_bam_device_de_init(struct sps_bam *dev); /** * BAM device reset * * This Function resets a BAM device. * * @dev - pointer to BAM device descriptor * * @return 0 on success, negative value on error * */ int sps_bam_reset(struct sps_bam *dev); /** * BAM device enable * * This function enables a BAM device. * * @dev - pointer to BAM device descriptor * * @return 0 on success, negative value on error * */ int sps_bam_enable(struct sps_bam *dev); /** * BAM device disable * * This Function disables a BAM device. * * @dev - pointer to BAM device descriptor * * @return 0 on success, negative value on error * */ int sps_bam_disable(struct sps_bam *dev); /** * Allocate a BAM pipe * * This function allocates a BAM pipe. * * @dev - pointer to BAM device descriptor * * @pipe_index - client-specified pipe index, or SPS_BAM_PIPE_INVALID if * any available pipe is acceptable * * @return - allocated pipe index, or SPS_BAM_PIPE_INVALID on error * */ u32 sps_bam_pipe_alloc(struct sps_bam *dev, u32 pipe_index); /** * Free a BAM pipe * * This function frees a BAM pipe. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * */ void sps_bam_pipe_free(struct sps_bam *dev, u32 pipe_index); /** * Establish BAM pipe connection * * This function establishes a connection for a BAM pipe (end point). * * @client - pointer to client pipe state struct * * @params - connection parameters * * @return 0 on success, negative value on error * */ int sps_bam_pipe_connect(struct sps_pipe *client, const struct sps_bam_connect_param *params); /** * Disconnect a BAM pipe connection * * This function disconnects a connection for a BAM pipe (end point). * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @return 0 on success, negative value on error * */ int sps_bam_pipe_disconnect(struct sps_bam *dev, u32 pipe_index); /** * Set BAM pipe parameters * * This function sets parameters for a BAM pipe. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @options - bitflag options (see SPS_O_*) * * @return 0 on success, negative value on error * */ int sps_bam_pipe_set_params(struct sps_bam *dev, u32 pipe_index, u32 options); /** * Enable a BAM pipe * * This function enables a BAM pipe. Note that this function * is separate from the pipe connect function to allow proper * sequencing of consumer enable followed by producer enable. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @return 0 on success, negative value on error * */ int sps_bam_pipe_enable(struct sps_bam *dev, u32 pipe_index); /** * Disable a BAM pipe * * This function disables a BAM pipe. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @return 0 on success, negative value on error * */ int sps_bam_pipe_disable(struct sps_bam *dev, u32 pipe_index); /** * Register an event for a BAM pipe * * This function registers an event for a BAM pipe. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @reg - pointer to event registration struct * * @return 0 on success, negative value on error * */ int sps_bam_pipe_reg_event(struct sps_bam *dev, u32 pipe_index, struct sps_register_event *reg); /** * Submit a transfer of a single buffer to a BAM pipe * * This function submits a transfer of a single buffer to a BAM pipe. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @addr - physical address of buffer to transfer * * @size - number of bytes to transfer * * @user - user pointer to register for event * * @flags - descriptor flags (see SPS_IOVEC_FLAG defines) * * @return 0 on success, negative value on error * */ int sps_bam_pipe_transfer_one(struct sps_bam *dev, u32 pipe_index, u32 addr, u32 size, void *user, u32 flags); /** * Submit a transfer to a BAM pipe * * This function submits a transfer to a BAM pipe. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @transfer - pointer to transfer struct * * @return 0 on success, negative value on error * */ int sps_bam_pipe_transfer(struct sps_bam *dev, u32 pipe_index, struct sps_transfer *transfer); /** * Get a BAM pipe event * * This function polls for a BAM pipe event. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @notify - pointer to event notification struct * * @return 0 on success, negative value on error * */ int sps_bam_pipe_get_event(struct sps_bam *dev, u32 pipe_index, struct sps_event_notify *notify); /** * Get processed I/O vector * * This function fetches the next processed I/O vector. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @iovec - Pointer to I/O vector struct (output). * This struct will be zeroed if there are no more processed I/O vectors. * * @return 0 on success, negative value on error */ int sps_bam_pipe_get_iovec(struct sps_bam *dev, u32 pipe_index, struct sps_iovec *iovec); /** * Determine whether a BAM pipe descriptor FIFO is empty * * This function returns the empty state of a BAM pipe descriptor FIFO. * * The pipe mutex must be locked before calling this function. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @empty - pointer to client's empty status word (boolean) * * @return 0 on success, negative value on error * */ int sps_bam_pipe_is_empty(struct sps_bam *dev, u32 pipe_index, u32 *empty); /** * Get number of free slots in a BAM pipe descriptor FIFO * * This function returns the number of free slots in a BAM pipe descriptor FIFO. * * The pipe mutex must be locked before calling this function. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @count - pointer to count status * * @return 0 on success, negative value on error * */ int sps_bam_get_free_count(struct sps_bam *dev, u32 pipe_index, u32 *count); /** * Set BAM pipe to satellite ownership * * This function sets the BAM pipe to satellite ownership. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @return 0 on success, negative value on error * */ int sps_bam_set_satellite(struct sps_bam *dev, u32 pipe_index); /** * Perform BAM pipe timer control * * This function performs BAM pipe timer control operations. * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @timer_ctrl - Pointer to timer control specification * * @timer_result - Pointer to buffer for timer operation result. * This argument can be NULL if no result is expected for the operation. * If non-NULL, the current timer value will always provided. * * @return 0 on success, negative value on error * */ int sps_bam_pipe_timer_ctrl(struct sps_bam *dev, u32 pipe_index, struct sps_timer_ctrl *timer_ctrl, struct sps_timer_result *timer_result); /** * Get the number of unused descriptors in the descriptor FIFO * of a pipe * * @dev - pointer to BAM device descriptor * * @pipe_index - pipe index * * @desc_num - number of unused descriptors * */ int sps_bam_pipe_get_unused_desc_num(struct sps_bam *dev, u32 pipe_index, u32 *desc_num); /* * sps_bam_check_irq - check IRQ of a BAM device. * @dev - pointer to BAM device descriptor * * This function checks any pending interrupt of a BAM device. * * Return: 0 on success, negative value on error */ int sps_bam_check_irq(struct sps_bam *dev); /* * sps_bam_pipe_pending_desc - checking pending descriptor. * @dev: BAM device handle * @pipe_index: pipe index * * This function checks if a pipe of a BAM has any pending descriptor. * * @return true if there is any desc pending */ bool sps_bam_pipe_pending_desc(struct sps_bam *dev, u32 pipe_index); /* * sps_bam_pipe_inject_zlt - inject a ZLT with EOT. * @dev: BAM device handle * @pipe_index: pipe index * * This function injects a ZLT with EOT for a pipe of a BAM. * * Return: 0 on success, negative value on error */ int sps_bam_pipe_inject_zlt(struct sps_bam *dev, u32 pipe_index); #endif /* _SPSBAM_H_ */