diff mbox series

[v4] i2c: tegra: Add the ACPI support

Message ID 1637859224-5179-1-git-send-email-akhilrajeev@nvidia.com
State Handled Elsewhere
Headers show
Series [v4] i2c: tegra: Add the ACPI support | expand

Commit Message

Akhil R Nov. 25, 2021, 4:53 p.m. UTC
Add support for the ACPI based device registration so that the driver
can be also enabled through ACPI table.

This does not include the ACPI support for Tegra VI and DVC I2C.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
 drivers/i2c/busses/i2c-tegra.c | 52 ++++++++++++++++++++++++++++++++----------
 1 file changed, 40 insertions(+), 12 deletions(-)

v4 changes:
  * changed has_acpi_companion to ACPI_HANDLE for consistency across 
    all functions
v3 - https://lkml.org/lkml/2021/11/25/173
v2 - https://lkml.org/lkml/2021/11/23/82
v1 - https://lkml.org/lkml/2021/11/19/393

Comments

Andy Shevchenko Nov. 25, 2021, 7:28 p.m. UTC | #1
On Thu, Nov 25, 2021 at 6:54 PM Akhil R <akhilrajeev@nvidia.com> wrote:
>
> Add support for the ACPI based device registration so that the driver
> can be also enabled through ACPI table.
>
> This does not include the ACPI support for Tegra VI and DVC I2C.

Thanks for an update, my comments below.

...

> -       err = reset_control_reset(i2c_dev->rst);
> +       if (handle)

> +               err = acpi_evaluate_object(handle, "_RST", NULL, NULL);

Does it compile for CONFIG_ACPI=n case?

> +       else
> +               err = reset_control_reset(i2c_dev->rst);

If not, you will need something like this instead:

#ifdef CONFIG_ACPI
               err = acpi_evaluate_object(ACPI_HANDLE(...), "_RST", NULL, NULL);
#else
               err = reset_control_reset(i2c_dev->rst);
#endif

...

> +       err = device_property_read_u32(i2c_dev->dev, "clock-frequency",
> +                                      &i2c_dev->bus_clk_rate);
>         if (err)
>                 i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ;

Actually you need to switch to use i2c_timings data structure and
corresponding methods.
This change will be incorporated there. I.o.w. do it as a prerequisite
to this patch.

...

> +       if (ACPI_HANDLE(i2c_dev->dev))
> +               return 0;

With above mentioned ifdeffery this may be converted back to
has_acpi_companion() which is slightly better in this case.

> +       if (ACPI_HANDLE(i2c_dev->dev))
> +               return 0;

Ditto.

P.S> Sorry if I missed something in the previous reviews.
Dmitry Osipenko Nov. 26, 2021, 12:37 a.m. UTC | #2
25.11.2021 22:28, Andy Shevchenko пишет:
>> -       err = reset_control_reset(i2c_dev->rst);
>> +       if (handle)
>> +               err = acpi_evaluate_object(handle, "_RST", NULL, NULL);
> Does it compile for CONFIG_ACPI=n case?
> 

It compiles and works fine with CONFIG_ACPI=n.
Dmitry Osipenko Nov. 26, 2021, 1:02 a.m. UTC | #3
25.11.2021 19:53, Akhil R пишет:
> Add support for the ACPI based device registration so that the driver
> can be also enabled through ACPI table.
> 
> This does not include the ACPI support for Tegra VI and DVC I2C.
> 
> Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
> ---
>  drivers/i2c/busses/i2c-tegra.c | 52 ++++++++++++++++++++++++++++++++----------
>  1 file changed, 40 insertions(+), 12 deletions(-)
> 
> v4 changes:
>   * changed has_acpi_companion to ACPI_HANDLE for consistency across 
>     all functions
> v3 - https://lkml.org/lkml/2021/11/25/173
> v2 - https://lkml.org/lkml/2021/11/23/82
> v1 - https://lkml.org/lkml/2021/11/19/393

Andy suggested to make v5 with extra patch that will make use of the
generic i2c_timings, but it should be a separate change.

This patch is good to me. Please provide the full changelog for each
version next time, instead of the links. Thanks!

If you'll make v5, then feel free to add my r-b:

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Wolfram Sang Nov. 29, 2021, 8:46 a.m. UTC | #4
On Thu, Nov 25, 2021 at 10:23:44PM +0530, Akhil R wrote:
> Add support for the ACPI based device registration so that the driver
> can be also enabled through ACPI table.
> 
> This does not include the ACPI support for Tegra VI and DVC I2C.
> 
> Signed-off-by: Akhil R <akhilrajeev@nvidia.com>

