Loading drivers/platform/msm/gsi/gsi.c +68 −2 Original line number Diff line number Diff line Loading @@ -264,6 +264,11 @@ static void gsi_handle_glob_err(uint32_t err) } } static void gsi_handle_gp_int1(void) { complete(&gsi_ctx->gen_ee_cmd_compl); } static void gsi_handle_glob_ee(int ee) { uint32_t val; Loading @@ -288,8 +293,7 @@ static void gsi_handle_glob_ee(int ee) } if (val & GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT1_BMSK) { notify.evt_id = GSI_PER_EVT_GLOB_GP1; gsi_ctx->per.notify_cb(¬ify); gsi_handle_gp_int1(); } if (val & GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT2_BMSK) { Loading Loading @@ -2745,6 +2749,67 @@ void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, } EXPORT_SYMBOL(gsi_get_inst_ram_offset_and_size); int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code) { enum gsi_generic_ee_cmd_opcode op = GSI_GEN_EE_CMD_HALT_CHANNEL; uint32_t val; int res; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } if (chan_idx >= gsi_ctx->max_ch || !code) { GSIERR("bad params chan_idx=%d\n", chan_idx); return -GSI_STATUS_INVALID_PARAMS; } mutex_lock(&gsi_ctx->mlock); reinit_completion(&gsi_ctx->gen_ee_cmd_compl); /* invalidate the response */ gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee)); gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code = 0; gsi_writel(gsi_ctx->scratch.word0.val, gsi_ctx->base + GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee)); gsi_ctx->gen_ee_cmd_dbg.halt_channel++; val = (((op << GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT) & GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK) | ((chan_idx << GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT) & GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK) | ((ee << GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT) & GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK)); gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_EE_GENERIC_CMD_OFFS(gsi_ctx->per.ee)); res = wait_for_completion_timeout(&gsi_ctx->gen_ee_cmd_compl, msecs_to_jiffies(GSI_CMD_TIMEOUT)); if (res == 0) { GSIERR("chan_idx=%u ee=%u timed out\n", chan_idx, ee); res = -GSI_STATUS_TIMED_OUT; goto free_lock; } gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee)); if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code == 0) { GSIERR("No response received\n"); res = -GSI_STATUS_ERROR; goto free_lock; } res = GSI_STATUS_SUCCESS; *code = gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code; free_lock: mutex_unlock(&gsi_ctx->mlock); return res; } EXPORT_SYMBOL(gsi_halt_channel_ee); static int msm_gsi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; Loading @@ -2757,6 +2822,7 @@ static int msm_gsi_probe(struct platform_device *pdev) } gsi_ctx->dev = dev; init_completion(&gsi_ctx->gen_ee_cmd_compl); gsi_debugfs_init(); return 0; Loading drivers/platform/msm/gsi/gsi.h +24 −3 Original line number Diff line number Diff line /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-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 Loading Loading @@ -115,9 +115,12 @@ struct gsi_evt_ctx { struct gsi_ee_scratch { union __packed { struct { uint32_t resvd1:15; uint32_t inter_ee_cmd_return_code:3; uint32_t resvd1:2; uint32_t generic_ee_cmd_return_code:3; uint32_t resvd2:7; uint32_t max_usb_pkt_size:1; uint32_t resvd2:8; uint32_t resvd3:8; uint32_t mhi_base_chan_idx:8; } s; uint32_t val; Loading @@ -135,6 +138,10 @@ struct ch_debug_stats { unsigned long cmd_completed; }; struct gsi_generic_ee_cmd_debug_stats { unsigned long halt_channel; }; struct gsi_ctx { void __iomem *base; struct device *dev; Loading @@ -143,6 +150,7 @@ struct gsi_ctx { struct gsi_chan_ctx chan[GSI_CHAN_MAX]; struct ch_debug_stats ch_dbg[GSI_CHAN_MAX]; struct gsi_evt_ctx evtr[GSI_EVT_RING_MAX]; struct gsi_generic_ee_cmd_debug_stats gen_ee_cmd_dbg; struct mutex mlock; spinlock_t slock; unsigned long evt_bmap; Loading @@ -154,6 +162,7 @@ struct gsi_ctx { struct workqueue_struct *dp_stat_wq; u32 max_ch; u32 max_ev; struct completion gen_ee_cmd_compl; }; enum gsi_re_type { Loading Loading @@ -227,6 +236,18 @@ enum gsi_evt_ch_cmd_opcode { GSI_EVT_DE_ALLOC = 0xa, }; enum gsi_generic_ee_cmd_opcode { GSI_GEN_EE_CMD_HALT_CHANNEL = 0x1, }; enum gsi_generic_ee_cmd_return_code { GSI_GEN_EE_CMD_RETURN_CODE_SUCCESS = 0x1, GSI_GEN_EE_CMD_RETURN_CODE_CHANNEL_NOT_RUNNING = 0x2, GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_DIRECTION = 0x3, GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_TYPE = 0x4, GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_INDEX = 0x5, }; extern struct gsi_ctx *gsi_ctx; void gsi_debugfs_init(void); uint16_t gsi_find_idx_from_addr(struct gsi_ring_ctx *ctx, uint64_t addr); Loading drivers/platform/msm/gsi/gsi_reg.h +5 −1 Original line number Diff line number Diff line Loading @@ -1365,8 +1365,12 @@ (GSI_GSI_REG_BASE_OFFS + 0x0001f018 + 0x4000 * (n)) #define GSI_EE_n_GSI_EE_GENERIC_CMD_RMSK 0xffffffff #define GSI_EE_n_GSI_EE_GENERIC_CMD_MAXn 3 #define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK 0xffffffff #define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK 0x1f #define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT 0x0 #define GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK 0x3e0 #define GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT 0x5 #define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK 0x3c00 #define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT 0xa /* v1.0 */ #define GSI_V1_0_EE_n_GSI_HW_PARAM_OFFS(n) \ Loading include/linux/msm_gsi.h +18 −0 Original line number Diff line number Diff line Loading @@ -1053,6 +1053,18 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size); void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, unsigned long *size); /** * gsi_halt_channel_ee - Peripheral should call this function * to stop other EE's channel. This is usually used in SSR clean * * @chan_idx: Virtual channel index * @ee: EE * @code: [out] response code for operation * @Return gsi_status */ int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code); /* * Here is a typical sequence of calls * Loading Loading @@ -1250,5 +1262,11 @@ static inline void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, unsigned long *size) { } static inline int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code) { return -GSI_STATUS_UNSUPPORTED_OP; } #endif #endif Loading
drivers/platform/msm/gsi/gsi.c +68 −2 Original line number Diff line number Diff line Loading @@ -264,6 +264,11 @@ static void gsi_handle_glob_err(uint32_t err) } } static void gsi_handle_gp_int1(void) { complete(&gsi_ctx->gen_ee_cmd_compl); } static void gsi_handle_glob_ee(int ee) { uint32_t val; Loading @@ -288,8 +293,7 @@ static void gsi_handle_glob_ee(int ee) } if (val & GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT1_BMSK) { notify.evt_id = GSI_PER_EVT_GLOB_GP1; gsi_ctx->per.notify_cb(¬ify); gsi_handle_gp_int1(); } if (val & GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT2_BMSK) { Loading Loading @@ -2745,6 +2749,67 @@ void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, } EXPORT_SYMBOL(gsi_get_inst_ram_offset_and_size); int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code) { enum gsi_generic_ee_cmd_opcode op = GSI_GEN_EE_CMD_HALT_CHANNEL; uint32_t val; int res; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } if (chan_idx >= gsi_ctx->max_ch || !code) { GSIERR("bad params chan_idx=%d\n", chan_idx); return -GSI_STATUS_INVALID_PARAMS; } mutex_lock(&gsi_ctx->mlock); reinit_completion(&gsi_ctx->gen_ee_cmd_compl); /* invalidate the response */ gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee)); gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code = 0; gsi_writel(gsi_ctx->scratch.word0.val, gsi_ctx->base + GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee)); gsi_ctx->gen_ee_cmd_dbg.halt_channel++; val = (((op << GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT) & GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK) | ((chan_idx << GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT) & GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK) | ((ee << GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT) & GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK)); gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_EE_GENERIC_CMD_OFFS(gsi_ctx->per.ee)); res = wait_for_completion_timeout(&gsi_ctx->gen_ee_cmd_compl, msecs_to_jiffies(GSI_CMD_TIMEOUT)); if (res == 0) { GSIERR("chan_idx=%u ee=%u timed out\n", chan_idx, ee); res = -GSI_STATUS_TIMED_OUT; goto free_lock; } gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee)); if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code == 0) { GSIERR("No response received\n"); res = -GSI_STATUS_ERROR; goto free_lock; } res = GSI_STATUS_SUCCESS; *code = gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code; free_lock: mutex_unlock(&gsi_ctx->mlock); return res; } EXPORT_SYMBOL(gsi_halt_channel_ee); static int msm_gsi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; Loading @@ -2757,6 +2822,7 @@ static int msm_gsi_probe(struct platform_device *pdev) } gsi_ctx->dev = dev; init_completion(&gsi_ctx->gen_ee_cmd_compl); gsi_debugfs_init(); return 0; Loading
drivers/platform/msm/gsi/gsi.h +24 −3 Original line number Diff line number Diff line /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-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 Loading Loading @@ -115,9 +115,12 @@ struct gsi_evt_ctx { struct gsi_ee_scratch { union __packed { struct { uint32_t resvd1:15; uint32_t inter_ee_cmd_return_code:3; uint32_t resvd1:2; uint32_t generic_ee_cmd_return_code:3; uint32_t resvd2:7; uint32_t max_usb_pkt_size:1; uint32_t resvd2:8; uint32_t resvd3:8; uint32_t mhi_base_chan_idx:8; } s; uint32_t val; Loading @@ -135,6 +138,10 @@ struct ch_debug_stats { unsigned long cmd_completed; }; struct gsi_generic_ee_cmd_debug_stats { unsigned long halt_channel; }; struct gsi_ctx { void __iomem *base; struct device *dev; Loading @@ -143,6 +150,7 @@ struct gsi_ctx { struct gsi_chan_ctx chan[GSI_CHAN_MAX]; struct ch_debug_stats ch_dbg[GSI_CHAN_MAX]; struct gsi_evt_ctx evtr[GSI_EVT_RING_MAX]; struct gsi_generic_ee_cmd_debug_stats gen_ee_cmd_dbg; struct mutex mlock; spinlock_t slock; unsigned long evt_bmap; Loading @@ -154,6 +162,7 @@ struct gsi_ctx { struct workqueue_struct *dp_stat_wq; u32 max_ch; u32 max_ev; struct completion gen_ee_cmd_compl; }; enum gsi_re_type { Loading Loading @@ -227,6 +236,18 @@ enum gsi_evt_ch_cmd_opcode { GSI_EVT_DE_ALLOC = 0xa, }; enum gsi_generic_ee_cmd_opcode { GSI_GEN_EE_CMD_HALT_CHANNEL = 0x1, }; enum gsi_generic_ee_cmd_return_code { GSI_GEN_EE_CMD_RETURN_CODE_SUCCESS = 0x1, GSI_GEN_EE_CMD_RETURN_CODE_CHANNEL_NOT_RUNNING = 0x2, GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_DIRECTION = 0x3, GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_TYPE = 0x4, GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_INDEX = 0x5, }; extern struct gsi_ctx *gsi_ctx; void gsi_debugfs_init(void); uint16_t gsi_find_idx_from_addr(struct gsi_ring_ctx *ctx, uint64_t addr); Loading
drivers/platform/msm/gsi/gsi_reg.h +5 −1 Original line number Diff line number Diff line Loading @@ -1365,8 +1365,12 @@ (GSI_GSI_REG_BASE_OFFS + 0x0001f018 + 0x4000 * (n)) #define GSI_EE_n_GSI_EE_GENERIC_CMD_RMSK 0xffffffff #define GSI_EE_n_GSI_EE_GENERIC_CMD_MAXn 3 #define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK 0xffffffff #define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK 0x1f #define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT 0x0 #define GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK 0x3e0 #define GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT 0x5 #define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK 0x3c00 #define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT 0xa /* v1.0 */ #define GSI_V1_0_EE_n_GSI_HW_PARAM_OFFS(n) \ Loading
include/linux/msm_gsi.h +18 −0 Original line number Diff line number Diff line Loading @@ -1053,6 +1053,18 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size); void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, unsigned long *size); /** * gsi_halt_channel_ee - Peripheral should call this function * to stop other EE's channel. This is usually used in SSR clean * * @chan_idx: Virtual channel index * @ee: EE * @code: [out] response code for operation * @Return gsi_status */ int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code); /* * Here is a typical sequence of calls * Loading Loading @@ -1250,5 +1262,11 @@ static inline void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, unsigned long *size) { } static inline int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code) { return -GSI_STATUS_UNSUPPORTED_OP; } #endif #endif