Loading drivers/spi/spi_qsd.c +25 −124 Original line number Diff line number Diff line Loading @@ -286,106 +286,23 @@ static void msm_spi_clock_set(struct msm_spi *dd, int speed) dd->clock_speed = rate; } static void msm_spi_clk_path_vote(struct msm_spi *dd) static void msm_spi_clk_path_vote(struct msm_spi *dd, u32 rate) { if (dd->clk_path_vote.client_hdl) msm_bus_scale_client_update_request( dd->clk_path_vote.client_hdl, MSM_SPI_CLK_PATH_RESUME_VEC); } if (dd->bus_cl_hdl) { u64 ib = rate * dd->pdata->bus_width; static void msm_spi_clk_path_unvote(struct msm_spi *dd) { if (dd->clk_path_vote.client_hdl) msm_bus_scale_client_update_request( dd->clk_path_vote.client_hdl, MSM_SPI_CLK_PATH_SUSPEND_VEC); } static void msm_spi_clk_path_teardown(struct msm_spi *dd) { msm_spi_clk_path_unvote(dd); if (dd->clk_path_vote.client_hdl) { msm_bus_scale_unregister_client(dd->clk_path_vote.client_hdl); dd->clk_path_vote.client_hdl = 0; msm_bus_scale_update_bw(dd->bus_cl_hdl, 0, ib); } } /** * msm_spi_clk_path_init_structs: internal impl detail of msm_spi_clk_path_init * * allocates and initilizes the bus scaling vectors. */ static int msm_spi_clk_path_init_structs(struct msm_spi *dd) static void msm_spi_clk_path_teardown(struct msm_spi *dd) { struct msm_bus_vectors *paths = NULL; struct msm_bus_paths *usecases = NULL; msm_spi_clk_path_vote(dd, 0); dev_dbg(dd->dev, "initialises path clock voting structs"); paths = devm_kzalloc(dd->dev, sizeof(*paths) * 2, GFP_KERNEL); if (!paths) { dev_err(dd->dev, "msm_bus_paths.paths memory allocation failed"); return -ENOMEM; } usecases = devm_kzalloc(dd->dev, sizeof(*usecases) * 2, GFP_KERNEL); if (!usecases) { dev_err(dd->dev, "msm_bus_scale_pdata.usecases memory allocation failed"); goto path_init_err; if (dd->bus_cl_hdl) { msm_bus_scale_unregister(dd->bus_cl_hdl); dd->bus_cl_hdl = NULL; } dd->clk_path_vote.pdata = devm_kzalloc(dd->dev, sizeof(*dd->clk_path_vote.pdata), GFP_KERNEL); if (!dd->clk_path_vote.pdata) { dev_err(dd->dev, "msm_bus_scale_pdata memory allocation failed"); goto path_init_err; } paths[MSM_SPI_CLK_PATH_SUSPEND_VEC] = (struct msm_bus_vectors) { .src = dd->pdata->master_id, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }; paths[MSM_SPI_CLK_PATH_RESUME_VEC] = (struct msm_bus_vectors) { .src = dd->pdata->master_id, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = MSM_SPI_CLK_PATH_BRST_BW(dd), }; usecases[MSM_SPI_CLK_PATH_SUSPEND_VEC] = (struct msm_bus_paths) { .num_paths = 1, .vectors = &paths[MSM_SPI_CLK_PATH_SUSPEND_VEC], }; usecases[MSM_SPI_CLK_PATH_RESUME_VEC] = (struct msm_bus_paths) { .num_paths = 1, .vectors = &paths[MSM_SPI_CLK_PATH_RESUME_VEC], }; *dd->clk_path_vote.pdata = (struct msm_bus_scale_pdata) { .active_only = 0, .name = dev_name(dd->dev), .num_usecases = 2, .usecase = usecases, }; return 0; path_init_err: devm_kfree(dd->dev, paths); devm_kfree(dd->dev, usecases); devm_kfree(dd->dev, dd->clk_path_vote.pdata); dd->clk_path_vote.pdata = NULL; return -ENOMEM; } /** Loading @@ -402,32 +319,19 @@ path_init_err: */ static int msm_spi_clk_path_postponed_register(struct msm_spi *dd) { dd->clk_path_vote.client_hdl = msm_bus_scale_register_client( dd->clk_path_vote.pdata); if (dd->clk_path_vote.client_hdl) { if (dd->clk_path_vote.reg_err) { /* log a success message if an error msg was logged */ dd->clk_path_vote.reg_err = false; dev_info(dd->dev, "msm_bus_scale_register_client(mstr-id:%d): 0x%x", dd->pdata->master_id, dd->clk_path_vote.client_hdl); } int ret = 0; msm_spi_clk_path_vote(dd); } else { /* guard to log only one error on multiple failure */ if (!dd->clk_path_vote.reg_err) { dd->clk_path_vote.reg_err = true; dd->bus_cl_hdl = msm_bus_scale_register(dd->pdata->master_id, MSM_BUS_SLAVE_EBI_CH0, (char *)dev_name(dd->dev), false); dev_info(dd->dev, "msm_bus_scale_register_client(mstr-id:%d): 0", dd->pdata->master_id); } if (IS_ERR_OR_NULL(dd->bus_cl_hdl)) { ret = (dd->bus_cl_hdl ? PTR_ERR(dd->bus_cl_hdl) : -EAGAIN); dev_err(dd->dev, "Failed bus registration Err %d", ret); } return dd->clk_path_vote.client_hdl ? 0 : -EAGAIN; return ret; } static void msm_spi_clk_path_init(struct msm_spi *dd) Loading @@ -436,20 +340,13 @@ static void msm_spi_clk_path_init(struct msm_spi *dd) * bail out if path voting is diabled (master_id == 0) or if it is * already registered (client_hdl != 0) */ if (!dd->pdata->master_id || dd->clk_path_vote.client_hdl) if (!dd->pdata->master_id || dd->bus_cl_hdl) return; /* if fail once then try no more */ if (!dd->clk_path_vote.pdata && msm_spi_clk_path_init_structs(dd)) { dd->pdata->master_id = 0; return; }; /* on failure try again later */ if (msm_spi_clk_path_postponed_register(dd)) return; msm_spi_clk_path_vote(dd); } static int msm_spi_calculate_size(int *fifo_size, Loading Loading @@ -1556,6 +1453,7 @@ static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag) return; } msm_spi_clk_path_vote(dd, spi->max_speed_hz); if (!(spi->mode & SPI_CS_HIGH)) set_flag = !set_flag; Loading Loading @@ -1608,6 +1506,7 @@ static void put_local_resources(struct msm_spi *dd) } msm_spi_disable_irqs(dd); clk_disable_unprepare(dd->clk); dd->clock_speed = 0; clk_disable_unprepare(dd->pclk); /* Free the spi clk, miso, mosi, cs gpio */ Loading Loading @@ -2248,6 +2147,8 @@ struct msm_spi_platform_data *msm_spi_dt_to_pdata( &pdata->infinite_mode, DT_OPT, DT_U32, 0}, {"qcom,master-id", &pdata->master_id, DT_SGST, DT_U32, 0}, {"qcom,bus-width", &pdata->bus_width, DT_OPT, DT_U32, 8}, {"qcom,ver-reg-exists", &pdata->ver_reg_exists, DT_OPT, DT_BOOL, 0}, {"qcom,use-bam", Loading Loading @@ -2663,7 +2564,7 @@ static int msm_spi_pm_suspend_runtime(struct device *device) put_local_resources(dd); if (dd->pdata) msm_spi_clk_path_unvote(dd); msm_spi_clk_path_vote(dd, 0); suspend_exit: return 0; Loading Loading @@ -2693,7 +2594,7 @@ static int msm_spi_pm_resume_runtime(struct device *device) dd->is_init_complete = true; } msm_spi_clk_path_init(dd); msm_spi_clk_path_vote(dd); msm_spi_clk_path_vote(dd, dd->pdata->max_clock_speed); if (!dd->pdata->is_shared) { ret = get_local_resources(dd); Loading drivers/spi/spi_qsd.h +1 −17 Original line number Diff line number Diff line Loading @@ -262,22 +262,6 @@ static struct msm_spi_regs{ }; #endif /** * qup_i2c_clk_path_vote: data to use bus scaling driver for clock path vote * * @client_hdl when zero, client is not registered with the bus scaling driver, * and bus scaling functionality should not be used. When non zero, it * is a bus scaling client id and may be used to vote for clock path. * @reg_err when true, registration error was detected and an error message was * logged. i2c will attempt to re-register but will log error only once. * once registration succeed, the flag is set to false. */ struct qup_i2c_clk_path_vote { u32 client_hdl; struct msm_bus_scale_pdata *pdata; bool reg_err; }; struct msm_spi_bam_pipe { const char *name; struct sps_pipe *handle; Loading Loading @@ -312,7 +296,7 @@ struct msm_spi { struct completion rx_transfer_complete; struct clk *clk; /* core clock */ struct clk *pclk; /* interface clock */ struct qup_i2c_clk_path_vote clk_path_vote; struct msm_bus_client_handle *bus_cl_hdl; unsigned long mem_phys_addr; size_t mem_size; int input_fifo_size; Loading include/linux/spi/qcom-spi.h +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ struct msm_spi_platform_data { u32 max_clock_speed; u32 master_id; u32 bus_width; int (*gpio_config)(void); void (*gpio_release)(void); int (*dma_config)(void); Loading Loading
drivers/spi/spi_qsd.c +25 −124 Original line number Diff line number Diff line Loading @@ -286,106 +286,23 @@ static void msm_spi_clock_set(struct msm_spi *dd, int speed) dd->clock_speed = rate; } static void msm_spi_clk_path_vote(struct msm_spi *dd) static void msm_spi_clk_path_vote(struct msm_spi *dd, u32 rate) { if (dd->clk_path_vote.client_hdl) msm_bus_scale_client_update_request( dd->clk_path_vote.client_hdl, MSM_SPI_CLK_PATH_RESUME_VEC); } if (dd->bus_cl_hdl) { u64 ib = rate * dd->pdata->bus_width; static void msm_spi_clk_path_unvote(struct msm_spi *dd) { if (dd->clk_path_vote.client_hdl) msm_bus_scale_client_update_request( dd->clk_path_vote.client_hdl, MSM_SPI_CLK_PATH_SUSPEND_VEC); } static void msm_spi_clk_path_teardown(struct msm_spi *dd) { msm_spi_clk_path_unvote(dd); if (dd->clk_path_vote.client_hdl) { msm_bus_scale_unregister_client(dd->clk_path_vote.client_hdl); dd->clk_path_vote.client_hdl = 0; msm_bus_scale_update_bw(dd->bus_cl_hdl, 0, ib); } } /** * msm_spi_clk_path_init_structs: internal impl detail of msm_spi_clk_path_init * * allocates and initilizes the bus scaling vectors. */ static int msm_spi_clk_path_init_structs(struct msm_spi *dd) static void msm_spi_clk_path_teardown(struct msm_spi *dd) { struct msm_bus_vectors *paths = NULL; struct msm_bus_paths *usecases = NULL; msm_spi_clk_path_vote(dd, 0); dev_dbg(dd->dev, "initialises path clock voting structs"); paths = devm_kzalloc(dd->dev, sizeof(*paths) * 2, GFP_KERNEL); if (!paths) { dev_err(dd->dev, "msm_bus_paths.paths memory allocation failed"); return -ENOMEM; } usecases = devm_kzalloc(dd->dev, sizeof(*usecases) * 2, GFP_KERNEL); if (!usecases) { dev_err(dd->dev, "msm_bus_scale_pdata.usecases memory allocation failed"); goto path_init_err; if (dd->bus_cl_hdl) { msm_bus_scale_unregister(dd->bus_cl_hdl); dd->bus_cl_hdl = NULL; } dd->clk_path_vote.pdata = devm_kzalloc(dd->dev, sizeof(*dd->clk_path_vote.pdata), GFP_KERNEL); if (!dd->clk_path_vote.pdata) { dev_err(dd->dev, "msm_bus_scale_pdata memory allocation failed"); goto path_init_err; } paths[MSM_SPI_CLK_PATH_SUSPEND_VEC] = (struct msm_bus_vectors) { .src = dd->pdata->master_id, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }; paths[MSM_SPI_CLK_PATH_RESUME_VEC] = (struct msm_bus_vectors) { .src = dd->pdata->master_id, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = MSM_SPI_CLK_PATH_BRST_BW(dd), }; usecases[MSM_SPI_CLK_PATH_SUSPEND_VEC] = (struct msm_bus_paths) { .num_paths = 1, .vectors = &paths[MSM_SPI_CLK_PATH_SUSPEND_VEC], }; usecases[MSM_SPI_CLK_PATH_RESUME_VEC] = (struct msm_bus_paths) { .num_paths = 1, .vectors = &paths[MSM_SPI_CLK_PATH_RESUME_VEC], }; *dd->clk_path_vote.pdata = (struct msm_bus_scale_pdata) { .active_only = 0, .name = dev_name(dd->dev), .num_usecases = 2, .usecase = usecases, }; return 0; path_init_err: devm_kfree(dd->dev, paths); devm_kfree(dd->dev, usecases); devm_kfree(dd->dev, dd->clk_path_vote.pdata); dd->clk_path_vote.pdata = NULL; return -ENOMEM; } /** Loading @@ -402,32 +319,19 @@ path_init_err: */ static int msm_spi_clk_path_postponed_register(struct msm_spi *dd) { dd->clk_path_vote.client_hdl = msm_bus_scale_register_client( dd->clk_path_vote.pdata); if (dd->clk_path_vote.client_hdl) { if (dd->clk_path_vote.reg_err) { /* log a success message if an error msg was logged */ dd->clk_path_vote.reg_err = false; dev_info(dd->dev, "msm_bus_scale_register_client(mstr-id:%d): 0x%x", dd->pdata->master_id, dd->clk_path_vote.client_hdl); } int ret = 0; msm_spi_clk_path_vote(dd); } else { /* guard to log only one error on multiple failure */ if (!dd->clk_path_vote.reg_err) { dd->clk_path_vote.reg_err = true; dd->bus_cl_hdl = msm_bus_scale_register(dd->pdata->master_id, MSM_BUS_SLAVE_EBI_CH0, (char *)dev_name(dd->dev), false); dev_info(dd->dev, "msm_bus_scale_register_client(mstr-id:%d): 0", dd->pdata->master_id); } if (IS_ERR_OR_NULL(dd->bus_cl_hdl)) { ret = (dd->bus_cl_hdl ? PTR_ERR(dd->bus_cl_hdl) : -EAGAIN); dev_err(dd->dev, "Failed bus registration Err %d", ret); } return dd->clk_path_vote.client_hdl ? 0 : -EAGAIN; return ret; } static void msm_spi_clk_path_init(struct msm_spi *dd) Loading @@ -436,20 +340,13 @@ static void msm_spi_clk_path_init(struct msm_spi *dd) * bail out if path voting is diabled (master_id == 0) or if it is * already registered (client_hdl != 0) */ if (!dd->pdata->master_id || dd->clk_path_vote.client_hdl) if (!dd->pdata->master_id || dd->bus_cl_hdl) return; /* if fail once then try no more */ if (!dd->clk_path_vote.pdata && msm_spi_clk_path_init_structs(dd)) { dd->pdata->master_id = 0; return; }; /* on failure try again later */ if (msm_spi_clk_path_postponed_register(dd)) return; msm_spi_clk_path_vote(dd); } static int msm_spi_calculate_size(int *fifo_size, Loading Loading @@ -1556,6 +1453,7 @@ static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag) return; } msm_spi_clk_path_vote(dd, spi->max_speed_hz); if (!(spi->mode & SPI_CS_HIGH)) set_flag = !set_flag; Loading Loading @@ -1608,6 +1506,7 @@ static void put_local_resources(struct msm_spi *dd) } msm_spi_disable_irqs(dd); clk_disable_unprepare(dd->clk); dd->clock_speed = 0; clk_disable_unprepare(dd->pclk); /* Free the spi clk, miso, mosi, cs gpio */ Loading Loading @@ -2248,6 +2147,8 @@ struct msm_spi_platform_data *msm_spi_dt_to_pdata( &pdata->infinite_mode, DT_OPT, DT_U32, 0}, {"qcom,master-id", &pdata->master_id, DT_SGST, DT_U32, 0}, {"qcom,bus-width", &pdata->bus_width, DT_OPT, DT_U32, 8}, {"qcom,ver-reg-exists", &pdata->ver_reg_exists, DT_OPT, DT_BOOL, 0}, {"qcom,use-bam", Loading Loading @@ -2663,7 +2564,7 @@ static int msm_spi_pm_suspend_runtime(struct device *device) put_local_resources(dd); if (dd->pdata) msm_spi_clk_path_unvote(dd); msm_spi_clk_path_vote(dd, 0); suspend_exit: return 0; Loading Loading @@ -2693,7 +2594,7 @@ static int msm_spi_pm_resume_runtime(struct device *device) dd->is_init_complete = true; } msm_spi_clk_path_init(dd); msm_spi_clk_path_vote(dd); msm_spi_clk_path_vote(dd, dd->pdata->max_clock_speed); if (!dd->pdata->is_shared) { ret = get_local_resources(dd); Loading
drivers/spi/spi_qsd.h +1 −17 Original line number Diff line number Diff line Loading @@ -262,22 +262,6 @@ static struct msm_spi_regs{ }; #endif /** * qup_i2c_clk_path_vote: data to use bus scaling driver for clock path vote * * @client_hdl when zero, client is not registered with the bus scaling driver, * and bus scaling functionality should not be used. When non zero, it * is a bus scaling client id and may be used to vote for clock path. * @reg_err when true, registration error was detected and an error message was * logged. i2c will attempt to re-register but will log error only once. * once registration succeed, the flag is set to false. */ struct qup_i2c_clk_path_vote { u32 client_hdl; struct msm_bus_scale_pdata *pdata; bool reg_err; }; struct msm_spi_bam_pipe { const char *name; struct sps_pipe *handle; Loading Loading @@ -312,7 +296,7 @@ struct msm_spi { struct completion rx_transfer_complete; struct clk *clk; /* core clock */ struct clk *pclk; /* interface clock */ struct qup_i2c_clk_path_vote clk_path_vote; struct msm_bus_client_handle *bus_cl_hdl; unsigned long mem_phys_addr; size_t mem_size; int input_fifo_size; Loading
include/linux/spi/qcom-spi.h +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ struct msm_spi_platform_data { u32 max_clock_speed; u32 master_id; u32 bus_width; int (*gpio_config)(void); void (*gpio_release)(void); int (*dma_config)(void); Loading