Commit ec9187ec authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 785d21ba 39244cc7
# 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_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_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_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_TAR_10BITADDR_MASTER BIT(12)
#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_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_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_ERR_TX_ABRT 0x1
#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 @@ static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev)
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);
ret = pm_runtime_get_sync(i2c->dev);
if (ret < 0)
return ret;
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment