2018-11-16 10:52:05

by Pierre-Yves MORDRET

[permalink] [raw]
Subject: [PATCH v1] i2c: i2c-stm32f7: add PM Runtime support

Use PM Runtime API to enable/disable clock

Signed-off-by: Pierre-Yves MORDRET <[email protected]>
---
Version history:
v1:
* Initial
---
---
drivers/i2c/busses/i2c-stm32f7.c | 142 +++++++++++++++++++++++++++------------
1 file changed, 99 insertions(+), 43 deletions(-)

diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
index 62d023e..4623b82 100644
--- a/drivers/i2c/busses/i2c-stm32f7.c
+++ b/drivers/i2c/busses/i2c-stm32f7.c
@@ -27,6 +27,8 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/slab.h>

@@ -1545,15 +1547,13 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
i2c_dev->msg_id = 0;
f7_msg->smbus = false;

- ret = clk_enable(i2c_dev->clk);
- if (ret) {
- dev_err(i2c_dev->dev, "Failed to enable clock\n");
+ ret = pm_runtime_get_sync(i2c_dev->dev);
+ if (ret < 0)
return ret;
- }

ret = stm32f7_i2c_wait_free_bus(i2c_dev);
if (ret)
- goto clk_free;
+ goto pm_free;

stm32f7_i2c_xfer_msg(i2c_dev, msgs);

@@ -1569,8 +1569,9 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
ret = -ETIMEDOUT;
}

-clk_free:
- clk_disable(i2c_dev->clk);
+pm_free:
+ pm_runtime_mark_last_busy(i2c_dev->dev);
+ pm_runtime_put_autosuspend(i2c_dev->dev);

return (ret < 0) ? ret : num;
}
@@ -1592,39 +1593,37 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
f7_msg->read_write = read_write;
f7_msg->smbus = true;

- ret = clk_enable(i2c_dev->clk);
- if (ret) {
- dev_err(i2c_dev->dev, "Failed to enable clock\n");
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0)
return ret;
- }

ret = stm32f7_i2c_wait_free_bus(i2c_dev);
if (ret)
- goto clk_free;
+ goto pm_free;

ret = stm32f7_i2c_smbus_xfer_msg(i2c_dev, flags, command, data);
if (ret)
- goto clk_free;
+ goto pm_free;

timeout = wait_for_completion_timeout(&i2c_dev->complete,
i2c_dev->adap.timeout);
ret = f7_msg->result;
if (ret)
- goto clk_free;
+ goto pm_free;

if (!timeout) {
dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
if (i2c_dev->use_dma)
dmaengine_terminate_all(dma->chan_using);
ret = -ETIMEDOUT;
- goto clk_free;
+ goto pm_free;
}

/* Check PEC */
if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && read_write) {
ret = stm32f7_i2c_smbus_check_pec(i2c_dev);
if (ret)
- goto clk_free;
+ goto pm_free;
}

if (read_write && size != I2C_SMBUS_QUICK) {
@@ -1649,8 +1648,9 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
}
}

-clk_free:
- clk_disable(i2c_dev->clk);
+pm_free:
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
return ret;
}

@@ -1676,13 +1676,9 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
if (ret)
return ret;

- if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
- ret = clk_enable(i2c_dev->clk);
- if (ret) {
- dev_err(dev, "Failed to enable clock\n");
- return ret;
- }
- }
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0)
+ return ret;

if (id == 0) {
/* Configure Own Address 1 */
@@ -1703,7 +1699,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
oar2 &= ~STM32F7_I2C_OAR2_MASK;
if (slave->flags & I2C_CLIENT_TEN) {
ret = -EOPNOTSUPP;
- goto exit;
+ goto pm_free;
}

oar2 |= STM32F7_I2C_OAR2_OA2_7(slave->addr);
@@ -1712,7 +1708,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2);
} else {
ret = -ENODEV;
- goto exit;
+ goto pm_free;
}

/* Enable ACK */
@@ -1723,11 +1719,10 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
STM32F7_I2C_CR1_PE;
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);

- return 0;
-
-exit:
- if (!(stm32f7_i2c_is_slave_registered(i2c_dev)))
- clk_disable(i2c_dev->clk);
+ ret = 0;
+pm_free:
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);

return ret;
}
@@ -1745,6 +1740,10 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)

WARN_ON(!i2c_dev->slave[id]);

+ ret = pm_runtime_get_sync(i2c_dev->dev);
+ if (ret < 0)
+ return ret;
+
if (id == 0) {
mask = STM32F7_I2C_OAR1_OA1EN;
stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask);
@@ -1755,10 +1754,11 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)

