mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 10:42:11 +00:00
I2C has largely driver updates for 6.7., i.e. feature additions (like
adding transfers while in atomic mode), using new helpers (like devm_clk_get_enabled), new IDs, documentation fixes and additions... you name it. The core got a memleak fix and better support for nested muxes. -----BEGIN PGP SIGNATURE----- iQJCBAABCgAtFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmVHnGkPHHdzYUBrZXJu ZWwub3JnAAoJEBQN5MwUoCm2ZosP9jLusVXmRi3BSwnCqNVBD6z6fDcYpIi71zTF P9GALIdxf2lPwUs+GrS/GVsdNzIhA6Fl5847uGaSd9ijaVjaBgjIqt2DRy7zBdwD bvE7mbSRBYLmUF3SgxrmS559MiYTTOJvImR1BTUTOgHXSfnymufCv+s2MGKiI9aa 6jK9SuFXRwgMubzQkl4VT6By/TsnuCF7+9pr2fU9lR5b+mN5JT0EYBF5CPfpdfca UcREhZXkHd758icJ/T0CSqZ6y7/3RmAC8L+vQBcluoXucFfTcIqdZ44+SaiV9pAh kicvsm5Vyme/hCe+mnBRVWDBSJUpvgj48084qZj+QCfrsaqBadA8KCMZFB1ZLi3e eMtEFlt4OtXwL2PpbGjDhG59XWQosPc5ii7Fwu1EA8flW2p+H5NoRPCrFUEBKvDa BkHduxRykJVm86L6vFh6XN93JnbWzBqE6IKnJWEnPNcA2+2RbcenYWghQDE8vS6E bJ2SdHC2S1VOY6KKN6HsGJT4tfpKPP/o+8eabkhrLups/tilNhbct5xjOCtRaV74 mSkwn+I5yJJ43ZdDrTycbe2qd5yrE0hXRfBDXiDpsVlKAJOXtEzhfNJc1j8oNdKX BSz6Bci3GSKcycrSjPJxu0ynW6GgMzvo18N+JENhSuRA5WNVJqrVq76fTDTRSf5T C/ouFqg= =nfX/ -----END PGP SIGNATURE----- Merge tag 'i2c-for-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux Pull i2c updates from Wolfram Sang: "I2C has largely driver updates for 6.7, i.e. feature additions (like adding transfers while in atomic mode), using new helpers (like devm_clk_get_enabled), new IDs, documentation fixes and additions... you name it. The core got a memleak fix and better support for nested muxes" * tag 'i2c-for-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (53 commits) i2c: s3c2410: make i2c_s3c_irq_nextbyte() void i2c: qcom-geni: add ACPI device id for sc8180x Documentation: i2c: add fault code for not supporting 10 bit addresses i2c: sun6i-p2wi: Prevent potential division by zero i2c: mux: demux-pinctrl: Convert to use sysfs_emit_at() API i2c: i801: Use new helper acpi_use_parent_companion ACPI: Add helper acpi_use_parent_companion MAINTAINERS: add YAML file for i2c-demux-pinctrl i2c: core: fix lockdep warning for sparsely nested adapter chain i2c: axxia: eliminate kernel-doc warnings dt-bindings: i2c: i2c-demux-pinctrl: Convert to json-schema i2c: stm32f7: Use devm_clk_get_enabled() i2c: stm32f4: Use devm_clk_get_enabled() i2c: stm32f7: add description of atomic in struct stm32f7_i2c_dev i2c: fix memleak in i2c_new_client_device() i2c: exynos5: Calculate t_scl_l, t_scl_h according to i2c spec i2c: i801: Simplify class-based client device instantiation i2c: exynos5: add support for atomic transfers i2c: at91-core: Use devm_clk_get_enabled() eeprom: at24: add ST M24C64-D Additional Write lockable page support ...
This commit is contained in:
commit
3d05e493e4
@ -68,10 +68,14 @@ properties:
|
||||
pattern: cs16$
|
||||
- items:
|
||||
pattern: c32$
|
||||
- items:
|
||||
pattern: c32d-wl$
|
||||
- items:
|
||||
pattern: cs32$
|
||||
- items:
|
||||
pattern: c64$
|
||||
- items:
|
||||
pattern: c64d-wl$
|
||||
- items:
|
||||
pattern: cs64$
|
||||
- items:
|
||||
|
@ -1,135 +0,0 @@
|
||||
Pinctrl-based I2C Bus DeMux
|
||||
|
||||
This binding describes an I2C bus demultiplexer that uses pin multiplexing to
|
||||
route the I2C signals, and represents the pin multiplexing configuration using
|
||||
the pinctrl device tree bindings. This may be used to select one I2C IP core at
|
||||
runtime which may have a better feature set for a given task than another I2C
|
||||
IP core on the SoC. The most simple example is to fall back to GPIO bitbanging
|
||||
if your current runtime configuration hits an errata of the internal IP core.
|
||||
|
||||
+-------------------------------+
|
||||
| SoC |
|
||||
| | +-----+ +-----+
|
||||
| +------------+ | | dev | | dev |
|
||||
| |I2C IP Core1|--\ | +-----+ +-----+
|
||||
| +------------+ \-------+ | | |
|
||||
| |Pinctrl|--|------+--------+
|
||||
| +------------+ +-------+ |
|
||||
| |I2C IP Core2|--/ |
|
||||
| +------------+ |
|
||||
| |
|
||||
+-------------------------------+
|
||||
|
||||
Required properties:
|
||||
- compatible: "i2c-demux-pinctrl"
|
||||
- i2c-parent: List of phandles of I2C masters available for selection. The first
|
||||
one will be used as default.
|
||||
- i2c-bus-name: The name of this bus. Also needed as pinctrl-name for the I2C
|
||||
parents.
|
||||
|
||||
Furthermore, I2C mux properties and child nodes. See i2c-mux.yaml in this
|
||||
directory.
|
||||
|
||||
Example:
|
||||
|
||||
Here is a snipplet for a bus to be demuxed. It contains various i2c clients for
|
||||
HDMI, so the bus is named "i2c-hdmi":
|
||||
|
||||
i2chdmi: i2c@8 {
|
||||
|
||||
compatible = "i2c-demux-pinctrl";
|
||||
i2c-parent = <&gpioi2c>, <&iic2>, <&i2c2>;
|
||||
i2c-bus-name = "i2c-hdmi";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ak4643: sound-codec@12 {
|
||||
compatible = "asahi-kasei,ak4643";
|
||||
|
||||
#sound-dai-cells = <0>;
|
||||
reg = <0x12>;
|
||||
};
|
||||
|
||||
composite-in@20 {
|
||||
compatible = "adi,adv7180";
|
||||
reg = <0x20>;
|
||||
remote = <&vin1>;
|
||||
|
||||
port {
|
||||
adv7180: endpoint {
|
||||
bus-width = <8>;
|
||||
remote-endpoint = <&vin1ep0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hdmi@39 {
|
||||
compatible = "adi,adv7511w";
|
||||
reg = <0x39>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
adi,input-depth = <8>;
|
||||
adi,input-colorspace = "rgb";
|
||||
adi,input-clock = "1x";
|
||||
adi,input-style = <1>;
|
||||
adi,input-justification = "evenly";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
adv7511_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds0>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
adv7511_out: endpoint {
|
||||
remote-endpoint = <&hdmi_con>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
And for clarification, here are the snipplets for the i2c-parents:
|
||||
|
||||
gpioi2c: i2c@9 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "i2c-gpio";
|
||||
gpios = <&gpio5 6 GPIO_ACTIVE_HIGH /* sda */
|
||||
&gpio5 5 GPIO_ACTIVE_HIGH /* scl */
|
||||
>;
|
||||
i2c-gpio,delay-us = <5>;
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
&i2c2 {
|
||||
pinctrl-0 = <&i2c2_pins>;
|
||||
pinctrl-names = "i2c-hdmi";
|
||||
|
||||
clock-frequency = <100000>;
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
&iic2 {
|
||||
pinctrl-0 = <&iic2_pins>;
|
||||
pinctrl-names = "i2c-hdmi";
|
||||
|
||||
clock-frequency = <100000>;
|
||||
};
|
||||
|
||||
Please note:
|
||||
|
||||
- pinctrl properties for the parent I2C controllers need a pinctrl state
|
||||
with the same name as i2c-bus-name, not "default"!
|
||||
|
||||
- the i2c masters must have their status "disabled". This driver will
|
||||
enable them at runtime when needed.
|
172
Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml
Normal file
172
Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml
Normal file
@ -0,0 +1,172 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/i2c/i2c-demux-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Pinctrl-based I2C Bus Demultiplexer
|
||||
|
||||
maintainers:
|
||||
- Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||
|
||||
description: |
|
||||
This binding describes an I2C bus demultiplexer that uses pin multiplexing to
|
||||
route the I2C signals, and represents the pin multiplexing configuration
|
||||
using the pinctrl device tree bindings. This may be used to select one I2C
|
||||
IP core at runtime which may have a better feature set for a given task than
|
||||
another I2C IP core on the SoC. The most simple example is to fall back to
|
||||
GPIO bitbanging if your current runtime configuration hits an errata of the
|
||||
internal IP core.
|
||||
|
||||
+-------------------------------+
|
||||
| SoC |
|
||||
| | +-----+ +-----+
|
||||
| +------------+ | | dev | | dev |
|
||||
| |I2C IP Core1|--\ | +-----+ +-----+
|
||||
| +------------+ \-------+ | | |
|
||||
| |Pinctrl|--|------+--------+
|
||||
| +------------+ +-------+ |
|
||||
| |I2C IP Core2|--/ |
|
||||
| +------------+ |
|
||||
| |
|
||||
+-------------------------------+
|
||||
|
||||
allOf:
|
||||
- $ref: i2c-mux.yaml
|
||||
- $ref: /schemas/i2c/i2c-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: i2c-demux-pinctrl
|
||||
|
||||
i2c-parent:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description:
|
||||
List of phandles of I2C masters available for selection. The first one
|
||||
will be used as default.
|
||||
|
||||
i2c-bus-name:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
The name of this bus. Also needed as pinctrl-name for the I2C parents.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- i2c-parent
|
||||
- i2c-bus-name
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
gpioi2c2: i2c-9 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "i2c-gpio";
|
||||
scl-gpios = <&gpio5 5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio5 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <5>;
|
||||
|
||||
// The I2C controller must have its status "disabled". The I2C bus
|
||||
// demultiplexer will enable it at runtime when needed.
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
iic2: i2c@e6520000 {
|
||||
reg = <0xe6520000 0x425>;
|
||||
pinctrl-0 = <&iic2_pins>;
|
||||
// The pinctrl property for the parent I2C controller needs a pinctrl
|
||||
// state with the same name as i2c-bus-name in the I2C bus demultiplexer
|
||||
// node, not "default"!
|
||||
pinctrl-names = "i2c-hdmi";
|
||||
|
||||
clock-frequency = <100000>;
|
||||
|
||||
// The I2C controller must have its status "disabled". The I2C bus
|
||||
// demultiplexer will enable it at runtime when needed.
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c2: i2c@e6530000 {
|
||||
reg = <0 0xe6530000 0 0x40>;
|
||||
pinctrl-0 = <&i2c2_pins>;
|
||||
// The pinctrl property for the parent I2C controller needs a pinctrl
|
||||
// state with the same name as i2c-bus-name in the I2C bus demultiplexer
|
||||
// node, not "default"!
|
||||
pinctrl-names = "i2c-hdmi";
|
||||
|
||||
clock-frequency = <100000>;
|
||||
|
||||
// The I2C controller must have its status "disabled". The I2C bus
|
||||
// demultiplexer will enable it at runtime when needed.
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
// Example for a bus to be demuxed. It contains various I2C clients for
|
||||
// HDMI, so the bus is named "i2c-hdmi":
|
||||
i2chdmi: i2c-mux3 {
|
||||
compatible = "i2c-demux-pinctrl";
|
||||
i2c-parent = <&iic2>, <&i2c2>, <&gpioi2c2>;
|
||||
i2c-bus-name = "i2c-hdmi";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ak4643: codec@12 {
|
||||
compatible = "asahi-kasei,ak4643";
|
||||
#sound-dai-cells = <0>;
|
||||
reg = <0x12>;
|
||||
};
|
||||
|
||||
composite-in@20 {
|
||||
compatible = "adi,adv7180";
|
||||
reg = <0x20>;
|
||||
|
||||
port {
|
||||
adv7180: endpoint {
|
||||
bus-width = <8>;
|
||||
remote-endpoint = <&vin1ep0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hdmi@39 {
|
||||
compatible = "adi,adv7511w";
|
||||
reg = <0x39>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
|
||||
clocks = <&cec_clock>;
|
||||
clock-names = "cec";
|
||||
|
||||
avdd-supply = <&fixedregulator1v8>;
|
||||
dvdd-supply = <&fixedregulator1v8>;
|
||||
pvdd-supply = <&fixedregulator1v8>;
|
||||
dvdd-3v-supply = <&fixedregulator3v3>;
|
||||
bgvdd-supply = <&fixedregulator1v8>;
|
||||
|
||||
adi,input-depth = <8>;
|
||||
adi,input-colorspace = "rgb";
|
||||
adi,input-clock = "1x";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
adv7511_in: endpoint {
|
||||
remote-endpoint = <&lvds0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
adv7511_out: endpoint {
|
||||
remote-endpoint = <&hdmi_con_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -25,6 +25,7 @@ properties:
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sc7280-cci
|
||||
- qcom,sdm845-cci
|
||||
- qcom,sm6350-cci
|
||||
- qcom,sm8250-cci
|
||||
@ -159,6 +160,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc7280-cci
|
||||
- qcom,sm8250-cci
|
||||
- qcom,sm8450-cci
|
||||
then:
|
||||
|
@ -47,6 +47,7 @@ Supported adapters:
|
||||
* Intel Alder Lake (PCH)
|
||||
* Intel Raptor Lake (PCH)
|
||||
* Intel Meteor Lake (SOC and PCH)
|
||||
* Intel Birch Stream (SOC)
|
||||
|
||||
Datasheets: Publicly available at the Intel website
|
||||
|
||||
|
@ -39,6 +39,10 @@ Also, codes returned by adapter probe methods follow rules which are
|
||||
specific to their host bus (such as PCI, or the platform bus).
|
||||
|
||||
|
||||
EAFNOSUPPORT
|
||||
Returned by I2C adapters not supporting 10 bit addresses when
|
||||
they are requested to use such an address.
|
||||
|
||||
EAGAIN
|
||||
Returned by I2C adapters when they lose arbitration in master
|
||||
transmit mode: some other master was transmitting different
|
||||
|
@ -8825,6 +8825,7 @@ F: include/linux/phy/
|
||||
GENERIC PINCTRL I2C DEMULTIPLEXER DRIVER
|
||||
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml
|
||||
F: drivers/i2c/muxes/i2c-demux-pinctrl.c
|
||||
|
||||
GENERIC PM DOMAINS
|
||||
|
@ -158,6 +158,7 @@ config I2C_I801
|
||||
Alder Lake (PCH)
|
||||
Raptor Lake (PCH)
|
||||
Meteor Lake (SOC and PCH)
|
||||
Birch Stream (SOC)
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called i2c-i801.
|
||||
|
@ -221,11 +221,10 @@ static int at91_twi_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
dev->clk = devm_clk_get(dev->dev, NULL);
|
||||
dev->clk = devm_clk_get_enabled(dev->dev, NULL);
|
||||
if (IS_ERR(dev->clk))
|
||||
return dev_err_probe(dev->dev, PTR_ERR(dev->clk), "no clock defined\n");
|
||||
|
||||
clk_prepare_enable(dev->clk);
|
||||
return dev_err_probe(dev->dev, PTR_ERR(dev->clk),
|
||||
"failed to enable clock\n");
|
||||
|
||||
snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
|
||||
i2c_set_adapdata(&dev->adapter, dev);
|
||||
@ -254,8 +253,6 @@ static int at91_twi_probe(struct platform_device *pdev)
|
||||
|
||||
rc = i2c_add_numbered_adapter(&dev->adapter);
|
||||
if (rc) {
|
||||
clk_disable_unprepare(dev->clk);
|
||||
|
||||
pm_runtime_disable(dev->dev);
|
||||
pm_runtime_set_suspended(dev->dev);
|
||||
|
||||
@ -272,7 +269,6 @@ static void at91_twi_remove(struct platform_device *pdev)
|
||||
struct at91_twi_dev *dev = platform_get_drvdata(pdev);
|
||||
|
||||
i2c_del_adapter(&dev->adapter);
|
||||
clk_disable_unprepare(dev->clk);
|
||||
|
||||
pm_runtime_disable(dev->dev);
|
||||
pm_runtime_set_suspended(dev->dev);
|
||||
|
@ -131,6 +131,8 @@
|
||||
* @i2c_clk: clock reference for i2c input clock
|
||||
* @bus_clk_rate: current i2c bus clock rate
|
||||
* @last: a flag indicating is this is last message in transfer
|
||||
* @slave: associated &i2c_client
|
||||
* @irq: platform device IRQ number
|
||||
*/
|
||||
struct axxia_i2c_dev {
|
||||
void __iomem *base;
|
||||
@ -165,7 +167,7 @@ static void i2c_int_enable(struct axxia_i2c_dev *idev, u32 mask)
|
||||
writel(int_en | mask, idev->base + MST_INT_ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* ns_to_clk - Convert time (ns) to clock cycles for the given clock frequency.
|
||||
*/
|
||||
static u32 ns_to_clk(u64 ns, u32 clk_mhz)
|
||||
@ -263,7 +265,7 @@ static int i2c_m_recv_len(const struct i2c_msg *msg)
|
||||
return (msg->flags & I2C_M_RECV_LEN) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* axxia_i2c_empty_rx_fifo - Fetch data from RX FIFO and update SMBus block
|
||||
* transfer length if this is the first byte of such a transfer.
|
||||
*/
|
||||
@ -295,7 +297,7 @@ static int axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* axxia_i2c_fill_tx_fifo - Fill TX FIFO from current message buffer.
|
||||
* @return: Number of bytes left to transfer.
|
||||
*/
|
||||
|
@ -160,6 +160,7 @@ struct brcmstb_i2c_dev {
|
||||
struct completion done;
|
||||
u32 clk_freq_hz;
|
||||
int data_regsz;
|
||||
bool atomic;
|
||||
};
|
||||
|
||||
/* register accessors for both be and le cpu arch */
|
||||
@ -240,7 +241,7 @@ static int brcmstb_i2c_wait_for_completion(struct brcmstb_i2c_dev *dev)
|
||||
int ret = 0;
|
||||
unsigned long timeout = msecs_to_jiffies(I2C_TIMEOUT);
|
||||
|
||||
if (dev->irq >= 0) {
|
||||
if (dev->irq >= 0 && !dev->atomic) {
|
||||
if (!wait_for_completion_timeout(&dev->done, timeout))
|
||||
ret = -ETIMEDOUT;
|
||||
} else {
|
||||
@ -287,7 +288,7 @@ static int brcmstb_send_i2c_cmd(struct brcmstb_i2c_dev *dev,
|
||||
return rc;
|
||||
|
||||
/* only if we are in interrupt mode */
|
||||
if (dev->irq >= 0)
|
||||
if (dev->irq >= 0 && !dev->atomic)
|
||||
reinit_completion(&dev->done);
|
||||
|
||||
/* enable BSC CTL interrupt line */
|
||||
@ -520,6 +521,23 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
|
||||
|
||||
}
|
||||
|
||||
static int brcmstb_i2c_xfer_atomic(struct i2c_adapter *adapter,
|
||||
struct i2c_msg msgs[], int num)
|
||||
{
|
||||
struct brcmstb_i2c_dev *dev = i2c_get_adapdata(adapter);
|
||||
int ret;
|
||||
|
||||
if (dev->irq >= 0)
|
||||
disable_irq(dev->irq);
|
||||
dev->atomic = true;
|
||||
ret = brcmstb_i2c_xfer(adapter, msgs, num);
|
||||
dev->atomic = false;
|
||||
if (dev->irq >= 0)
|
||||
enable_irq(dev->irq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 brcmstb_i2c_functionality(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR
|
||||
@ -528,6 +546,7 @@ static u32 brcmstb_i2c_functionality(struct i2c_adapter *adap)
|
||||
|
||||
static const struct i2c_algorithm brcmstb_i2c_algo = {
|
||||
.master_xfer = brcmstb_i2c_xfer,
|
||||
.master_xfer_atomic = brcmstb_i2c_xfer_atomic,
|
||||
.functionality = brcmstb_i2c_functionality,
|
||||
};
|
||||
|
||||
|
@ -298,7 +298,7 @@ cp2615_i2c_probe(struct usb_interface *usbif, const struct usb_device_id *id)
|
||||
if (!adap)
|
||||
return -ENOMEM;
|
||||
|
||||
strncpy(adap->name, usbdev->serial, sizeof(adap->name) - 1);
|
||||
strscpy(adap->name, usbdev->serial, sizeof(adap->name));
|
||||
adap->owner = THIS_MODULE;
|
||||
adap->dev.parent = &usbif->dev;
|
||||
adap->dev.of_node = usbif->dev.of_node;
|
||||
|
@ -194,6 +194,11 @@ struct exynos5_i2c {
|
||||
*/
|
||||
int trans_done;
|
||||
|
||||
/*
|
||||
* Called from atomic context, don't use interrupts.
|
||||
*/
|
||||
unsigned int atomic;
|
||||
|
||||
/* Controller operating frequency */
|
||||
unsigned int op_clock;
|
||||
|
||||
@ -265,7 +270,7 @@ static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
|
||||
* exynos5_i2c_set_timing: updates the registers with appropriate
|
||||
* timing values calculated
|
||||
*
|
||||
* Timing values for operation are calculated against either 100kHz
|
||||
* Timing values for operation are calculated against 100kHz, 400kHz
|
||||
* or 1MHz controller operating frequency.
|
||||
*
|
||||
* Returns 0 on success, -EINVAL if the cycle length cannot
|
||||
@ -328,6 +333,23 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
|
||||
*
|
||||
* Constraints: 4 <= temp, 0 <= CLK_DIV < 256, 2 <= clk_cycle <= 510
|
||||
*
|
||||
* To split SCL clock into low, high periods appropriately, one
|
||||
* proportion factor for each I2C mode is used, which is calculated
|
||||
* using this formula.
|
||||
* ```
|
||||
* ((t_low_min + (scl_clock - t_low_min - t_high_min) / 2) / scl_clock)
|
||||
* ```
|
||||
* where:
|
||||
* t_low_min is the minimal value of low period of the SCL clock in us;
|
||||
* t_high_min is the minimal value of high period of the SCL clock in us;
|
||||
* scl_clock is converted from SCL clock frequency into us.
|
||||
*
|
||||
* Below are the proportion factors for these I2C modes:
|
||||
* t_low_min, t_high_min, scl_clock, proportion
|
||||
* Standard Mode: 4.7us, 4.0us, 10us, 0.535
|
||||
* Fast Mode: 1.3us, 0.6us, 2.5us, 0.64
|
||||
* Fast-Plus Mode: 0.5us, 0.26us, 1us, 0.62
|
||||
*
|
||||
*/
|
||||
t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7;
|
||||
temp = clkin / op_clk - 8 - t_ftl_cycle;
|
||||
@ -341,8 +363,19 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
t_scl_l = clk_cycle / 2;
|
||||
t_scl_h = clk_cycle / 2;
|
||||
/*
|
||||
* Scale clk_cycle to get t_scl_l using the proption factors for individual I2C modes.
|
||||
*/
|
||||
if (op_clk <= I2C_MAX_STANDARD_MODE_FREQ)
|
||||
t_scl_l = clk_cycle * 535 / 1000;
|
||||
else if (op_clk <= I2C_MAX_FAST_MODE_FREQ)
|
||||
t_scl_l = clk_cycle * 64 / 100;
|
||||
else
|
||||
t_scl_l = clk_cycle * 62 / 100;
|
||||
|
||||
if (t_scl_l > 0xFF)
|
||||
t_scl_l = 0xFF;
|
||||
t_scl_h = clk_cycle - t_scl_l;
|
||||
t_start_su = t_scl_l;
|
||||
t_start_hd = t_scl_l;
|
||||
t_stop_su = t_scl_l;
|
||||
@ -711,6 +744,22 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
|
||||
spin_unlock_irqrestore(&i2c->lock, flags);
|
||||
}
|
||||
|
||||
static bool exynos5_i2c_poll_irqs_timeout(struct exynos5_i2c *i2c,
|
||||
unsigned long timeout)
|
||||
{
|
||||
unsigned long time_left = jiffies + timeout;
|
||||
|
||||
while (time_before(jiffies, time_left) &&
|
||||
!((i2c->trans_done && (i2c->msg->len == i2c->msg_ptr)) ||
|
||||
(i2c->state < 0))) {
|
||||
while (readl(i2c->regs + HSI2C_INT_ENABLE) &
|
||||
readl(i2c->regs + HSI2C_INT_STATUS))
|
||||
exynos5_i2c_irq(i2c->irq, i2c);
|
||||
usleep_range(100, 200);
|
||||
}
|
||||
return time_before(jiffies, time_left);
|
||||
}
|
||||
|
||||
static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c,
|
||||
struct i2c_msg *msgs, int stop)
|
||||
{
|
||||
@ -725,8 +774,13 @@ static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c,
|
||||
|
||||
exynos5_i2c_message_start(i2c, stop);
|
||||
|
||||
timeout = wait_for_completion_timeout(&i2c->msg_complete,
|
||||
EXYNOS5_I2C_TIMEOUT);
|
||||
if (!i2c->atomic)
|
||||
timeout = wait_for_completion_timeout(&i2c->msg_complete,
|
||||
EXYNOS5_I2C_TIMEOUT);
|
||||
else
|
||||
timeout = exynos5_i2c_poll_irqs_timeout(i2c,
|
||||
EXYNOS5_I2C_TIMEOUT);
|
||||
|
||||
if (timeout == 0)
|
||||
ret = -ETIMEDOUT;
|
||||
else
|
||||
@ -777,6 +831,21 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
|
||||
return ret ?: num;
|
||||
}
|
||||
|
||||
static int exynos5_i2c_xfer_atomic(struct i2c_adapter *adap,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct exynos5_i2c *i2c = adap->algo_data;
|
||||
int ret;
|
||||
|
||||
disable_irq(i2c->irq);
|
||||
i2c->atomic = true;
|
||||
ret = exynos5_i2c_xfer(adap, msgs, num);
|
||||
i2c->atomic = false;
|
||||
enable_irq(i2c->irq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 exynos5_i2c_func(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
|
||||
@ -784,6 +853,7 @@ static u32 exynos5_i2c_func(struct i2c_adapter *adap)
|
||||
|
||||
static const struct i2c_algorithm exynos5_i2c_algorithm = {
|
||||
.master_xfer = exynos5_i2c_xfer,
|
||||
.master_xfer_atomic = exynos5_i2c_xfer_atomic,
|
||||
.functionality = exynos5_i2c_func,
|
||||
};
|
||||
|
||||
|
@ -263,15 +263,10 @@ static void i2c_gpio_fault_injector_init(struct platform_device *pdev)
|
||||
* 'fault-injector' dir there. Until then, we have a global dir with
|
||||
* all adapters as subdirs.
|
||||
*/
|
||||
if (!i2c_gpio_debug_dir) {
|
||||
if (!i2c_gpio_debug_dir)
|
||||
i2c_gpio_debug_dir = debugfs_create_dir("i2c-fault-injector", NULL);
|
||||
if (!i2c_gpio_debug_dir)
|
||||
return;
|
||||
}
|
||||
|
||||
priv->debug_dir = debugfs_create_dir(pdev->name, i2c_gpio_debug_dir);
|
||||
if (!priv->debug_dir)
|
||||
return;
|
||||
|
||||
init_completion(&priv->scl_irq_completion);
|
||||
|
||||
|
@ -79,6 +79,7 @@
|
||||
* Meteor Lake-P (SOC) 0x7e22 32 hard yes yes yes
|
||||
* Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes
|
||||
* Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes
|
||||
* Birch Stream (SOC) 0x5796 32 hard yes yes yes
|
||||
*
|
||||
* Features supported by this driver:
|
||||
* Software PEC no
|
||||
@ -231,6 +232,7 @@
|
||||
#define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3
|
||||
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3
|
||||
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3
|
||||
#define PCI_DEVICE_ID_INTEL_BIRCH_STREAM_SMBUS 0x5796
|
||||
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
|
||||
#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23
|
||||
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3
|
||||
@ -285,7 +287,6 @@ struct i801_priv {
|
||||
u8 *data;
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
|
||||
const struct i801_mux_config *mux_drvdata;
|
||||
struct platform_device *mux_pdev;
|
||||
struct gpiod_lookup_table *lookup;
|
||||
#endif
|
||||
@ -293,10 +294,9 @@ struct i801_priv {
|
||||
|
||||
/*
|
||||
* If set to true the host controller registers are reserved for
|
||||
* ACPI AML use. Protected by acpi_lock.
|
||||
* ACPI AML use.
|
||||
*/
|
||||
bool acpi_reserved;
|
||||
struct mutex acpi_lock;
|
||||
};
|
||||
|
||||
#define FEATURE_SMBUS_PEC BIT(0)
|
||||
@ -679,15 +679,11 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
|
||||
return result ? priv->status : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (len == 1 && read_write == I2C_SMBUS_READ)
|
||||
smbcmd |= SMBHSTCNT_LAST_BYTE;
|
||||
outb_p(smbcmd | SMBHSTCNT_START, SMBHSTCNT(priv));
|
||||
|
||||
for (i = 1; i <= len; i++) {
|
||||
if (i == len && read_write == I2C_SMBUS_READ)
|
||||
smbcmd |= SMBHSTCNT_LAST_BYTE;
|
||||
outb_p(smbcmd, SMBHSTCNT(priv));
|
||||
|
||||
if (i == 1)
|
||||
outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START,
|
||||
SMBHSTCNT(priv));
|
||||
|
||||
status = i801_wait_byte_done(priv);
|
||||
if (status)
|
||||
return status;
|
||||
@ -710,9 +706,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
|
||||
data->block[0] = len;
|
||||
}
|
||||
|
||||
/* Retrieve/store value in SMBBLKDAT */
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
if (read_write == I2C_SMBUS_READ) {
|
||||
data->block[i] = inb_p(SMBBLKDAT(priv));
|
||||
if (i == len - 1)
|
||||
outb_p(smbcmd | SMBHSTCNT_LAST_BYTE, SMBHSTCNT(priv));
|
||||
}
|
||||
|
||||
if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
|
||||
outb_p(data->block[i+1], SMBBLKDAT(priv));
|
||||
|
||||
@ -875,11 +874,8 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
|
||||
int hwpec, ret;
|
||||
struct i801_priv *priv = i2c_get_adapdata(adap);
|
||||
|
||||
mutex_lock(&priv->acpi_lock);
|
||||
if (priv->acpi_reserved) {
|
||||
mutex_unlock(&priv->acpi_lock);
|
||||
if (priv->acpi_reserved)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(&priv->pci_dev->dev);
|
||||
|
||||
@ -920,7 +916,6 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
|
||||
|
||||
pm_runtime_mark_last_busy(&priv->pci_dev->dev);
|
||||
pm_runtime_put_autosuspend(&priv->pci_dev->dev);
|
||||
mutex_unlock(&priv->acpi_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1044,6 +1039,7 @@ static const struct pci_device_id i801_ids[] = {
|
||||
{ PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
||||
{ PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
||||
{ PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
||||
{ PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
@ -1288,7 +1284,7 @@ static void i801_probe_optional_slaves(struct i801_priv *priv)
|
||||
|
||||
/* Instantiate SPD EEPROMs unless the SMBus is multiplexed */
|
||||
#if IS_ENABLED(CONFIG_I2C_MUX_GPIO)
|
||||
if (!priv->mux_drvdata)
|
||||
if (!priv->mux_pdev)
|
||||
#endif
|
||||
i2c_register_spd(&priv->adapter);
|
||||
}
|
||||
@ -1390,11 +1386,14 @@ static void i801_add_mux(struct i801_priv *priv)
|
||||
const struct i801_mux_config *mux_config;
|
||||
struct i2c_mux_gpio_platform_data gpio_data;
|
||||
struct gpiod_lookup_table *lookup;
|
||||
const struct dmi_system_id *id;
|
||||
int i;
|
||||
|
||||
if (!priv->mux_drvdata)
|
||||
id = dmi_first_match(mux_dmi_table);
|
||||
if (!id)
|
||||
return;
|
||||
mux_config = priv->mux_drvdata;
|
||||
|
||||
mux_config = id->driver_data;
|
||||
|
||||
/* Prepare the platform data */
|
||||
memset(&gpio_data, 0, sizeof(struct i2c_mux_gpio_platform_data));
|
||||
@ -1438,35 +1437,9 @@ static void i801_del_mux(struct i801_priv *priv)
|
||||
platform_device_unregister(priv->mux_pdev);
|
||||
gpiod_remove_lookup_table(priv->lookup);
|
||||
}
|
||||
|
||||
static unsigned int i801_get_adapter_class(struct i801_priv *priv)
|
||||
{
|
||||
const struct dmi_system_id *id;
|
||||
const struct i801_mux_config *mux_config;
|
||||
unsigned int class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
int i;
|
||||
|
||||
id = dmi_first_match(mux_dmi_table);
|
||||
if (id) {
|
||||
/* Remove branch classes from trunk */
|
||||
mux_config = id->driver_data;
|
||||
for (i = 0; i < mux_config->n_values; i++)
|
||||
class &= ~mux_config->classes[i];
|
||||
|
||||
/* Remember for later */
|
||||
priv->mux_drvdata = mux_config;
|
||||
}
|
||||
|
||||
return class;
|
||||
}
|
||||
#else
|
||||
static inline void i801_add_mux(struct i801_priv *priv) { }
|
||||
static inline void i801_del_mux(struct i801_priv *priv) { }
|
||||
|
||||
static inline unsigned int i801_get_adapter_class(struct i801_priv *priv)
|
||||
{
|
||||
return I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct platform_device *
|
||||
@ -1572,7 +1545,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
|
||||
* further access from the driver itself. This device is now owned
|
||||
* by the system firmware.
|
||||
*/
|
||||
mutex_lock(&priv->acpi_lock);
|
||||
i2c_lock_bus(&priv->adapter, I2C_LOCK_SEGMENT);
|
||||
|
||||
if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) {
|
||||
priv->acpi_reserved = true;
|
||||
@ -1592,7 +1565,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
|
||||
else
|
||||
status = acpi_os_write_port(address, (u32)*value, bits);
|
||||
|
||||
mutex_unlock(&priv->acpi_lock);
|
||||
i2c_unlock_bus(&priv->adapter, I2C_LOCK_SEGMENT);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1630,6 +1603,12 @@ static void i801_setup_hstcfg(struct i801_priv *priv)
|
||||
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg);
|
||||
}
|
||||
|
||||
static void i801_restore_regs(struct i801_priv *priv)
|
||||
{
|
||||
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
|
||||
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg);
|
||||
}
|
||||
|
||||
static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
int err, i;
|
||||
@ -1641,12 +1620,11 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
|
||||
i2c_set_adapdata(&priv->adapter, priv);
|
||||
priv->adapter.owner = THIS_MODULE;
|
||||
priv->adapter.class = i801_get_adapter_class(priv);
|
||||
priv->adapter.class = I2C_CLASS_HWMON;
|
||||
priv->adapter.algo = &smbus_algorithm;
|
||||
priv->adapter.dev.parent = &dev->dev;
|
||||
ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&dev->dev));
|
||||
acpi_use_parent_companion(&priv->adapter.dev);
|
||||
priv->adapter.retries = 3;
|
||||
mutex_init(&priv->acpi_lock);
|
||||
|
||||
priv->pci_dev = dev;
|
||||
priv->features = id->driver_data;
|
||||
@ -1756,6 +1734,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
if (err) {
|
||||
platform_device_unregister(priv->tco_pdev);
|
||||
i801_acpi_remove(priv);
|
||||
i801_restore_regs(priv);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1780,12 +1759,10 @@ static void i801_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct i801_priv *priv = pci_get_drvdata(dev);
|
||||
|
||||
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
|
||||
i801_disable_host_notify(priv);
|
||||
i801_del_mux(priv);
|
||||
i2c_del_adapter(&priv->adapter);
|
||||
i801_acpi_remove(priv);
|
||||
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
|
||||
|
||||
platform_device_unregister(priv->tco_pdev);
|
||||
|
||||
@ -1793,6 +1770,8 @@ static void i801_remove(struct pci_dev *dev)
|
||||
if (!priv->acpi_reserved)
|
||||
pm_runtime_get_noresume(&dev->dev);
|
||||
|
||||
i801_restore_regs(priv);
|
||||
|
||||
/*
|
||||
* do not call pci_disable_device(dev) since it can cause hard hangs on
|
||||
* some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
|
||||
@ -1803,18 +1782,18 @@ static void i801_shutdown(struct pci_dev *dev)
|
||||
{
|
||||
struct i801_priv *priv = pci_get_drvdata(dev);
|
||||
|
||||
/* Restore config registers to avoid hard hang on some systems */
|
||||
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
|
||||
i801_disable_host_notify(priv);
|
||||
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
|
||||
/* Restore config registers to avoid hard hang on some systems */
|
||||
i801_restore_regs(priv);
|
||||
}
|
||||
|
||||
static int i801_suspend(struct device *dev)
|
||||
{
|
||||
struct i801_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
|
||||
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg);
|
||||
i2c_mark_adapter_suspended(&priv->adapter);
|
||||
i801_restore_regs(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1824,6 +1803,7 @@ static int i801_resume(struct device *dev)
|
||||
|
||||
i801_setup_hstcfg(priv);
|
||||
i801_enable_host_notify(&priv->adapter);
|
||||
i2c_mark_adapter_resumed(&priv->adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1842,16 +1822,11 @@ static struct pci_driver i801_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init i2c_i801_init(void)
|
||||
static int __init i2c_i801_init(struct pci_driver *drv)
|
||||
{
|
||||
if (dmi_name_in_vendors("FUJITSU"))
|
||||
input_apanel_init();
|
||||
return pci_register_driver(&i801_driver);
|
||||
}
|
||||
|
||||
static void __exit i2c_i801_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&i801_driver);
|
||||
return pci_register_driver(drv);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
|
||||
@ -1859,5 +1834,4 @@ MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
|
||||
MODULE_DESCRIPTION("I801 SMBus driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(i2c_i801_init);
|
||||
module_exit(i2c_i801_exit);
|
||||
module_driver(i801_driver, i2c_i801_init, pci_unregister_driver);
|
||||
|
@ -1442,15 +1442,19 @@ static int mtk_i2c_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk))
|
||||
return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk);
|
||||
|
||||
i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get_optional(&pdev->dev, "pmic");
|
||||
if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) {
|
||||
dev_err(&pdev->dev, "cannot get pmic clock\n");
|
||||
return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk);
|
||||
}
|
||||
|
||||
if (i2c->have_pmic) {
|
||||
i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get(&pdev->dev, "pmic");
|
||||
if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) {
|
||||
if (!i2c->clocks[I2C_MT65XX_CLK_PMIC].clk) {
|
||||
dev_err(&pdev->dev, "cannot get pmic clock\n");
|
||||
return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk);
|
||||
return -ENODEV;
|
||||
}
|
||||
speed_clk = I2C_MT65XX_CLK_PMIC;
|
||||
} else {
|
||||
i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = NULL;
|
||||
speed_clk = I2C_MT65XX_CLK_MAIN;
|
||||
}
|
||||
|
||||
|
@ -19,11 +19,10 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
@ -859,7 +858,7 @@ static int
|
||||
mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
|
||||
struct device *dev)
|
||||
{
|
||||
const struct of_device_id *device;
|
||||
const struct mv64xxx_i2c_regs *data;
|
||||
struct device_node *np = dev->of_node;
|
||||
u32 bus_freq, tclk;
|
||||
int rc = 0;
|
||||
@ -897,11 +896,11 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
|
||||
*/
|
||||
drv_data->adapter.timeout = HZ;
|
||||
|
||||
device = of_match_device(mv64xxx_i2c_of_match_table, dev);
|
||||
if (!device)
|
||||
data = device_get_match_data(dev);
|
||||
if (!data)
|
||||
return -ENODEV;
|
||||
|
||||
memcpy(&drv_data->reg_offsets, device->data, sizeof(drv_data->reg_offsets));
|
||||
memcpy(&drv_data->reg_offsets, data, sizeof(drv_data->reg_offsets));
|
||||
|
||||
/*
|
||||
* For controllers embedded in new SoCs activate the
|
||||
|
@ -25,11 +25,11 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
/* I2C controller revisions */
|
||||
#define OMAP_I2C_OMAP1_REV_2 0x20
|
||||
@ -1358,7 +1358,6 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||
const struct omap_i2c_bus_platform_data *pdata =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
int irq;
|
||||
int r;
|
||||
u32 rev;
|
||||
@ -1376,11 +1375,10 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(omap->base))
|
||||
return PTR_ERR(omap->base);
|
||||
|
||||
match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev);
|
||||
if (match) {
|
||||
if (pdev->dev.of_node) {
|
||||
u32 freq = I2C_MAX_STANDARD_MODE_FREQ;
|
||||
|
||||
pdata = match->data;
|
||||
pdata = device_get_match_data(&pdev->dev);
|
||||
omap->flags = pdata->flags;
|
||||
|
||||
of_property_read_u32(node, "clock-frequency", &freq);
|
||||
|
@ -231,7 +231,7 @@ static void i2c_powermac_create_one(struct i2c_adapter *adap,
|
||||
struct i2c_board_info info = {};
|
||||
struct i2c_client *newdev;
|
||||
|
||||
strncpy(info.type, type, sizeof(info.type));
|
||||
strscpy(info.type, type, sizeof(info.type));
|
||||
info.addr = addr;
|
||||
newdev = i2c_new_client_device(adap, &info);
|
||||
if (IS_ERR(newdev))
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/i2c-pxa.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* I2C register field definitions */
|
||||
@ -1252,10 +1253,8 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
|
||||
enum pxa_i2c_types *i2c_types)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(i2c_pxa_dt_ids, &pdev->dev);
|
||||
|
||||
if (!of_id)
|
||||
if (!pdev->dev.of_node)
|
||||
return 1;
|
||||
|
||||
/* For device tree we always use the dynamic or alias-assigned ID */
|
||||
@ -1264,7 +1263,7 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
|
||||
i2c->use_pio = of_property_read_bool(np, "mrvl,i2c-polling");
|
||||
i2c->fast_mode = of_property_read_bool(np, "mrvl,i2c-fast-mode");
|
||||
|
||||
*i2c_types = (enum pxa_i2c_types)(of_id->data);
|
||||
*i2c_types = (enum pxa_i2c_types)device_get_match_data(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -722,6 +722,7 @@ static const struct i2c_algorithm geni_i2c_algo = {
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id geni_i2c_acpi_match[] = {
|
||||
{ "QCOM0220"},
|
||||
{ "QCOM0411" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, geni_i2c_acpi_match);
|
||||
|
@ -41,6 +41,10 @@
|
||||
#define ICSAR 0x1C /* slave address */
|
||||
#define ICMAR 0x20 /* master address */
|
||||
#define ICRXTX 0x24 /* data port */
|
||||
#define ICCCR2 0x28 /* Clock control 2 */
|
||||
#define ICMPR 0x2C /* SCL mask control */
|
||||
#define ICHPR 0x30 /* SCL HIGH control */
|
||||
#define ICLPR 0x34 /* SCL LOW control */
|
||||
#define ICFBSCR 0x38 /* first bit setup cycle (Gen3) */
|
||||
#define ICDMAER 0x3c /* DMA enable (Gen3) */
|
||||
|
||||
@ -84,11 +88,25 @@
|
||||
#define RMDMAE BIT(1) /* DMA Master Received Enable */
|
||||
#define TMDMAE BIT(0) /* DMA Master Transmitted Enable */
|
||||
|
||||
/* ICCCR2 */
|
||||
#define CDFD BIT(2) /* CDF Disable */
|
||||
#define HLSE BIT(1) /* HIGH/LOW Separate Control Enable */
|
||||
#define SME BIT(0) /* SCL Mask Enable */
|
||||
|
||||
/* ICFBSCR */
|
||||
#define TCYC17 0x0f /* 17*Tcyc delay 1st bit between SDA and SCL */
|
||||
|
||||
#define RCAR_MIN_DMA_LEN 8
|
||||
|
||||
/* SCL low/high ratio 5:4 to meet all I2C timing specs (incl safety margin) */
|
||||
#define RCAR_SCLD_RATIO 5
|
||||
#define RCAR_SCHD_RATIO 4
|
||||
/*
|
||||
* SMD should be smaller than SCLD/SCHD and is always around 20 in the docs.
|
||||
* Thus, we simply use 20 which works for low and high speeds.
|
||||
*/
|
||||
#define RCAR_DEFAULT_SMD 20
|
||||
|
||||
#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
|
||||
#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
|
||||
#define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB)
|
||||
@ -128,6 +146,8 @@ struct rcar_i2c_priv {
|
||||
|
||||
int pos;
|
||||
u32 icccr;
|
||||
u16 schd;
|
||||
u16 scld;
|
||||
u8 recovery_icmcr; /* protected by adapter lock */
|
||||
enum rcar_i2c_type devtype;
|
||||
struct i2c_client *slave;
|
||||
@ -216,11 +236,16 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
|
||||
rcar_i2c_write(priv, ICMCR, MDBS);
|
||||
rcar_i2c_write(priv, ICMSR, 0);
|
||||
/* start clock */
|
||||
rcar_i2c_write(priv, ICCCR, priv->icccr);
|
||||
|
||||
if (priv->devtype == I2C_RCAR_GEN3)
|
||||
if (priv->devtype < I2C_RCAR_GEN3) {
|
||||
rcar_i2c_write(priv, ICCCR, priv->icccr);
|
||||
} else {
|
||||
rcar_i2c_write(priv, ICCCR2, CDFD | HLSE | SME);
|
||||
rcar_i2c_write(priv, ICCCR, priv->icccr);
|
||||
rcar_i2c_write(priv, ICMPR, RCAR_DEFAULT_SMD);
|
||||
rcar_i2c_write(priv, ICHPR, priv->schd);
|
||||
rcar_i2c_write(priv, ICLPR, priv->scld);
|
||||
rcar_i2c_write(priv, ICFBSCR, TCYC17);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
|
||||
@ -241,7 +266,7 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
|
||||
|
||||
static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
|
||||
{
|
||||
u32 scgd, cdf, round, ick, sum, scl, cdf_width;
|
||||
u32 cdf, round, ick, sum, scl, cdf_width;
|
||||
unsigned long rate;
|
||||
struct device *dev = rcar_i2c_priv_to_dev(priv);
|
||||
struct i2c_timings t = {
|
||||
@ -254,27 +279,17 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
|
||||
/* Fall back to previously used values if not supplied */
|
||||
i2c_parse_fw_timings(dev, &t, false);
|
||||
|
||||
switch (priv->devtype) {
|
||||
case I2C_RCAR_GEN1:
|
||||
cdf_width = 2;
|
||||
break;
|
||||
case I2C_RCAR_GEN2:
|
||||
case I2C_RCAR_GEN3:
|
||||
cdf_width = 3;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "device type error\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate SCL clock
|
||||
* see
|
||||
* ICCCR
|
||||
* ICCCR (and ICCCR2 for Gen3+)
|
||||
*
|
||||
* ick = clkp / (1 + CDF)
|
||||
* SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
|
||||
*
|
||||
* for Gen3+:
|
||||
* SCL = clkp / (8 + SMD * 2 + SCLD + SCHD +F[(ticf + tr + intd) * clkp])
|
||||
*
|
||||
* ick : I2C internal clock < 20 MHz
|
||||
* ticf : I2C SCL falling time
|
||||
* tr : I2C SCL rising time
|
||||
@ -284,52 +299,82 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
|
||||
*/
|
||||
rate = clk_get_rate(priv->clk);
|
||||
cdf = rate / 20000000;
|
||||
if (cdf >= 1U << cdf_width) {
|
||||
dev_err(dev, "Input clock %lu too high\n", rate);
|
||||
return -EIO;
|
||||
}
|
||||
ick = rate / (cdf + 1);
|
||||
cdf_width = (priv->devtype == I2C_RCAR_GEN1) ? 2 : 3;
|
||||
if (cdf >= 1U << cdf_width)
|
||||
goto err_no_val;
|
||||
|
||||
/* On Gen3+, we use cdf only for the filters, not as a SCL divider */
|
||||
ick = rate / (priv->devtype < I2C_RCAR_GEN3 ? (cdf + 1) : 1);
|
||||
|
||||
/*
|
||||
* it is impossible to calculate large scale
|
||||
* number on u32. separate it
|
||||
* It is impossible to calculate a large scale number on u32. Separate it.
|
||||
*
|
||||
* F[(ticf + tr + intd) * ick] with sum = (ticf + tr + intd)
|
||||
* = F[sum * ick / 1000000000]
|
||||
* = F[(ick / 1000000) * sum / 1000]
|
||||
*/
|
||||
sum = t.scl_fall_ns + t.scl_rise_ns + t.scl_int_delay_ns;
|
||||
round = (ick + 500000) / 1000000 * sum;
|
||||
round = (round + 500) / 1000;
|
||||
round = DIV_ROUND_CLOSEST(ick, 1000000);
|
||||
round = DIV_ROUND_CLOSEST(round * sum, 1000);
|
||||
|
||||
/*
|
||||
* SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
|
||||
*
|
||||
* Calculation result (= SCL) should be less than
|
||||
* bus_speed for hardware safety
|
||||
*
|
||||
* We could use something along the lines of
|
||||
* div = ick / (bus_speed + 1) + 1;
|
||||
* scgd = (div - 20 - round + 7) / 8;
|
||||
* scl = ick / (20 + (scgd * 8) + round);
|
||||
* (not fully verified) but that would get pretty involved
|
||||
*/
|
||||
for (scgd = 0; scgd < 0x40; scgd++) {
|
||||
scl = ick / (20 + (scgd * 8) + round);
|
||||
if (scl <= t.bus_freq_hz)
|
||||
goto scgd_find;
|
||||
if (priv->devtype < I2C_RCAR_GEN3) {
|
||||
u32 scgd;
|
||||
/*
|
||||
* SCL = ick / (20 + 8 * SCGD + F[(ticf + tr + intd) * ick])
|
||||
* 20 + 8 * SCGD + F[...] = ick / SCL
|
||||
* SCGD = ((ick / SCL) - 20 - F[...]) / 8
|
||||
* Result (= SCL) should be less than bus_speed for hardware safety
|
||||
*/
|
||||
scgd = DIV_ROUND_UP(ick, t.bus_freq_hz ?: 1);
|
||||
scgd = DIV_ROUND_UP(scgd - 20 - round, 8);
|
||||
scl = ick / (20 + 8 * scgd + round);
|
||||
|
||||
if (scgd > 0x3f)
|
||||
goto err_no_val;
|
||||
|
||||
dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u, SCGD: %u\n",
|
||||
scl, t.bus_freq_hz, rate, round, cdf, scgd);
|
||||
|
||||
priv->icccr = scgd << cdf_width | cdf;
|
||||
} else {
|
||||
u32 x, sum_ratio = RCAR_SCHD_RATIO + RCAR_SCLD_RATIO;
|
||||
/*
|
||||
* SCLD/SCHD ratio and SMD default value are explained above
|
||||
* where they are defined. With these definitions, we can compute
|
||||
* x as a base value for the SCLD/SCHD ratio:
|
||||
*
|
||||
* SCL = clkp / (8 + 2 * SMD + SCLD + SCHD + F[(ticf + tr + intd) * clkp])
|
||||
* SCL = clkp / (8 + 2 * RCAR_DEFAULT_SMD + RCAR_SCLD_RATIO * x
|
||||
* + RCAR_SCHD_RATIO * x + F[...])
|
||||
*
|
||||
* with: sum_ratio = RCAR_SCLD_RATIO + RCAR_SCHD_RATIO
|
||||
* and: smd = RCAR_DEFAULT_SMD
|
||||
*
|
||||
* SCL = clkp / (8 + 2 * smd + sum_ratio * x + F[...])
|
||||
* 8 + 2 * smd + sum_ratio * x + F[...] = clkp / SCL
|
||||
* x = ((clkp / SCL) - 8 - 2 * smd - F[...]) / sum_ratio
|
||||
*/
|
||||
x = DIV_ROUND_UP(rate, t.bus_freq_hz ?: 1);
|
||||
x = DIV_ROUND_UP(x - 8 - 2 * RCAR_DEFAULT_SMD - round, sum_ratio);
|
||||
scl = rate / (8 + 2 * RCAR_DEFAULT_SMD + sum_ratio * x + round);
|
||||
|
||||
/* Bail out if values don't fit into 16 bit or SMD became too large */
|
||||
if (x * RCAR_SCLD_RATIO > 0xffff || RCAR_DEFAULT_SMD > x * RCAR_SCHD_RATIO)
|
||||
goto err_no_val;
|
||||
|
||||
priv->icccr = cdf;
|
||||
priv->schd = RCAR_SCHD_RATIO * x;
|
||||
priv->scld = RCAR_SCLD_RATIO * x;
|
||||
|
||||
dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u SCHD %u SCLD %u\n",
|
||||
scl, t.bus_freq_hz, rate, round, cdf, priv->schd, priv->scld);
|
||||
}
|
||||
dev_err(dev, "it is impossible to calculate best SCL\n");
|
||||
return -EIO;
|
||||
|
||||
scgd_find:
|
||||
dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n",
|
||||
scl, t.bus_freq_hz, rate, round, cdf, scgd);
|
||||
|
||||
/* keep icccr value */
|
||||
priv->icccr = scgd << cdf_width | cdf;
|
||||
|
||||
return 0;
|
||||
|
||||
err_no_val:
|
||||
dev_err(dev, "it is impossible to calculate best SCL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -843,12 +888,10 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
|
||||
|
||||
/* Gen3 needs a reset before allowing RXDMA once */
|
||||
if (priv->devtype == I2C_RCAR_GEN3) {
|
||||
priv->flags |= ID_P_NO_RXDMA;
|
||||
if (!IS_ERR(priv->rstc)) {
|
||||
ret = rcar_i2c_do_reset(priv);
|
||||
if (ret == 0)
|
||||
priv->flags &= ~ID_P_NO_RXDMA;
|
||||
}
|
||||
priv->flags &= ~ID_P_NO_RXDMA;
|
||||
ret = rcar_i2c_do_reset(priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rcar_i2c_init(priv);
|
||||
@ -1099,15 +1142,6 @@ static int rcar_i2c_probe(struct platform_device *pdev)
|
||||
irqhandler = rcar_i2c_gen2_irq;
|
||||
}
|
||||
|
||||
if (priv->devtype == I2C_RCAR_GEN3) {
|
||||
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (!IS_ERR(priv->rstc)) {
|
||||
ret = reset_control_status(priv->rstc);
|
||||
if (ret < 0)
|
||||
priv->rstc = ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stay always active when multi-master to keep arbitration working */
|
||||
if (of_property_read_bool(dev->of_node, "multi-master"))
|
||||
priv->flags |= ID_P_PM_BLOCKED;
|
||||
@ -1117,6 +1151,18 @@ static int rcar_i2c_probe(struct platform_device *pdev)
|
||||
if (of_property_read_bool(dev->of_node, "smbus"))
|
||||
priv->flags |= ID_P_HOST_NOTIFY;
|
||||
|
||||
if (priv->devtype == I2C_RCAR_GEN3) {
|
||||
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->rstc)) {
|
||||
ret = PTR_ERR(priv->rstc);
|
||||
goto out_pm_put;
|
||||
}
|
||||
|
||||
ret = reset_control_status(priv->rstc);
|
||||
if (ret < 0)
|
||||
goto out_pm_put;
|
||||
}
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
goto out_pm_put;
|
||||
|
@ -313,7 +313,7 @@ static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
|
||||
* frequency with only 62 clock ticks max (31 high, 31 low).
|
||||
* Aim for a duty of 60% LOW, 40% HIGH.
|
||||
*/
|
||||
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz);
|
||||
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz ?: 1);
|
||||
|
||||
for (cks = 0; cks < 7; cks++) {
|
||||
/*
|
||||
|
@ -133,7 +133,7 @@ static const struct platform_device_id s3c24xx_driver_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
|
||||
|
||||
static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat);
|
||||
static void i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id s3c24xx_i2c_match[] = {
|
||||
@ -377,11 +377,10 @@ static inline int is_msgend(struct s3c24xx_i2c *i2c)
|
||||
/*
|
||||
* process an interrupt and work out what to do
|
||||
*/
|
||||
static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
|
||||
static void i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
|
||||
{
|
||||
unsigned long tmp;
|
||||
unsigned char byte;
|
||||
int ret = 0;
|
||||
|
||||
switch (i2c->state) {
|
||||
|
||||
@ -544,7 +543,7 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
|
||||
tmp &= ~S3C2410_IICCON_IRQPEND;
|
||||
writel(tmp, i2c->regs + S3C2410_IICCON);
|
||||
out:
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -783,23 +783,17 @@ static int stm32f4_i2c_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
i2c_dev->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(i2c_dev->clk)) {
|
||||
dev_err(&pdev->dev, "Error: Missing controller clock\n");
|
||||
dev_err(&pdev->dev, "Failed to enable clock\n");
|
||||
return PTR_ERR(i2c_dev->clk);
|
||||
}
|
||||
ret = clk_prepare_enable(i2c_dev->clk);
|
||||
if (ret) {
|
||||
dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(rst)) {
|
||||
ret = dev_err_probe(&pdev->dev, PTR_ERR(rst),
|
||||
"Error: Missing reset ctrl\n");
|
||||
goto clk_free;
|
||||
}
|
||||
if (IS_ERR(rst))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(rst),
|
||||
"Error: Missing reset ctrl\n");
|
||||
|
||||
reset_control_assert(rst);
|
||||
udelay(2);
|
||||
reset_control_deassert(rst);
|
||||
@ -816,7 +810,7 @@ static int stm32f4_i2c_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq event %i\n",
|
||||
irq_event);
|
||||
goto clk_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq_error, stm32f4_i2c_isr_error, 0,
|
||||
@ -824,12 +818,12 @@ static int stm32f4_i2c_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq error %i\n",
|
||||
irq_error);
|
||||
goto clk_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = stm32f4_i2c_hw_config(i2c_dev);
|
||||
if (ret)
|
||||
goto clk_free;
|
||||
return ret;
|
||||
|
||||
adap = &i2c_dev->adap;
|
||||
i2c_set_adapdata(adap, i2c_dev);
|
||||
@ -845,7 +839,7 @@ static int stm32f4_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
ret = i2c_add_adapter(adap);
|
||||
if (ret)
|
||||
goto clk_free;
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, i2c_dev);
|
||||
|
||||
@ -854,10 +848,6 @@ static int stm32f4_i2c_probe(struct platform_device *pdev)
|
||||
dev_info(i2c_dev->dev, "STM32F4 I2C driver registered\n");
|
||||
|
||||
return 0;
|
||||
|
||||
clk_free:
|
||||
clk_disable_unprepare(i2c_dev->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stm32f4_i2c_remove(struct platform_device *pdev)
|
||||
@ -865,8 +855,6 @@ static void stm32f4_i2c_remove(struct platform_device *pdev)
|
||||
struct stm32f4_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
|
||||
|
||||
i2c_del_adapter(&i2c_dev->adap);
|
||||
|
||||
clk_unprepare(i2c_dev->clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id stm32f4_i2c_match[] = {
|
||||
|
@ -325,6 +325,7 @@ struct stm32f7_i2c_alert {
|
||||
* @dnf_dt: value of digital filter requested via dt
|
||||
* @dnf: value of digital filter to apply
|
||||
* @alert: SMBus alert specific data
|
||||
* @atomic: boolean indicating that current transfer is atomic
|
||||
*/
|
||||
struct stm32f7_i2c_dev {
|
||||
struct i2c_adapter adap;
|
||||
@ -357,6 +358,7 @@ struct stm32f7_i2c_dev {
|
||||
u32 dnf_dt;
|
||||
u32 dnf;
|
||||
struct stm32f7_i2c_alert *alert;
|
||||
bool atomic;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -915,7 +917,8 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
|
||||
|
||||
/* Configure DMA or enable RX/TX interrupt */
|
||||
i2c_dev->use_dma = false;
|
||||
if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
|
||||
if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN
|
||||
&& !i2c_dev->atomic) {
|
||||
ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
|
||||
msg->flags & I2C_M_RD,
|
||||
f7_msg->count, f7_msg->buf,
|
||||
@ -939,6 +942,9 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
|
||||
cr1 |= STM32F7_I2C_CR1_TXDMAEN;
|
||||
}
|
||||
|
||||
if (i2c_dev->atomic)
|
||||
cr1 &= ~STM32F7_I2C_ALL_IRQ_MASK; /* Disable all interrupts */
|
||||
|
||||
/* Configure Start/Repeated Start */
|
||||
cr2 |= STM32F7_I2C_CR2_START;
|
||||
|
||||
@ -1673,7 +1679,22 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
static int stm32f7_i2c_wait_polling(struct stm32f7_i2c_dev *i2c_dev)
|
||||
{
|
||||
ktime_t timeout = ktime_add_ms(ktime_get(), i2c_dev->adap.timeout);
|
||||
|
||||
while (ktime_compare(ktime_get(), timeout) < 0) {
|
||||
udelay(5);
|
||||
stm32f7_i2c_isr_event(0, i2c_dev);
|
||||
|
||||
if (completion_done(&i2c_dev->complete))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32f7_i2c_xfer_core(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg msgs[], int num)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
|
||||
@ -1697,8 +1718,12 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
|
||||
stm32f7_i2c_xfer_msg(i2c_dev, msgs);
|
||||
|
||||
time_left = wait_for_completion_timeout(&i2c_dev->complete,
|
||||
i2c_dev->adap.timeout);
|
||||
if (!i2c_dev->atomic)
|
||||
time_left = wait_for_completion_timeout(&i2c_dev->complete,
|
||||
i2c_dev->adap.timeout);
|
||||
else
|
||||
time_left = stm32f7_i2c_wait_polling(i2c_dev);
|
||||
|
||||
ret = f7_msg->result;
|
||||
if (ret) {
|
||||
if (i2c_dev->use_dma)
|
||||
@ -1730,6 +1755,24 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
return (ret < 0) ? ret : num;
|
||||
}
|
||||
|
||||
static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg msgs[], int num)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
|
||||
|
||||
i2c_dev->atomic = false;
|
||||
return stm32f7_i2c_xfer_core(i2c_adap, msgs, num);
|
||||
}
|
||||
|
||||
static int stm32f7_i2c_xfer_atomic(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg msgs[], int num)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
|
||||
|
||||
i2c_dev->atomic = true;
|
||||
return stm32f7_i2c_xfer_core(i2c_adap, msgs, num);
|
||||
}
|
||||
|
||||
static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size,
|
||||
@ -2098,6 +2141,7 @@ static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
|
||||
|
||||
static const struct i2c_algorithm stm32f7_i2c_algo = {
|
||||
.master_xfer = stm32f7_i2c_xfer,
|
||||
.master_xfer_atomic = stm32f7_i2c_xfer_atomic,
|
||||
.smbus_xfer = stm32f7_i2c_smbus_xfer,
|
||||
.functionality = stm32f7_i2c_func,
|
||||
.reg_slave = stm32f7_i2c_reg_slave,
|
||||
@ -2134,23 +2178,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node,
|
||||
"wakeup-source");
|
||||
|
||||
i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
i2c_dev->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(i2c_dev->clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(i2c_dev->clk),
|
||||
"Failed to get controller clock\n");
|
||||
|
||||
ret = clk_prepare_enable(i2c_dev->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to prepare_enable clock\n");
|
||||
return ret;
|
||||
}
|
||||
"Failed to enable controller clock\n");
|
||||
|
||||
rst = devm_reset_control_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(rst)) {
|
||||
ret = dev_err_probe(&pdev->dev, PTR_ERR(rst),
|
||||
"Error: Missing reset ctrl\n");
|
||||
goto clk_free;
|
||||
}
|
||||
if (IS_ERR(rst))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(rst),
|
||||
"Error: Missing reset ctrl\n");
|
||||
|
||||
reset_control_assert(rst);
|
||||
udelay(2);
|
||||
reset_control_deassert(rst);
|
||||
@ -2165,7 +2202,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq event %i\n",
|
||||
irq_event);
|
||||
goto clk_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0,
|
||||
@ -2173,29 +2210,28 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq error %i\n",
|
||||
irq_error);
|
||||
goto clk_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
setup = of_device_get_match_data(&pdev->dev);
|
||||
if (!setup) {
|
||||
dev_err(&pdev->dev, "Can't get device data\n");
|
||||
ret = -ENODEV;
|
||||
goto clk_free;
|
||||
return -ENODEV;
|
||||
}
|
||||
i2c_dev->setup = *setup;
|
||||
|
||||
ret = stm32f7_i2c_setup_timing(i2c_dev, &i2c_dev->setup);
|
||||
if (ret)
|
||||
goto clk_free;
|
||||
return ret;
|
||||
|
||||
/* Setup Fast mode plus if necessary */
|
||||
if (i2c_dev->bus_rate > I2C_MAX_FAST_MODE_FREQ) {
|
||||
ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
|
||||
if (ret)
|
||||
goto clk_free;
|
||||
return ret;
|
||||
ret = stm32f7_i2c_write_fm_plus_bits(i2c_dev, true);
|
||||
if (ret)
|
||||
goto clk_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
adap = &i2c_dev->adap;
|
||||
@ -2306,9 +2342,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
fmp_clear:
|
||||
stm32f7_i2c_write_fm_plus_bits(i2c_dev, false);
|
||||
|
||||
clk_free:
|
||||
clk_disable_unprepare(i2c_dev->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2342,8 +2375,6 @@ static void stm32f7_i2c_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
stm32f7_i2c_write_fm_plus_bits(i2c_dev, false);
|
||||
|
||||
clk_disable_unprepare(i2c_dev->clk);
|
||||
}
|
||||
|
||||
static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev)
|
||||
|
@ -201,6 +201,11 @@ static int p2wi_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (clk_freq == 0) {
|
||||
dev_err(dev, "clock-frequency is set to 0 in DT\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_get_child_count(np) > 1) {
|
||||
dev_err(dev, "P2WI only supports one slave device\n");
|
||||
return -EINVAL;
|
||||
|
@ -94,7 +94,7 @@ struct i2c_atr {
|
||||
|
||||
struct notifier_block i2c_nb;
|
||||
|
||||
struct i2c_adapter *adapter[];
|
||||
struct i2c_adapter *adapter[] __counted_by(max_adapters);
|
||||
};
|
||||
|
||||
static struct i2c_atr_alias_pair *
|
||||
|
@ -931,8 +931,9 @@ int i2c_dev_irq_from_resources(const struct resource *resources,
|
||||
struct i2c_client *
|
||||
i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
|
||||
{
|
||||
struct i2c_client *client;
|
||||
int status;
|
||||
struct i2c_client *client;
|
||||
bool need_put = false;
|
||||
int status;
|
||||
|
||||
client = kzalloc(sizeof *client, GFP_KERNEL);
|
||||
if (!client)
|
||||
@ -970,7 +971,6 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
|
||||
client->dev.fwnode = info->fwnode;
|
||||
|
||||
device_enable_async_suspend(&client->dev);
|
||||
i2c_dev_set_name(adap, client, info);
|
||||
|
||||
if (info->swnode) {
|
||||
status = device_add_software_node(&client->dev, info->swnode);
|
||||
@ -982,6 +982,7 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
|
||||
}
|
||||
}
|
||||
|
||||
i2c_dev_set_name(adap, client, info);
|
||||
status = device_register(&client->dev);
|
||||
if (status)
|
||||
goto out_remove_swnode;
|
||||
@ -993,6 +994,7 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
|
||||
|
||||
out_remove_swnode:
|
||||
device_remove_software_node(&client->dev);
|
||||
need_put = true;
|
||||
out_err_put_of_node:
|
||||
of_node_put(info->of_node);
|
||||
out_err:
|
||||
@ -1000,7 +1002,10 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
|
||||
"Failed to register i2c client %s at 0x%02x (%d)\n",
|
||||
client->name, client->addr, status);
|
||||
out_err_silent:
|
||||
kfree(client);
|
||||
if (need_put)
|
||||
put_device(&client->dev);
|
||||
else
|
||||
kfree(client);
|
||||
return ERR_PTR(status);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(i2c_new_client_device);
|
||||
@ -1189,9 +1194,11 @@ static void i2c_adapter_dev_release(struct device *dev)
|
||||
unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
|
||||
{
|
||||
unsigned int depth = 0;
|
||||
struct device *parent;
|
||||
|
||||
while ((adapter = i2c_parent_is_i2c_adapter(adapter)))
|
||||
depth++;
|
||||
for (parent = adapter->dev.parent; parent; parent = parent->parent)
|
||||
if (parent->type == &i2c_adapter_type)
|
||||
depth++;
|
||||
|
||||
WARN_ONCE(depth >= MAX_LOCKDEP_SUBCLASSES,
|
||||
"adapter depth exceeds lockdep subclass limit\n");
|
||||
|
@ -636,7 +636,10 @@ static const struct file_operations i2cdev_fops = {
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static struct class *i2c_dev_class;
|
||||
static const struct class i2c_dev_class = {
|
||||
.name = "i2c-dev",
|
||||
.dev_groups = i2c_groups,
|
||||
};
|
||||
|
||||
static void i2cdev_dev_release(struct device *dev)
|
||||
{
|
||||
@ -665,7 +668,7 @@ static int i2cdev_attach_adapter(struct device *dev)
|
||||
|
||||
device_initialize(&i2c_dev->dev);
|
||||
i2c_dev->dev.devt = MKDEV(I2C_MAJOR, adap->nr);
|
||||
i2c_dev->dev.class = i2c_dev_class;
|
||||
i2c_dev->dev.class = &i2c_dev_class;
|
||||
i2c_dev->dev.parent = &adap->dev;
|
||||
i2c_dev->dev.release = i2cdev_dev_release;
|
||||
|
||||
@ -751,12 +754,9 @@ static int __init i2c_dev_init(void)
|
||||
if (res)
|
||||
goto out;
|
||||
|
||||
i2c_dev_class = class_create("i2c-dev");
|
||||
if (IS_ERR(i2c_dev_class)) {
|
||||
res = PTR_ERR(i2c_dev_class);
|
||||
res = class_register(&i2c_dev_class);
|
||||
if (res)
|
||||
goto out_unreg_chrdev;
|
||||
}
|
||||
i2c_dev_class->dev_groups = i2c_groups;
|
||||
|
||||
/* Keep track of adapters which will be added or removed later */
|
||||
res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
|
||||
@ -769,7 +769,7 @@ static int __init i2c_dev_init(void)
|
||||
return 0;
|
||||
|
||||
out_unreg_class:
|
||||
class_destroy(i2c_dev_class);
|
||||
class_unregister(&i2c_dev_class);
|
||||
out_unreg_chrdev:
|
||||
unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
|
||||
out:
|
||||
@ -781,7 +781,7 @@ static void __exit i2c_dev_exit(void)
|
||||
{
|
||||
bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
|
||||
i2c_for_each_dev(NULL, i2c_dev_detach_adapter);
|
||||
class_destroy(i2c_dev_class);
|
||||
class_unregister(&i2c_dev_class);
|
||||
unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ struct i2c_demux_pinctrl_priv {
|
||||
const char *bus_name;
|
||||
struct i2c_adapter cur_adap;
|
||||
struct i2c_algorithm algo;
|
||||
struct i2c_demux_pinctrl_chan chan[];
|
||||
struct i2c_demux_pinctrl_chan chan[] __counted_by(num_chan);
|
||||
};
|
||||
|
||||
static int i2c_demux_master_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
@ -167,9 +167,9 @@ static ssize_t available_masters_show(struct device *dev,
|
||||
int count = 0, i;
|
||||
|
||||
for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++)
|
||||
count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%pOF%c",
|
||||
i, priv->chan[i].parent_np,
|
||||
i == priv->num_chan - 1 ? '\n' : ' ');
|
||||
count += sysfs_emit_at(buf, count, "%d:%pOF%c",
|
||||
i, priv->chan[i].parent_np,
|
||||
i == priv->num_chan - 1 ? '\n' : ' ');
|
||||
|
||||
return count;
|
||||
}
|
||||
@ -226,6 +226,8 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
|
||||
if (!priv || !props)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->num_chan = num_chan;
|
||||
|
||||
err = of_property_read_string(np, "i2c-bus-name", &priv->bus_name);
|
||||
if (err)
|
||||
return err;
|
||||
@ -253,9 +255,7 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
|
||||
of_changeset_update_property(&priv->chan[i].chgset, adap_np, &props[i]);
|
||||
}
|
||||
|
||||
priv->num_chan = num_chan;
|
||||
priv->dev = &pdev->dev;
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
pm_runtime_no_callbacks(&pdev->dev);
|
||||
|
@ -22,7 +22,7 @@ struct gpiomux {
|
||||
struct gpio_desc **gpios;
|
||||
};
|
||||
|
||||
static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
|
||||
static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned int val)
|
||||
{
|
||||
DECLARE_BITMAP(values, BITS_PER_TYPE(val));
|
||||
|
||||
@ -58,7 +58,7 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,
|
||||
struct device_node *adapter_np;
|
||||
struct i2c_adapter *adapter = NULL;
|
||||
struct fwnode_handle *child;
|
||||
unsigned *values;
|
||||
unsigned int *values;
|
||||
int rc, i = 0;
|
||||
|
||||
if (is_of_node(fwnode)) {
|
||||
@ -101,7 +101,6 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,
|
||||
device_for_each_child_node(dev, child) {
|
||||
if (is_of_node(child)) {
|
||||
fwnode_property_read_u32(child, "reg", values + i);
|
||||
|
||||
} else if (is_acpi_node(child)) {
|
||||
rc = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), values + i);
|
||||
if (rc) {
|
||||
@ -126,7 +125,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
|
||||
struct gpiomux *mux;
|
||||
struct i2c_adapter *parent;
|
||||
struct i2c_adapter *root;
|
||||
unsigned initial_state;
|
||||
unsigned int initial_state;
|
||||
int i, ngpios, ret;
|
||||
|
||||
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
|
||||
|
@ -92,7 +92,7 @@ struct at24_data {
|
||||
* them for us.
|
||||
*/
|
||||
u8 bank_addr_shift;
|
||||
struct regmap *client_regmaps[];
|
||||
struct regmap *client_regmaps[] __counted_by(num_addresses);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -191,9 +191,13 @@ AT24_CHIP_DATA(at24_data_24c16, 16384 / 8, 0);
|
||||
AT24_CHIP_DATA(at24_data_24cs16, 16,
|
||||
AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24c32, 32768 / 8, AT24_FLAG_ADDR16);
|
||||
/* M24C32-D Additional Write lockable page (M24C32-D order codes) */
|
||||
AT24_CHIP_DATA(at24_data_24c32d_wlp, 32, AT24_FLAG_ADDR16);
|
||||
AT24_CHIP_DATA(at24_data_24cs32, 16,
|
||||
AT24_FLAG_ADDR16 | AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24c64, 65536 / 8, AT24_FLAG_ADDR16);
|
||||
/* M24C64-D Additional Write lockable page (M24C64-D order codes) */
|
||||
AT24_CHIP_DATA(at24_data_24c64d_wlp, 32, AT24_FLAG_ADDR16);
|
||||
AT24_CHIP_DATA(at24_data_24cs64, 16,
|
||||
AT24_FLAG_ADDR16 | AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24c128, 131072 / 8, AT24_FLAG_ADDR16);
|
||||
@ -222,8 +226,10 @@ static const struct i2c_device_id at24_ids[] = {
|
||||
{ "24c16", (kernel_ulong_t)&at24_data_24c16 },
|
||||
{ "24cs16", (kernel_ulong_t)&at24_data_24cs16 },
|
||||
{ "24c32", (kernel_ulong_t)&at24_data_24c32 },
|
||||
{ "24c32d-wl", (kernel_ulong_t)&at24_data_24c32d_wlp },
|
||||
{ "24cs32", (kernel_ulong_t)&at24_data_24cs32 },
|
||||
{ "24c64", (kernel_ulong_t)&at24_data_24c64 },
|
||||
{ "24c64-wl", (kernel_ulong_t)&at24_data_24c64d_wlp },
|
||||
{ "24cs64", (kernel_ulong_t)&at24_data_24cs64 },
|
||||
{ "24c128", (kernel_ulong_t)&at24_data_24c128 },
|
||||
{ "24c256", (kernel_ulong_t)&at24_data_24c256 },
|
||||
@ -252,8 +258,10 @@ static const struct of_device_id at24_of_match[] = {
|
||||
{ .compatible = "atmel,24c16", .data = &at24_data_24c16 },
|
||||
{ .compatible = "atmel,24cs16", .data = &at24_data_24cs16 },
|
||||
{ .compatible = "atmel,24c32", .data = &at24_data_24c32 },
|
||||
{ .compatible = "atmel,24c32d-wl", .data = &at24_data_24c32d_wlp },
|
||||
{ .compatible = "atmel,24cs32", .data = &at24_data_24cs32 },
|
||||
{ .compatible = "atmel,24c64", .data = &at24_data_24c64 },
|
||||
{ .compatible = "atmel,24c64d-wl", .data = &at24_data_24c64d_wlp },
|
||||
{ .compatible = "atmel,24cs64", .data = &at24_data_24cs64 },
|
||||
{ .compatible = "atmel,24c128", .data = &at24_data_24c128 },
|
||||
{ .compatible = "atmel,24c256", .data = &at24_data_24c256 },
|
||||
@ -509,32 +517,6 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct at24_chip_data *at24_get_chip_data(struct device *dev)
|
||||
{
|
||||
struct device_node *of_node = dev->of_node;
|
||||
const struct at24_chip_data *cdata;
|
||||
const struct i2c_device_id *id;
|
||||
|
||||
id = i2c_match_id(at24_ids, to_i2c_client(dev));
|
||||
|
||||
/*
|
||||
* The I2C core allows OF nodes compatibles to match against the
|
||||
* I2C device ID table as a fallback, so check not only if an OF
|
||||
* node is present but also if it matches an OF device ID entry.
|
||||
*/
|
||||
if (of_node && of_match_device(at24_of_match, dev))
|
||||
cdata = of_device_get_match_data(dev);
|
||||
else if (id)
|
||||
cdata = (void *)id->driver_data;
|
||||
else
|
||||
cdata = acpi_device_get_match_data(dev);
|
||||
|
||||
if (!cdata)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
return cdata;
|
||||
}
|
||||
|
||||
static int at24_make_dummy_client(struct at24_data *at24, unsigned int index,
|
||||
struct i2c_client *base_client,
|
||||
struct regmap_config *regmap_config)
|
||||
@ -601,9 +583,9 @@ static int at24_probe(struct i2c_client *client)
|
||||
i2c_fn_block = i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK);
|
||||
|
||||
cdata = at24_get_chip_data(dev);
|
||||
if (IS_ERR(cdata))
|
||||
return PTR_ERR(cdata);
|
||||
cdata = i2c_get_match_data(client);
|
||||
if (!cdata)
|
||||
return -ENODEV;
|
||||
|
||||
err = device_property_read_u32(dev, "pagesize", &page_size);
|
||||
if (err)
|
||||
|
@ -1531,4 +1531,9 @@ static inline void acpi_device_notify(struct device *dev) { }
|
||||
static inline void acpi_device_notify_remove(struct device *dev) { }
|
||||
#endif
|
||||
|
||||
static inline void acpi_use_parent_companion(struct device *dev)
|
||||
{
|
||||
ACPI_COMPANION_SET(dev, ACPI_COMPANION(dev->parent));
|
||||
}
|
||||
|
||||
#endif /*_LINUX_ACPI_H*/
|
||||
|
Loading…
Reference in New Issue
Block a user