diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-14 10:21:46 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-14 10:21:46 +0300 |
commit | 9bca19a01d50143b736f0f59eb3ccc05b1106172 (patch) | |
tree | 3321118b4a6bd4c949634bbdbb3d2c03454ae33b /drivers/i2c/busses/i2c-qup.c | |
parent | 463f202172c31b9c36278001cabfbad4e12da42e (diff) | |
parent | 53e39628ac228fada53cc0106be62c6f65f67501 (diff) | |
download | linux-9bca19a01d50143b736f0f59eb3ccc05b1106172.tar.xz |
Merge branch 'i2c/for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
- mainly feature additions to drivers (stm32f7, qup, xlp9xx, mlxcpld, ...)
- conversion to use the i2c_8bit_addr_from_msg macro consistently
- move includes to platform_data
- core updates to allow the (still in review) I3C subsystem to connect
- and the regular share of smaller driver updates
* 'i2c/for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (68 commits)
i2c: qup: fix building without CONFIG_ACPI
i2c: tegra: Remove suspend-resume
i2c: imx-lpi2c: Switch to SPDX identifier
i2c: mxs: Switch to SPDX identifier
i2c: busses: make use of i2c_8bit_addr_from_msg
i2c: algos: make use of i2c_8bit_addr_from_msg
i2c: rcar: document R8A77980 bindings
i2c: qup: Add command-line parameter to override SCL frequency
i2c: qup: Correct duty cycle for FM and FM+
i2c: qup: Add support for Fast Mode Plus
i2c: qup: add probe path for Centriq ACPI devices
i2c: robotfuzz-osif: drop pointless test
i2c: robotfuzz-osif: remove pointless local variable
i2c: rk3x: Don't print visible virtual mapping MMIO address
i2c: opal: don't check number of messages in the driver
i2c: ibm_iic: don't check number of messages in the driver
i2c: imx: Switch to SPDX identifier
i2c: mux: pca954x: merge calls to of_match_device and of_device_get_match_data
i2c: mux: demux-pinctrl: use proper parent device for demux adapter
i2c: mux: improve error message for failed symlink
...
Diffstat (limited to 'drivers/i2c/busses/i2c-qup.c')
-rw-r--r-- | drivers/i2c/busses/i2c-qup.c | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index ebbf9cdec86b..c86c3ae1318f 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -136,8 +136,13 @@ */ #define TOUT_MIN 2 +/* I2C Frequency Modes */ +#define I2C_STANDARD_FREQ 100000 +#define I2C_FAST_MODE_FREQ 400000 +#define I2C_FAST_MODE_PLUS_FREQ 1000000 + /* Default values. Use these if FW query fails */ -#define DEFAULT_CLK_FREQ 100000 +#define DEFAULT_CLK_FREQ I2C_STANDARD_FREQ #define DEFAULT_SRC_CLK 20000000 /* @@ -150,6 +155,10 @@ /* TAG length for DATA READ in RX FIFO */ #define READ_RX_TAGS_LEN 2 +static unsigned int scl_freq; +module_param_named(scl_freq, scl_freq, uint, 0444); +MODULE_PARM_DESC(scl_freq, "SCL frequency override"); + /* * count: no of blocks * pos: current block number @@ -453,7 +462,7 @@ static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup) { struct qup_i2c_block *blk = &qup->blk; struct i2c_msg *msg = qup->msg; - u32 addr = msg->addr << 1; + u32 addr = i2c_8bit_addr_from_msg(msg); u32 qup_tag; int idx; u32 val; @@ -1648,6 +1657,12 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup) clk_disable_unprepare(qup->pclk); } +static const struct acpi_device_id qup_i2c_acpi_match[] = { + { "QCOM8010"}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_match); + static int qup_i2c_probe(struct platform_device *pdev) { static const int blk_sizes[] = {4, 16, 32}; @@ -1669,10 +1684,15 @@ static int qup_i2c_probe(struct platform_device *pdev) init_completion(&qup->xfer); platform_set_drvdata(pdev, qup); - ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq); - if (ret) { - dev_notice(qup->dev, "using default clock-frequency %d", - DEFAULT_CLK_FREQ); + if (scl_freq) { + dev_notice(qup->dev, "Using override frequency of %u\n", scl_freq); + clk_freq = scl_freq; + } else { + ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq); + if (ret) { + dev_notice(qup->dev, "using default clock-frequency %d", + DEFAULT_CLK_FREQ); + } } if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) { @@ -1682,7 +1702,10 @@ static int qup_i2c_probe(struct platform_device *pdev) } else { qup->adap.algo = &qup_i2c_algo_v2; is_qup_v1 = false; - ret = qup_i2c_req_dma(qup); + if (acpi_match_device(qup_i2c_acpi_match, qup->dev)) + goto nodma; + else + ret = qup_i2c_req_dma(qup); if (ret == -EPROBE_DEFER) goto fail_dma; @@ -1734,8 +1757,8 @@ static int qup_i2c_probe(struct platform_device *pdev) } nodma: - /* We support frequencies up to FAST Mode (400KHz) */ - if (!clk_freq || clk_freq > 400000) { + /* We support frequencies up to FAST Mode Plus (1MHz) */ + if (!clk_freq || clk_freq > I2C_FAST_MODE_PLUS_FREQ) { dev_err(qup->dev, "clock frequency not supported %d\n", clk_freq); return -EINVAL; @@ -1839,9 +1862,15 @@ nodma: size = QUP_INPUT_FIFO_SIZE(io_mode); qup->in_fifo_sz = qup->in_blk_sz * (2 << size); - fs_div = ((src_clk_freq / clk_freq) / 2) - 3; hs_div = 3; - qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff); + if (clk_freq <= I2C_STANDARD_FREQ) { + fs_div = ((src_clk_freq / clk_freq) / 2) - 3; + qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff); + } else { + /* 33%/66% duty cycle */ + fs_div = ((src_clk_freq / clk_freq) - 6) * 2 / 3; + qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff); + } /* * Time it takes for a byte to be clocked out on the bus. @@ -1959,14 +1988,6 @@ static const struct of_device_id qup_i2c_dt_match[] = { }; MODULE_DEVICE_TABLE(of, qup_i2c_dt_match); -#if IS_ENABLED(CONFIG_ACPI) -static const struct acpi_device_id qup_i2c_acpi_match[] = { - { "QCOM8010"}, - { }, -}; -MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_match); -#endif - static struct platform_driver qup_i2c_driver = { .probe = qup_i2c_probe, .remove = qup_i2c_remove, |