i2c_dev->slave[id] = NULL;

- if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
+ if (!(stm32f7_i2c_is_slave_registered(i2c_dev)))
stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
- clk_disable(i2c_dev->clk);
- }
+
+ pm_runtime_mark_last_busy(i2c_dev->dev);
+ pm_runtime_put_autosuspend(i2c_dev->dev);

return 0;
}
@@ -1819,6 +1819,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Error: Missing controller clock\n");
return PTR_ERR(i2c_dev->clk);
}
+
ret = clk_prepare_enable(i2c_dev->clk);
if (ret) {
dev_err(&pdev->dev, "Failed to prepare_enable clock\n");
@@ -1888,8 +1889,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
if (ret)
goto clk_free;

- stm32f7_i2c_hw_config(i2c_dev);
-
adap = &i2c_dev->adap;
i2c_set_adapdata(adap, i2c_dev);
snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)",
@@ -1908,18 +1907,35 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
STM32F7_I2C_TXDR,
STM32F7_I2C_RXDR);

- ret = i2c_add_adapter(adap);
- if (ret)
- goto clk_free;
-
platform_set_drvdata(pdev, i2c_dev);

- clk_disable(i2c_dev->clk);
+ pm_runtime_set_autosuspend_delay(i2c_dev->dev,
+ STM32F7_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(i2c_dev->dev);
+ pm_runtime_set_active(i2c_dev->dev);
+ pm_runtime_enable(i2c_dev->dev);
+
+ pm_runtime_get_noresume(&pdev->dev);
+
+ stm32f7_i2c_hw_config(i2c_dev);
+
+ ret = i2c_add_adapter(adap);
+ if (ret)
+ goto pm_disable;

dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr);

+ pm_runtime_mark_last_busy(i2c_dev->dev);
+ pm_runtime_put_autosuspend(i2c_dev->dev);
+
return 0;

+pm_disable:
+ pm_runtime_put_noidle(i2c_dev->dev);
+ pm_runtime_disable(i2c_dev->dev);
+ pm_runtime_set_suspended(i2c_dev->dev);
+ pm_runtime_dont_use_autosuspend(i2c_dev->dev);
+
clk_free:
clk_disable_unprepare(i2c_dev->clk);

@@ -1936,12 +1952,51 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
}

i2c_del_adapter(&i2c_dev->adap);
+ pm_runtime_get_sync(i2c_dev->dev);
+
+ clk_disable_unprepare(i2c_dev->clk);

- clk_unprepare(i2c_dev->clk);
+ pm_runtime_put_noidle(i2c_dev->dev);
+ pm_runtime_disable(i2c_dev->dev);
+ pm_runtime_set_suspended(i2c_dev->dev);
+ pm_runtime_dont_use_autosuspend(i2c_dev->dev);

return 0;
}

