From c82036b6da3eb59c9350513c5ebf384a14aebaff Mon Sep 17 00:00:00 2001 From: Steve Jeong Date: Fri, 7 Apr 2023 12:03:14 +0900 Subject: [PATCH] ODROID-M1: driver/i2c: Add driver "speed" attribution for change i2c bus freq dynamically. e.g. $ echo 400000 | sudo tee /sys/bus/i2c/devices/i2c-0/device/speed Signed-off-by: Steve Jeong Change-Id: Ifcccf9bb61ed65133b64c803b53fb4e46d470e26 --- drivers/i2c/busses/i2c-rk3x.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 8372214f062e..f0e1726aa7a5 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -1897,6 +1897,32 @@ static void rk3x_i2c_tb_cb(void *data) enable_irq(i2c->irq); } +static ssize_t rk3x_i2c_speed_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct rk3x_i2c *i2c = dev_get_drvdata(dev); + struct i2c_timings *t = &i2c->t; + + return snprintf(buf, PAGE_SIZE, "%u\n", t->bus_freq_hz); +} + +static ssize_t rk3x_i2c_speed_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct rk3x_i2c *i2c = dev_get_drvdata(dev); + struct i2c_timings *t = &i2c->t; + int ret, freq; + + ret = kstrtoint(buf, 10, &freq); + if (ret < 0) + return ret; + + t->bus_freq_hz = (uint32_t)freq; + rk3x_i2c_adapt_div(i2c, clk_get_rate(i2c->clk)); + + return count; +} + +static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR, rk3x_i2c_speed_show, rk3x_i2c_speed_store); + static int rk3x_i2c_probe(struct platform_device *pdev) { struct fwnode_handle *fw = dev_fwnode(&pdev->dev); @@ -1911,6 +1937,11 @@ static int rk3x_i2c_probe(struct platform_device *pdev) if (!i2c) return -ENOMEM; + ret = device_create_file(&pdev->dev, &dev_attr_speed); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to create speed attribute file: %d\n", ret); + } + i2c->soc_data = (struct rk3x_i2c_soc_data *)device_get_match_data(&pdev->dev); ret = rk3x_i2c_acpi_get_bus_id(&pdev->dev, i2c); @@ -2097,6 +2128,7 @@ static int rk3x_i2c_remove(struct platform_device *pdev) if (i2c->soc_data->dma_control) i2c->soc_data->dma_control(pdev, false); + device_remove_file(&pdev->dev, &dev_attr_speed); unregister_restart_handler(&i2c->i2c_restart_nb); clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb); clk_unprepare(i2c->pclk);