i2c: bcm2835: Store pointer to bus clock
authorStefan Wahren <wahrenst@gmx.net>
Sat, 4 Jan 2020 15:13:20 +0000 (16:13 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Jan 2020 18:48:17 +0000 (19:48 +0100)
commit 3b722da6672df8392f9c43d7c7e04bddd81d7e37 upstream.

The commit bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF") introduced
a NULL pointer dereference on driver unload. It seems that we can't fetch
the bus clock via devm_clk_get in bcm2835_i2c_remove. As an alternative
approach store a pointer to the bus clock in the private driver structure.

Fixes: bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/i2c/busses/i2c-bcm2835.c

index e01b2b5..5ab901a 100644 (file)
@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev {
        struct i2c_adapter adapter;
        struct completion completion;
        struct i2c_msg *curr_msg;
+       struct clk *bus_clk;
        int num_msgs;
        u32 msg_err;
        u8 *msg_buf;
@@ -404,7 +405,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
        struct resource *mem, *irq;
        int ret;
        struct i2c_adapter *adap;
-       struct clk *bus_clk;
        struct clk *mclk;
        u32 bus_clk_rate;
 
@@ -427,11 +427,11 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
                return PTR_ERR(mclk);
        }
 
-       bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
+       i2c_dev->bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
 
-       if (IS_ERR(bus_clk)) {
+       if (IS_ERR(i2c_dev->bus_clk)) {
                dev_err(&pdev->dev, "Could not register clock\n");
-               return PTR_ERR(bus_clk);
+               return PTR_ERR(i2c_dev->bus_clk);
        }
 
        ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
@@ -442,13 +442,13 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
                bus_clk_rate = 100000;
        }
 
-       ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
+       ret = clk_set_rate_exclusive(i2c_dev->bus_clk, bus_clk_rate);
        if (ret < 0) {
                dev_err(&pdev->dev, "Could not set clock frequency\n");
                return ret;
        }
 
-       ret = clk_prepare_enable(bus_clk);
+       ret = clk_prepare_enable(i2c_dev->bus_clk);
        if (ret) {
                dev_err(&pdev->dev, "Couldn't prepare clock");
                return ret;
@@ -491,10 +491,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
 static int bcm2835_i2c_remove(struct platform_device *pdev)
 {
        struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
-       struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
 
-       clk_rate_exclusive_put(bus_clk);
-       clk_disable_unprepare(bus_clk);
+       clk_rate_exclusive_put(i2c_dev->bus_clk);
+       clk_disable_unprepare(i2c_dev->bus_clk);
 
        free_irq(i2c_dev->irq, i2c_dev);
        i2c_del_adapter(&i2c_dev->adapter);