diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 92cccb1cce69..96dbf04138be 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -80,6 +80,10 @@ enum geni_i2c_err_code { struct geni_i2c_desc { bool no_dma_support; unsigned int tx_fifo_depth; + int (*resources_init)(struct geni_se *se); + int (*set_rate)(struct geni_se *se, unsigned long freq); + int (*power_on)(struct geni_se *se); + int (*power_off)(struct geni_se *se); }; #define QCOM_I2C_MIN_NUM_OF_MSGS_MULTI_DESC 2 @@ -200,8 +204,9 @@ static int geni_i2c_clk_map_idx(struct geni_i2c_dev *gi2c) return -EINVAL; } -static void qcom_geni_i2c_conf(struct geni_i2c_dev *gi2c) +static int qcom_geni_i2c_conf(struct geni_se *se, unsigned long freq) { + struct geni_i2c_dev *gi2c = dev_get_drvdata(se->dev); const struct geni_i2c_clk_fld *itr = gi2c->clk_fld; u32 val; @@ -214,6 +219,7 @@ static void qcom_geni_i2c_conf(struct geni_i2c_dev *gi2c) val |= itr->t_low_cnt << LOW_COUNTER_SHFT; val |= itr->t_cycle_cnt; writel_relaxed(val, gi2c->se.base + SE_I2C_SCL_COUNTERS); + return 0; } static void geni_i2c_err_misc(struct geni_i2c_dev *gi2c) @@ -919,7 +925,9 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, return ret; } - qcom_geni_i2c_conf(gi2c); + ret = gi2c->dev_data->set_rate(&gi2c->se, gi2c->clk_freq_out); + if (ret) + return ret; if (gi2c->gpi_mode) ret = geni_i2c_gpi_xfer(gi2c, msgs, num); @@ -1045,8 +1053,9 @@ static int geni_i2c_init(struct geni_i2c_dev *gi2c) return ret; } -static int geni_i2c_resources_init(struct geni_i2c_dev *gi2c) +static int geni_i2c_resources_init(struct geni_se *se) { + struct geni_i2c_dev *gi2c = dev_get_drvdata(se->dev); int ret; ret = geni_se_resources_init(&gi2c->se); @@ -1101,7 +1110,7 @@ static int geni_i2c_probe(struct platform_device *pdev) spin_lock_init(&gi2c->lock); platform_set_drvdata(pdev, gi2c); - ret = geni_i2c_resources_init(gi2c); + ret = gi2c->dev_data->resources_init(&gi2c->se); if (ret) return ret; @@ -1159,15 +1168,17 @@ static void geni_i2c_shutdown(struct platform_device *pdev) static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev) { - int ret; + int ret = 0; struct geni_i2c_dev *gi2c = dev_get_drvdata(dev); disable_irq(gi2c->irq); - ret = geni_se_resources_deactivate(&gi2c->se); - if (ret) { - enable_irq(gi2c->irq); - return ret; + if (gi2c->dev_data->power_off) { + ret = gi2c->dev_data->power_off(&gi2c->se); + if (ret) { + enable_irq(gi2c->irq); + return ret; + } } return 0; @@ -1175,12 +1186,14 @@ static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev) static int __maybe_unused geni_i2c_runtime_resume(struct device *dev) { - int ret; + int ret = 0; struct geni_i2c_dev *gi2c = dev_get_drvdata(dev); - ret = geni_se_resources_activate(&gi2c->se); - if (ret) - return ret; + if (gi2c->dev_data->power_on) { + ret = gi2c->dev_data->power_on(&gi2c->se); + if (ret) + return ret; + } enable_irq(gi2c->irq); @@ -1220,11 +1233,25 @@ static const struct dev_pm_ops geni_i2c_pm_ops = { NULL) }; -static const struct geni_i2c_desc geni_i2c = {}; +static const struct geni_i2c_desc geni_i2c = { + .resources_init = geni_i2c_resources_init, + .set_rate = qcom_geni_i2c_conf, + .power_on = geni_se_resources_activate, + .power_off = geni_se_resources_deactivate, +}; static const struct geni_i2c_desc i2c_master_hub = { .no_dma_support = true, .tx_fifo_depth = 16, + .resources_init = geni_i2c_resources_init, + .set_rate = qcom_geni_i2c_conf, + .power_on = geni_se_resources_activate, + .power_off = geni_se_resources_deactivate, +}; + +static const struct geni_i2c_desc sa8255p_geni_i2c = { + .resources_init = geni_se_domain_attach, + .set_rate = geni_se_set_perf_opp, }; #ifdef CONFIG_ACPI @@ -1239,6 +1266,7 @@ MODULE_DEVICE_TABLE(acpi, geni_i2c_acpi_match); static const struct of_device_id geni_i2c_dt_match[] = { { .compatible = "qcom,geni-i2c", .data = &geni_i2c }, { .compatible = "qcom,geni-i2c-master-hub", .data = &i2c_master_hub }, + { .compatible = "qcom,sa8255p-geni-i2c", .data = &sa8255p_geni_i2c }, {} }; MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);