diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 025165c4b952..88ac0833351c 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -78,6 +78,13 @@ #define GSI_CPHA BIT(4) #define GSI_CPOL BIT(5) +struct geni_spi_desc { + int (*resources_init)(struct geni_se *se); + int (*set_rate)(struct geni_se *se, unsigned long clk_freq); + int (*power_on)(struct geni_se *se); + int (*power_off)(struct geni_se *se); +}; + struct spi_geni_master { struct geni_se se; struct device *dev; @@ -105,6 +112,7 @@ struct spi_geni_master { struct dma_chan *tx; struct dma_chan *rx; int cur_xfer_mode; + const struct geni_spi_desc *dev_data; }; static void spi_slv_setup(struct spi_geni_master *mas) @@ -305,11 +313,12 @@ static void spi_setup_word_len(struct spi_geni_master *mas, u16 mode, writel(word_len, se->base + SE_SPI_WORD_LEN); } -static int geni_spi_set_clock_and_bw(struct spi_geni_master *mas, - unsigned long clk_hz) +static int geni_spi_set_clock_and_bw(struct geni_se *se, + unsigned long clk_hz) { + struct spi_controller *spi = dev_get_drvdata(se->dev); + struct spi_geni_master *mas = spi_controller_get_devdata(spi); u32 clk_sel, m_clk_cfg, idx, div; - struct geni_se *se = &mas->se; int ret; if (clk_hz == mas->cur_speed_hz) @@ -825,7 +834,7 @@ static int setup_se_xfer(struct spi_transfer *xfer, } /* Speed and bits per word can be overridden per transfer */ - ret = geni_spi_set_clock_and_bw(mas, xfer->speed_hz); + ret = mas->dev_data->set_rate(&mas->se, xfer->speed_hz); if (ret) return ret; @@ -1075,7 +1084,11 @@ static int spi_geni_probe(struct platform_device *pdev) mas->se.wrapper = dev_get_drvdata(dev->parent); mas->se.base = base; - ret = geni_se_resources_init(&mas->se); + mas->dev_data = device_get_match_data(&pdev->dev); + if (!mas->dev_data) + return -EINVAL; + + ret = mas->dev_data->resources_init(&mas->se); if (ret) return ret; @@ -1131,7 +1144,8 @@ static int __maybe_unused spi_geni_runtime_suspend(struct device *dev) struct spi_controller *spi = dev_get_drvdata(dev); struct spi_geni_master *mas = spi_controller_get_devdata(spi); - return geni_se_resources_deactivate(&mas->se); + return mas->dev_data->power_off ? + mas->dev_data->power_off(&mas->se) : 0; } static int __maybe_unused spi_geni_runtime_resume(struct device *dev) @@ -1140,9 +1154,11 @@ static int __maybe_unused spi_geni_runtime_resume(struct device *dev) struct spi_geni_master *mas = spi_controller_get_devdata(spi); int ret; - ret = geni_se_resources_activate(&mas->se); - if (ret) - return ret; + if (mas->dev_data->power_on) { + ret = mas->dev_data->power_on(&mas->se); + if (ret) + return ret; + } if (mas->se.has_opp) return dev_pm_opp_set_rate(mas->dev, mas->cur_sclk_hz); @@ -1188,8 +1204,21 @@ static const struct dev_pm_ops spi_geni_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(spi_geni_suspend, spi_geni_resume) }; +static const struct geni_spi_desc geni_spi = { + .resources_init = geni_se_resources_init, + .set_rate = geni_spi_set_clock_and_bw, + .power_on = geni_se_resources_activate, + .power_off = geni_se_resources_deactivate, +}; + +static const struct geni_spi_desc sa8255p_geni_spi = { + .resources_init = geni_se_domain_attach, + .set_rate = geni_se_set_perf_opp, +}; + static const struct of_device_id spi_geni_dt_match[] = { - { .compatible = "qcom,geni-spi" }, + { .compatible = "qcom,geni-spi", .data = &geni_spi }, + { .compatible = "qcom,sa8255p-geni-spi", .data = &sa8255p_geni_spi }, {} }; MODULE_DEVICE_TABLE(of, spi_geni_dt_match);