diff mbox series

[2/3] i2c: qup: Introduce SCL/SDA noise rejection

Message ID 20210113182522.443262-3-angelogioacchino.delregno@somainline.org
State Superseded
Headers show
Series QCOM QUP I2C - Add noise rejection, convert to YAML | expand

Commit Message

AngeloGioacchino Del Regno Jan. 13, 2021, 6:25 p.m. UTC
Some I2C devices may be glitchy due to electrical noise coming
from the device itself or because of possible board design issues.
To overcome this issue, the QUP's I2C in Qualcomm SoCs supports
a noise rejection setting for both SCL and SDA lines.

Introduce a setting for noise rejection through device properties,
"qcom,noise-reject-sda" and "qcom,noise-reject-scl", which will
be used to set the level of noise rejection sensitivity.
If the properties are not specified, noise rejection will not be
enabled.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
---
 drivers/i2c/busses/i2c-qup.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Comments

kernel test robot Jan. 14, 2021, 3:57 a.m. UTC | #1
Hi AngeloGioacchino,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on linux/master robh/for-next linus/master v5.11-rc3 next-20210113]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/AngeloGioacchino-Del-Regno/QCOM-QUP-I2C-Add-noise-rejection-convert-to-YAML/20210114-023032
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: arm-allyesconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/a124c4d6bf942e45b63addcef97f56f2a8934fe8
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review AngeloGioacchino-Del-Regno/QCOM-QUP-I2C-Add-noise-rejection-convert-to-YAML/20210114-023032
        git checkout a124c4d6bf942e45b63addcef97f56f2a8934fe8
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/i2c/busses/i2c-qup.c: In function 'qup_i2c_probe':
>> drivers/i2c/busses/i2c-qup.c:1870:19: error: implicit declaration of function 'FIELD_PREP' [-Werror=implicit-function-declaration]

    1870 |   qup->clk_ctl |= FIELD_PREP(QUP_I2C_CLK_CTL_SCL_NR,
         |                   ^~~~~~~~~~
   cc1: some warnings being treated as errors


vim +/FIELD_PREP +1870 drivers/i2c/busses/i2c-qup.c

  1658	
  1659	static int qup_i2c_probe(struct platform_device *pdev)
  1660	{
  1661		static const int blk_sizes[] = {4, 16, 32};
  1662		struct qup_i2c_dev *qup;
  1663		unsigned long one_bit_t;
  1664		u32 io_mode, hw_ver, size;
  1665		int ret, fs_div, hs_div;
  1666		u32 src_clk_freq = DEFAULT_SRC_CLK;
  1667		u32 clk_freq = DEFAULT_CLK_FREQ;
  1668		u32 noise_reject_scl = 0, noise_reject_sda = 0;
  1669		int blocks;
  1670		bool is_qup_v1;
  1671	
  1672		qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
  1673		if (!qup)
  1674			return -ENOMEM;
  1675	
  1676		qup->dev = &pdev->dev;
  1677		init_completion(&qup->xfer);
  1678		platform_set_drvdata(pdev, qup);
  1679	
  1680		if (scl_freq) {
  1681			dev_notice(qup->dev, "Using override frequency of %u\n", scl_freq);
  1682			clk_freq = scl_freq;
  1683		} else {
  1684			ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
  1685			if (ret) {
  1686				dev_notice(qup->dev, "using default clock-frequency %d",
  1687					DEFAULT_CLK_FREQ);
  1688			}
  1689		}
  1690	
  1691		if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
  1692			qup->adap.algo = &qup_i2c_algo;
  1693			qup->adap.quirks = &qup_i2c_quirks;
  1694			is_qup_v1 = true;
  1695		} else {
  1696			qup->adap.algo = &qup_i2c_algo_v2;
  1697			qup->adap.quirks = &qup_i2c_quirks_v2;
  1698			is_qup_v1 = false;
  1699			if (acpi_match_device(qup_i2c_acpi_match, qup->dev))
  1700				goto nodma;
  1701			else
  1702				ret = qup_i2c_req_dma(qup);
  1703	
  1704			if (ret == -EPROBE_DEFER)
  1705				goto fail_dma;
  1706			else if (ret != 0)
  1707				goto nodma;
  1708	
  1709			qup->max_xfer_sg_len = (MX_BLOCKS << 1);
  1710			blocks = (MX_DMA_BLOCKS << 1) + 1;
  1711			qup->btx.sg = devm_kcalloc(&pdev->dev,
  1712						   blocks, sizeof(*qup->btx.sg),
  1713						   GFP_KERNEL);
  1714			if (!qup->btx.sg) {
  1715				ret = -ENOMEM;
  1716				goto fail_dma;
  1717			}
  1718			sg_init_table(qup->btx.sg, blocks);
  1719	
  1720			qup->brx.sg = devm_kcalloc(&pdev->dev,
  1721						   blocks, sizeof(*qup->brx.sg),
  1722						   GFP_KERNEL);
  1723			if (!qup->brx.sg) {
  1724				ret = -ENOMEM;
  1725				goto fail_dma;
  1726			}
  1727			sg_init_table(qup->brx.sg, blocks);
  1728	
  1729			/* 2 tag bytes for each block + 5 for start, stop tags */
  1730			size = blocks * 2 + 5;
  1731	
  1732			qup->start_tag.start = devm_kzalloc(&pdev->dev,
  1733							    size, GFP_KERNEL);
  1734			if (!qup->start_tag.start) {
  1735				ret = -ENOMEM;
  1736				goto fail_dma;
  1737			}
  1738	
  1739			qup->brx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
  1740			if (!qup->brx.tag.start) {
  1741				ret = -ENOMEM;
  1742				goto fail_dma;
  1743			}
  1744	
  1745			qup->btx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
  1746			if (!qup->btx.tag.start) {
  1747				ret = -ENOMEM;
  1748				goto fail_dma;
  1749			}
  1750			qup->is_dma = true;
  1751		}
  1752	
  1753	nodma:
  1754		/* We support frequencies up to FAST Mode Plus (1MHz) */
  1755		if (!clk_freq || clk_freq > I2C_MAX_FAST_MODE_PLUS_FREQ) {
  1756			dev_err(qup->dev, "clock frequency not supported %d\n",
  1757				clk_freq);
  1758			return -EINVAL;
  1759		}
  1760	
  1761		qup->base = devm_platform_ioremap_resource(pdev, 0);
  1762		if (IS_ERR(qup->base))
  1763			return PTR_ERR(qup->base);
  1764	
  1765		qup->irq = platform_get_irq(pdev, 0);
  1766		if (qup->irq < 0)
  1767			return qup->irq;
  1768	
  1769		if (has_acpi_companion(qup->dev)) {
  1770			ret = device_property_read_u32(qup->dev,
  1771					"src-clock-hz", &src_clk_freq);
  1772			if (ret) {
  1773				dev_notice(qup->dev, "using default src-clock-hz %d",
  1774					DEFAULT_SRC_CLK);
  1775			}
  1776			ACPI_COMPANION_SET(&qup->adap.dev, ACPI_COMPANION(qup->dev));
  1777		} else {
  1778			qup->clk = devm_clk_get(qup->dev, "core");
  1779			if (IS_ERR(qup->clk)) {
  1780				dev_err(qup->dev, "Could not get core clock\n");
  1781				return PTR_ERR(qup->clk);
  1782			}
  1783	
  1784			qup->pclk = devm_clk_get(qup->dev, "iface");
  1785			if (IS_ERR(qup->pclk)) {
  1786				dev_err(qup->dev, "Could not get iface clock\n");
  1787				return PTR_ERR(qup->pclk);
  1788			}
  1789			qup_i2c_enable_clocks(qup);
  1790			src_clk_freq = clk_get_rate(qup->clk);
  1791		}
  1792	
  1793		/*
  1794		 * Bootloaders might leave a pending interrupt on certain QUP's,
  1795		 * so we reset the core before registering for interrupts.
  1796		 */
  1797		writel(1, qup->base + QUP_SW_RESET);
  1798		ret = qup_i2c_poll_state_valid(qup);
  1799		if (ret)
  1800			goto fail;
  1801	
  1802		ret = devm_request_irq(qup->dev, qup->irq, qup_i2c_interrupt,
  1803				       IRQF_TRIGGER_HIGH, "i2c_qup", qup);
  1804		if (ret) {
  1805			dev_err(qup->dev, "Request %d IRQ failed\n", qup->irq);
  1806			goto fail;
  1807		}
  1808		disable_irq(qup->irq);
  1809	
  1810		hw_ver = readl(qup->base + QUP_HW_VERSION);
  1811		dev_dbg(qup->dev, "Revision %x\n", hw_ver);
  1812	
  1813		io_mode = readl(qup->base + QUP_IO_MODE);
  1814	
  1815		/*
  1816		 * The block/fifo size w.r.t. 'actual data' is 1/2 due to 'tag'
  1817		 * associated with each byte written/received
  1818		 */
  1819		size = QUP_OUTPUT_BLOCK_SIZE(io_mode);
  1820		if (size >= ARRAY_SIZE(blk_sizes)) {
  1821			ret = -EIO;
  1822			goto fail;
  1823		}
  1824		qup->out_blk_sz = blk_sizes[size];
  1825	
  1826		size = QUP_INPUT_BLOCK_SIZE(io_mode);
  1827		if (size >= ARRAY_SIZE(blk_sizes)) {
  1828			ret = -EIO;
  1829			goto fail;
  1830		}
  1831		qup->in_blk_sz = blk_sizes[size];
  1832	
  1833		if (is_qup_v1) {
  1834			/*
  1835			 * in QUP v1, QUP_CONFIG uses N as 15 i.e 16 bits constitutes a
  1836			 * single transfer but the block size is in bytes so divide the
  1837			 * in_blk_sz and out_blk_sz by 2
  1838			 */
  1839			qup->in_blk_sz /= 2;
  1840			qup->out_blk_sz /= 2;
  1841			qup->write_tx_fifo = qup_i2c_write_tx_fifo_v1;
  1842			qup->read_rx_fifo = qup_i2c_read_rx_fifo_v1;
  1843			qup->write_rx_tags = qup_i2c_write_rx_tags_v1;
  1844		} else {
  1845			qup->write_tx_fifo = qup_i2c_write_tx_fifo_v2;
  1846			qup->read_rx_fifo = qup_i2c_read_rx_fifo_v2;
  1847			qup->write_rx_tags = qup_i2c_write_rx_tags_v2;
  1848		}
  1849	
  1850		size = QUP_OUTPUT_FIFO_SIZE(io_mode);
  1851		qup->out_fifo_sz = qup->out_blk_sz * (2 << size);
  1852	
  1853		size = QUP_INPUT_FIFO_SIZE(io_mode);
  1854		qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
  1855	
  1856		hs_div = 3;
  1857		if (clk_freq <= I2C_MAX_STANDARD_MODE_FREQ) {
  1858			fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
  1859			qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
  1860		} else {
  1861			/* 33%/66% duty cycle */
  1862			fs_div = ((src_clk_freq / clk_freq) - 6) * 2 / 3;
  1863			qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
  1864		}
  1865	
  1866		/* SCL/SDA Noise rejection (optional) */
  1867		ret = device_property_read_u32(qup->dev, "qcom,noise-reject-scl",
  1868					      &noise_reject_scl);
  1869		if (ret == 0)
> 1870			qup->clk_ctl |= FIELD_PREP(QUP_I2C_CLK_CTL_SCL_NR,

  1871						   noise_reject_scl);
  1872	
  1873		ret = device_property_read_u32(qup->dev, "qcom,noise-reject-sda",
  1874					      &noise_reject_sda);
  1875		if (ret == 0)
  1876			qup->clk_ctl |= FIELD_PREP(QUP_I2C_CLK_CTL_SDA_NR,
  1877						   noise_reject_sda);
  1878	
  1879		/*
  1880		 * Time it takes for a byte to be clocked out on the bus.
  1881		 * Each byte takes 9 clock cycles (8 bits + 1 ack).
  1882		 */
  1883		one_bit_t = (USEC_PER_SEC / clk_freq) + 1;
  1884		qup->one_byte_t = one_bit_t * 9;
  1885		qup->xfer_timeout = TOUT_MIN * HZ +
  1886			usecs_to_jiffies(MX_DMA_TX_RX_LEN * qup->one_byte_t);
  1887	
  1888		dev_dbg(qup->dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
  1889			qup->in_blk_sz, qup->in_fifo_sz,
  1890			qup->out_blk_sz, qup->out_fifo_sz);
  1891	
  1892		i2c_set_adapdata(&qup->adap, qup);
  1893		qup->adap.dev.parent = qup->dev;
  1894		qup->adap.dev.of_node = pdev->dev.of_node;
  1895		qup->is_last = true;
  1896	
  1897		strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name));
  1898	
  1899		pm_runtime_set_autosuspend_delay(qup->dev, MSEC_PER_SEC);
  1900		pm_runtime_use_autosuspend(qup->dev);
  1901		pm_runtime_set_active(qup->dev);
  1902		pm_runtime_enable(qup->dev);
  1903	
  1904		ret = i2c_add_adapter(&qup->adap);
  1905		if (ret)
  1906			goto fail_runtime;
  1907	
  1908		return 0;
  1909	
  1910	fail_runtime:
  1911		pm_runtime_disable(qup->dev);
  1912		pm_runtime_set_suspended(qup->dev);
  1913	fail:
  1914		qup_i2c_disable_clocks(qup);
  1915	fail_dma:
  1916		if (qup->btx.dma)
  1917			dma_release_channel(qup->btx.dma);
  1918		if (qup->brx.dma)
  1919			dma_release_channel(qup->brx.dma);
  1920		return ret;
  1921	}
  1922	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 5a47915869ae..35cc47f010e3 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -39,6 +39,8 @@ 
 #define QUP_MX_READ_CNT		0x208
 #define QUP_IN_FIFO_BASE	0x218
 #define QUP_I2C_CLK_CTL		0x400
