Loading drivers/soc/qcom/bgcom_spi.c +73 −62 Original line number Diff line number Diff line Loading @@ -65,25 +65,33 @@ struct bg_spi_priv { int irq_lock; }; struct bg_context { struct bg_spi_priv *bg_spi; enum bgcom_state state; }; struct cb_data { struct bg_context *handle; void *priv; void *handle; void (*bgcom_notification_cb)(void *handle, void *priv, enum bgcom_event_type event, union bgcom_event_data_type *event_data); struct list_head list; }; static struct cb_data *irq_notification; struct bg_context { struct bg_spi_priv *bg_spi; enum bgcom_state state; struct cb_data *cb; }; static void *bg_com_drv; static uint32_t g_slav_status_reg; /* BGCOM client callbacks set-up */ static struct list_head cb_head = LIST_HEAD_INIT(cb_head); static inline void add_to_irq_list(struct cb_data *data) { list_add_tail(&data->list, &cb_head); } static bool is_bgcom_ready(void) { return bg_com_drv ? true : false; Loading Loading @@ -169,14 +177,20 @@ static int bgcom_transfer(void *handle, uint8_t *tx_buf, /* BG-COM Interrupt handling */ static inline void send_event(struct cb_data *cb, enum bgcom_event_type event, void *data) void send_event(enum bgcom_event_type event, void *data) { if (!cb) return; struct list_head *pos; struct cb_data *cb; /* send interrupt notification for each registered call-back */ list_for_each(pos, &cb_head) { cb = list_entry(pos, struct cb_data, list); cb->bgcom_notification_cb(cb->handle, cb->priv, event, data); } } static void send_back_notification(uint32_t slav_status_reg, uint32_t slav_status_auto_clear_reg, Loading @@ -192,73 +206,62 @@ static void send_back_notification(uint32_t slav_status_reg, slave_fifo_free = (uint16_t)(fifo_fill_reg >> 16); if (slav_status_auto_clear_reg & BIT(31)) send_event(irq_notification, BGCOM_EVENT_RESET_OCCURRED, NULL); send_event(BGCOM_EVENT_RESET_OCCURRED, NULL); if (slav_status_auto_clear_reg & BIT(30)) send_event(irq_notification, BGCOM_EVENT_ERROR_WRITE_FIFO_OVERRUN, NULL); send_event(BGCOM_EVENT_ERROR_WRITE_FIFO_OVERRUN, NULL); if (slav_status_auto_clear_reg & BIT(29)) send_event(irq_notification, BGCOM_EVENT_ERROR_WRITE_FIFO_BUS_ERR, NULL); send_event(BGCOM_EVENT_ERROR_WRITE_FIFO_BUS_ERR, NULL); if (slav_status_auto_clear_reg & BIT(28)) send_event(irq_notification, BGCOM_EVENT_ERROR_WRITE_FIFO_ACCESS, NULL); send_event(BGCOM_EVENT_ERROR_WRITE_FIFO_ACCESS, NULL); if (slav_status_auto_clear_reg & BIT(27)) send_event(irq_notification, BGCOM_EVENT_ERROR_READ_FIFO_UNDERRUN, NULL); send_event(BGCOM_EVENT_ERROR_READ_FIFO_UNDERRUN, NULL); if (slav_status_auto_clear_reg & BIT(26)) send_event(irq_notification, BGCOM_EVENT_ERROR_READ_FIFO_BUS_ERR, NULL); send_event(BGCOM_EVENT_ERROR_READ_FIFO_BUS_ERR, NULL); if (slav_status_auto_clear_reg & BIT(25)) send_event(irq_notification, BGCOM_EVENT_ERROR_READ_FIFO_ACCESS, NULL); send_event(BGCOM_EVENT_ERROR_READ_FIFO_ACCESS, NULL); if (slav_status_auto_clear_reg & BIT(24)) send_event(irq_notification, BGCOM_EVENT_ERROR_TRUNCATED_READ, NULL); send_event(BGCOM_EVENT_ERROR_TRUNCATED_READ, NULL); if (slav_status_auto_clear_reg & BIT(23)) send_event(irq_notification, BGCOM_EVENT_ERROR_TRUNCATED_WRITE, NULL); send_event(BGCOM_EVENT_ERROR_TRUNCATED_WRITE, NULL); if (slav_status_auto_clear_reg & BIT(22)) send_event(irq_notification, BGCOM_EVENT_ERROR_AHB_ILLEGAL_ADDRESS, NULL); send_event(BGCOM_EVENT_ERROR_AHB_ILLEGAL_ADDRESS, NULL); if (slav_status_auto_clear_reg & BIT(21)) send_event(irq_notification, BGCOM_EVENT_ERROR_AHB_BUS_ERR, NULL); send_event(BGCOM_EVENT_ERROR_AHB_BUS_ERR, NULL); /* check if BG status is changed */ if (g_slav_status_reg ^ slav_status_reg) { if (slav_status_reg & BIT(30)) { event_data.application_running = true; send_event(irq_notification, BGCOM_EVENT_APPLICATION_RUNNING, &event_data); send_event(BGCOM_EVENT_APPLICATION_RUNNING, &event_data); } if (slav_status_reg & BIT(29)) { event_data.to_slave_fifo_ready = true; send_event(irq_notification, BGCOM_EVENT_TO_SLAVE_FIFO_READY, &event_data); send_event(BGCOM_EVENT_TO_SLAVE_FIFO_READY, &event_data); } if (slav_status_reg & BIT(28)) { event_data.to_master_fifo_ready = true; send_event(irq_notification, BGCOM_EVENT_TO_MASTER_FIFO_READY, &event_data); send_event(BGCOM_EVENT_TO_MASTER_FIFO_READY, &event_data); } if (slav_status_reg & BIT(27)) { event_data.ahb_ready = true; send_event(irq_notification, BGCOM_EVENT_AHB_READY, &event_data); send_event(BGCOM_EVENT_AHB_READY, &event_data); } } Loading @@ -272,8 +275,7 @@ static void send_back_notification(uint32_t slav_status_reg, event_data.fifo_data.to_master_fifo_used = master_fifo_used; event_data.fifo_data.data = ptr; send_event(irq_notification, BGCOM_EVENT_TO_MASTER_FIFO_USED, send_event(BGCOM_EVENT_TO_MASTER_FIFO_USED, &event_data); } } Loading @@ -281,8 +283,7 @@ static void send_back_notification(uint32_t slav_status_reg, if (slave_fifo_free > 0) { event_data.to_slave_fifo_free = slave_fifo_free; send_event(irq_notification, BGCOM_EVENT_TO_SLAVE_FIFO_FREE, &event_data); send_event(BGCOM_EVENT_TO_SLAVE_FIFO_FREE, &event_data); } } Loading Loading @@ -577,6 +578,7 @@ EXPORT_SYMBOL(bgcom_suspend); void *bgcom_open(struct bgcom_open_config_type *open_config) { struct bg_spi_priv *spi; struct cb_data *irq_notification; struct bg_context *clnt_handle = kzalloc(sizeof(*clnt_handle), GFP_KERNEL); Loading @@ -592,33 +594,42 @@ void *bgcom_open(struct bgcom_open_config_type *open_config) clnt_handle->bg_spi = spi; clnt_handle->state = BGCOM_PROB_SUCCESS; } clnt_handle->cb = NULL; /* Interrupt callback Set-up */ if (open_config && open_config->bgcom_notification_cb) { /* deregister the prevoius call-back */ if (irq_notification) { pr_debug("freeing previous callback\n"); kfree(irq_notification); } irq_notification = kzalloc(sizeof(*irq_notification), GFP_KERNEL); if (!irq_notification) { kfree(clnt_handle); return NULL; } if (!irq_notification) goto error_ret; /* set irq node */ irq_notification->handle = clnt_handle; irq_notification->priv = open_config->priv; irq_notification->bgcom_notification_cb = open_config->bgcom_notification_cb; add_to_irq_list(irq_notification); clnt_handle->cb = irq_notification; } return clnt_handle; error_ret: kfree(clnt_handle); return NULL; } EXPORT_SYMBOL(bgcom_open); int bgcom_close(void **handle) { struct bg_context *lhandle; struct cb_data *cb = NULL; if (*handle == NULL) return -EINVAL; lhandle = *handle; cb = lhandle->cb; if (cb) list_del(&cb->list); kfree(*handle); *handle = NULL; return 0; Loading @@ -628,8 +639,8 @@ EXPORT_SYMBOL(bgcom_close); static irqreturn_t bg_irq_tasklet_hndlr(int irq, void *device) { struct bg_spi_priv *bg_spi = device; if (!irq_notification || !irq_notification->bgcom_notification_cb) { /* check if call-back exists */ if (list_empty(&cb_head)) { pr_debug("No callback registered\n"); return IRQ_HANDLED; } Loading Loading
drivers/soc/qcom/bgcom_spi.c +73 −62 Original line number Diff line number Diff line Loading @@ -65,25 +65,33 @@ struct bg_spi_priv { int irq_lock; }; struct bg_context { struct bg_spi_priv *bg_spi; enum bgcom_state state; }; struct cb_data { struct bg_context *handle; void *priv; void *handle; void (*bgcom_notification_cb)(void *handle, void *priv, enum bgcom_event_type event, union bgcom_event_data_type *event_data); struct list_head list; }; static struct cb_data *irq_notification; struct bg_context { struct bg_spi_priv *bg_spi; enum bgcom_state state; struct cb_data *cb; }; static void *bg_com_drv; static uint32_t g_slav_status_reg; /* BGCOM client callbacks set-up */ static struct list_head cb_head = LIST_HEAD_INIT(cb_head); static inline void add_to_irq_list(struct cb_data *data) { list_add_tail(&data->list, &cb_head); } static bool is_bgcom_ready(void) { return bg_com_drv ? true : false; Loading Loading @@ -169,14 +177,20 @@ static int bgcom_transfer(void *handle, uint8_t *tx_buf, /* BG-COM Interrupt handling */ static inline void send_event(struct cb_data *cb, enum bgcom_event_type event, void *data) void send_event(enum bgcom_event_type event, void *data) { if (!cb) return; struct list_head *pos; struct cb_data *cb; /* send interrupt notification for each registered call-back */ list_for_each(pos, &cb_head) { cb = list_entry(pos, struct cb_data, list); cb->bgcom_notification_cb(cb->handle, cb->priv, event, data); } } static void send_back_notification(uint32_t slav_status_reg, uint32_t slav_status_auto_clear_reg, Loading @@ -192,73 +206,62 @@ static void send_back_notification(uint32_t slav_status_reg, slave_fifo_free = (uint16_t)(fifo_fill_reg >> 16); if (slav_status_auto_clear_reg & BIT(31)) send_event(irq_notification, BGCOM_EVENT_RESET_OCCURRED, NULL); send_event(BGCOM_EVENT_RESET_OCCURRED, NULL); if (slav_status_auto_clear_reg & BIT(30)) send_event(irq_notification, BGCOM_EVENT_ERROR_WRITE_FIFO_OVERRUN, NULL); send_event(BGCOM_EVENT_ERROR_WRITE_FIFO_OVERRUN, NULL); if (slav_status_auto_clear_reg & BIT(29)) send_event(irq_notification, BGCOM_EVENT_ERROR_WRITE_FIFO_BUS_ERR, NULL); send_event(BGCOM_EVENT_ERROR_WRITE_FIFO_BUS_ERR, NULL); if (slav_status_auto_clear_reg & BIT(28)) send_event(irq_notification, BGCOM_EVENT_ERROR_WRITE_FIFO_ACCESS, NULL); send_event(BGCOM_EVENT_ERROR_WRITE_FIFO_ACCESS, NULL); if (slav_status_auto_clear_reg & BIT(27)) send_event(irq_notification, BGCOM_EVENT_ERROR_READ_FIFO_UNDERRUN, NULL); send_event(BGCOM_EVENT_ERROR_READ_FIFO_UNDERRUN, NULL); if (slav_status_auto_clear_reg & BIT(26)) send_event(irq_notification, BGCOM_EVENT_ERROR_READ_FIFO_BUS_ERR, NULL); send_event(BGCOM_EVENT_ERROR_READ_FIFO_BUS_ERR, NULL); if (slav_status_auto_clear_reg & BIT(25)) send_event(irq_notification, BGCOM_EVENT_ERROR_READ_FIFO_ACCESS, NULL); send_event(BGCOM_EVENT_ERROR_READ_FIFO_ACCESS, NULL); if (slav_status_auto_clear_reg & BIT(24)) send_event(irq_notification, BGCOM_EVENT_ERROR_TRUNCATED_READ, NULL); send_event(BGCOM_EVENT_ERROR_TRUNCATED_READ, NULL); if (slav_status_auto_clear_reg & BIT(23)) send_event(irq_notification, BGCOM_EVENT_ERROR_TRUNCATED_WRITE, NULL); send_event(BGCOM_EVENT_ERROR_TRUNCATED_WRITE, NULL); if (slav_status_auto_clear_reg & BIT(22)) send_event(irq_notification, BGCOM_EVENT_ERROR_AHB_ILLEGAL_ADDRESS, NULL); send_event(BGCOM_EVENT_ERROR_AHB_ILLEGAL_ADDRESS, NULL); if (slav_status_auto_clear_reg & BIT(21)) send_event(irq_notification, BGCOM_EVENT_ERROR_AHB_BUS_ERR, NULL); send_event(BGCOM_EVENT_ERROR_AHB_BUS_ERR, NULL); /* check if BG status is changed */ if (g_slav_status_reg ^ slav_status_reg) { if (slav_status_reg & BIT(30)) { event_data.application_running = true; send_event(irq_notification, BGCOM_EVENT_APPLICATION_RUNNING, &event_data); send_event(BGCOM_EVENT_APPLICATION_RUNNING, &event_data); } if (slav_status_reg & BIT(29)) { event_data.to_slave_fifo_ready = true; send_event(irq_notification, BGCOM_EVENT_TO_SLAVE_FIFO_READY, &event_data); send_event(BGCOM_EVENT_TO_SLAVE_FIFO_READY, &event_data); } if (slav_status_reg & BIT(28)) { event_data.to_master_fifo_ready = true; send_event(irq_notification, BGCOM_EVENT_TO_MASTER_FIFO_READY, &event_data); send_event(BGCOM_EVENT_TO_MASTER_FIFO_READY, &event_data); } if (slav_status_reg & BIT(27)) { event_data.ahb_ready = true; send_event(irq_notification, BGCOM_EVENT_AHB_READY, &event_data); send_event(BGCOM_EVENT_AHB_READY, &event_data); } } Loading @@ -272,8 +275,7 @@ static void send_back_notification(uint32_t slav_status_reg, event_data.fifo_data.to_master_fifo_used = master_fifo_used; event_data.fifo_data.data = ptr; send_event(irq_notification, BGCOM_EVENT_TO_MASTER_FIFO_USED, send_event(BGCOM_EVENT_TO_MASTER_FIFO_USED, &event_data); } } Loading @@ -281,8 +283,7 @@ static void send_back_notification(uint32_t slav_status_reg, if (slave_fifo_free > 0) { event_data.to_slave_fifo_free = slave_fifo_free; send_event(irq_notification, BGCOM_EVENT_TO_SLAVE_FIFO_FREE, &event_data); send_event(BGCOM_EVENT_TO_SLAVE_FIFO_FREE, &event_data); } } Loading Loading @@ -577,6 +578,7 @@ EXPORT_SYMBOL(bgcom_suspend); void *bgcom_open(struct bgcom_open_config_type *open_config) { struct bg_spi_priv *spi; struct cb_data *irq_notification; struct bg_context *clnt_handle = kzalloc(sizeof(*clnt_handle), GFP_KERNEL); Loading @@ -592,33 +594,42 @@ void *bgcom_open(struct bgcom_open_config_type *open_config) clnt_handle->bg_spi = spi; clnt_handle->state = BGCOM_PROB_SUCCESS; } clnt_handle->cb = NULL; /* Interrupt callback Set-up */ if (open_config && open_config->bgcom_notification_cb) { /* deregister the prevoius call-back */ if (irq_notification) { pr_debug("freeing previous callback\n"); kfree(irq_notification); } irq_notification = kzalloc(sizeof(*irq_notification), GFP_KERNEL); if (!irq_notification) { kfree(clnt_handle); return NULL; } if (!irq_notification) goto error_ret; /* set irq node */ irq_notification->handle = clnt_handle; irq_notification->priv = open_config->priv; irq_notification->bgcom_notification_cb = open_config->bgcom_notification_cb; add_to_irq_list(irq_notification); clnt_handle->cb = irq_notification; } return clnt_handle; error_ret: kfree(clnt_handle); return NULL; } EXPORT_SYMBOL(bgcom_open); int bgcom_close(void **handle) { struct bg_context *lhandle; struct cb_data *cb = NULL; if (*handle == NULL) return -EINVAL; lhandle = *handle; cb = lhandle->cb; if (cb) list_del(&cb->list); kfree(*handle); *handle = NULL; return 0; Loading @@ -628,8 +639,8 @@ EXPORT_SYMBOL(bgcom_close); static irqreturn_t bg_irq_tasklet_hndlr(int irq, void *device) { struct bg_spi_priv *bg_spi = device; if (!irq_notification || !irq_notification->bgcom_notification_cb) { /* check if call-back exists */ if (list_empty(&cb_head)) { pr_debug("No callback registered\n"); return IRQ_HANDLED; } Loading