mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
i2c-for-6.17-rc1-part2
- acpi: enable 100kHz workaround for DLL0945 - apple: add support for Apple A7–A11, T2 chips; Kconfig update - mux: mule: fix error handling path - qcom-geni: fix controller frequency mapping - stm32f7: add DMA-safe transfer support - tegra: use controller reset if device reset is missing - tegra: remove unnecessary dma_sync*() calls -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmiRKoIACgkQFA3kzBSg KbakqA//W1G20/oKi+Anj4SBK6Bj5YkW0hYyBrzaEKu2xQ4yay+gCkKAxqRictG6 OWVPZ/uuB2I9kr5LEMj1MnZpp3CjexFK2pbPrxt8xqr5inTjo/P4kqUWblRfiIn+ /68ekxyuANA+WXsgDxTsEMmY4h5vkyv1PfV6odC/w8dxnOqRizJwgPUVRgGI//vf u74VuYwUs2kpYsPqvCJ2PzwoHDVBwklKo4RYatvguJHrvUAlsIMsVS+TLESQPhAd o6SANAe2ZVntql+R3jAjzE/ykFxPyc2YrNS+F6ipVarAR5MEza+HWpy0x4p2P1Eb R+zAQRxApFRiCMZaYnyNMOq2AMp0NbRIrTnDVjajGd0bNpzAwSNd0yxIv6dHIljx d368FgUKRFjLidUF2sMu/FvWTiuJxprWiYA/VzdXtQey1b5SeKn14dbI224jJAQT 9Bs6ZhQ7cdNC78BWqUmISoF4vhn/k1RYpks4UmrXmV1Z3j9LgIDHo2DcFEhIuqa0 /xY7HQIOKBTVLFfNJIbwOzUWEkCeHNEX8Zh+ivtY9hm9nl9IWivFXrX+gW6vT6a4 r7r3cv1Vwe3CV5v+JPBgN2wdUwkhIvxvIO8wswNAkBombt5T13tnHB7ciiouupq0 uNcjBlCOXbJt3GdDsfAuCRXZ8JyY379jMaRSTkgfZ3ngXg1xY0E= =Uf9H -----END PGP SIGNATURE----- Merge tag 'i2c-for-6.17-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux Pull more i2c updates from Wolfram Sang: "A few more patches from I2C. Some are fixes which would be nice to have in rc1 already, some patches have nearly been fallen through the cracks, some just needed a bit more testing. - acpi: enable 100kHz workaround for DLL0945 - apple: add support for Apple A7–A11, T2 chips; Kconfig update - mux: mule: fix error handling path - qcom-geni: fix controller frequency mapping - stm32f7: add DMA-safe transfer support - tegra: use controller reset if device reset is missing - tegra: remove unnecessary dma_sync*() calls" * tag 'i2c-for-6.17-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: muxes: mule: Fix an error handling path in mule_i2c_mux_probe() i2c: Force DLL0945 touchpad i2c freq to 100khz i2c: apple: Drop default ARCH_APPLE in Kconfig i2c: qcom-geni: fix I2C frequency table to achieve accurate bus rates dt-bindings: i2c: apple,i2c: Document Apple A7-A11, T2 compatibles i2c: tegra: Remove dma_sync_*() calls i2c: tegra: Use internal reset when reset property is not available i2c: stm32f7: support i2c_*_dma_safe_msg_buf APIs
This commit is contained in:
commit
7e161a991e
7 changed files with 75 additions and 37 deletions
|
@ -22,6 +22,11 @@ properties:
|
|||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- apple,s5l8960x-i2c
|
||||
- apple,t7000-i2c
|
||||
- apple,s8000-i2c
|
||||
- apple,t8010-i2c
|
||||
- apple,t8015-i2c
|
||||
- apple,t8103-i2c
|
||||
- apple,t8112-i2c
|
||||
- apple,t6000-i2c
|
||||
|
|
|
@ -992,7 +992,6 @@ config I2C_APPLE
|
|||
tristate "Apple SMBus platform driver"
|
||||
depends on !I2C_PASEMI
|
||||
depends on ARCH_APPLE || COMPILE_TEST
|
||||
default ARCH_APPLE
|
||||
help
|
||||
Say Y here if you want to use the I2C controller present on Apple
|
||||
Silicon chips such as the M1.
|
||||
|
|
|
@ -155,9 +155,9 @@ static const struct geni_i2c_clk_fld geni_i2c_clk_map_19p2mhz[] = {
|
|||
|
||||
/* source_clock = 32 MHz */
|
||||
static const struct geni_i2c_clk_fld geni_i2c_clk_map_32mhz[] = {
|
||||
{ I2C_MAX_STANDARD_MODE_FREQ, 8, 14, 18, 40 },
|
||||
{ I2C_MAX_FAST_MODE_FREQ, 4, 3, 11, 20 },
|
||||
{ I2C_MAX_FAST_MODE_PLUS_FREQ, 2, 3, 6, 15 },
|
||||
{ I2C_MAX_STANDARD_MODE_FREQ, 8, 14, 18, 38 },
|
||||
{ I2C_MAX_FAST_MODE_FREQ, 4, 3, 9, 19 },
|
||||
{ I2C_MAX_FAST_MODE_PLUS_FREQ, 2, 3, 5, 15 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -742,11 +742,14 @@ static void stm32f7_i2c_dma_callback(void *arg)
|
|||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = arg;
|
||||
struct stm32_i2c_dma *dma = i2c_dev->dma;
|
||||
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
|
||||
|
||||
stm32f7_i2c_disable_dma_req(i2c_dev);
|
||||
dmaengine_terminate_async(dma->chan_using);
|
||||
dma_unmap_single(i2c_dev->dev, dma->dma_buf, dma->dma_len,
|
||||
dma->dma_data_dir);
|
||||
if (!f7_msg->smbus)
|
||||
i2c_put_dma_safe_msg_buf(f7_msg->buf, i2c_dev->msg, true);
|
||||
complete(&dma->dma_complete);
|
||||
}
|
||||
|
||||
|
@ -882,6 +885,7 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
|
|||
{
|
||||
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
|
||||
void __iomem *base = i2c_dev->base;
|
||||
u8 *dma_buf;
|
||||
u32 cr1, cr2;
|
||||
int ret;
|
||||
|
||||
|
@ -931,17 +935,23 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
|
|||
|
||||
/* Configure DMA or enable RX/TX interrupt */
|
||||
i2c_dev->use_dma = false;
|
||||
if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN
|
||||
&& !i2c_dev->atomic) {
|
||||
ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
|
||||
msg->flags & I2C_M_RD,
|
||||
f7_msg->count, f7_msg->buf,
|
||||
stm32f7_i2c_dma_callback,
|
||||
i2c_dev);
|
||||
if (!ret)
|
||||
i2c_dev->use_dma = true;
|
||||
else
|
||||
dev_warn(i2c_dev->dev, "can't use DMA\n");
|
||||
if (i2c_dev->dma && !i2c_dev->atomic) {
|
||||
dma_buf = i2c_get_dma_safe_msg_buf(msg, STM32F7_I2C_DMA_LEN_MIN);
|
||||
if (dma_buf) {
|
||||
f7_msg->buf = dma_buf;
|
||||
ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
|
||||
msg->flags & I2C_M_RD,
|
||||
f7_msg->count, f7_msg->buf,
|
||||
stm32f7_i2c_dma_callback,
|
||||
i2c_dev);
|
||||
if (ret) {
|
||||
dev_warn(i2c_dev->dev, "can't use DMA\n");
|
||||
i2c_put_dma_safe_msg_buf(f7_msg->buf, msg, false);
|
||||
f7_msg->buf = msg->buf;
|
||||
} else {
|
||||
i2c_dev->use_dma = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!i2c_dev->use_dma) {
|
||||
|
|
|
@ -134,6 +134,8 @@
|
|||
#define I2C_MST_FIFO_STATUS_TX GENMASK(23, 16)
|
||||
#define I2C_MST_FIFO_STATUS_RX GENMASK(7, 0)
|
||||
|
||||
#define I2C_MASTER_RESET_CNTRL 0x0a8
|
||||
|
||||
/* configuration load timeout in microseconds */
|
||||
#define I2C_CONFIG_LOAD_TIMEOUT 1000000
|
||||
|
||||
|
@ -184,6 +186,9 @@ enum msg_end_type {
|
|||
* @has_mst_fifo: The I2C controller contains the new MST FIFO interface that
|
||||
* provides additional features and allows for longer messages to
|
||||
* be transferred in one go.
|
||||
* @has_mst_reset: The I2C controller contains MASTER_RESET_CTRL register which
|
||||
* provides an alternative to controller reset when configured as
|
||||
* I2C master
|
||||
* @quirks: I2C adapter quirks for limiting write/read transfer size and not
|
||||
* allowing 0 length transfers.
|
||||
* @supports_bus_clear: Bus Clear support to recover from bus hang during
|
||||
|
@ -213,6 +218,7 @@ struct tegra_i2c_hw_feature {
|
|||
bool has_multi_master_mode;
|
||||
bool has_slcg_override_reg;
|
||||
bool has_mst_fifo;
|
||||
bool has_mst_reset;
|
||||
const struct i2c_adapter_quirks *quirks;
|
||||
bool supports_bus_clear;
|
||||
bool has_apb_dma;
|
||||
|
@ -605,12 +611,42 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_i2c_master_reset(struct tegra_i2c_dev *i2c_dev)
|
||||
{
|
||||
if (!i2c_dev->hw->has_mst_reset)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* Writing 1 to I2C_MASTER_RESET_CNTRL will reset all internal state of
|
||||
* Master logic including FIFOs. Clear this bit to 0 for normal operation.
|
||||
* SW needs to wait for 2us after assertion and de-assertion of this soft
|
||||
* reset.
|
||||
*/
|
||||
i2c_writel(i2c_dev, 0x1, I2C_MASTER_RESET_CNTRL);
|
||||
fsleep(2);
|
||||
|
||||
i2c_writel(i2c_dev, 0x0, I2C_MASTER_RESET_CNTRL);
|
||||
fsleep(2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
|
||||
{
|
||||
u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode;
|
||||
struct i2c_timings *t = &i2c_dev->timings;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Reset the controller before initializing it.
|
||||
* In case if device_reset() returns -ENOENT, i.e. when the reset is
|
||||
* not available, the internal software reset will be used if it is
|
||||
* supported by the controller.
|
||||
*/
|
||||
err = device_reset(i2c_dev->dev);
|
||||
if (err == -ENOENT)
|
||||
err = tegra_i2c_master_reset(i2c_dev);
|
||||
|
||||
/*
|
||||
* The reset shouldn't ever fail in practice. The failure will be a
|
||||
* sign of a severe problem that needs to be resolved. Still we don't
|
||||
|
@ -619,7 +655,6 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
|
|||
* emit a noisy warning on error, which won't stay unnoticed and
|
||||
* won't hose machine entirely.
|
||||
*/
|
||||
err = device_reset(i2c_dev->dev);
|
||||
WARN_ON_ONCE(err);
|
||||
|
||||
if (IS_DVC(i2c_dev))
|
||||
|
@ -1266,17 +1301,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
|
|||
|
||||
if (i2c_dev->dma_mode) {
|
||||
if (i2c_dev->msg_read) {
|
||||
dma_sync_single_for_device(i2c_dev->dma_dev,
|
||||
i2c_dev->dma_phys,
|
||||
xfer_size, DMA_FROM_DEVICE);
|
||||
|
||||
err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
dma_sync_single_for_cpu(i2c_dev->dma_dev,
|
||||
i2c_dev->dma_phys,
|
||||
xfer_size, DMA_TO_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1286,11 +1313,6 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
|
|||
if (i2c_dev->dma_mode) {
|
||||
memcpy(i2c_dev->dma_buf + I2C_PACKET_HEADER_SIZE,
|
||||
msg->buf, i2c_dev->msg_len);
|
||||
|
||||
dma_sync_single_for_device(i2c_dev->dma_dev,
|
||||
i2c_dev->dma_phys,
|
||||
xfer_size, DMA_TO_DEVICE);
|
||||
|
||||
err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -1331,13 +1353,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE) {
|
||||
dma_sync_single_for_cpu(i2c_dev->dma_dev,
|
||||
i2c_dev->dma_phys,
|
||||
xfer_size, DMA_FROM_DEVICE);
|
||||
|
||||
if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE)
|
||||
memcpy(i2c_dev->msg_buf, i2c_dev->dma_buf, i2c_dev->msg_len);
|
||||
}
|
||||
}
|
||||
|
||||
time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete,
|
||||
|
@ -1468,6 +1485,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
|
|||
.has_multi_master_mode = false,
|
||||
.has_slcg_override_reg = false,
|
||||
.has_mst_fifo = false,
|
||||
.has_mst_reset = false,
|
||||
.quirks = &tegra_i2c_quirks,
|
||||
.supports_bus_clear = false,
|
||||
.has_apb_dma = true,
|
||||
|
@ -1492,6 +1510,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
|
|||
.has_multi_master_mode = false,
|
||||
.has_slcg_override_reg = false,
|
||||
.has_mst_fifo = false,
|
||||
.has_mst_reset = false,
|
||||
.quirks = &tegra_i2c_quirks,
|
||||
.supports_bus_clear = false,
|
||||
.has_apb_dma = true,
|
||||
|
@ -1516,6 +1535,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
|
|||
.has_multi_master_mode = false,
|
||||
.has_slcg_override_reg = false,
|
||||
.has_mst_fifo = false,
|
||||
.has_mst_reset = false,
|
||||
.quirks = &tegra_i2c_quirks,
|
||||
.supports_bus_clear = true,
|
||||
.has_apb_dma = true,
|
||||
|
@ -1540,6 +1560,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
|
|||
.has_multi_master_mode = false,
|
||||
.has_slcg_override_reg = true,
|
||||
.has_mst_fifo = false,
|
||||
.has_mst_reset = false,
|
||||
.quirks = &tegra_i2c_quirks,
|
||||
.supports_bus_clear = true,
|
||||
.has_apb_dma = true,
|
||||
|
@ -1564,6 +1585,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
|
|||
.has_multi_master_mode = false,
|
||||
.has_slcg_override_reg = true,
|
||||
.has_mst_fifo = false,
|
||||
.has_mst_reset = false,
|
||||
.quirks = &tegra_i2c_quirks,
|
||||
.supports_bus_clear = true,
|
||||
.has_apb_dma = true,
|
||||
|
@ -1588,6 +1610,7 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
|
|||
.has_multi_master_mode = false,
|
||||
.has_slcg_override_reg = true,
|
||||
.has_mst_fifo = false,
|
||||
.has_mst_reset = false,
|
||||
.quirks = &tegra_i2c_quirks,
|
||||
.supports_bus_clear = true,
|
||||
.has_apb_dma = false,
|
||||
|
@ -1612,6 +1635,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
|
|||
.has_multi_master_mode = true,
|
||||
.has_slcg_override_reg = true,
|
||||
.has_mst_fifo = true,
|
||||
.has_mst_reset = true,
|
||||
.quirks = &tegra194_i2c_quirks,
|
||||
.supports_bus_clear = true,
|
||||
.has_apb_dma = false,
|
||||
|
|
|
@ -370,6 +370,7 @@ static const struct acpi_device_id i2c_acpi_force_100khz_device_ids[] = {
|
|||
* the device works without issues on Windows at what is expected to be
|
||||
* a 400KHz frequency. The root cause of the issue is not known.
|
||||
*/
|
||||
{ "DLL0945", 0 },
|
||||
{ "ELAN06FA", 0 },
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -47,7 +47,6 @@ static int mule_i2c_mux_probe(struct platform_device *pdev)
|
|||
struct mule_i2c_reg_mux *priv;
|
||||
struct i2c_client *client;
|
||||
struct i2c_mux_core *muxc;
|
||||
struct device_node *dev;
|
||||
unsigned int readback;
|
||||
int ndev, ret;
|
||||
bool old_fw;
|
||||
|
@ -95,7 +94,7 @@ static int mule_i2c_mux_probe(struct platform_device *pdev)
|
|||
"Failed to register mux remove\n");
|
||||
|
||||
/* Create device adapters */
|
||||
for_each_child_of_node(mux_dev->of_node, dev) {
|
||||
for_each_child_of_node_scoped(mux_dev->of_node, dev) {
|
||||
u32 reg;
|
||||
|
||||
ret = of_property_read_u32(dev, "reg", ®);
|
||||
|
|
Loading…
Add table
Reference in a new issue