| /* linux/include/asm-arm/arch-msm/msm_smd.h |
| * |
| * Copyright (C) 2007 Google, Inc. |
| * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved. |
| * Author: Brian Swetland <swetland@google.com> |
| * |
| * This software is licensed under the terms of the GNU General Public |
| * License version 2, as published by the Free Software Foundation, and |
| * may be copied, distributed, and modified under those terms. |
| * |
| * 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. |
| * |
| */ |
| |
| #ifndef __ASM_ARCH_MSM_SMD_H |
| #define __ASM_ARCH_MSM_SMD_H |
| |
| #include <linux/io.h> |
| #include <mach/msm_smsm.h> |
| |
| typedef struct smd_channel smd_channel_t; |
| |
| #define SMD_MAX_CH_NAME_LEN 20 /* includes null char at end */ |
| |
| #define SMD_EVENT_DATA 1 |
| #define SMD_EVENT_OPEN 2 |
| #define SMD_EVENT_CLOSE 3 |
| #define SMD_EVENT_STATUS 4 |
| #define SMD_EVENT_REOPEN_READY 5 |
| |
| /* |
| * SMD Processor ID's. |
| * |
| * For all processors that have both SMSM and SMD clients, |
| * the SMSM Processor ID and the SMD Processor ID will |
| * be the same. In cases where a processor only supports |
| * SMD, the entry will only exist in this enum. |
| */ |
| enum { |
| SMD_APPS = SMSM_APPS, |
| SMD_MODEM = SMSM_MODEM, |
| SMD_Q6 = SMSM_Q6, |
| SMD_WCNSS = SMSM_WCNSS, |
| SMD_DSPS = SMSM_DSPS, |
| SMD_MODEM_Q6_FW, |
| SMD_RPM, |
| NUM_SMD_SUBSYSTEMS, |
| }; |
| |
| enum { |
| SMD_APPS_MODEM = 0, |
| SMD_APPS_QDSP, |
| SMD_MODEM_QDSP, |
| SMD_APPS_DSPS, |
| SMD_MODEM_DSPS, |
| SMD_QDSP_DSPS, |
| SMD_APPS_WCNSS, |
| SMD_MODEM_WCNSS, |
| SMD_QDSP_WCNSS, |
| SMD_DSPS_WCNSS, |
| SMD_APPS_Q6FW, |
| SMD_MODEM_Q6FW, |
| SMD_QDSP_Q6FW, |
| SMD_DSPS_Q6FW, |
| SMD_WCNSS_Q6FW, |
| SMD_APPS_RPM, |
| SMD_MODEM_RPM, |
| SMD_QDSP_RPM, |
| SMD_WCNSS_RPM, |
| SMD_NUM_TYPE, |
| SMD_LOOPBACK_TYPE = 100, |
| |
| }; |
| |
| /* |
| * SMD IRQ Configuration |
| * |
| * Used to initialize IRQ configurations from platform data |
| * |
| * @irq_name: irq_name to query platform data |
| * @irq_id: initialized to -1 in platform data, stores actual irq id on |
| * successful registration |
| * @out_base: if not null then settings used for outgoing interrupt |
| * initialied from platform data |
| */ |
| |
| struct smd_irq_config { |
| /* incoming interrupt config */ |
| const char *irq_name; |
| unsigned long flags; |
| int irq_id; |
| const char *device_name; |
| const void *dev_id; |
| |
| /* outgoing interrupt config */ |
| uint32_t out_bit_pos; |
| void __iomem *out_base; |
| uint32_t out_offset; |
| }; |
| |
| /* |
| * SMD subsystem configurations |
| * |
| * SMD subsystems configurations for platform data. This contains the |
| * M2A and A2M interrupt configurations for both SMD and SMSM per |
| * subsystem. |
| * |
| * @subsys_name: name of subsystem passed to PIL |
| * @irq_config_id: unique id for each subsystem |
| * @edge: maps to actual remote subsystem edge |
| * |
| */ |
| struct smd_subsystem_config { |
| unsigned irq_config_id; |
| const char *subsys_name; |
| int edge; |
| |
| struct smd_irq_config smd_int; |
| struct smd_irq_config smsm_int; |
| |
| }; |
| |
| /* |
| * Subsystem Restart Configuration |
| * |
| * @disable_smsm_reset_handshake |
| */ |
| struct smd_subsystem_restart_config { |
| int disable_smsm_reset_handshake; |
| }; |
| |
| /* |
| * Shared Memory Regions |
| * |
| * the array of these regions is expected to be in ascending order by phys_addr |
| * |
| * @phys_addr: physical base address of the region |
| * @size: size of the region in bytes |
| */ |
| struct smd_smem_regions { |
| void *phys_addr; |
| unsigned size; |
| }; |
| |
| struct smd_platform { |
| uint32_t num_ss_configs; |
| struct smd_subsystem_config *smd_ss_configs; |
| struct smd_subsystem_restart_config *smd_ssr_config; |
| uint32_t num_smem_areas; |
| struct smd_smem_regions *smd_smem_areas; |
| }; |
| |
| #ifdef CONFIG_MSM_SMD |
| /* warning: notify() may be called before open returns */ |
| int smd_open(const char *name, smd_channel_t **ch, void *priv, |
| void (*notify)(void *priv, unsigned event)); |
| |
| int smd_close(smd_channel_t *ch); |
| |
| /* passing a null pointer for data reads and discards */ |
| int smd_read(smd_channel_t *ch, void *data, int len); |
| int smd_read_from_cb(smd_channel_t *ch, void *data, int len); |
| /* Same as smd_read() but takes a data buffer from userspace |
| * The function might sleep. Only safe to call from user context |
| */ |
| int smd_read_user_buffer(smd_channel_t *ch, void *data, int len); |
| |
| /* Write to stream channels may do a partial write and return |
| ** the length actually written. |
| ** Write to packet channels will never do a partial write -- |
| ** it will return the requested length written or an error. |
| */ |
| int smd_write(smd_channel_t *ch, const void *data, int len); |
| /* Same as smd_write() but takes a data buffer from userspace |
| * The function might sleep. Only safe to call from user context |
| */ |
| int smd_write_user_buffer(smd_channel_t *ch, const void *data, int len); |
| |
| int smd_write_avail(smd_channel_t *ch); |
| int smd_read_avail(smd_channel_t *ch); |
| |
| /* Returns the total size of the current packet being read. |
| ** Returns 0 if no packets available or a stream channel. |
| */ |
| int smd_cur_packet_size(smd_channel_t *ch); |
| |
| |
| #if 0 |
| /* these are interruptable waits which will block you until the specified |
| ** number of bytes are readable or writable. |
| */ |
| int smd_wait_until_readable(smd_channel_t *ch, int bytes); |
| int smd_wait_until_writable(smd_channel_t *ch, int bytes); |
| #endif |
| |
| /* these are used to get and set the IF sigs of a channel. |
| * DTR and RTS can be set; DSR, CTS, CD and RI can be read. |
| */ |
| int smd_tiocmget(smd_channel_t *ch); |
| int smd_tiocmset(smd_channel_t *ch, unsigned int set, unsigned int clear); |
| int |
| smd_tiocmset_from_cb(smd_channel_t *ch, unsigned int set, unsigned int clear); |
| int smd_named_open_on_edge(const char *name, uint32_t edge, smd_channel_t **_ch, |
| void *priv, void (*notify)(void *, unsigned)); |
| |
| /* Tells the other end of the smd channel that this end wants to recieve |
| * interrupts when the written data is read. Read interrupts should only |
| * enabled when there is no space left in the buffer to write to, thus the |
| * interrupt acts as notification that space may be avaliable. If the |
| * other side does not support enabling/disabling interrupts on demand, |
| * then this function has no effect if called. |
| */ |
| void smd_enable_read_intr(smd_channel_t *ch); |
| |
| /* Tells the other end of the smd channel that this end does not want |
| * interrupts when written data is read. The interrupts should be |
| * disabled by default. If the other side does not support enabling/ |
| * disabling interrupts on demand, then this function has no effect if |
| * called. |
| */ |
| void smd_disable_read_intr(smd_channel_t *ch); |
| |
| /** |
| * Enable/disable receive interrupts for the remote processor used by a |
| * particular channel. |
| * @ch: open channel handle to use for the edge |
| * @mask: 1 = mask interrupts; 0 = unmask interrupts |
| * @returns: 0 for success; < 0 for failure |
| * |
| * Note that this enables/disables all interrupts from the remote subsystem for |
| * all channels. As such, it should be used with care and only for specific |
| * use cases such as power-collapse sequencing. |
| */ |
| int smd_mask_receive_interrupt(smd_channel_t *ch, bool mask); |
| |
| /* Starts a packet transaction. The size of the packet may exceed the total |
| * size of the smd ring buffer. |
| * |
| * @ch: channel to write the packet to |
| * @len: total length of the packet |
| * |
| * Returns: |
| * 0 - success |
| * -ENODEV - invalid smd channel |
| * -EACCES - non-packet channel specified |
| * -EINVAL - invalid length |
| * -EBUSY - transaction already in progress |
| * -EAGAIN - no enough memory in ring buffer to start transaction |
| * -EPERM - unable to sucessfully start transaction due to write error |
| */ |
| int smd_write_start(smd_channel_t *ch, int len); |
| |
| /* Writes a segment of the packet for a packet transaction. |
| * |
| * @ch: channel to write packet to |
| * @data: buffer of data to write |
| * @len: length of data buffer |
| * @user_buf: (0) - buffer from kernelspace (1) - buffer from userspace |
| * |
| * Returns: |
| * number of bytes written |
| * -ENODEV - invalid smd channel |
| * -EINVAL - invalid length |
| * -ENOEXEC - transaction not started |
| */ |
| int smd_write_segment(smd_channel_t *ch, void *data, int len, int user_buf); |
| |
| /* Completes a packet transaction. Do not call from interrupt context. |
| * |
| * @ch: channel to complete transaction on |
| * |
| * Returns: |
| * 0 - success |
| * -ENODEV - invalid smd channel |
| * -E2BIG - some ammount of packet is not yet written |
| */ |
| int smd_write_end(smd_channel_t *ch); |
| |
| /* |
| * Returns a pointer to the subsystem name or NULL if no |
| * subsystem name is available. |
| * |
| * @type - Edge definition |
| */ |
| const char *smd_edge_to_subsystem(uint32_t type); |
| |
| /* |
| * Returns a pointer to the subsystem name given the |
| * remote processor ID. |
| * |
| * @pid Remote processor ID |
| * @returns Pointer to subsystem name or NULL if not found |
| */ |
| const char *smd_pid_to_subsystem(uint32_t pid); |
| |
| /* |
| * Checks to see if a new packet has arrived on the channel. Only to be |
| * called with interrupts disabled. |
| * |
| * @ch: channel to check if a packet has arrived |
| * |
| * Returns: |
| * 0 - packet not available |
| * 1 - packet available |
| * -EINVAL - NULL parameter or non-packet based channel provided |
| */ |
| int smd_is_pkt_avail(smd_channel_t *ch); |
| |
| /** |
| * smd_module_init_notifier_register() - Register a smd module |
| * init notifier block |
| * @nb: Notifier block to be registered |
| * |
| * In order to mark the dependency on SMD Driver module initialization |
| * register a notifier using this API. Once the smd module_init is |
| * done, notification will be passed to the registered module. |
| */ |
| int smd_module_init_notifier_register(struct notifier_block *nb); |
| |
| /** |
| * smd_module_init_notifier_register() - Unregister a smd module |
| * init notifier block |
| * @nb: Notifier block to be registered |
| */ |
| int smd_module_init_notifier_unregister(struct notifier_block *nb); |
| |
| /* |
| * SMD initialization function that registers for a SMD platform driver. |
| * |
| * returns success on successful driver registration. |
| */ |
| int __init msm_smd_init(void); |
| |
| #else |
| |
| static inline int smd_open(const char *name, smd_channel_t **ch, void *priv, |
| void (*notify)(void *priv, unsigned event)) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_close(smd_channel_t *ch) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_read(smd_channel_t *ch, void *data, int len) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_read_from_cb(smd_channel_t *ch, void *data, int len) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_read_user_buffer(smd_channel_t *ch, void *data, int len) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_write(smd_channel_t *ch, const void *data, int len) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int |
| smd_write_user_buffer(smd_channel_t *ch, const void *data, int len) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_write_avail(smd_channel_t *ch) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_read_avail(smd_channel_t *ch) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_cur_packet_size(smd_channel_t *ch) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_tiocmget(smd_channel_t *ch) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int |
| smd_tiocmset(smd_channel_t *ch, unsigned int set, unsigned int clear) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int |
| smd_tiocmset_from_cb(smd_channel_t *ch, unsigned int set, unsigned int clear) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int |
| smd_named_open_on_edge(const char *name, uint32_t edge, smd_channel_t **_ch, |
| void *priv, void (*notify)(void *, unsigned)) |
| { |
| return -ENODEV; |
| } |
| |
| static inline void smd_enable_read_intr(smd_channel_t *ch) |
| { |
| } |
| |
| static inline void smd_disable_read_intr(smd_channel_t *ch) |
| { |
| } |
| |
| static inline int smd_mask_receive_interrupt(smd_channel_t *ch, bool mask) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_write_start(smd_channel_t *ch, int len) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int |
| smd_write_segment(smd_channel_t *ch, void *data, int len, int user_buf) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_write_end(smd_channel_t *ch) |
| { |
| return -ENODEV; |
| } |
| |
| static inline const char *smd_edge_to_subsystem(uint32_t type) |
| { |
| return NULL; |
| } |
| |
| static inline const char *smd_pid_to_subsystem(uint32_t pid) |
| { |
| return NULL; |
| } |
| |
| static inline int smd_is_pkt_avail(smd_channel_t *ch) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_module_init_notifier_register(struct notifier_block *nb) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int smd_module_init_notifier_unregister(struct notifier_block *nb) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int __init msm_smd_init(void) |
| { |
| return 0; |
| } |
| #endif |
| |
| #endif |