+#ifdef CONFIG_PM
+static int stm32f7_i2c_runtime_suspend(struct device *dev)
+{
+ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev))
+ clk_disable_unprepare(i2c_dev->clk);
+
+ return 0;
+}
+
+static int stm32f7_i2c_runtime_resume(struct device *dev)
+{
+ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+ int ret;
+
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
+ ret = clk_prepare_enable(i2c_dev->clk);
+ if (ret) {
+ dev_err(dev, "failed to prepare_enable clock\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops stm32f7_i2c_pm_ops = {
+ SET_RUNTIME_PM_OPS(stm32f7_i2c_runtime_suspend,
+ stm32f7_i2c_runtime_resume, NULL)
+};
+
static const struct of_device_id stm32f7_i2c_match[] = {
{ .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup},
{},
@@ -1952,6 +2007,7 @@ static struct platform_driver stm32f7_i2c_driver = {
.driver = {
.name = "stm32f7-i2c",
.of_match_table = stm32f7_i2c_match,
+ .pm = &stm32f7_i2c_pm_ops,
},
.probe = stm32f7_i2c_probe,
.remove = stm32f7_i2c_remove,
--
2.7.4



2018-11-18 16:35:32

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v1] i2c: i2c-stm32f7: add PM Runtime support

Hi Pierre-Yves,

I love your patch! Yet something to improve:

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v4.20-rc2 next-20181116]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Pierre-Yves-MORDRET/i2c-i2c-stm32f7-add-PM-Runtime-support/20181118-230534
base: https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: xtensa-allyesconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 8.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.1.0 make.cross ARCH=xtensa

All errors (new ones prefixed by >>):

drivers/i2c/busses/i2c-stm32f7.c: In function 'stm32f7_i2c_probe':
>> drivers/i2c/busses/i2c-stm32f7.c:1913:7: error: 'STM32F7_AUTOSUSPEND_DELAY' undeclared (first use in this function); did you mean 'RPM_REQ_AUTOSUSPEND'?
STM32F7_AUTOSUSPEND_DELAY);
^~~~~~~~~~~~~~~~~~~~~~~~~
RPM_REQ_AUTOSUSPEND
drivers/i2c/busses/i2c-stm32f7.c:1913:7: note: each undeclared identifier is reported only once for each function it appears in

vim +1913 drivers/i2c/busses/i2c-stm32f7.c

1782
1783 static int stm32f7_i2c_probe(struct platform_device *pdev)
1784 {
1785 struct device_node *np = pdev->dev.of_node;
1786 struct stm32f7_i2c_dev *i2c_dev;
1787 const struct stm32f7_i2c_setup *setup;
1788 struct resource *res;
1789 u32 irq_error, irq_event, clk_rate, rise_time, fall_time;
1790 struct i2c_adapter *adap;
1791 struct reset_control *rst;
1792 dma_addr_t phy_addr;
1793 int ret;
1794
1795 i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
1796 if (!i2c_dev)
1797 return -ENOMEM;
1798
1799 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1800 i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
1801 if (IS_ERR(i2c_dev->base))
1802 return PTR_ERR(i2c_dev->base);
1803 phy_addr = (dma_addr_t)res->start;
1804
1805 irq_event = irq_of_parse_and_map(np, 0);
1806 if (!irq_event) {
1807 dev_err(&pdev->dev, "IRQ event missing or invalid\n");
1808 return -EINVAL;
1809 }
1810
1811 irq_error = irq_of_parse_and_map(np, 1);
1812 if (!irq_error) {
1813 dev_err(&pdev->dev, "IRQ error missing or invalid\n");
1814 return -EINVAL;
1815 }
1816
1817 i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
1818 if (IS_ERR(i2c_dev->clk)) {
1819 dev_err(&pdev->dev, "Error: Missing controller clock\n");
1820 return PTR_ERR(i2c_dev->clk);
1821 }
1822
1823 ret = clk_prepare_enable(i2c_dev->clk);
1824 if (ret) {
1825 dev_err(&pdev->dev, "Failed to prepare_enable clock\n");
1826 return ret;
1827 }
1828
1829 i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
1830 ret = device_property_read_u32(&pdev->dev, "clock-frequency",
1831 &clk_rate);
1832 if (!ret && clk_rate >= 1000000)
1833 i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS;
1834 else if (!ret && clk_rate >= 400000)
1835 i2c_dev->speed = STM32_I2C_SPEED_FAST;
1836 else if (!ret && clk_rate >= 100000)
1837 i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
1838
1839 rst = devm_reset_control_get(&pdev->dev, NULL);
1840 if (IS_ERR(rst)) {
1841 dev_err(&pdev->dev, "Error: Missing controller reset\n");
1842 ret = PTR_ERR(rst);
1843 goto clk_free;
1844 }
1845 reset_control_assert(rst);
1846 udelay(2);
1847 reset_control_deassert(rst);
1848
1849 i2c_dev->dev = &pdev->dev;
1850
1851 ret = devm_request_threaded_irq(&pdev->dev, irq_event,
1852 stm32f7_i2c_isr_event,
1853 stm32f7_i2c_isr_event_thread,
1854 IRQF_ONESHOT,
1855 pdev->name, i2c_dev);
1856 if (ret) {
1857 dev_err(&pdev->dev, "Failed to request irq event %i\n",
1858 irq_event);
1859 goto clk_free;
1860 }
1861
1862 ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0,
1863 pdev->name, i2c_dev);
1864 if (ret) {
1865 dev_err(&pdev->dev, "Failed to request irq error %i\n",
1866 irq_error);
1867 goto clk_free;
1868 }
1869
1870 setup = of_device_get_match_data(&pdev->dev);
1871 if (!setup) {
1872 dev_err(&pdev->dev, "Can't get device data\n");
1873 ret = -ENODEV;
1874 goto clk_free;
1875 }
1876 i2c_dev->setup = *setup;
1877
1878 ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-rising-time-ns",
1879 &rise_time);
1880 if (!ret)
1881 i2c_dev->setup.rise_time = rise_time;
1882
1883 ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-falling-time-ns",
1884 &fall_time);
1885 if (!ret)
1886 i2c_dev->setup.fall_time = fall_time;
1887
1888 ret = stm32f7_i2c_setup_timing(i2c_dev, &i2c_dev->setup);
1889 if (ret)
1890 goto clk_free;
1891
1892 adap = &i2c_dev->adap;
1893 i2c_set_adapdata(adap, i2c_dev);
1894 snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)",
1895 &res->start);
1896 adap->owner = THIS_MODULE;
1897 adap->timeout = 2 * HZ;
1898 adap->retries = 3;
1899 adap->algo = &stm32f7_i2c_algo;
1900 adap->dev.parent = &pdev->dev;
1901 adap->dev.of_node = pdev->dev.of_node;
1902
1903 init_completion(&i2c_dev->complete);
1904
1905 /* Init DMA config if supported */
1906 i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr,
1907 STM32F7_I2C_TXDR,
1908 STM32F7_I2C_RXDR);
1909
1910 platform_set_drvdata(pdev, i2c_dev);
1911
1912 pm_runtime_set_autosuspend_delay(i2c_dev->dev,
> 1913 STM32F7_AUTOSUSPEND_DELAY);
1914 pm_runtime_use_autosuspend(i2c_dev->dev);
1915 pm_runtime_set_active(i2c_dev->dev);
1916 pm_runtime_enable(i2c_dev->dev);
1917
1918 pm_runtime_get_noresume(&pdev->dev);
1919
1920 stm32f7_i2c_hw_config(i2c_dev);
1921
1922 ret = i2c_add_adapter(adap);
1923 if (ret)
1924 goto pm_disable;
1925
1926 dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr);
1927
1928 pm_runtime_mark_last_busy(i2c_dev->dev);
1929 pm_runtime_put_autosuspend(i2c_dev->dev);
1930
1931 return 0;
1932
1933 pm_disable:
1934 pm_runtime_put_noidle(i2c_dev->dev);
1935 pm_runtime_disable(i2c_dev->dev);
1936 pm_runtime_set_suspended(i2c_dev->dev);
1937 pm_runtime_dont_use_autosuspend(i2c_dev->dev);
1938
1939 clk_free:
1940 clk_disable_unprepare(i2c_dev->clk);
1941
1942 return ret;
1943 }
1944

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (6.91 kB)
.config.gz (54.44 kB)
Download all attachments