Applied to for-next, thanks!
diff mbox series

Patch

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index c883044..6986eb9 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -6,6 +6,7 @@ 
  * Author: Colin Cross <ccross@android.com>
  */
 
+#include <linux/acpi.h>
 #include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -608,6 +609,7 @@  static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
 static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 {
 	u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode;
+	acpi_handle handle = ACPI_HANDLE(i2c_dev->dev);
 	int err;
 
 	/*
@@ -618,7 +620,11 @@  static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 	 * emit a noisy warning on error, which won't stay unnoticed and
 	 * won't hose machine entirely.
 	 */
-	err = reset_control_reset(i2c_dev->rst);
+	if (handle)
+		err = acpi_evaluate_object(handle, "_RST", NULL, NULL);
+	else
+		err = reset_control_reset(i2c_dev->rst);
+
 	WARN_ON_ONCE(err);
 
 	if (i2c_dev->is_dvc)
@@ -1627,12 +1633,12 @@  static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
 	bool multi_mode;
 	int err;
 
-	err = of_property_read_u32(np, "clock-frequency",
-				   &i2c_dev->bus_clk_rate);
+	err = device_property_read_u32(i2c_dev->dev, "clock-frequency",
+				       &i2c_dev->bus_clk_rate);
 	if (err)
 		i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ;
 
-	multi_mode = of_property_read_bool(np, "multi-master");
+	multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master");
 	i2c_dev->multimaster_mode = multi_mode;
 
 	if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
@@ -1642,10 +1648,26 @@  static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
 		i2c_dev->is_vi = true;
 }
 
+static int tegra_i2c_init_reset(struct tegra_i2c_dev *i2c_dev)
+{
+	if (ACPI_HANDLE(i2c_dev->dev))
+		return 0;
+
+	i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c");
+	if (IS_ERR(i2c_dev->rst))
+		return dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst),
+				      "failed to get reset control\n");
+
+	return 0;
+}
+
 static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
 {
 	int err;
 
+	if (ACPI_HANDLE(i2c_dev->dev))
+		return 0;
+
 	i2c_dev->clocks[i2c_dev->nclocks++].id = "div-clk";
 
 	if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw)
@@ -1720,7 +1742,7 @@  static int tegra_i2c_probe(struct platform_device *pdev)
 	init_completion(&i2c_dev->msg_complete);
 	init_completion(&i2c_dev->dma_complete);
 
-	i2c_dev->hw = of_device_get_match_data(&pdev->dev);
+	i2c_dev->hw = device_get_match_data(&pdev->dev);
 	i2c_dev->cont_id = pdev->id;
 	i2c_dev->dev = &pdev->dev;
 
@@ -1746,15 +1768,12 @@  static int tegra_i2c_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c");
-	if (IS_ERR(i2c_dev->rst)) {
-		dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst),
-			      "failed to get reset control\n");
-		return PTR_ERR(i2c_dev->rst);
-	}
-
 	tegra_i2c_parse_dt(i2c_dev);
 
+	err = tegra_i2c_init_reset(i2c_dev);
+	if (err)
+		return err;
+
 	err = tegra_i2c_init_clocks(i2c_dev);
 	if (err)
 		return err;
@@ -1923,12 +1942,21 @@  static const struct dev_pm_ops tegra_i2c_pm = {
 			   NULL)
 };
 
+static const struct acpi_device_id tegra_i2c_acpi_match[] = {
+	{.id = "NVDA0101", .driver_data = (kernel_ulong_t)&tegra210_i2c_hw},
+	{.id = "NVDA0201", .driver_data = (kernel_ulong_t)&tegra186_i2c_hw},
+	{.id = "NVDA0301", .driver_data = (kernel_ulong_t)&tegra194_i2c_hw},
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, tegra_i2c_acpi_match);
+
 static struct platform_driver tegra_i2c_driver = {
 	.probe = tegra_i2c_probe,
 	.remove = tegra_i2c_remove,
 	.driver = {
 		.name = "tegra-i2c",
 		.of_match_table = tegra_i2c_of_match,
+		.acpi_match_table = tegra_i2c_acpi_match,
 		.pm = &tegra_i2c_pm,
 	},
 };