From 50a5ba876908147b36441c754e835588143c6b54 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 13 Jan 2016 15:29:27 +0100 Subject: i2c: mux: demux-pinctrl: add driver This driver allows an I2C bus to switch between multiple masters. This is not hot-switching because connected I2C slaves will be re-instantiated. It is meant to select the best I2C core at runtime once the task is known. Example: Prefer i2c-gpio over another I2C core because of HW errata affecting your use case. Signed-off-by: Wolfram Sang Acked-by: Rob Herring Signed-off-by: Wolfram Sang --- .../ABI/testing/sysfs-platform-i2c-demux-pinctrl | 23 ++++ .../devicetree/bindings/i2c/i2c-demux-pinctrl.txt | 135 +++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-platform-i2c-demux-pinctrl create mode 100644 Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-platform-i2c-demux-pinctrl b/Documentation/ABI/testing/sysfs-platform-i2c-demux-pinctrl new file mode 100644 index 000000000000..7ac7d7262bb7 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-i2c-demux-pinctrl @@ -0,0 +1,23 @@ +What: /sys/devices/platform//cur_master +Date: January 2016 +KernelVersion: 4.6 +Contact: Wolfram Sang +Description: + +This file selects the active I2C master for a demultiplexed bus. + +Write 0 there for the first master, 1 for the second etc. Reading the file will +give you a list with the active master marked. Example from a Renesas Lager +board: + +root@Lager:~# cat /sys/devices/platform/i2c@8/cur_master +* 0 - /i2c@9 + 1 - /i2c@e6520000 + 2 - /i2c@e6530000 + +root@Lager:~# echo 2 > /sys/devices/platform/i2c@8/cur_master + +root@Lager:~# cat /sys/devices/platform/i2c@8/cur_master + 0 - /i2c@9 + 1 - /i2c@e6520000 +* 2 - /i2c@e6530000 diff --git a/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt new file mode 100644 index 000000000000..6078aefe7ed4 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt @@ -0,0 +1,135 @@ +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 mux.txt 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"; + status = "disabled"; + 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. -- cgit v1.2.3-59-g8ed1b From 36ecbcab84d02381ab40363546616c0719adafdb Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Wed, 2 Mar 2016 17:34:06 +0530 Subject: i2c: xiic: Implement power management Enable power management. This patch enables the clocks before transfer and disables after the transfer. It also adds the clock description. Signed-off-by: Shubhrajyoti Datta Acked-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-xiic.txt | 3 + drivers/i2c/busses/i2c-xiic.c | 88 ++++++++++++++++++++-- 2 files changed, 84 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/i2c/i2c-xiic.txt b/Documentation/devicetree/bindings/i2c/i2c-xiic.txt index ceabbe91ae44..caf42e989462 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-xiic.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-xiic.txt @@ -6,14 +6,17 @@ Required properties: - interrupts : IIC controller unterrupt - #address-cells = <1> - #size-cells = <0> +- clocks: Input clock specifier. Refer to common clock bindings. Optional properties: - Child nodes conforming to i2c bus binding +- clock-names: Input clock name, should be 'pclk'. Example: axi_iic_0: i2c@40800000 { compatible = "xlnx,xps-iic-2.00.a"; + clocks = <&clkc 15>; interrupts = < 1 2 >; reg = < 0x40800000 0x10000 >; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 6efd20095d5d..74f54f2f471f 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #define DRIVER_NAME "xiic-i2c" @@ -66,6 +68,7 @@ enum xiic_endian { * @endianness: big/little-endian byte order */ struct xiic_i2c { + struct device *dev; void __iomem *base; wait_queue_head_t wait; struct i2c_adapter adap; @@ -77,6 +80,7 @@ struct xiic_i2c { struct i2c_msg *rx_msg; int rx_pos; enum xiic_endian endianness; + struct clk *clk; }; @@ -164,6 +168,7 @@ struct xiic_i2c { #define XIIC_RESET_MASK 0xAUL +#define XIIC_PM_TIMEOUT 1000 /* ms */ /* * The following constant is used for the device global interrupt enable * register, to enable all interrupts for the device, this is the only bit @@ -676,9 +681,13 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)); + err = pm_runtime_get_sync(i2c->dev); + if (err < 0) + return err; + err = xiic_busy(i2c); if (err) - return err; + goto out; i2c->tx_msg = msgs; i2c->nmsgs = num; @@ -686,14 +695,20 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) xiic_start_xfer(i2c); if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || - (i2c->state == STATE_DONE), HZ)) - return (i2c->state == STATE_DONE) ? num : -EIO; - else { + (i2c->state == STATE_DONE), HZ)) { + err = (i2c->state == STATE_DONE) ? num : -EIO; + goto out; + } else { i2c->tx_msg = NULL; i2c->rx_msg = NULL; i2c->nmsgs = 0; - return -ETIMEDOUT; + err = -ETIMEDOUT; + goto out; } +out: + pm_runtime_mark_last_busy(i2c->dev); + pm_runtime_put_autosuspend(i2c->dev); + return err; } static u32 xiic_func(struct i2c_adapter *adap) @@ -748,13 +763,28 @@ static int xiic_i2c_probe(struct platform_device *pdev) mutex_init(&i2c->lock); init_waitqueue_head(&i2c->wait); + i2c->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(i2c->clk)) { + dev_err(&pdev->dev, "input clock not found.\n"); + return PTR_ERR(i2c->clk); + } + ret = clk_prepare_enable(i2c->clk); + if (ret) { + dev_err(&pdev->dev, "Unable to enable clock.\n"); + return ret; + } + i2c->dev = &pdev->dev; + pm_runtime_enable(i2c->dev); + pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT); + pm_runtime_use_autosuspend(i2c->dev); + pm_runtime_set_active(i2c->dev); ret = devm_request_threaded_irq(&pdev->dev, irq, xiic_isr, xiic_process, IRQF_ONESHOT, pdev->name, i2c); if (ret < 0) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); - return ret; + goto err_clk_dis; } /* @@ -776,7 +806,7 @@ static int xiic_i2c_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Failed to add adapter\n"); xiic_deinit(i2c); - return ret; + goto err_clk_dis; } if (pdata) { @@ -786,16 +816,30 @@ static int xiic_i2c_probe(struct platform_device *pdev) } return 0; + +err_clk_dis: + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_disable(&pdev->dev); + clk_disable_unprepare(i2c->clk); + return ret; } static int xiic_i2c_remove(struct platform_device *pdev) { struct xiic_i2c *i2c = platform_get_drvdata(pdev); + int ret; /* remove adapter & data */ i2c_del_adapter(&i2c->adap); + ret = clk_prepare_enable(i2c->clk); + if (ret) { + dev_err(&pdev->dev, "Unable to enable clock.\n"); + return ret; + } xiic_deinit(i2c); + clk_disable_unprepare(i2c->clk); + pm_runtime_disable(&pdev->dev); return 0; } @@ -808,12 +852,42 @@ static const struct of_device_id xiic_of_match[] = { MODULE_DEVICE_TABLE(of, xiic_of_match); #endif +static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct xiic_i2c *i2c = platform_get_drvdata(pdev); + + clk_disable(i2c->clk); + + return 0; +} + +static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct xiic_i2c *i2c = platform_get_drvdata(pdev); + int ret; + + ret = clk_enable(i2c->clk); + if (ret) { + dev_err(dev, "Cannot enable clock.\n"); + return ret; + } + + return 0; +} + +static const struct dev_pm_ops xiic_dev_pm_ops = { + SET_RUNTIME_PM_OPS(cdns_i2c_runtime_suspend, + cdns_i2c_runtime_resume, NULL) +}; static struct platform_driver xiic_i2c_driver = { .probe = xiic_i2c_probe, .remove = xiic_i2c_remove, .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(xiic_of_match), + .pm = &xiic_dev_pm_ops, }, }; -- cgit v1.2.3-59-g8ed1b From ddf3dc82f10e15469b3967ae777d39745d3aab16 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 15 Mar 2016 17:51:28 +0100 Subject: dt-bindings: i2c: Spelling s/propoerty/property/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-imx.txt | 2 +- Documentation/devicetree/bindings/i2c/i2c-rcar.txt | 2 +- Documentation/devicetree/bindings/i2c/i2c-sirf.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx.txt b/Documentation/devicetree/bindings/i2c/i2c-imx.txt index eab5836ba7f9..b967544590e8 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-imx.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-imx.txt @@ -11,7 +11,7 @@ Required properties: Optional properties: - clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz. - The absence of the propoerty indicates the default frequency 100 kHz. + The absence of the property indicates the default frequency 100 kHz. - dmas: A list of two dma specifiers, one for each entry in dma-names. - dma-names: should contain "tx" and "rx". - scl-gpios: specify the gpio related to SCL pin diff --git a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt index 95e97223a71c..cf8bfc956cdc 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt @@ -17,7 +17,7 @@ Required properties: Optional properties: - clock-frequency: desired I2C bus clock frequency in Hz. The absence of this - propoerty indicates the default frequency 100 kHz. + property indicates the default frequency 100 kHz. - clocks: clock specifier. - i2c-scl-falling-time-ns: see i2c.txt diff --git a/Documentation/devicetree/bindings/i2c/i2c-sirf.txt b/Documentation/devicetree/bindings/i2c/i2c-sirf.txt index 7baf9e133fa8..2701eefb00f7 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-sirf.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-sirf.txt @@ -8,7 +8,7 @@ Required properties : Optional properties: - clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz. - The absence of the propoerty indicates the default frequency 100 kHz. + The absence of the property indicates the default frequency 100 kHz. Examples : -- cgit v1.2.3-59-g8ed1b