2018-11-18 17:30:55

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v1] i2c: i2c-stm32f7: add PM Runtime support

Hi Pierre-Yves,

I love your patch! Yet something to improve:

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v4.20-rc2 next-20181116]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Pierre-Yves-MORDRET/i2c-i2c-stm32f7-add-PM-Runtime-support/20181118-230534
base: https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: nds32-allmodconfig (attached as .config)
compiler: nds32le-linux-gcc (GCC) 6.4.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=6.4.0 make.cross ARCH=nds32

All errors (new ones prefixed by >>):

drivers/i2c/busses/i2c-stm32f7.c: In function 'stm32f7_i2c_probe':
>> drivers/i2c/busses/i2c-stm32f7.c:1913:7: error: 'STM32F7_AUTOSUSPEND_DELAY' undeclared (first use in this function)
STM32F7_AUTOSUSPEND_DELAY);
^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/i2c/busses/i2c-stm32f7.c:1913:7: note: each undeclared identifier is reported only once for each function it appears in

vim +/STM32F7_AUTOSUSPEND_DELAY +1913 drivers/i2c/busses/i2c-stm32f7.c

1782
1783 static int stm32f7_i2c_probe(struct platform_device *pdev)
1784 {
1785 struct device_node *np = pdev->dev.of_node;
1786 struct stm32f7_i2c_dev *i2c_dev;
1787 const struct stm32f7_i2c_setup *setup;
1788 struct resource *res;
1789 u32 irq_error, irq_event, clk_rate, rise_time, fall_time;
1790 struct i2c_adapter *adap;
1791 struct reset_control *rst;
1792 dma_addr_t phy_addr;
1793 int ret;
1794
1795 i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
1796 if (!i2c_dev)
1797 return -ENOMEM;
1798
1799 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1800 i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
1801 if (IS_ERR(i2c_dev->base))
1802 return PTR_ERR(i2c_dev->base);
1803 phy_addr = (dma_addr_t)res->start;
1804
1805 irq_event = irq_of_parse_and_map(np, 0);
1806 if (!irq_event) {
1807 dev_err(&pdev->dev, "IRQ event missing or invalid\n");
1808 return -EINVAL;
1809 }
1810
1811 irq_error = irq_of_parse_and_map(np, 1);
1812 if (!irq_error) {
1813 dev_err(&pdev->dev, "IRQ error missing or invalid\n");
1814 return -EINVAL;
1815 }
1816
1817 i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
1818 if (IS_ERR(i2c_dev->clk)) {
1819 dev_err(&pdev->dev, "Error: Missing controller clock\n");
1820 return PTR_ERR(i2c_dev->clk);
1821 }
1822
1823 ret = clk_prepare_enable(i2c_dev->clk);
1824 if (ret) {
1825 dev_err(&pdev->dev, "Failed to prepare_enable clock\n");
1826 return ret;
1827 }
1828
1829 i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
1830 ret = device_property_read_u32(&pdev->dev, "clock-frequency",
1831 &clk_rate);
1832 if (!ret && clk_rate >= 1000000)
1833 i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS;
1834 else if (!ret && clk_rate >= 400000)
1835 i2c_dev->speed = STM32_I2C_SPEED_FAST;
1836 else if (!ret && clk_rate >= 100000)
1837 i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
1838
1839 rst = devm_reset_control_get(&pdev->dev, NULL);
1840 if (IS_ERR(rst)) {
1841 dev_err(&pdev->dev, "Error: Missing controller reset\n");
1842 ret = PTR_ERR(rst);
1843 goto clk_free;
1844 }
1845 reset_control_assert(rst);
1846 udelay(2);
1847 reset_control_deassert(rst);
1848
1849 i2c_dev->dev = &pdev->dev;
1850
1851 ret = devm_request_threaded_irq(&pdev->dev, irq_event,
1852 stm32f7_i2c_isr_event,
1853 stm32f7_i2c_isr_event_thread,
1854 IRQF_ONESHOT,
1855 pdev->name, i2c_dev);
1856 if (ret) {
1857 dev_err(&pdev->dev, "Failed to request irq event %i\n",
1858 irq_event);
1859 goto clk_free;
1860 }
1861
1862 ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0,
1863 pdev->name, i2c_dev);
1864 if (ret) {
1865 dev_err(&pdev->dev, "Failed to request irq error %i\n",
1866 irq_error);
1867 goto clk_free;
1868 }
1869
1870 setup = of_device_get_match_data(&pdev->dev);
1871 if (!setup) {
1872 dev_err(&pdev->dev, "Can't get device data\n");
1873 ret = -ENODEV;
1874 goto clk_free;
1875 }
1876 i2c_dev->setup = *setup;
1877
1878 ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-rising-time-ns",
1879 &rise_time);
1880 if (!ret)
1881 i2c_dev->setup.rise_time = rise_time;
1882
1883 ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-falling-time-ns",
1884 &fall_time);
1885 if (!ret)
1886 i2c_dev->setup.fall_time = fall_time;
1887
1888 ret = stm32f7_i2c_setup_timing(i2c_dev, &i2c_dev->setup);
1889 if (ret)
1890 goto clk_free;
1891
1892 adap = &i2c_dev->adap;
1893 i2c_set_adapdata(adap, i2c_dev);
1894 snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)",
1895 &res->start);
1896 adap->owner = THIS_MODULE;
1897 adap->timeout = 2 * HZ;
1898 adap->retries = 3;
1899 adap->algo = &stm32f7_i2c_algo;
1900 adap->dev.parent = &pdev->dev;
1901 adap->dev.of_node = pdev->dev.of_node;
1902
1903 init_completion(&i2c_dev->complete);
1904
1905 /* Init DMA config if supported */
1906 i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr,
1907 STM32F7_I2C_TXDR,
1908 STM32F7_I2C_RXDR);
1909
1910 platform_set_drvdata(pdev, i2c_dev);
1911
1912 pm_runtime_set_autosuspend_delay(i2c_dev->dev,
> 1913 STM32F7_AUTOSUSPEND_DELAY);
1914 pm_runtime_use_autosuspend(i2c_dev->dev);
1915 pm_runtime_set_active(i2c_dev->dev);
1916 pm_runtime_enable(i2c_dev->dev);
1917
1918 pm_runtime_get_noresume(&pdev->dev);
1919
1920 stm32f7_i2c_hw_config(i2c_dev);
1921
1922 ret = i2c_add_adapter(adap);
1923 if (ret)
1924 goto pm_disable;
1925
1926 dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr);
1927
1928 pm_runtime_mark_last_busy(i2c_dev->dev);
1929 pm_runtime_put_autosuspend(i2c_dev->dev);
1930
1931 return 0;
1932
1933 pm_disable:
1934 pm_runtime_put_noidle(i2c_dev->dev);
1935 pm_runtime_disable(i2c_dev->dev);
1936 pm_runtime_set_suspended(i2c_dev->dev);
1937 pm_runtime_dont_use_autosuspend(i2c_dev->dev);
1938
1939 clk_free:
1940 clk_disable_unprepare(i2c_dev->clk);
1941
1942 return ret;
1943 }
1944

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (6.87 kB)
.config.gz (47.35 kB)
Download all attachments