mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
Core got a new helper 'i2c_client_get_device_id', designware got some
bigger updates, the rest is driver updates all over the place -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmOblO4ACgkQFA3kzBSg KbYeXxAAkvs2PnC9lycrhTbtFqKrw9BJQHnQatFiRshtq4tB5WgLmNuD1hU4dSFB PZakK30KaH41ns2oCYD/koFzMNyhTlBXj2fwRrtYgqtksTXnf+aHFLip8i5Fk8te rzJSEbQSO7q9CqI6yq3viK35Muf9dfJQexGlFoe0OG1dOPrsF4LooNKkM43E2xyZ BG6vxhx4ZkqMVBo1s+3IsOlsdeemI+Yk97g2BEHmPdaMSj63o4ebh+8Oyw5ySNWk vlmdvWmyEHwNRkKTJ0lPa2wlILJMMpwOSomjrdVKPg/Wh1tP8IZ8rPCOJMwvvUrv MfUSviVYUreloiKfiEWac+wmZ3FKXBizAdlHBuKhujz9pBM8mEsHhQippq0gd+k6 J/KdZs1h5mt3/MeYPNCbDzibTE8umng5ocxep+glfZGMBFaGUNm32l5Ebh6xvyCX bVZFRvGu27YXMPoxSFOgo9sFYNgpUvjdcxI+0kTJiFZ7ujuK6mQ/5Q4EUk7tF5zr vLEWS+S3v6SU0bcooDkdncnN4XTn1c7r0e7Klj140qOTBRmFT5huiTEDg8Or0uB4 zBy4UV+FsR6+aPyWkLfEfvBpFPCjBERlraaaf1S5B/HquyGiU0RnHFLqOhPBkx8j 4APAw8oqWsQ5ftRN3tIDT9CcN7wDfC0KkEaIxCf4rd6Zm1fTSmw= =/It5 -----END PGP SIGNATURE----- Merge tag 'i2c-for-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux Pull i2c updates from Wolfram Sang: "Core got a new helper 'i2c_client_get_device_id()', designware got some bigger updates, the rest is driver updates all over the place" * tag 'i2c-for-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (41 commits) i2c: ismt: Fix an out-of-bounds bug in ismt_access() i2c: mux: reg: check return value after calling platform_get_resource() i2c: xiic: Make sure to disable clock on .remove() i2c: hisi: Add support to get clock frequency from clock i2c: pxa-pci: fix missing pci_disable_device() on error in ce4100_i2c_probe i2c: slave-eeprom: Convert to i2c's .probe_new() i2c: mux: pca954x: Convert to i2c's .probe_new() drivers/i2c: use simple i2c probe i2c: mux: pca9541: switch to using .probe_new i2c: gpio: Fix potential unused warning for 'i2c_gpio_dt_ids' i2c: qcom-geni: add support for I2C Master Hub variant i2c: qcom-geni: add desc struct to prepare support for I2C Master Hub variant soc: qcom: geni-se: add support for I2C Master Hub wrapper variant soc: qcom: geni-se: add desc struct to specify clocks from device match data dt-bindings: i2c: qcom-geni: document I2C Master Hub serial I2C engine dt-bindings: qcom: geni-se: document I2C Master Hub wrapper variant dt-bindings: i2c: renesas,riic: Document RZ/Five SoC i2c: tegra: Set ACPI node as primary fwnode i2c: smbus: add DDR support for SPD i2c: /pasemi: PASemi I2C controller IRQ enablement ...
This commit is contained in:
commit
ec9187ecea
@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/i2c/hisilicon,ascend910-i2c.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: HiSilicon common I2C controller
|
||||
|
||||
maintainers:
|
||||
- Yicong Yang <yangyicong@hisilicon.com>
|
||||
|
||||
description:
|
||||
The HiSilicon common I2C controller can be used for many different
|
||||
types of SoC such as Huawei Ascend AI series chips.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/i2c/i2c-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: hisilicon,ascend910-i2c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-frequency:
|
||||
default: 400000
|
||||
|
||||
i2c-sda-falling-time-ns:
|
||||
default: 343
|
||||
|
||||
i2c-scl-falling-time-ns:
|
||||
default: 203
|
||||
|
||||
i2c-sda-hold-time-ns:
|
||||
default: 830
|
||||
|
||||
i2c-scl-rising-time-ns:
|
||||
default: 365
|
||||
|
||||
i2c-digital-filter-width-ns:
|
||||
default: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
i2c@38b0000 {
|
||||
compatible = "hisilicon,ascend910-i2c";
|
||||
reg = <0x38b0000 0x10000>;
|
||||
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
|
||||
i2c-sda-falling-time-ns = <56>;
|
||||
i2c-scl-falling-time-ns = <56>;
|
||||
i2c-sda-hold-time-ns = <56>;
|
||||
i2c-scl-rising-time-ns = <56>;
|
||||
i2c-digital-filter;
|
||||
i2c-digital-filter-width-ns = <0x0>;
|
||||
clocks = <&alg_clk>;
|
||||
clock-frequency = <400000>;
|
||||
};
|
@ -23,6 +23,7 @@ properties:
|
||||
- const: mediatek,mt6577-i2c
|
||||
- const: mediatek,mt6589-i2c
|
||||
- const: mediatek,mt7622-i2c
|
||||
- const: mediatek,mt7986-i2c
|
||||
- const: mediatek,mt8168-i2c
|
||||
- const: mediatek,mt8173-i2c
|
||||
- const: mediatek,mt8183-i2c
|
||||
|
@ -19,6 +19,7 @@ properties:
|
||||
- const: allwinner,sun6i-a31-i2c
|
||||
- items:
|
||||
- enum:
|
||||
- allwinner,suniv-f1c100s-i2c
|
||||
- allwinner,sun8i-a23-i2c
|
||||
- allwinner,sun8i-a83t-i2c
|
||||
- allwinner,sun8i-v536-i2c
|
||||
|
@ -10,18 +10,19 @@ maintainers:
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/i2c/i2c-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,geni-i2c
|
||||
enum:
|
||||
- qcom,geni-i2c
|
||||
- qcom,geni-i2c-master-hub
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
const: se
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clock-frequency:
|
||||
default: 100000
|
||||
@ -35,13 +36,12 @@ properties:
|
||||
- const: rx
|
||||
|
||||
interconnects:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: qup-core
|
||||
- const: qup-config
|
||||
- const: qup-memory
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
@ -71,6 +71,50 @@ required:
|
||||
- clock-names
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/i2c/i2c-controller.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,geni-i2c-master-hub
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: se
|
||||
- const: core
|
||||
|
||||
dmas: false
|
||||
dma-names: false
|
||||
|
||||
interconnects:
|
||||
maxItems: 2
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: qup-core
|
||||
- const: qup-config
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: se
|
||||
|
||||
interconnects:
|
||||
minItems: 3
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: qup-core
|
||||
- const: qup-config
|
||||
- const: qup-memory
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -19,7 +19,7 @@ properties:
|
||||
- enum:
|
||||
- renesas,riic-r7s72100 # RZ/A1H
|
||||
- renesas,riic-r7s9210 # RZ/A2M
|
||||
- renesas,riic-r9a07g043 # RZ/G2UL
|
||||
- renesas,riic-r9a07g043 # RZ/G2UL and RZ/Five
|
||||
- renesas,riic-r9a07g044 # RZ/G2{L,LC}
|
||||
- renesas,riic-r9a07g054 # RZ/V2L
|
||||
- const: renesas,riic-rz # RZ/A or RZ/G2L
|
||||
|
@ -21,20 +21,19 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,geni-se-qup
|
||||
- qcom,geni-se-i2c-master-hub
|
||||
|
||||
reg:
|
||||
description: QUP wrapper common register address and length.
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: m-ahb
|
||||
- const: s-ahb
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Master AHB Clock
|
||||
- description: Slave AHB Clock
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
"#address-cells":
|
||||
const: 2
|
||||
@ -81,6 +80,39 @@ patternProperties:
|
||||
description: GENI Serial Engine based UART Controller.
|
||||
$ref: /schemas/serial/qcom,serial-geni-qcom.yaml#
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,geni-se-i2c-master-hub
|
||||
then:
|
||||
properties:
|
||||
clock-names:
|
||||
items:
|
||||
- const: s-ahb
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Slave AHB Clock
|
||||
|
||||
iommus: false
|
||||
|
||||
patternProperties:
|
||||
"spi@[0-9a-f]+$": false
|
||||
"serial@[0-9a-f]+$": false
|
||||
else:
|
||||
properties:
|
||||
clock-names:
|
||||
items:
|
||||
- const: m-ahb
|
||||
- const: s-ahb
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Master AHB Clock
|
||||
- description: Slave AHB Clock
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -9290,6 +9290,7 @@ M: Yicong Yang <yangyicong@hisilicon.com>
|
||||
L: linux-i2c@vger.kernel.org
|
||||
S: Maintained
|
||||
W: https://www.hisilicon.com
|
||||
F: Documentation/devicetree/bindings/i2c/hisilicon,ascend910-i2c.yaml
|
||||
F: drivers/i2c/busses/i2c-hisi.c
|
||||
|
||||
HISILICON LPC BUS DRIVER
|
||||
|
@ -673,7 +673,7 @@ config I2C_HIGHLANDER
|
||||
|
||||
config I2C_HISI
|
||||
tristate "HiSilicon I2C controller"
|
||||
depends on (ARM64 && ACPI) || COMPILE_TEST
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
help
|
||||
Say Y here if you want to have Hisilicon I2C controller support
|
||||
available on the Kunpeng Server.
|
||||
|
@ -288,7 +288,7 @@ static void amd_mp2_clear_reg(struct amd_mp2_dev *privdata)
|
||||
static int amd_mp2_pci_init(struct amd_mp2_dev *privdata,
|
||||
struct pci_dev *pci_dev)
|
||||
{
|
||||
int rc;
|
||||
int irq_flag = 0, rc;
|
||||
|
||||
pci_set_drvdata(pci_dev, privdata);
|
||||
|
||||
@ -311,17 +311,29 @@ static int amd_mp2_pci_init(struct amd_mp2_dev *privdata,
|
||||
if (rc)
|
||||
goto err_dma_mask;
|
||||
|
||||
/* Set up intx irq */
|
||||
/* request and enable interrupt */
|
||||
writel(0, privdata->mmio + AMD_P2C_MSG_INTEN);
|
||||
pci_intx(pci_dev, 1);
|
||||
rc = devm_request_irq(&pci_dev->dev, pci_dev->irq, amd_mp2_irq_isr,
|
||||
IRQF_SHARED, dev_name(&pci_dev->dev), privdata);
|
||||
if (rc)
|
||||
pci_err(pci_dev, "Failure requesting irq %i: %d\n",
|
||||
pci_dev->irq, rc);
|
||||
rc = pci_alloc_irq_vectors(pci_dev, 1, 1, PCI_IRQ_ALL_TYPES);
|
||||
if (rc < 0) {
|
||||
dev_err(&pci_dev->dev, "Failed to allocate single IRQ err=%d\n", rc);
|
||||
goto err_dma_mask;
|
||||
}
|
||||
|
||||
privdata->dev_irq = pci_irq_vector(pci_dev, 0);
|
||||
if (!pci_dev->msix_enabled && !pci_dev->msi_enabled)
|
||||
irq_flag = IRQF_SHARED;
|
||||
|
||||
rc = devm_request_irq(&pci_dev->dev, privdata->dev_irq,
|
||||
amd_mp2_irq_isr, irq_flag, dev_name(&pci_dev->dev), privdata);
|
||||
if (rc) {
|
||||
pci_err(pci_dev, "Failure requesting irq %i: %d\n", privdata->dev_irq, rc);
|
||||
goto free_irq_vectors;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
free_irq_vectors:
|
||||
free_irq(privdata->dev_irq, privdata);
|
||||
err_dma_mask:
|
||||
pci_clear_master(pci_dev);
|
||||
err_pci_enable:
|
||||
@ -364,7 +376,7 @@ static void amd_mp2_pci_remove(struct pci_dev *pci_dev)
|
||||
pm_runtime_forbid(&pci_dev->dev);
|
||||
pm_runtime_get_noresume(&pci_dev->dev);
|
||||
|
||||
pci_intx(pci_dev, 0);
|
||||
free_irq(privdata->dev_irq, privdata);
|
||||
pci_clear_master(pci_dev);
|
||||
|
||||
amd_mp2_clear_reg(privdata);
|
||||
|
@ -183,6 +183,7 @@ struct amd_mp2_dev {
|
||||
struct mutex c2p_lock;
|
||||
u8 c2p_lock_busid;
|
||||
unsigned int probed;
|
||||
int dev_irq;
|
||||
};
|
||||
|
||||
/* PCIe communication driver */
|
||||
|
@ -625,10 +625,5 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
|
||||
i2c_dw_release_lock(dev);
|
||||
}
|
||||
|
||||
void i2c_dw_disable_int(struct dw_i2c_dev *dev)
|
||||
{
|
||||
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -18,12 +18,12 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \
|
||||
I2C_FUNC_SMBUS_BYTE | \
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | \
|
||||
I2C_FUNC_SMBUS_WORD_DATA | \
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA | \
|
||||
I2C_FUNC_SMBUS_I2C_BLOCK)
|
||||
#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \
|
||||
I2C_FUNC_SMBUS_BYTE | \
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | \
|
||||
I2C_FUNC_SMBUS_WORD_DATA | \
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA | \
|
||||
I2C_FUNC_SMBUS_I2C_BLOCK)
|
||||
|
||||
#define DW_IC_CON_MASTER BIT(0)
|
||||
#define DW_IC_CON_SPEED_STD (1 << 1)
|
||||
@ -43,98 +43,98 @@
|
||||
/*
|
||||
* Registers offset
|
||||
*/
|
||||
#define DW_IC_CON 0x00
|
||||
#define DW_IC_TAR 0x04
|
||||
#define DW_IC_SAR 0x08
|
||||
#define DW_IC_DATA_CMD 0x10
|
||||
#define DW_IC_SS_SCL_HCNT 0x14
|
||||
#define DW_IC_SS_SCL_LCNT 0x18
|
||||
#define DW_IC_FS_SCL_HCNT 0x1c
|
||||
#define DW_IC_FS_SCL_LCNT 0x20
|
||||
#define DW_IC_HS_SCL_HCNT 0x24
|
||||
#define DW_IC_HS_SCL_LCNT 0x28
|
||||
#define DW_IC_INTR_STAT 0x2c
|
||||
#define DW_IC_INTR_MASK 0x30
|
||||
#define DW_IC_RAW_INTR_STAT 0x34
|
||||
#define DW_IC_RX_TL 0x38
|
||||
#define DW_IC_TX_TL 0x3c
|
||||
#define DW_IC_CLR_INTR 0x40
|
||||
#define DW_IC_CLR_RX_UNDER 0x44
|
||||
#define DW_IC_CLR_RX_OVER 0x48
|
||||
#define DW_IC_CLR_TX_OVER 0x4c
|
||||
#define DW_IC_CLR_RD_REQ 0x50
|
||||
#define DW_IC_CLR_TX_ABRT 0x54
|
||||
#define DW_IC_CLR_RX_DONE 0x58
|
||||
#define DW_IC_CLR_ACTIVITY 0x5c
|
||||
#define DW_IC_CLR_STOP_DET 0x60
|
||||
#define DW_IC_CLR_START_DET 0x64
|
||||
#define DW_IC_CLR_GEN_CALL 0x68
|
||||
#define DW_IC_ENABLE 0x6c
|
||||
#define DW_IC_STATUS 0x70
|
||||
#define DW_IC_TXFLR 0x74
|
||||
#define DW_IC_RXFLR 0x78
|
||||
#define DW_IC_SDA_HOLD 0x7c
|
||||
#define DW_IC_TX_ABRT_SOURCE 0x80
|
||||
#define DW_IC_ENABLE_STATUS 0x9c
|
||||
#define DW_IC_CLR_RESTART_DET 0xa8
|
||||
#define DW_IC_COMP_PARAM_1 0xf4
|
||||
#define DW_IC_COMP_VERSION 0xf8
|
||||
#define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A
|
||||
#define DW_IC_COMP_TYPE 0xfc
|
||||
#define DW_IC_COMP_TYPE_VALUE 0x44570140
|
||||
#define DW_IC_CON 0x00
|
||||
#define DW_IC_TAR 0x04
|
||||
#define DW_IC_SAR 0x08
|
||||
#define DW_IC_DATA_CMD 0x10
|
||||
#define DW_IC_SS_SCL_HCNT 0x14
|
||||
#define DW_IC_SS_SCL_LCNT 0x18
|
||||
#define DW_IC_FS_SCL_HCNT 0x1c
|
||||
#define DW_IC_FS_SCL_LCNT 0x20
|
||||
#define DW_IC_HS_SCL_HCNT 0x24
|
||||
#define DW_IC_HS_SCL_LCNT 0x28
|
||||
#define DW_IC_INTR_STAT 0x2c
|
||||
#define DW_IC_INTR_MASK 0x30
|
||||
#define DW_IC_RAW_INTR_STAT 0x34
|
||||
#define DW_IC_RX_TL 0x38
|
||||
#define DW_IC_TX_TL 0x3c
|
||||
#define DW_IC_CLR_INTR 0x40
|
||||
#define DW_IC_CLR_RX_UNDER 0x44
|
||||
#define DW_IC_CLR_RX_OVER 0x48
|
||||
#define DW_IC_CLR_TX_OVER 0x4c
|
||||
#define DW_IC_CLR_RD_REQ 0x50
|
||||
#define DW_IC_CLR_TX_ABRT 0x54
|
||||
#define DW_IC_CLR_RX_DONE 0x58
|
||||
#define DW_IC_CLR_ACTIVITY 0x5c
|
||||
#define DW_IC_CLR_STOP_DET 0x60
|
||||
#define DW_IC_CLR_START_DET 0x64
|
||||
#define DW_IC_CLR_GEN_CALL 0x68
|
||||
#define DW_IC_ENABLE 0x6c
|
||||
#define DW_IC_STATUS 0x70
|
||||
#define DW_IC_TXFLR 0x74
|
||||
#define DW_IC_RXFLR 0x78
|
||||
#define DW_IC_SDA_HOLD 0x7c
|
||||
#define DW_IC_TX_ABRT_SOURCE 0x80
|
||||
#define DW_IC_ENABLE_STATUS 0x9c
|
||||
#define DW_IC_CLR_RESTART_DET 0xa8
|
||||
#define DW_IC_COMP_PARAM_1 0xf4
|
||||
#define DW_IC_COMP_VERSION 0xf8
|
||||
#define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A /* "111*" == v1.11* */
|
||||
#define DW_IC_COMP_TYPE 0xfc
|
||||
#define DW_IC_COMP_TYPE_VALUE 0x44570140 /* "DW" + 0x0140 */
|
||||
|
||||
#define DW_IC_INTR_RX_UNDER BIT(0)
|
||||
#define DW_IC_INTR_RX_OVER BIT(1)
|
||||
#define DW_IC_INTR_RX_FULL BIT(2)
|
||||
#define DW_IC_INTR_TX_OVER BIT(3)
|
||||
#define DW_IC_INTR_TX_EMPTY BIT(4)
|
||||
#define DW_IC_INTR_RD_REQ BIT(5)
|
||||
#define DW_IC_INTR_TX_ABRT BIT(6)
|
||||
#define DW_IC_INTR_RX_DONE BIT(7)
|
||||
#define DW_IC_INTR_ACTIVITY BIT(8)
|
||||
#define DW_IC_INTR_STOP_DET BIT(9)
|
||||
#define DW_IC_INTR_START_DET BIT(10)
|
||||
#define DW_IC_INTR_GEN_CALL BIT(11)
|
||||
#define DW_IC_INTR_RESTART_DET BIT(12)
|
||||
#define DW_IC_INTR_RX_UNDER BIT(0)
|
||||
#define DW_IC_INTR_RX_OVER BIT(1)
|
||||
#define DW_IC_INTR_RX_FULL BIT(2)
|
||||
#define DW_IC_INTR_TX_OVER BIT(3)
|
||||
#define DW_IC_INTR_TX_EMPTY BIT(4)
|
||||
#define DW_IC_INTR_RD_REQ BIT(5)
|
||||
#define DW_IC_INTR_TX_ABRT BIT(6)
|
||||
#define DW_IC_INTR_RX_DONE BIT(7)
|
||||
#define DW_IC_INTR_ACTIVITY BIT(8)
|
||||
#define DW_IC_INTR_STOP_DET BIT(9)
|
||||
#define DW_IC_INTR_START_DET BIT(10)
|
||||
#define DW_IC_INTR_GEN_CALL BIT(11)
|
||||
#define DW_IC_INTR_RESTART_DET BIT(12)
|
||||
|
||||
#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
|
||||
DW_IC_INTR_TX_ABRT | \
|
||||
DW_IC_INTR_STOP_DET)
|
||||
#define DW_IC_INTR_MASTER_MASK (DW_IC_INTR_DEFAULT_MASK | \
|
||||
DW_IC_INTR_TX_EMPTY)
|
||||
#define DW_IC_INTR_SLAVE_MASK (DW_IC_INTR_DEFAULT_MASK | \
|
||||
DW_IC_INTR_RX_DONE | \
|
||||
DW_IC_INTR_RX_UNDER | \
|
||||
DW_IC_INTR_RD_REQ)
|
||||
#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
|
||||
DW_IC_INTR_TX_ABRT | \
|
||||
DW_IC_INTR_STOP_DET)
|
||||
#define DW_IC_INTR_MASTER_MASK (DW_IC_INTR_DEFAULT_MASK | \
|
||||
DW_IC_INTR_TX_EMPTY)
|
||||
#define DW_IC_INTR_SLAVE_MASK (DW_IC_INTR_DEFAULT_MASK | \
|
||||
DW_IC_INTR_RX_UNDER | \
|
||||
DW_IC_INTR_RD_REQ)
|
||||
|
||||
#define DW_IC_STATUS_ACTIVITY BIT(0)
|
||||
#define DW_IC_STATUS_TFE BIT(2)
|
||||
#define DW_IC_STATUS_MASTER_ACTIVITY BIT(5)
|
||||
#define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6)
|
||||
#define DW_IC_STATUS_ACTIVITY BIT(0)
|
||||
#define DW_IC_STATUS_TFE BIT(2)
|
||||
#define DW_IC_STATUS_RFNE BIT(3)
|
||||
#define DW_IC_STATUS_MASTER_ACTIVITY BIT(5)
|
||||
#define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6)
|
||||
|
||||
#define DW_IC_SDA_HOLD_RX_SHIFT 16
|
||||
#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, 16)
|
||||
#define DW_IC_SDA_HOLD_RX_SHIFT 16
|
||||
#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, 16)
|
||||
|
||||
#define DW_IC_ERR_TX_ABRT 0x1
|
||||
#define DW_IC_ERR_TX_ABRT 0x1
|
||||
|
||||
#define DW_IC_TAR_10BITADDR_MASTER BIT(12)
|
||||
#define DW_IC_TAR_10BITADDR_MASTER BIT(12)
|
||||
|
||||
#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3))
|
||||
#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2)
|
||||
|
||||
/*
|
||||
* status codes
|
||||
* Sofware status flags
|
||||
*/
|
||||
#define STATUS_IDLE 0x0
|
||||
#define STATUS_ACTIVE 0x1
|
||||
#define STATUS_WRITE_IN_PROGRESS 0x2
|
||||
#define STATUS_READ_IN_PROGRESS 0x4
|
||||
#define STATUS_ACTIVE BIT(0)
|
||||
#define STATUS_WRITE_IN_PROGRESS BIT(1)
|
||||
#define STATUS_READ_IN_PROGRESS BIT(2)
|
||||
#define STATUS_MASK GENMASK(2, 0)
|
||||
|
||||
/*
|
||||
* operation modes
|
||||
*/
|
||||
#define DW_IC_MASTER 0
|
||||
#define DW_IC_SLAVE 1
|
||||
#define DW_IC_MASTER 0
|
||||
#define DW_IC_SLAVE 1
|
||||
|
||||
/*
|
||||
* Hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
|
||||
@ -142,20 +142,20 @@
|
||||
* Only expected abort codes are listed here
|
||||
* refer to the datasheet for the full list
|
||||
*/
|
||||
#define ABRT_7B_ADDR_NOACK 0
|
||||
#define ABRT_10ADDR1_NOACK 1
|
||||
#define ABRT_10ADDR2_NOACK 2
|
||||
#define ABRT_TXDATA_NOACK 3
|
||||
#define ABRT_GCALL_NOACK 4
|
||||
#define ABRT_GCALL_READ 5
|
||||
#define ABRT_SBYTE_ACKDET 7
|
||||
#define ABRT_SBYTE_NORSTRT 9
|
||||
#define ABRT_10B_RD_NORSTRT 10
|
||||
#define ABRT_MASTER_DIS 11
|
||||
#define ARB_LOST 12
|
||||
#define ABRT_SLAVE_FLUSH_TXFIFO 13
|
||||
#define ABRT_SLAVE_ARBLOST 14
|
||||
#define ABRT_SLAVE_RD_INTX 15
|
||||
#define ABRT_7B_ADDR_NOACK 0
|
||||
#define ABRT_10ADDR1_NOACK 1
|
||||
#define ABRT_10ADDR2_NOACK 2
|
||||
#define ABRT_TXDATA_NOACK 3
|
||||
#define ABRT_GCALL_NOACK 4
|
||||
#define ABRT_GCALL_READ 5
|
||||
#define ABRT_SBYTE_ACKDET 7
|
||||
#define ABRT_SBYTE_NORSTRT 9
|
||||
#define ABRT_10B_RD_NORSTRT 10
|
||||
#define ABRT_MASTER_DIS 11
|
||||
#define ARB_LOST 12
|
||||
#define ABRT_SLAVE_FLUSH_TXFIFO 13
|
||||
#define ABRT_SLAVE_ARBLOST 14
|
||||
#define ABRT_SLAVE_RD_INTX 15
|
||||
|
||||
#define DW_IC_TX_ABRT_7B_ADDR_NOACK BIT(ABRT_7B_ADDR_NOACK)
|
||||
#define DW_IC_TX_ABRT_10ADDR1_NOACK BIT(ABRT_10ADDR1_NOACK)
|
||||
@ -172,11 +172,11 @@
|
||||
#define DW_IC_RX_ABRT_SLAVE_ARBLOST BIT(ABRT_SLAVE_ARBLOST)
|
||||
#define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO BIT(ABRT_SLAVE_FLUSH_TXFIFO)
|
||||
|
||||
#define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \
|
||||
DW_IC_TX_ABRT_10ADDR1_NOACK | \
|
||||
DW_IC_TX_ABRT_10ADDR2_NOACK | \
|
||||
DW_IC_TX_ABRT_TXDATA_NOACK | \
|
||||
DW_IC_TX_ABRT_GCALL_NOACK)
|
||||
#define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \
|
||||
DW_IC_TX_ABRT_10ADDR1_NOACK | \
|
||||
DW_IC_TX_ABRT_10ADDR2_NOACK | \
|
||||
DW_IC_TX_ABRT_TXDATA_NOACK | \
|
||||
DW_IC_TX_ABRT_GCALL_NOACK)
|
||||
|
||||
struct clk;
|
||||
struct device;
|
||||
@ -232,7 +232,6 @@ struct reset_control;
|
||||
* -1 if there is no semaphore.
|
||||
* @shared_with_punit: true if this bus is shared with the SoCs PUNIT
|
||||
* @disable: function to disable the controller
|
||||
* @disable_int: function to disable all interrupts
|
||||
* @init: function to initialize the I2C hardware
|
||||
* @set_sda_hold_time: callback to retrieve IP specific SDA hold timing
|
||||
* @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE
|
||||
@ -290,28 +289,27 @@ struct dw_i2c_dev {
|
||||
int semaphore_idx;
|
||||
bool shared_with_punit;
|
||||
void (*disable)(struct dw_i2c_dev *dev);
|
||||
void (*disable_int)(struct dw_i2c_dev *dev);
|
||||
int (*init)(struct dw_i2c_dev *dev);
|
||||
int (*set_sda_hold_time)(struct dw_i2c_dev *dev);
|
||||
int mode;
|
||||
struct i2c_bus_recovery_info rinfo;
|
||||
};
|
||||
|
||||
#define ACCESS_INTR_MASK BIT(0)
|
||||
#define ACCESS_NO_IRQ_SUSPEND BIT(1)
|
||||
#define ARBITRATION_SEMAPHORE BIT(2)
|
||||
#define ACCESS_INTR_MASK BIT(0)
|
||||
#define ACCESS_NO_IRQ_SUSPEND BIT(1)
|
||||
#define ARBITRATION_SEMAPHORE BIT(2)
|
||||
|
||||
#define MODEL_MSCC_OCELOT BIT(8)
|
||||
#define MODEL_BAIKAL_BT1 BIT(9)
|
||||
#define MODEL_AMD_NAVI_GPU BIT(10)
|
||||
#define MODEL_MASK GENMASK(11, 8)
|
||||
#define MODEL_MSCC_OCELOT BIT(8)
|
||||
#define MODEL_BAIKAL_BT1 BIT(9)
|
||||
#define MODEL_AMD_NAVI_GPU BIT(10)
|
||||
#define MODEL_MASK GENMASK(11, 8)
|
||||
|
||||
/*
|
||||
* Enable UCSI interrupt by writing 0xd at register
|
||||
* offset 0x474 specified in hardware specification.
|
||||
*/
|
||||
#define AMD_UCSI_INTR_REG 0x474
|
||||
#define AMD_UCSI_INTR_EN 0xd
|
||||
#define AMD_UCSI_INTR_REG 0x474
|
||||
#define AMD_UCSI_INTR_EN 0xd
|
||||
|
||||
struct i2c_dw_semaphore_callbacks {
|
||||
int (*probe)(struct dw_i2c_dev *dev);
|
||||
@ -331,7 +329,6 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev);
|
||||
int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev);
|
||||
u32 i2c_dw_func(struct i2c_adapter *adap);
|
||||
void i2c_dw_disable(struct dw_i2c_dev *dev);
|
||||
void i2c_dw_disable_int(struct dw_i2c_dev *dev);
|
||||
|
||||
static inline void __i2c_dw_enable(struct dw_i2c_dev *dev)
|
||||
{
|
||||
|
@ -239,7 +239,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
|
||||
msgs[dev->msg_write_idx].addr | ic_tar);
|
||||
|
||||
/* Enforce disabled interrupts (due to HW issues) */
|
||||
i2c_dw_disable_int(dev);
|
||||
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
|
||||
|
||||
/* Enable the adapter */
|
||||
__i2c_dw_enable(dev);
|
||||
@ -299,7 +299,7 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
||||
dev->msgs = msgs;
|
||||
dev->msgs_num = num_msgs;
|
||||
i2c_dw_xfer_init(dev);
|
||||
i2c_dw_disable_int(dev);
|
||||
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
|
||||
|
||||
/* Initiate messages read/write transaction */
|
||||
for (msg_wrt_idx = 0; msg_wrt_idx < num_msgs; msg_wrt_idx++) {
|
||||
@ -574,7 +574,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
dev->msg_write_idx = 0;
|
||||
dev->msg_read_idx = 0;
|
||||
dev->msg_err = 0;
|
||||
dev->status = STATUS_IDLE;
|
||||
dev->status = 0;
|
||||
dev->abort_source = 0;
|
||||
dev->rx_outstanding = 0;
|
||||
|
||||
@ -711,9 +711,18 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
|
||||
* Interrupt service routine. This gets called whenever an I2C master interrupt
|
||||
* occurs.
|
||||
*/
|
||||
static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev)
|
||||
static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
|
||||
{
|
||||
u32 stat;
|
||||
struct dw_i2c_dev *dev = dev_id;
|
||||
u32 stat, enabled;
|
||||
|
||||
regmap_read(dev->map, DW_IC_ENABLE, &enabled);
|
||||
regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat);
|
||||
if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
|
||||
return IRQ_NONE;
|
||||
if (pm_runtime_suspended(dev->dev) || stat == GENMASK(31, 0))
|
||||
return IRQ_NONE;
|
||||
dev_dbg(dev->dev, "enabled=%#x stat=%#x\n", enabled, stat);
|
||||
|
||||
stat = i2c_dw_read_clear_intrbits(dev);
|
||||
|
||||
@ -726,12 +735,12 @@ static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev)
|
||||
* the HW active).
|
||||
*/
|
||||
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (stat & DW_IC_INTR_TX_ABRT) {
|
||||
dev->cmd_err |= DW_IC_ERR_TX_ABRT;
|
||||
dev->status = STATUS_IDLE;
|
||||
dev->status &= ~STATUS_MASK;
|
||||
dev->rx_outstanding = 0;
|
||||
|
||||
/*
|
||||
@ -761,26 +770,10 @@ tx_aborted:
|
||||
else if (unlikely(dev->flags & ACCESS_INTR_MASK)) {
|
||||
/* Workaround to trigger pending interrupt */
|
||||
regmap_read(dev->map, DW_IC_INTR_MASK, &stat);
|
||||
i2c_dw_disable_int(dev);
|
||||
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
|
||||
regmap_write(dev->map, DW_IC_INTR_MASK, stat);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
|
||||
{
|
||||
struct dw_i2c_dev *dev = dev_id;
|
||||
u32 stat, enabled;
|
||||
|
||||
regmap_read(dev->map, DW_IC_ENABLE, &enabled);
|
||||
regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat);
|
||||
dev_dbg(dev->dev, "enabled=%#x stat=%#x\n", enabled, stat);
|
||||
if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
|
||||
return IRQ_NONE;
|
||||
|
||||
i2c_dw_irq_handler_master(dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -878,7 +871,6 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
|
||||
|
||||
dev->init = i2c_dw_init_master;
|
||||
dev->disable = i2c_dw_disable;
|
||||
dev->disable_int = i2c_dw_disable_int;
|
||||
|
||||
ret = i2c_dw_init_regmap(dev);
|
||||
if (ret)
|
||||
@ -917,7 +909,7 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
i2c_dw_disable_int(dev);
|
||||
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
|
||||
i2c_dw_release_lock(dev);
|
||||
|
||||
ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags,
|
||||
|
@ -78,13 +78,7 @@ static int i2c_dw_reg_slave(struct i2c_client *slave)
|
||||
|
||||
__i2c_dw_enable(dev);
|
||||
|
||||
dev->cmd_err = 0;
|
||||
dev->msg_write_idx = 0;
|
||||
dev->msg_read_idx = 0;
|
||||
dev->msg_err = 0;
|
||||
dev->status = STATUS_IDLE;
|
||||
dev->abort_source = 0;
|
||||
dev->rx_outstanding = 0;
|
||||
dev->status = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -93,7 +87,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave)
|
||||
{
|
||||
struct dw_i2c_dev *dev = i2c_get_adapdata(slave->adapter);
|
||||
|
||||
dev->disable_int(dev);
|
||||
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
|
||||
dev->disable(dev);
|
||||
synchronize_irq(dev->irq);
|
||||
dev->slave = NULL;
|
||||
@ -153,9 +147,9 @@ static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)
|
||||
* Interrupt service routine. This gets called whenever an I2C slave interrupt
|
||||
* occurs.
|
||||
*/
|
||||
|
||||
static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
|
||||
static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
|
||||
{
|
||||
struct dw_i2c_dev *dev = dev_id;
|
||||
u32 raw_stat, stat, enabled, tmp;
|
||||
u8 val = 0, slave_activity;
|
||||
|
||||
@ -165,7 +159,7 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
|
||||
slave_activity = ((tmp & DW_IC_STATUS_SLAVE_ACTIVITY) >> 6);
|
||||
|
||||
if (!enabled || !(raw_stat & ~DW_IC_INTR_ACTIVITY) || !dev->slave)
|
||||
return 0;
|
||||
return IRQ_NONE;
|
||||
|
||||
stat = i2c_dw_read_clear_intrbits_slave(dev);
|
||||
dev_dbg(dev->dev,
|
||||
@ -173,55 +167,45 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
|
||||
enabled, slave_activity, raw_stat, stat);
|
||||
|
||||
if (stat & DW_IC_INTR_RX_FULL) {
|
||||
if (dev->status != STATUS_WRITE_IN_PROGRESS) {
|
||||
dev->status = STATUS_WRITE_IN_PROGRESS;
|
||||
if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
|
||||
dev->status |= STATUS_WRITE_IN_PROGRESS;
|
||||
dev->status &= ~STATUS_READ_IN_PROGRESS;
|
||||
i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED,
|
||||
&val);
|
||||
}
|
||||
|
||||
regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
|
||||
val = tmp;
|
||||
if (!i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED,
|
||||
&val))
|
||||
dev_vdbg(dev->dev, "Byte %X acked!", val);
|
||||
do {
|
||||
regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
|
||||
val = tmp;
|
||||
i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED,
|
||||
&val);
|
||||
regmap_read(dev->map, DW_IC_STATUS, &tmp);
|
||||
} while (tmp & DW_IC_STATUS_RFNE);
|
||||
}
|
||||
|
||||
if (stat & DW_IC_INTR_RD_REQ) {
|
||||
if (slave_activity) {
|
||||
regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp);
|
||||
|
||||
dev->status = STATUS_READ_IN_PROGRESS;
|
||||
if (!i2c_slave_event(dev->slave,
|
||||
I2C_SLAVE_READ_REQUESTED,
|
||||
&val))
|
||||
regmap_write(dev->map, DW_IC_DATA_CMD, val);
|
||||
if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
|
||||
i2c_slave_event(dev->slave,
|
||||
I2C_SLAVE_READ_REQUESTED,
|
||||
&val);
|
||||
dev->status |= STATUS_READ_IN_PROGRESS;
|
||||
dev->status &= ~STATUS_WRITE_IN_PROGRESS;
|
||||
} else {
|
||||
i2c_slave_event(dev->slave,
|
||||
I2C_SLAVE_READ_PROCESSED,
|
||||
&val);
|
||||
}
|
||||
regmap_write(dev->map, DW_IC_DATA_CMD, val);
|
||||
}
|
||||
}
|
||||
|
||||
if (stat & DW_IC_INTR_RX_DONE) {
|
||||
if (!i2c_slave_event(dev->slave, I2C_SLAVE_READ_PROCESSED,
|
||||
&val))
|
||||
regmap_read(dev->map, DW_IC_CLR_RX_DONE, &tmp);
|
||||
}
|
||||
|
||||
if (stat & DW_IC_INTR_STOP_DET) {
|
||||
dev->status = STATUS_IDLE;
|
||||
if (stat & DW_IC_INTR_STOP_DET)
|
||||
i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
|
||||
{
|
||||
struct dw_i2c_dev *dev = dev_id;
|
||||
int ret;
|
||||
|
||||
ret = i2c_dw_irq_handler_slave(dev);
|
||||
if (ret > 0)
|
||||
complete(&dev->cmd_complete);
|
||||
|
||||
return IRQ_RETVAL(ret);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm i2c_dw_algo = {
|
||||
@ -246,11 +230,8 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
|
||||
struct i2c_adapter *adap = &dev->adapter;
|
||||
int ret;
|
||||
|
||||
init_completion(&dev->cmd_complete);
|
||||
|
||||
dev->init = i2c_dw_init_slave;
|
||||
dev->disable = i2c_dw_disable;
|
||||
dev->disable_int = i2c_dw_disable_int;
|
||||
|
||||
ret = i2c_dw_init_regmap(dev);
|
||||
if (ret)
|
||||
|
@ -482,19 +482,17 @@ static int i2c_gpio_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id i2c_gpio_dt_ids[] = {
|
||||
{ .compatible = "i2c-gpio", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver i2c_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "i2c-gpio",
|
||||
.of_match_table = of_match_ptr(i2c_gpio_dt_ids),
|
||||
.of_match_table = i2c_gpio_dt_ids,
|
||||
},
|
||||
.probe = i2c_gpio_probe,
|
||||
.remove = i2c_gpio_remove,
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -88,6 +89,7 @@ struct hisi_i2c_controller {
|
||||
struct i2c_adapter adapter;
|
||||
void __iomem *iobase;
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
int irq;
|
||||
|
||||
/* Intermediates for recording the transfer process */
|
||||
@ -454,10 +456,15 @@ static int hisi_i2c_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = device_property_read_u64(dev, "clk_rate", &clk_rate_hz);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get clock frequency, ret = %d\n", ret);
|
||||
return ret;
|
||||
ctlr->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR_OR_NULL(ctlr->clk)) {
|
||||
ret = device_property_read_u64(dev, "clk_rate", &clk_rate_hz);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get clock frequency, ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
clk_rate_hz = clk_get_rate(ctlr->clk);
|
||||
}
|
||||
|
||||
ctlr->clk_rate_khz = DIV_ROUND_UP_ULL(clk_rate_hz, HZ_PER_KHZ);
|
||||
@ -489,11 +496,18 @@ static const struct acpi_device_id hisi_i2c_acpi_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, hisi_i2c_acpi_ids);
|
||||
|
||||
static const struct of_device_id hisi_i2c_dts_ids[] = {
|
||||
{ .compatible = "hisilicon,ascend910-i2c", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, hisi_i2c_dts_ids);
|
||||
|
||||
static struct platform_driver hisi_i2c_driver = {
|
||||
.probe = hisi_i2c_probe,
|
||||
.driver = {
|
||||
.name = "hisi-i2c",
|
||||
.acpi_match_table = hisi_i2c_acpi_ids,
|
||||
.of_match_table = hisi_i2c_dts_ids,
|
||||
},
|
||||
};
|
||||
module_platform_driver(hisi_i2c_driver);
|
||||
|
@ -1451,8 +1451,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
|
@ -509,6 +509,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
/* Block Write */
|
||||
dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: WRITE\n");
|
||||
if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
dma_size = data->block[0] + 1;
|
||||
dma_direction = DMA_TO_DEVICE;
|
||||
desc->wr_len_cmd = dma_size;
|
||||
|
@ -431,6 +431,19 @@ static const struct mtk_i2c_compatible mt8168_compat = {
|
||||
.max_dma_support = 33,
|
||||
};
|
||||
|
||||
static const struct mtk_i2c_compatible mt7986_compat = {
|
||||
.quirks = &mt7622_i2c_quirks,
|
||||
.regs = mt_i2c_regs_v1,
|
||||
.pmic_i2c = 0,
|
||||
.dcm = 1,
|
||||
.auto_restart = 1,
|
||||
.aux_len_reg = 1,
|
||||
.timing_adjust = 0,
|
||||
.dma_sync = 1,
|
||||
.ltiming_adjust = 0,
|
||||
.max_dma_support = 32,
|
||||
};
|
||||
|
||||
static const struct mtk_i2c_compatible mt8173_compat = {
|
||||
.regs = mt_i2c_regs_v1,
|
||||
.pmic_i2c = 0,
|
||||
@ -503,6 +516,7 @@ static const struct of_device_id mtk_i2c_of_match[] = {
|
||||
{ .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
|
||||
{ .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
|
||||
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
|
||||
{ .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat },
|
||||
{ .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat },
|
||||
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
|
||||
{ .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
|
||||
|
@ -106,7 +106,7 @@ enum i2c_addr {
|
||||
#define NPCM_I2CCST3 0x19
|
||||
#define I2C_VER 0x1F
|
||||
|
||||
/*BANK0 regs*/
|
||||
/* BANK 0 regs */
|
||||
#define NPCM_I2CADDR3 0x10
|
||||
#define NPCM_I2CADDR7 0x11
|
||||
#define NPCM_I2CADDR4 0x12
|
||||
@ -115,6 +115,20 @@ enum i2c_addr {
|
||||
#define NPCM_I2CADDR9 0x15
|
||||
#define NPCM_I2CADDR6 0x16
|
||||
#define NPCM_I2CADDR10 0x17
|
||||
#define NPCM_I2CCTL4 0x1A
|
||||
#define NPCM_I2CCTL5 0x1B
|
||||
#define NPCM_I2CSCLLT 0x1C /* SCL Low Time */
|
||||
#define NPCM_I2CFIF_CTL 0x1D /* FIFO Control */
|
||||
#define NPCM_I2CSCLHT 0x1E /* SCL High Time */
|
||||
|
||||
/* BANK 1 regs */
|
||||
#define NPCM_I2CFIF_CTS 0x10 /* Both FIFOs Control and Status */
|
||||
#define NPCM_I2CTXF_CTL 0x12 /* Tx-FIFO Control */
|
||||
#define NPCM_I2CT_OUT 0x14 /* Bus T.O. */
|
||||
#define NPCM_I2CPEC 0x16 /* PEC Data */
|
||||
#define NPCM_I2CTXF_STS 0x1A /* Tx-FIFO Status */
|
||||
#define NPCM_I2CRXF_STS 0x1C /* Rx-FIFO Status */
|
||||
#define NPCM_I2CRXF_CTL 0x1E /* Rx-FIFO Control */
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C_SLAVE)
|
||||
/*
|
||||
@ -131,66 +145,51 @@ static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#define NPCM_I2CCTL4 0x1A
|
||||
#define NPCM_I2CCTL5 0x1B
|
||||
#define NPCM_I2CSCLLT 0x1C /* SCL Low Time */
|
||||
#define NPCM_I2CFIF_CTL 0x1D /* FIFO Control */
|
||||
#define NPCM_I2CSCLHT 0x1E /* SCL High Time */
|
||||
|
||||
/* BANK 1 regs */
|
||||
#define NPCM_I2CFIF_CTS 0x10 /* Both FIFOs Control and Status */
|
||||
#define NPCM_I2CTXF_CTL 0x12 /* Tx-FIFO Control */
|
||||
#define NPCM_I2CT_OUT 0x14 /* Bus T.O. */
|
||||
#define NPCM_I2CPEC 0x16 /* PEC Data */
|
||||
#define NPCM_I2CTXF_STS 0x1A /* Tx-FIFO Status */
|
||||
#define NPCM_I2CRXF_STS 0x1C /* Rx-FIFO Status */
|
||||
#define NPCM_I2CRXF_CTL 0x1E /* Rx-FIFO Control */
|
||||
|
||||
/* NPCM_I2CST reg fields */
|
||||
#define NPCM_I2CST_XMIT BIT(0)
|
||||
#define NPCM_I2CST_MASTER BIT(1)
|
||||
#define NPCM_I2CST_NMATCH BIT(2)
|
||||
#define NPCM_I2CST_STASTR BIT(3)
|
||||
#define NPCM_I2CST_NEGACK BIT(4)
|
||||
#define NPCM_I2CST_BER BIT(5)
|
||||
#define NPCM_I2CST_SDAST BIT(6)
|
||||
#define NPCM_I2CST_SLVSTP BIT(7)
|
||||
#define NPCM_I2CST_XMIT BIT(0) /* Transmit mode */
|
||||
#define NPCM_I2CST_MASTER BIT(1) /* Master mode */
|
||||
#define NPCM_I2CST_NMATCH BIT(2) /* New match */
|
||||
#define NPCM_I2CST_STASTR BIT(3) /* Stall after start */
|
||||
#define NPCM_I2CST_NEGACK BIT(4) /* Negative ACK */
|
||||
#define NPCM_I2CST_BER BIT(5) /* Bus error */
|
||||
#define NPCM_I2CST_SDAST BIT(6) /* SDA status */
|
||||
#define NPCM_I2CST_SLVSTP BIT(7) /* Slave stop */
|
||||
|
||||
/* NPCM_I2CCST reg fields */
|
||||
#define NPCM_I2CCST_BUSY BIT(0)
|
||||
#define NPCM_I2CCST_BB BIT(1)
|
||||
#define NPCM_I2CCST_MATCH BIT(2)
|
||||
#define NPCM_I2CCST_GCMATCH BIT(3)
|
||||
#define NPCM_I2CCST_TSDA BIT(4)
|
||||
#define NPCM_I2CCST_TGSCL BIT(5)
|
||||
#define NPCM_I2CCST_MATCHAF BIT(6)
|
||||
#define NPCM_I2CCST_ARPMATCH BIT(7)
|
||||
#define NPCM_I2CCST_BUSY BIT(0) /* Busy */
|
||||
#define NPCM_I2CCST_BB BIT(1) /* Bus busy */
|
||||
#define NPCM_I2CCST_MATCH BIT(2) /* Address match */
|
||||
#define NPCM_I2CCST_GCMATCH BIT(3) /* Global call match */
|
||||
#define NPCM_I2CCST_TSDA BIT(4) /* Test SDA line */
|
||||
#define NPCM_I2CCST_TGSCL BIT(5) /* Toggle SCL line */
|
||||
#define NPCM_I2CCST_MATCHAF BIT(6) /* Match address field */
|
||||
#define NPCM_I2CCST_ARPMATCH BIT(7) /* ARP address match */
|
||||
|
||||
/* NPCM_I2CCTL1 reg fields */
|
||||
#define NPCM_I2CCTL1_START BIT(0)
|
||||
#define NPCM_I2CCTL1_STOP BIT(1)
|
||||
#define NPCM_I2CCTL1_INTEN BIT(2)
|
||||
#define NPCM_I2CCTL1_START BIT(0) /* Generate start condition */
|
||||
#define NPCM_I2CCTL1_STOP BIT(1) /* Generate stop condition */
|
||||
#define NPCM_I2CCTL1_INTEN BIT(2) /* Interrupt enable */
|
||||
#define NPCM_I2CCTL1_EOBINTE BIT(3)
|
||||
#define NPCM_I2CCTL1_ACK BIT(4)
|
||||
#define NPCM_I2CCTL1_GCMEN BIT(5)
|
||||
#define NPCM_I2CCTL1_NMINTE BIT(6)
|
||||
#define NPCM_I2CCTL1_STASTRE BIT(7)
|
||||
#define NPCM_I2CCTL1_GCMEN BIT(5) /* Global call match enable */
|
||||
#define NPCM_I2CCTL1_NMINTE BIT(6) /* New match interrupt enable */
|
||||
#define NPCM_I2CCTL1_STASTRE BIT(7) /* Stall after start enable */
|
||||
|
||||
/* RW1S fields (inside a RW reg): */
|
||||
#define NPCM_I2CCTL1_RWS \
|
||||
(NPCM_I2CCTL1_START | NPCM_I2CCTL1_STOP | NPCM_I2CCTL1_ACK)
|
||||
|
||||
/* npcm_i2caddr reg fields */
|
||||
#define NPCM_I2CADDR_A GENMASK(6, 0)
|
||||
#define NPCM_I2CADDR_SAEN BIT(7)
|
||||
#define NPCM_I2CADDR_A GENMASK(6, 0) /* Address */
|
||||
#define NPCM_I2CADDR_SAEN BIT(7) /* Slave address enable */
|
||||
|
||||
/* NPCM_I2CCTL2 reg fields */
|
||||
#define I2CCTL2_ENABLE BIT(0)
|
||||
#define I2CCTL2_SCLFRQ6_0 GENMASK(7, 1)
|
||||
#define I2CCTL2_ENABLE BIT(0) /* Module enable */
|
||||
#define I2CCTL2_SCLFRQ6_0 GENMASK(7, 1) /* Bits 0:6 of frequency divisor */
|
||||
|
||||
/* NPCM_I2CCTL3 reg fields */
|
||||
#define I2CCTL3_SCLFRQ8_7 GENMASK(1, 0)
|
||||
#define I2CCTL3_ARPMEN BIT(2)
|
||||
#define I2CCTL3_SCLFRQ8_7 GENMASK(1, 0) /* Bits 7:8 of frequency divisor */
|
||||
#define I2CCTL3_ARPMEN BIT(2) /* ARP match enable */
|
||||
#define I2CCTL3_IDL_START BIT(3)
|
||||
#define I2CCTL3_400K_MODE BIT(4)
|
||||
#define I2CCTL3_BNK_SEL BIT(5)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define REG_MTXFIFO 0x00
|
||||
#define REG_MRXFIFO 0x04
|
||||
#define REG_SMSTA 0x14
|
||||
#define REG_IMASK 0x18
|
||||
#define REG_CTL 0x1c
|
||||
#define REG_REV 0x28
|
||||
|
||||
@ -66,6 +67,7 @@ static void pasemi_reset(struct pasemi_smbus *smbus)
|
||||
val |= CTL_EN;
|
||||
|
||||
reg_write(smbus, REG_CTL, val);
|
||||
reinit_completion(&smbus->irq_completion);
|
||||
}
|
||||
|
||||
static void pasemi_smb_clear(struct pasemi_smbus *smbus)
|
||||
@ -78,14 +80,21 @@ static void pasemi_smb_clear(struct pasemi_smbus *smbus)
|
||||
|
||||
static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
|
||||
{
|
||||
int timeout = 10;
|
||||
int timeout = 100;
|
||||
unsigned int status;
|
||||
|
||||
status = reg_read(smbus, REG_SMSTA);
|
||||
|
||||
while (!(status & SMSTA_XEN) && timeout--) {
|
||||
msleep(1);
|
||||
if (smbus->use_irq) {
|
||||
reinit_completion(&smbus->irq_completion);
|
||||
reg_write(smbus, REG_IMASK, SMSTA_XEN | SMSTA_MTN);
|
||||
wait_for_completion_timeout(&smbus->irq_completion, msecs_to_jiffies(100));
|
||||
reg_write(smbus, REG_IMASK, 0);
|
||||
status = reg_read(smbus, REG_SMSTA);
|
||||
} else {
|
||||
status = reg_read(smbus, REG_SMSTA);
|
||||
while (!(status & SMSTA_XEN) && timeout--) {
|
||||
msleep(1);
|
||||
status = reg_read(smbus, REG_SMSTA);
|
||||
}
|
||||
}
|
||||
|
||||
/* Got NACK? */
|
||||
@ -344,10 +353,14 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
|
||||
|
||||
/* set up the sysfs linkage to our parent device */
|
||||
smbus->adapter.dev.parent = smbus->dev;
|
||||
smbus->use_irq = 0;
|
||||
init_completion(&smbus->irq_completion);
|
||||
|
||||
if (smbus->hw_rev != PASEMI_HW_REV_PCI)
|
||||
smbus->hw_rev = reg_read(smbus, REG_REV);
|
||||
|
||||
reg_write(smbus, REG_IMASK, 0);
|
||||
|
||||
pasemi_reset(smbus);
|
||||
|
||||
error = devm_i2c_add_adapter(smbus->dev, &smbus->adapter);
|
||||
@ -356,3 +369,12 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
irqreturn_t pasemi_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct pasemi_smbus *smbus = dev_id;
|
||||
|
||||
reg_write(smbus, REG_IMASK, 0);
|
||||
complete(&smbus->irq_completion);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/i2c-smbus.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#define PASEMI_HW_REV_PCI -1
|
||||
|
||||
@ -16,6 +17,10 @@ struct pasemi_smbus {
|
||||
void __iomem *ioaddr;
|
||||
unsigned int clk_div;
|
||||
int hw_rev;
|
||||
int use_irq;
|
||||
struct completion irq_completion;
|
||||
};
|
||||
|
||||
int pasemi_i2c_common_probe(struct pasemi_smbus *smbus);
|
||||
|
||||
irqreturn_t pasemi_irq_handler(int irq, void *dev_id);
|
||||
|
@ -49,6 +49,7 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev)
|
||||
struct pasemi_smbus *smbus;
|
||||
u32 frequency;
|
||||
int error;
|
||||
int irq_num;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(struct pasemi_platform_i2c_data),
|
||||
GFP_KERNEL);
|
||||
@ -82,6 +83,11 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev)
|
||||
if (error)
|
||||
goto out_clk_disable;
|
||||
|
||||
irq_num = platform_get_irq(pdev, 0);
|
||||
error = devm_request_irq(smbus->dev, irq_num, pasemi_irq_handler, 0, "pasemi_apple_i2c", (void *)smbus);
|
||||
|
||||
if (!error)
|
||||
smbus->use_irq = 1;
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
return 0;
|
||||
|
@ -105,7 +105,7 @@ static int ce4100_i2c_probe(struct pci_dev *dev,
|
||||
int i;
|
||||
struct ce4100_devices *sds;
|
||||
|
||||
ret = pci_enable_device_mem(dev);
|
||||
ret = pcim_enable_device(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -114,10 +114,8 @@ static int ce4100_i2c_probe(struct pci_dev *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
sds = kzalloc(sizeof(*sds), GFP_KERNEL);
|
||||
if (!sds) {
|
||||
ret = -ENOMEM;
|
||||
goto err_mem;
|
||||
}
|
||||
if (!sds)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
|
||||
sds->pdev[i] = add_i2c_device(dev, i);
|
||||
@ -133,8 +131,6 @@ static int ce4100_i2c_probe(struct pci_dev *dev,
|
||||
|
||||
err_dev_add:
|
||||
kfree(sds);
|
||||
err_mem:
|
||||
pci_disable_device(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ struct geni_i2c_dev {
|
||||
int cur_wr;
|
||||
int cur_rd;
|
||||
spinlock_t lock;
|
||||
struct clk *core_clk;
|
||||
u32 clk_freq_out;
|
||||
const struct geni_i2c_clk_fld *clk_fld;
|
||||
int suspended;
|
||||
@ -100,6 +101,13 @@ struct geni_i2c_dev {
|
||||
bool abort_done;
|
||||
};
|
||||
|
||||
struct geni_i2c_desc {
|
||||
bool has_core_clk;
|
||||
char *icc_ddr;
|
||||
bool no_dma_support;
|
||||
unsigned int tx_fifo_depth;
|
||||
};
|
||||
|
||||
struct geni_i2c_err_log {
|
||||
int err;
|
||||
const char *msg;
|
||||
@ -763,6 +771,7 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
u32 proto, tx_depth, fifo_disable;
|
||||
int ret;
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct geni_i2c_desc *desc = NULL;
|
||||
|
||||
gi2c = devm_kzalloc(dev, sizeof(*gi2c), GFP_KERNEL);
|
||||
if (!gi2c)
|
||||
@ -775,6 +784,14 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(gi2c->se.base))
|
||||
return PTR_ERR(gi2c->se.base);
|
||||
|
||||
desc = device_get_match_data(&pdev->dev);
|
||||
|
||||
if (desc && desc->has_core_clk) {
|
||||
gi2c->core_clk = devm_clk_get(dev, "core");
|
||||
if (IS_ERR(gi2c->core_clk))
|
||||
return PTR_ERR(gi2c->core_clk);
|
||||
}
|
||||
|
||||
gi2c->se.clk = devm_clk_get(dev, "se");
|
||||
if (IS_ERR(gi2c->se.clk) && !has_acpi_companion(dev))
|
||||
return PTR_ERR(gi2c->se.clk);
|
||||
@ -818,7 +835,7 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
gi2c->adap.dev.of_node = dev->of_node;
|
||||
strscpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
|
||||
|
||||
ret = geni_icc_get(&gi2c->se, "qup-memory");
|
||||
ret = geni_icc_get(&gi2c->se, desc ? desc->icc_ddr : "qup-memory");
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
@ -828,12 +845,17 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
*/
|
||||
gi2c->se.icc_paths[GENI_TO_CORE].avg_bw = GENI_DEFAULT_BW;
|
||||
gi2c->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW;
|
||||
gi2c->se.icc_paths[GENI_TO_DDR].avg_bw = Bps_to_icc(gi2c->clk_freq_out);
|
||||
if (!desc || desc->icc_ddr)
|
||||
gi2c->se.icc_paths[GENI_TO_DDR].avg_bw = Bps_to_icc(gi2c->clk_freq_out);
|
||||
|
||||
ret = geni_icc_set_bw(&gi2c->se);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(gi2c->core_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = geni_se_resources_on(&gi2c->se);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error turning on resources %d\n", ret);
|
||||
@ -843,10 +865,15 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
if (proto != GENI_SE_I2C) {
|
||||
dev_err(dev, "Invalid proto %d\n", proto);
|
||||
geni_se_resources_off(&gi2c->se);
|
||||
clk_disable_unprepare(gi2c->core_clk);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
fifo_disable = readl_relaxed(gi2c->se.base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE;
|
||||
if (desc && desc->no_dma_support)
|
||||
fifo_disable = false;
|
||||
else
|
||||
fifo_disable = readl_relaxed(gi2c->se.base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE;
|
||||
|
||||
if (fifo_disable) {
|
||||
/* FIFO is disabled, so we can only use GPI DMA */
|
||||
gi2c->gpi_mode = true;
|
||||
@ -858,6 +885,16 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
} else {
|
||||
gi2c->gpi_mode = false;
|
||||
tx_depth = geni_se_get_tx_fifo_depth(&gi2c->se);
|
||||
|
||||
/* I2C Master Hub Serial Elements doesn't have the HW_PARAM_0 register */
|
||||
if (!tx_depth && desc)
|
||||
tx_depth = desc->tx_fifo_depth;
|
||||
|
||||
if (!tx_depth) {
|
||||
dev_err(dev, "Invalid TX FIFO depth\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gi2c->tx_wm = tx_depth - 1;
|
||||
geni_se_init(&gi2c->se, gi2c->tx_wm, tx_depth);
|
||||
geni_se_config_packing(&gi2c->se, BITS_PER_BYTE,
|
||||
@ -866,6 +903,7 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
dev_dbg(dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(gi2c->core_clk);
|
||||
ret = geni_se_resources_off(&gi2c->se);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error turning off resources %d\n", ret);
|
||||
@ -931,6 +969,8 @@ static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev)
|
||||
gi2c->suspended = 1;
|
||||
}
|
||||
|
||||
clk_disable_unprepare(gi2c->core_clk);
|
||||
|
||||
return geni_icc_disable(&gi2c->se);
|
||||
}
|
||||
|
||||
@ -943,6 +983,10 @@ static int __maybe_unused geni_i2c_runtime_resume(struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(gi2c->core_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = geni_se_resources_on(&gi2c->se);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -981,8 +1025,16 @@ static const struct dev_pm_ops geni_i2c_pm_ops = {
|
||||
NULL)
|
||||
};
|
||||
|
||||
const struct geni_i2c_desc i2c_master_hub = {
|
||||
.has_core_clk = true,
|
||||
.icc_ddr = NULL,
|
||||
.no_dma_support = true,
|
||||
.tx_fifo_depth = 16,
|
||||
};
|
||||
|
||||
static const struct of_device_id geni_i2c_dt_match[] = {
|
||||
{ .compatible = "qcom,geni-i2c" },
|
||||
{ .compatible = "qcom,geni-i2c-master-hub", .data = &i2c_master_hub },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
|
||||
|
@ -1830,6 +1830,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
|
||||
i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
|
||||
i2c_dev->adapter.algo = &tegra_i2c_algo;
|
||||
i2c_dev->adapter.nr = pdev->id;
|
||||
ACPI_COMPANION_SET(&i2c_dev->adapter.dev, ACPI_COMPANION(&pdev->dev));
|
||||
|
||||
if (i2c_dev->hw->supports_bus_clear)
|
||||
i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
|
||||
|
@ -858,11 +858,14 @@ static int xiic_i2c_remove(struct platform_device *pdev)
|
||||
/* remove adapter & data */
|
||||
i2c_del_adapter(&i2c->adap);
|
||||
|
||||
ret = pm_runtime_resume_and_get(i2c->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = pm_runtime_get_sync(i2c->dev);
|
||||
|
||||
if (ret < 0)
|
||||
dev_warn(&pdev->dev, "Failed to activate device for removal (%pe)\n",
|
||||
ERR_PTR(ret));
|
||||
else
|
||||
xiic_deinit(i2c);
|
||||
|
||||
xiic_deinit(i2c);
|
||||
pm_runtime_put_sync(i2c->dev);
|
||||
clk_disable_unprepare(i2c->clk);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
@ -1018,15 +1018,14 @@ static const struct i2c_device_id dummy_id[] = {
|
||||
{ },
|
||||
};
|
||||
|
||||
static int dummy_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int dummy_probe(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver dummy_driver = {
|
||||
.driver.name = "dummy",
|
||||
.probe = dummy_probe,
|
||||
.probe_new = dummy_probe,
|
||||
.id_table = dummy_id,
|
||||
};
|
||||
|
||||
|
@ -140,8 +140,9 @@ static int i2c_slave_init_eeprom_data(struct eeprom_data *eeprom, struct i2c_cli
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_slave_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int i2c_slave_eeprom_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct eeprom_data *eeprom;
|
||||
int ret;
|
||||
unsigned int size = FIELD_GET(I2C_SLAVE_BYTELEN, id->driver_data) + 1;
|
||||
@ -206,7 +207,7 @@ static struct i2c_driver i2c_slave_eeprom_driver = {
|
||||
.driver = {
|
||||
.name = "i2c-slave-eeprom",
|
||||
},
|
||||
.probe = i2c_slave_eeprom_probe,
|
||||
.probe_new = i2c_slave_eeprom_probe,
|
||||
.remove = i2c_slave_eeprom_remove,
|
||||
.id_table = i2c_slave_eeprom_id,
|
||||
};
|
||||
|
@ -112,8 +112,7 @@ static void smbalert_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
/* Setup SMBALERT# infrastructure */
|
||||
static int smbalert_probe(struct i2c_client *ara,
|
||||
const struct i2c_device_id *id)
|
||||
static int smbalert_probe(struct i2c_client *ara)
|
||||
{
|
||||
struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);
|
||||
struct i2c_smbus_alert *alert;
|
||||
@ -170,7 +169,7 @@ static struct i2c_driver smbalert_driver = {
|
||||
.driver = {
|
||||
.name = "smbus_alert",
|
||||
},
|
||||
.probe = smbalert_probe,
|
||||
.probe_new = smbalert_probe,
|
||||
.remove = smbalert_remove,
|
||||
.id_table = smbalert_ids,
|
||||
};
|
||||
@ -361,9 +360,15 @@ void i2c_register_spd(struct i2c_adapter *adap)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory types could be found at section 7.18.2 (Memory Device — Type), table 78
|
||||
* https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.6.0.pdf
|
||||
*/
|
||||
switch (common_mem_type) {
|
||||
case 0x12: /* DDR */
|
||||
case 0x13: /* DDR2 */
|
||||
case 0x18: /* DDR3 */
|
||||
case 0x1B: /* LPDDR */
|
||||
case 0x1C: /* LPDDR2 */
|
||||
case 0x1D: /* LPDDR3 */
|
||||
name = "spd";
|
||||
|
@ -283,8 +283,7 @@ static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
/*
|
||||
* I2C init/probing/exit functions
|
||||
*/
|
||||
static int pca9541_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int pca9541_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct i2c_mux_core *muxc;
|
||||
@ -337,7 +336,7 @@ static struct i2c_driver pca9541_driver = {
|
||||
.name = "pca9541",
|
||||
.of_match_table = of_match_ptr(pca9541_of_match),
|
||||
},
|
||||
.probe = pca9541_probe,
|
||||
.probe_new = pca9541_probe,
|
||||
.remove = pca9541_remove,
|
||||
.id_table = pca9541_id,
|
||||
};
|
||||
|
@ -411,9 +411,9 @@ static int pca954x_init(struct i2c_client *client, struct pca954x *data)
|
||||
/*
|
||||
* I2C init/probing/exit functions
|
||||
*/
|
||||
static int pca954x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int pca954x_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
struct gpio_desc *gpio;
|
||||
@ -554,7 +554,7 @@ static struct i2c_driver pca954x_driver = {
|
||||
.pm = &pca954x_pm,
|
||||
.of_match_table = pca954x_of_match,
|
||||
},
|
||||
.probe = pca954x_probe,
|
||||
.probe_new = pca954x_probe,
|
||||
.remove = pca954x_remove,
|
||||
.id_table = pca954x_id,
|
||||
};
|
||||
|
@ -183,13 +183,12 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
|
||||
if (!mux->data.reg) {
|
||||
dev_info(&pdev->dev,
|
||||
"Register not set, using platform resource\n");
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
mux->data.reg_size = resource_size(res);
|
||||
mux->data.reg = devm_ioremap_resource(&pdev->dev, res);
|
||||
mux->data.reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(mux->data.reg)) {
|
||||
ret = PTR_ERR(mux->data.reg);
|
||||
goto err_put_parent;
|
||||
}
|
||||
mux->data.reg_size = resource_size(res);
|
||||
}
|
||||
|
||||
if (mux->data.reg_size != 4 && mux->data.reg_size != 2 &&
|
||||
|
@ -81,19 +81,31 @@
|
||||
*/
|
||||
|
||||
#define MAX_CLK_PERF_LEVEL 32
|
||||
#define NUM_AHB_CLKS 2
|
||||
#define MAX_CLKS 2
|
||||
|
||||
/**
|
||||
* struct geni_wrapper - Data structure to represent the QUP Wrapper Core
|
||||
* @dev: Device pointer of the QUP wrapper core
|
||||
* @base: Base address of this instance of QUP wrapper core
|
||||
* @ahb_clks: Handle to the primary & secondary AHB clocks
|
||||
* @clks: Handle to the primary & optional secondary AHB clocks
|
||||
* @num_clks: Count of clocks
|
||||
* @to_core: Core ICC path
|
||||
*/
|
||||
struct geni_wrapper {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
|
||||
struct clk_bulk_data clks[MAX_CLKS];
|
||||
unsigned int num_clks;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct geni_se_desc - Data structure to represent the QUP Wrapper resources
|
||||
* @clks: Name of the primary & optional secondary AHB clocks
|
||||
* @num_clks: Count of clock names
|
||||
*/
|
||||
struct geni_se_desc {
|
||||
unsigned int num_clks;
|
||||
const char * const *clks;
|
||||
};
|
||||
|
||||
static const char * const icc_path_names[] = {"qup-core", "qup-config",
|
||||
@ -496,8 +508,7 @@ static void geni_se_clks_off(struct geni_se *se)
|
||||
struct geni_wrapper *wrapper = se->wrapper;
|
||||
|
||||
clk_disable_unprepare(se->clk);
|
||||
clk_bulk_disable_unprepare(ARRAY_SIZE(wrapper->ahb_clks),
|
||||
wrapper->ahb_clks);
|
||||
clk_bulk_disable_unprepare(wrapper->num_clks, wrapper->clks);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -528,15 +539,13 @@ static int geni_se_clks_on(struct geni_se *se)
|
||||
int ret;
|
||||
struct geni_wrapper *wrapper = se->wrapper;
|
||||
|
||||
ret = clk_bulk_prepare_enable(ARRAY_SIZE(wrapper->ahb_clks),
|
||||
wrapper->ahb_clks);
|
||||
ret = clk_bulk_prepare_enable(wrapper->num_clks, wrapper->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(se->clk);
|
||||
if (ret)
|
||||
clk_bulk_disable_unprepare(ARRAY_SIZE(wrapper->ahb_clks),
|
||||
wrapper->ahb_clks);
|
||||
clk_bulk_disable_unprepare(wrapper->num_clks, wrapper->clks);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -887,11 +896,33 @@ static int geni_se_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(wrapper->base);
|
||||
|
||||
if (!has_acpi_companion(&pdev->dev)) {
|
||||
wrapper->ahb_clks[0].id = "m-ahb";
|
||||
wrapper->ahb_clks[1].id = "s-ahb";
|
||||
ret = devm_clk_bulk_get(dev, NUM_AHB_CLKS, wrapper->ahb_clks);
|
||||
const struct geni_se_desc *desc;
|
||||
int i;
|
||||
|
||||
desc = device_get_match_data(&pdev->dev);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
wrapper->num_clks = min_t(unsigned int, desc->num_clks, MAX_CLKS);
|
||||
|
||||
for (i = 0; i < wrapper->num_clks; ++i)
|
||||
wrapper->clks[i].id = desc->clks[i];
|
||||
|
||||
ret = of_count_phandle_with_args(dev->of_node, "clocks", "#clock-cells");
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "invalid clocks property at %pOF\n", dev->of_node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret < wrapper->num_clks) {
|
||||
dev_err(dev, "invalid clocks count at %pOF, expected %d entries\n",
|
||||
dev->of_node, wrapper->num_clks);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_clk_bulk_get(dev, wrapper->num_clks, wrapper->clks);
|
||||
if (ret) {
|
||||
dev_err(dev, "Err getting AHB clks %d\n", ret);
|
||||
dev_err(dev, "Err getting clks %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -901,8 +932,28 @@ static int geni_se_probe(struct platform_device *pdev)
|
||||
return devm_of_platform_populate(dev);
|
||||
}
|
||||
|
||||
static const char * const qup_clks[] = {
|
||||
"m-ahb",
|
||||
"s-ahb",
|
||||
};
|
||||
|
||||
static const struct geni_se_desc qup_desc = {
|
||||
.clks = qup_clks,
|
||||
.num_clks = ARRAY_SIZE(qup_clks),
|
||||
};
|
||||
|
||||
static const char * const i2c_master_hub_clks[] = {
|
||||
"s-ahb",
|
||||
};
|
||||
|
||||
static const struct geni_se_desc i2c_master_hub_desc = {
|
||||
.clks = i2c_master_hub_clks,
|
||||
.num_clks = ARRAY_SIZE(i2c_master_hub_clks),
|
||||
};
|
||||
|
||||
static const struct of_device_id geni_se_dt_match[] = {
|
||||
{ .compatible = "qcom,geni-se-qup", },
|
||||
{ .compatible = "qcom,geni-se-qup", .data = &qup_desc },
|
||||
{ .compatible = "qcom,geni-se-i2c-master-hub", .data = &i2c_master_hub_desc },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, geni_se_dt_match);
|
||||
|
Loading…
Reference in New Issue
Block a user