+#define  QUP_I2C_CLK_CTL_SDA_NR	GENMASK(27, 26)
+#define  QUP_I2C_CLK_CTL_SCL_NR	GENMASK(25, 24)
 #define QUP_I2C_STATUS		0x404
 #define QUP_I2C_MASTER_GEN	0x408
 
@@ -1663,6 +1665,7 @@  static int qup_i2c_probe(struct platform_device *pdev)
 	int ret, fs_div, hs_div;
 	u32 src_clk_freq = DEFAULT_SRC_CLK;
 	u32 clk_freq = DEFAULT_CLK_FREQ;
+	u32 noise_reject_scl = 0, noise_reject_sda = 0;
 	int blocks;
 	bool is_qup_v1;
 
@@ -1860,6 +1863,19 @@  static int qup_i2c_probe(struct platform_device *pdev)
 		qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
 	}
 
+	/* SCL/SDA Noise rejection (optional) */
+	ret = device_property_read_u32(qup->dev, "qcom,noise-reject-scl",
+				      &noise_reject_scl);
+	if (ret == 0)
+		qup->clk_ctl |= FIELD_PREP(QUP_I2C_CLK_CTL_SCL_NR,
+					   noise_reject_scl);
+
+	ret = device_property_read_u32(qup->dev, "qcom,noise-reject-sda",
+				      &noise_reject_sda);
+	if (ret == 0)
+		qup->clk_ctl |= FIELD_PREP(QUP_I2C_CLK_CTL_SDA_NR,
+					   noise_reject_sda);
+
 	/*
 	 * Time it takes for a byte to be clocked out on the bus.
 	 * Each byte takes 9 clock cycles (8 bits + 1 ack).