All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrey Smirnov <andrew.smirnov@gmail.com>
To: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Lucas Stach <l.stach@pengutronix.de>,
	Rob Herring <robh+dt@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	devicetree@vger.kernel.org,
	linux-kernel <linux-kernel@vger.kernel.org>,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v3] reset: Add i.MX7 SRC reset driver
Date: Mon, 20 Feb 2017 11:46:26 -0800	[thread overview]
Message-ID: <CAHQ1cqFKfez4mGS982mVUz7Sek9Ms2OAkqgd292aOh-RB3OQBg@mail.gmail.com> (raw)
In-Reply-To: <1487607099.3878.44.camel@pengutronix.de>

On Mon, Feb 20, 2017 at 8:11 AM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> Hi Andrey,
>
> On Mon, 2017-02-20 at 07:26 -0800, Andrey Smirnov wrote:
>> Add reset controller driver exposing various reset faculties,
>> implemented by System Reset Controller IP block.
>>
>> Cc: Lucas Stach <l.stach@pengutronix.de>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: devicetree@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: linux-arm-kernel@lists.infradead.org
>> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
>> ---
>>
>> Changes since v2 (see [v2]):
>>
>>       - Fix typos
>>
>>       - Kconfig/Makefile chagnes account for alphabetical sorting of
>>           those files
>>
>>       - Remove redundant includes
>>
>>       - Make use of regmap_attach_dev and avoid storing refernce to
>>           struct *dev in private data
>>
>>       - Change code and headers to expose almost all of the reset
>>           related bits in SRC IP block
>
> Thank you, this is looking much better!
>
>> Changes since v1 (see [v1]):
>>
>>       - Various small DT bindings description fixes as per feedback
>>           from Rob Herring
>>
>>
>> [v1] https://lkml.org/lkml/2017/2/6/554
>> [v2] https://lkml.org/lkml/2017/2/13/488
>>
>>
>>  .../devicetree/bindings/reset/fsl,imx7-src.txt     |  47 ++++++
>>  drivers/reset/Kconfig                              |   8 +
>>  drivers/reset/Makefile                             |   2 +
>>  drivers/reset/reset-imx7.c                         | 186 +++++++++++++++++++++
>>  include/dt-bindings/reset/imx7-reset.h             |  62 +++++++
>>  5 files changed, 305 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
>>  create mode 100644 drivers/reset/reset-imx7.c
>>  create mode 100644 include/dt-bindings/reset/imx7-reset.h
>>
>> diff --git a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
>> new file mode 100644
>> index 0000000..5e1afc3
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
>> @@ -0,0 +1,47 @@
>> +Freescale i.MX7 System Reset Controller
>> +======================================
>> +
>> +Please also refer to reset.txt in this directory for common reset
>> +controller binding usage.
>> +
>> +Required properties:
>> +- compatible: Should be "fsl,imx7-src", "syscon"
>> +- reg: should be register base and length as documented in the
>> +  datasheet
>> +- interrupts: Should contain SRC interrupt
>> +- #reset-cells: 1, see below
>> +
>> +example:
>> +
>> +src: reset-controller@30390000 {
>> +     compatible = "fsl,imx7d-src", "syscon";
>> +     reg = <0x30390000 0x2000>;
>> +     interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
>> +     #reset-cells = <1>;
>> +};
>> +
>> +
>> +Specifying reset lines connected to IP modules
>> +==============================================
>> +
>> +The system reset controller can be used to reset various set of
>> +peripherals. Device nodes that need access to reset lines should
>> +specify them as a reset phandle in their corresponding node as
>> +specified in reset.txt.
>> +
>> +Example:
>> +
>> +     pcie: pcie@33800000 {
>> +
>> +             ...
>> +
>> +             resets = <&src IMX7_RESET_PCIEPHY>,
>> +                      <&src IMX7_RESET_PCIE_CTRL_APPS_EN>;
>> +             reset-names = "pciephy", "apps";
>> +
>> +             ...
>> +        };
>> +
>> +
>> +For list of all valid reset indicies see
>> +<dt-bindings/reset/imx7-reset.h>
>> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
>> index 172dc96..bea1800 100644
>> --- a/drivers/reset/Kconfig
>> +++ b/drivers/reset/Kconfig
>> @@ -27,6 +27,14 @@ config RESET_BERLIN
>>       help
>>         This enables the reset controller driver for Marvell Berlin SoCs.
>>
>> +config RESET_IMX7
>> +     bool "i.MX7 Reset Driver"
>> +     depends on SOC_IMX7D || COMPILE_TEST
>> +     select MFD_SYSCON
>> +     default SOC_IMX7D
>> +     help
>> +       This enables the reset controller driver for i.MX7 SoCs.
>> +
>>  config RESET_LPC18XX
>>       bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST
>>       default ARCH_LPC18XX
>> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
>> index 13b346e..a24aa80 100644
>> --- a/drivers/reset/Makefile
>> +++ b/drivers/reset/Makefile
>> @@ -4,6 +4,7 @@ obj-$(CONFIG_ARCH_STI) += sti/
>>  obj-$(CONFIG_ARCH_TEGRA) += tegra/
>>  obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
>>  obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
>> +obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
>>  obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
>>  obj-$(CONFIG_RESET_MESON) += reset-meson.o
>>  obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
>> @@ -14,3 +15,4 @@ obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
>>  obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
>>  obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
>>  obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
>> +
>> diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
>> new file mode 100644
>> index 0000000..6e26796
>> --- /dev/null
>> +++ b/drivers/reset/reset-imx7.c
>> @@ -0,0 +1,186 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * i.MX7 System Reset Controller (SRC) driver
>> + *
>> + * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/reset-controller.h>
>> +#include <linux/regmap.h>
>> +#include <dt-bindings/reset/imx7-reset.h>
>> +
>> +struct imx7_src {
>> +     struct reset_controller_dev rcdev;
>> +     struct regmap *regmap;
>> +};
>> +
>> +enum imx7_src_registers {
>> +     SRC_A7RCR0              = 0x0004,
>> +     SRC_M4RCR               = 0x000c,
>> +     SRC_ERCR                = 0x0014,
>> +     SRC_HSICPHY_RCR         = 0x001c,
>> +     SRC_USBOPHY1_RCR        = 0x0020,
>> +     SRC_USBOPHY2_RCR        = 0x0024,
>> +     SRC_MIPIPHY_RCR         = 0x0028,
>> +     SRC_PCIEPHY_RCR         = 0x002c,
>> +     SRC_DDRC_RCR            = 0x1000,
>> +
>> +     SRC_PCIEPHY_RCR_PCIEPHY_G_RST   = BIT(1),
>> +     SRC_PCIEPHY_RCR_PCIEPHY_BTN     = BIT(2),
>> +};
>> +
>> +struct imx7_src_signal {
>> +     unsigned int offset, bit;
>> +};
>> +
>> +static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
>> +     [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
>> +     [IMX7_RESET_A7_CORE_POR_RESET1] = { SRC_A7RCR0, BIT(1) },
>> +     [IMX7_RESET_A7_CORE_RESET0]     = { SRC_A7RCR0, BIT(4) },
>> +     [IMX7_RESET_A7_CORE_RESET1]     = { SRC_A7RCR0, BIT(5) },
>> +     [IMX7_RESET_A7_DBG_RESET0]      = { SRC_A7RCR0, BIT(8) },
>> +     [IMX7_RESET_A7_DBG_RESET1]      = { SRC_A7RCR0, BIT(9) },
>> +     [IMX7_RESET_A7_ETM_RESET0]      = { SRC_A7RCR0, BIT(12) },
>> +     [IMX7_RESET_A7_ETM_RESET1]      = { SRC_A7RCR0, BIT(13) },
>> +     [IMX7_RESET_A7_SOC_DBG_RESET]   = { SRC_A7RCR0, BIT(20) },
>> +     [IMX7_RESET_A7_L2RESET]         = { SRC_A7RCR0, BIT(21) },
>> +     [IMX7_RESET_SW_M4C_RST]         = { SRC_M4RCR, BIT(1) },
>> +     [IMX7_RESET_SW_M4P_RST]         = { SRC_M4RCR, BIT(2) },
>> +     [IMX7_RESET_EIM_RST]            = { SRC_ERCR, BIT(0) },
>> +     [IMX7_RESET_HSICPHY_PORT_RST]   = { SRC_HSICPHY_RCR, BIT(1) },
>> +     [IMX7_RESET_USBPHY1_POR]        = { SRC_USBOPHY1_RCR, BIT(0) },
>> +     [IMX7_RESET_USBPHY1_PORT_RST]   = { SRC_USBOPHY1_RCR, BIT(1) },
>> +     [IMX7_RESET_USBPHY2_POR]        = { SRC_USBOPHY2_RCR, BIT(0) },
>> +     [IMX7_RESET_USBPHY2_PORT_RST]   = { SRC_USBOPHY2_RCR, BIT(1) },
>> +     [IMX7_RESET_MIPI_PHY_MRST]      = { SRC_MIPIPHY_RCR, BIT(1) },
>> +     [IMX7_RESET_MIPI_PHY_SRST]      = { SRC_MIPIPHY_RCR, BIT(2) },
>> +     [IMX7_RESET_PCIEPHY]            = { /* Placeholder */ },
>> +     [IMX7_RESET_PCIEPHY_PERST]      = { SRC_PCIEPHY_RCR, BIT(3) },
>> +     [IMX7_RESET_PCIE_CTRL_APPS_EN]  = { SRC_PCIEPHY_RCR, BIT(6) },
>> +     [IMX7_RESET_DDRC_PRST]          = { SRC_DDRC_RCR, BIT(0) },
>> +     [IMX7_RESET_DDRC_CORE_RST]      = { SRC_DDRC_RCR, BIT(1) },
>> +};
>> +
>> +static struct imx7_src *to_imx7_src(struct reset_controller_dev *rcdev)
>> +{
>> +     return container_of(rcdev, struct imx7_src, rcdev);
>> +}
>> +
>> +static int imx7_reset_assert(struct reset_controller_dev *rcdev,
>> +                          unsigned long id)
>> +{
>> +     struct imx7_src *imx7src = to_imx7_src(rcdev);
>> +     const struct imx7_src_signal *signal = &imx7_src_signals[id];
>> +     unsigned int value = signal->bit;
>> +
>> +     switch (id) {
>> +     case IMX7_RESET_PCIEPHY:
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_G_RST,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_G_RST);
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_BTN,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_BTN);
>
> Is it possible to assert (and deassert) both bits at the same time?
> That would allow to use the default case here.

Good point and I am not sure, I'll do an experiment and see if they can.

>
>> +             break;
>> +
>> +     case IMX7_RESET_PCIE_CTRL_APPS_EN:
>> +             value = 0;
>> +     default:                /* FALLTHROUGH */
>> +             regmap_update_bits(imx7src->regmap,
>> +                                signal->offset, signal->bit, value);
>> +             break;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int imx7_reset_deassert(struct reset_controller_dev *rcdev,
>> +                            unsigned long id)
>> +{
>> +     struct imx7_src *imx7src = to_imx7_src(rcdev);
>> +     const struct imx7_src_signal *signal = &imx7_src_signals[id];
>> +     unsigned int value = 0;
>> +
>> +     switch (id) {
>> +     case IMX7_RESET_PCIEPHY:
>> +             /*
>> +              * wait for more than 10us to release phy g_rst and
>> +              * btnrst
>> +              */
>> +             udelay(10);
>
> What is the purpose of this delay?

That's how downstream PCIe driver is using those lines. I haven't seen
anything in datasheet that would explain the purpose of it.

>
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_G_RST, 0);
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_BTN, 0);
>
> Same as above. Assert and deassert using the same order makes me think
> that the order may not be important at all. If they do on the other hand
> have to be flipped in a certain order, it would be better to expose them
> separately.
>
>> +             break;
>> +     case IMX7_RESET_PCIE_CTRL_APPS_EN:
>> +             value = signal->bit;
>> +     default:                /* FALLTHROUGH */
>> +             regmap_update_bits(imx7src->regmap,
>> +                                signal->offset, signal->bit, value);
>> +
>> +             break;
>> +     };
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct reset_control_ops imx7_reset_ops = {
>> +     .assert         = imx7_reset_assert,
>> +     .deassert       = imx7_reset_deassert,
>> +};
>> +
>> +static int imx7_reset_probe(struct platform_device *pdev)
>> +{
>> +     struct imx7_src *imx7src;
>> +     struct device *dev = &pdev->dev;
>> +     struct regmap_config config = { .name = "src" };
>> +
>> +     imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
>> +     if (!imx7src)
>> +             return -ENOMEM;
>> +
>> +     imx7src->regmap = syscon_node_to_regmap(dev->of_node);
>> +     if (IS_ERR(imx7src->regmap)) {
>> +             dev_err(dev, "Unable to get imx7-src regmap");
>> +             return PTR_ERR(imx7src->regmap);
>> +     }
>> +     regmap_attach_dev(dev, imx7src->regmap, &config);
>> +
>> +     imx7src->rcdev.owner     = THIS_MODULE;
>> +     imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
>> +     imx7src->rcdev.ops       = &imx7_reset_ops;
>> +     imx7src->rcdev.of_node   = dev->of_node;
>> +
>> +     return devm_reset_controller_register(dev, &imx7src->rcdev);
>> +}
>> +
>> +static const struct of_device_id imx7_reset_dt_ids[] = {
>> +     { .compatible = "fsl,imx7d-src", },
>> +     { /* sentinel */ },
>> +};
>> +
>> +static struct platform_driver imx7_reset_driver = {
>> +     .probe  = imx7_reset_probe,
>> +     .driver = {
>> +             .name           = KBUILD_MODNAME,
>> +             .of_match_table = imx7_reset_dt_ids,
>> +     },
>> +};
>> +builtin_platform_driver(imx7_reset_driver);
>> diff --git a/include/dt-bindings/reset/imx7-reset.h b/include/dt-bindings/reset/imx7-reset.h
>> new file mode 100644
>> index 0000000..6394817
>> --- /dev/null
>> +++ b/include/dt-bindings/reset/imx7-reset.h
>> @@ -0,0 +1,62 @@
>> +/*
>> + * Copyright (C) 2017 Impinj, Inc.
>> + *
>> + * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef DT_BINDING_RESET_IMX7_H
>> +#define DT_BINDING_RESET_IMX7_H
>> +
>> +#define IMX7_RESET_A7_CORE_POR_RESET0        0
>> +#define IMX7_RESET_A7_CORE_POR_RESET1        1
>> +#define IMX7_RESET_A7_CORE_RESET0    2
>> +#define IMX7_RESET_A7_CORE_RESET1    3
>> +#define IMX7_RESET_A7_DBG_RESET0     4
>> +#define IMX7_RESET_A7_DBG_RESET1     5
>> +#define IMX7_RESET_A7_ETM_RESET0     6
>> +#define IMX7_RESET_A7_ETM_RESET1     7
>> +#define IMX7_RESET_A7_SOC_DBG_RESET  8
>> +#define IMX7_RESET_A7_L2RESET                9
>> +#define IMX7_RESET_SW_M4C_RST                10
>> +#define IMX7_RESET_SW_M4P_RST                11
>> +#define IMX7_RESET_EIM_RST           12
>> +#define IMX7_RESET_HSICPHY_PORT_RST  13
>> +#define IMX7_RESET_USBPHY1_POR               14
>> +#define IMX7_RESET_USBPHY1_PORT_RST  15
>> +#define IMX7_RESET_USBPHY2_POR               16
>> +#define IMX7_RESET_USBPHY2_PORT_RST  17
>> +#define IMX7_RESET_MIPI_PHY_MRST     18
>> +#define IMX7_RESET_MIPI_PHY_SRST     19
>> +
>> +/*
>> + * IMX7_RESET_PCIEPHY is a logical reset line combining PCIEPHY_BTN
>> + * and PCIEPHY_G_RST
>> + */
>> +#define IMX7_RESET_PCIEPHY           20
>> +#define IMX7_RESET_PCIEPHY_PERST     21
>> +
>> +/*
>> + * IMX7_RESET_PCIE_CTRL_APPS_EN is not strictly a reset line, but it
>> + * can be used to inhibit PCIe LTTSM, so, in a way, it can be thoguht
>> + * of as one
>> + */
>> +#define IMX7_RESET_PCIE_CTRL_APPS_EN 22
>> +#define IMX7_RESET_DDRC_PRST         23
>> +#define IMX7_RESET_DDRC_CORE_RST     24
>> +
>> +#define IMX7_RESET_NUM                       25
>> +
>> +#endif
>> +
>
> regards
> Philipp
>
>

WARNING: multiple messages have this Message-ID (diff)
From: Andrey Smirnov <andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Cc: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>,
	Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel
	<linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Subject: Re: [PATCH v3] reset: Add i.MX7 SRC reset driver
Date: Mon, 20 Feb 2017 11:46:26 -0800	[thread overview]
Message-ID: <CAHQ1cqFKfez4mGS982mVUz7Sek9Ms2OAkqgd292aOh-RB3OQBg@mail.gmail.com> (raw)
In-Reply-To: <1487607099.3878.44.camel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

On Mon, Feb 20, 2017 at 8:11 AM, Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> wrote:
> Hi Andrey,
>
> On Mon, 2017-02-20 at 07:26 -0800, Andrey Smirnov wrote:
>> Add reset controller driver exposing various reset faculties,
>> implemented by System Reset Controller IP block.
>>
>> Cc: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
>> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>> Signed-off-by: Andrey Smirnov <andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>>
>> Changes since v2 (see [v2]):
>>
>>       - Fix typos
>>
>>       - Kconfig/Makefile chagnes account for alphabetical sorting of
>>           those files
>>
>>       - Remove redundant includes
>>
>>       - Make use of regmap_attach_dev and avoid storing refernce to
>>           struct *dev in private data
>>
>>       - Change code and headers to expose almost all of the reset
>>           related bits in SRC IP block
>
> Thank you, this is looking much better!
>
>> Changes since v1 (see [v1]):
>>
>>       - Various small DT bindings description fixes as per feedback
>>           from Rob Herring
>>
>>
>> [v1] https://lkml.org/lkml/2017/2/6/554
>> [v2] https://lkml.org/lkml/2017/2/13/488
>>
>>
>>  .../devicetree/bindings/reset/fsl,imx7-src.txt     |  47 ++++++
>>  drivers/reset/Kconfig                              |   8 +
>>  drivers/reset/Makefile                             |   2 +
>>  drivers/reset/reset-imx7.c                         | 186 +++++++++++++++++++++
>>  include/dt-bindings/reset/imx7-reset.h             |  62 +++++++
>>  5 files changed, 305 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
>>  create mode 100644 drivers/reset/reset-imx7.c
>>  create mode 100644 include/dt-bindings/reset/imx7-reset.h
>>
>> diff --git a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
>> new file mode 100644
>> index 0000000..5e1afc3
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
>> @@ -0,0 +1,47 @@
>> +Freescale i.MX7 System Reset Controller
>> +======================================
>> +
>> +Please also refer to reset.txt in this directory for common reset
>> +controller binding usage.
>> +
>> +Required properties:
>> +- compatible: Should be "fsl,imx7-src", "syscon"
>> +- reg: should be register base and length as documented in the
>> +  datasheet
>> +- interrupts: Should contain SRC interrupt
>> +- #reset-cells: 1, see below
>> +
>> +example:
>> +
>> +src: reset-controller@30390000 {
>> +     compatible = "fsl,imx7d-src", "syscon";
>> +     reg = <0x30390000 0x2000>;
>> +     interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
>> +     #reset-cells = <1>;
>> +};
>> +
>> +
>> +Specifying reset lines connected to IP modules
>> +==============================================
>> +
>> +The system reset controller can be used to reset various set of
>> +peripherals. Device nodes that need access to reset lines should
>> +specify them as a reset phandle in their corresponding node as
>> +specified in reset.txt.
>> +
>> +Example:
>> +
>> +     pcie: pcie@33800000 {
>> +
>> +             ...
>> +
>> +             resets = <&src IMX7_RESET_PCIEPHY>,
>> +                      <&src IMX7_RESET_PCIE_CTRL_APPS_EN>;
>> +             reset-names = "pciephy", "apps";
>> +
>> +             ...
>> +        };
>> +
>> +
>> +For list of all valid reset indicies see
>> +<dt-bindings/reset/imx7-reset.h>
>> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
>> index 172dc96..bea1800 100644
>> --- a/drivers/reset/Kconfig
>> +++ b/drivers/reset/Kconfig
>> @@ -27,6 +27,14 @@ config RESET_BERLIN
>>       help
>>         This enables the reset controller driver for Marvell Berlin SoCs.
>>
>> +config RESET_IMX7
>> +     bool "i.MX7 Reset Driver"
>> +     depends on SOC_IMX7D || COMPILE_TEST
>> +     select MFD_SYSCON
>> +     default SOC_IMX7D
>> +     help
>> +       This enables the reset controller driver for i.MX7 SoCs.
>> +
>>  config RESET_LPC18XX
>>       bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST
>>       default ARCH_LPC18XX
>> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
>> index 13b346e..a24aa80 100644
>> --- a/drivers/reset/Makefile
>> +++ b/drivers/reset/Makefile
>> @@ -4,6 +4,7 @@ obj-$(CONFIG_ARCH_STI) += sti/
>>  obj-$(CONFIG_ARCH_TEGRA) += tegra/
>>  obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
>>  obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
>> +obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
>>  obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
>>  obj-$(CONFIG_RESET_MESON) += reset-meson.o
>>  obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
>> @@ -14,3 +15,4 @@ obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
>>  obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
>>  obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
>>  obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
>> +
>> diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
>> new file mode 100644
>> index 0000000..6e26796
>> --- /dev/null
>> +++ b/drivers/reset/reset-imx7.c
>> @@ -0,0 +1,186 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * i.MX7 System Reset Controller (SRC) driver
>> + *
>> + * Author: Andrey Smirnov <andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/reset-controller.h>
>> +#include <linux/regmap.h>
>> +#include <dt-bindings/reset/imx7-reset.h>
>> +
>> +struct imx7_src {
>> +     struct reset_controller_dev rcdev;
>> +     struct regmap *regmap;
>> +};
>> +
>> +enum imx7_src_registers {
>> +     SRC_A7RCR0              = 0x0004,
>> +     SRC_M4RCR               = 0x000c,
>> +     SRC_ERCR                = 0x0014,
>> +     SRC_HSICPHY_RCR         = 0x001c,
>> +     SRC_USBOPHY1_RCR        = 0x0020,
>> +     SRC_USBOPHY2_RCR        = 0x0024,
>> +     SRC_MIPIPHY_RCR         = 0x0028,
>> +     SRC_PCIEPHY_RCR         = 0x002c,
>> +     SRC_DDRC_RCR            = 0x1000,
>> +
>> +     SRC_PCIEPHY_RCR_PCIEPHY_G_RST   = BIT(1),
>> +     SRC_PCIEPHY_RCR_PCIEPHY_BTN     = BIT(2),
>> +};
>> +
>> +struct imx7_src_signal {
>> +     unsigned int offset, bit;
>> +};
>> +
>> +static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
>> +     [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
>> +     [IMX7_RESET_A7_CORE_POR_RESET1] = { SRC_A7RCR0, BIT(1) },
>> +     [IMX7_RESET_A7_CORE_RESET0]     = { SRC_A7RCR0, BIT(4) },
>> +     [IMX7_RESET_A7_CORE_RESET1]     = { SRC_A7RCR0, BIT(5) },
>> +     [IMX7_RESET_A7_DBG_RESET0]      = { SRC_A7RCR0, BIT(8) },
>> +     [IMX7_RESET_A7_DBG_RESET1]      = { SRC_A7RCR0, BIT(9) },
>> +     [IMX7_RESET_A7_ETM_RESET0]      = { SRC_A7RCR0, BIT(12) },
>> +     [IMX7_RESET_A7_ETM_RESET1]      = { SRC_A7RCR0, BIT(13) },
>> +     [IMX7_RESET_A7_SOC_DBG_RESET]   = { SRC_A7RCR0, BIT(20) },
>> +     [IMX7_RESET_A7_L2RESET]         = { SRC_A7RCR0, BIT(21) },
>> +     [IMX7_RESET_SW_M4C_RST]         = { SRC_M4RCR, BIT(1) },
>> +     [IMX7_RESET_SW_M4P_RST]         = { SRC_M4RCR, BIT(2) },
>> +     [IMX7_RESET_EIM_RST]            = { SRC_ERCR, BIT(0) },
>> +     [IMX7_RESET_HSICPHY_PORT_RST]   = { SRC_HSICPHY_RCR, BIT(1) },
>> +     [IMX7_RESET_USBPHY1_POR]        = { SRC_USBOPHY1_RCR, BIT(0) },
>> +     [IMX7_RESET_USBPHY1_PORT_RST]   = { SRC_USBOPHY1_RCR, BIT(1) },
>> +     [IMX7_RESET_USBPHY2_POR]        = { SRC_USBOPHY2_RCR, BIT(0) },
>> +     [IMX7_RESET_USBPHY2_PORT_RST]   = { SRC_USBOPHY2_RCR, BIT(1) },
>> +     [IMX7_RESET_MIPI_PHY_MRST]      = { SRC_MIPIPHY_RCR, BIT(1) },
>> +     [IMX7_RESET_MIPI_PHY_SRST]      = { SRC_MIPIPHY_RCR, BIT(2) },
>> +     [IMX7_RESET_PCIEPHY]            = { /* Placeholder */ },
>> +     [IMX7_RESET_PCIEPHY_PERST]      = { SRC_PCIEPHY_RCR, BIT(3) },
>> +     [IMX7_RESET_PCIE_CTRL_APPS_EN]  = { SRC_PCIEPHY_RCR, BIT(6) },
>> +     [IMX7_RESET_DDRC_PRST]          = { SRC_DDRC_RCR, BIT(0) },
>> +     [IMX7_RESET_DDRC_CORE_RST]      = { SRC_DDRC_RCR, BIT(1) },
>> +};
>> +
>> +static struct imx7_src *to_imx7_src(struct reset_controller_dev *rcdev)
>> +{
>> +     return container_of(rcdev, struct imx7_src, rcdev);
>> +}
>> +
>> +static int imx7_reset_assert(struct reset_controller_dev *rcdev,
>> +                          unsigned long id)
>> +{
>> +     struct imx7_src *imx7src = to_imx7_src(rcdev);
>> +     const struct imx7_src_signal *signal = &imx7_src_signals[id];
>> +     unsigned int value = signal->bit;
>> +
>> +     switch (id) {
>> +     case IMX7_RESET_PCIEPHY:
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_G_RST,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_G_RST);
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_BTN,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_BTN);
>
> Is it possible to assert (and deassert) both bits at the same time?
> That would allow to use the default case here.

Good point and I am not sure, I'll do an experiment and see if they can.

>
>> +             break;
>> +
>> +     case IMX7_RESET_PCIE_CTRL_APPS_EN:
>> +             value = 0;
>> +     default:                /* FALLTHROUGH */
>> +             regmap_update_bits(imx7src->regmap,
>> +                                signal->offset, signal->bit, value);
>> +             break;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int imx7_reset_deassert(struct reset_controller_dev *rcdev,
>> +                            unsigned long id)
>> +{
>> +     struct imx7_src *imx7src = to_imx7_src(rcdev);
>> +     const struct imx7_src_signal *signal = &imx7_src_signals[id];
>> +     unsigned int value = 0;
>> +
>> +     switch (id) {
>> +     case IMX7_RESET_PCIEPHY:
>> +             /*
>> +              * wait for more than 10us to release phy g_rst and
>> +              * btnrst
>> +              */
>> +             udelay(10);
>
> What is the purpose of this delay?

That's how downstream PCIe driver is using those lines. I haven't seen
anything in datasheet that would explain the purpose of it.

>
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_G_RST, 0);
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_BTN, 0);
>
> Same as above. Assert and deassert using the same order makes me think
> that the order may not be important at all. If they do on the other hand
> have to be flipped in a certain order, it would be better to expose them
> separately.
>
>> +             break;
>> +     case IMX7_RESET_PCIE_CTRL_APPS_EN:
>> +             value = signal->bit;
>> +     default:                /* FALLTHROUGH */
>> +             regmap_update_bits(imx7src->regmap,
>> +                                signal->offset, signal->bit, value);
>> +
>> +             break;
>> +     };
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct reset_control_ops imx7_reset_ops = {
>> +     .assert         = imx7_reset_assert,
>> +     .deassert       = imx7_reset_deassert,
>> +};
>> +
>> +static int imx7_reset_probe(struct platform_device *pdev)
>> +{
>> +     struct imx7_src *imx7src;
>> +     struct device *dev = &pdev->dev;
>> +     struct regmap_config config = { .name = "src" };
>> +
>> +     imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
>> +     if (!imx7src)
>> +             return -ENOMEM;
>> +
>> +     imx7src->regmap = syscon_node_to_regmap(dev->of_node);
>> +     if (IS_ERR(imx7src->regmap)) {
>> +             dev_err(dev, "Unable to get imx7-src regmap");
>> +             return PTR_ERR(imx7src->regmap);
>> +     }
>> +     regmap_attach_dev(dev, imx7src->regmap, &config);
>> +
>> +     imx7src->rcdev.owner     = THIS_MODULE;
>> +     imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
>> +     imx7src->rcdev.ops       = &imx7_reset_ops;
>> +     imx7src->rcdev.of_node   = dev->of_node;
>> +
>> +     return devm_reset_controller_register(dev, &imx7src->rcdev);
>> +}
>> +
>> +static const struct of_device_id imx7_reset_dt_ids[] = {
>> +     { .compatible = "fsl,imx7d-src", },
>> +     { /* sentinel */ },
>> +};
>> +
>> +static struct platform_driver imx7_reset_driver = {
>> +     .probe  = imx7_reset_probe,
>> +     .driver = {
>> +             .name           = KBUILD_MODNAME,
>> +             .of_match_table = imx7_reset_dt_ids,
>> +     },
>> +};
>> +builtin_platform_driver(imx7_reset_driver);
>> diff --git a/include/dt-bindings/reset/imx7-reset.h b/include/dt-bindings/reset/imx7-reset.h
>> new file mode 100644
>> index 0000000..6394817
>> --- /dev/null
>> +++ b/include/dt-bindings/reset/imx7-reset.h
>> @@ -0,0 +1,62 @@
>> +/*
>> + * Copyright (C) 2017 Impinj, Inc.
>> + *
>> + * Author: Andrey Smirnov <andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef DT_BINDING_RESET_IMX7_H
>> +#define DT_BINDING_RESET_IMX7_H
>> +
>> +#define IMX7_RESET_A7_CORE_POR_RESET0        0
>> +#define IMX7_RESET_A7_CORE_POR_RESET1        1
>> +#define IMX7_RESET_A7_CORE_RESET0    2
>> +#define IMX7_RESET_A7_CORE_RESET1    3
>> +#define IMX7_RESET_A7_DBG_RESET0     4
>> +#define IMX7_RESET_A7_DBG_RESET1     5
>> +#define IMX7_RESET_A7_ETM_RESET0     6
>> +#define IMX7_RESET_A7_ETM_RESET1     7
>> +#define IMX7_RESET_A7_SOC_DBG_RESET  8
>> +#define IMX7_RESET_A7_L2RESET                9
>> +#define IMX7_RESET_SW_M4C_RST                10
>> +#define IMX7_RESET_SW_M4P_RST                11
>> +#define IMX7_RESET_EIM_RST           12
>> +#define IMX7_RESET_HSICPHY_PORT_RST  13
>> +#define IMX7_RESET_USBPHY1_POR               14
>> +#define IMX7_RESET_USBPHY1_PORT_RST  15
>> +#define IMX7_RESET_USBPHY2_POR               16
>> +#define IMX7_RESET_USBPHY2_PORT_RST  17
>> +#define IMX7_RESET_MIPI_PHY_MRST     18
>> +#define IMX7_RESET_MIPI_PHY_SRST     19
>> +
>> +/*
>> + * IMX7_RESET_PCIEPHY is a logical reset line combining PCIEPHY_BTN
>> + * and PCIEPHY_G_RST
>> + */
>> +#define IMX7_RESET_PCIEPHY           20
>> +#define IMX7_RESET_PCIEPHY_PERST     21
>> +
>> +/*
>> + * IMX7_RESET_PCIE_CTRL_APPS_EN is not strictly a reset line, but it
>> + * can be used to inhibit PCIe LTTSM, so, in a way, it can be thoguht
>> + * of as one
>> + */
>> +#define IMX7_RESET_PCIE_CTRL_APPS_EN 22
>> +#define IMX7_RESET_DDRC_PRST         23
>> +#define IMX7_RESET_DDRC_CORE_RST     24
>> +
>> +#define IMX7_RESET_NUM                       25
>> +
>> +#endif
>> +
>
> regards
> Philipp
>
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

WARNING: multiple messages have this Message-ID (diff)
From: andrew.smirnov@gmail.com (Andrey Smirnov)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3] reset: Add i.MX7 SRC reset driver
Date: Mon, 20 Feb 2017 11:46:26 -0800	[thread overview]
Message-ID: <CAHQ1cqFKfez4mGS982mVUz7Sek9Ms2OAkqgd292aOh-RB3OQBg@mail.gmail.com> (raw)
In-Reply-To: <1487607099.3878.44.camel@pengutronix.de>

On Mon, Feb 20, 2017 at 8:11 AM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> Hi Andrey,
>
> On Mon, 2017-02-20 at 07:26 -0800, Andrey Smirnov wrote:
>> Add reset controller driver exposing various reset faculties,
>> implemented by System Reset Controller IP block.
>>
>> Cc: Lucas Stach <l.stach@pengutronix.de>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: devicetree at vger.kernel.org
>> Cc: linux-kernel at vger.kernel.org
>> Cc: linux-arm-kernel at lists.infradead.org
>> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
>> ---
>>
>> Changes since v2 (see [v2]):
>>
>>       - Fix typos
>>
>>       - Kconfig/Makefile chagnes account for alphabetical sorting of
>>           those files
>>
>>       - Remove redundant includes
>>
>>       - Make use of regmap_attach_dev and avoid storing refernce to
>>           struct *dev in private data
>>
>>       - Change code and headers to expose almost all of the reset
>>           related bits in SRC IP block
>
> Thank you, this is looking much better!
>
>> Changes since v1 (see [v1]):
>>
>>       - Various small DT bindings description fixes as per feedback
>>           from Rob Herring
>>
>>
>> [v1] https://lkml.org/lkml/2017/2/6/554
>> [v2] https://lkml.org/lkml/2017/2/13/488
>>
>>
>>  .../devicetree/bindings/reset/fsl,imx7-src.txt     |  47 ++++++
>>  drivers/reset/Kconfig                              |   8 +
>>  drivers/reset/Makefile                             |   2 +
>>  drivers/reset/reset-imx7.c                         | 186 +++++++++++++++++++++
>>  include/dt-bindings/reset/imx7-reset.h             |  62 +++++++
>>  5 files changed, 305 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
>>  create mode 100644 drivers/reset/reset-imx7.c
>>  create mode 100644 include/dt-bindings/reset/imx7-reset.h
>>
>> diff --git a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
>> new file mode 100644
>> index 0000000..5e1afc3
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
>> @@ -0,0 +1,47 @@
>> +Freescale i.MX7 System Reset Controller
>> +======================================
>> +
>> +Please also refer to reset.txt in this directory for common reset
>> +controller binding usage.
>> +
>> +Required properties:
>> +- compatible: Should be "fsl,imx7-src", "syscon"
>> +- reg: should be register base and length as documented in the
>> +  datasheet
>> +- interrupts: Should contain SRC interrupt
>> +- #reset-cells: 1, see below
>> +
>> +example:
>> +
>> +src: reset-controller at 30390000 {
>> +     compatible = "fsl,imx7d-src", "syscon";
>> +     reg = <0x30390000 0x2000>;
>> +     interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
>> +     #reset-cells = <1>;
>> +};
>> +
>> +
>> +Specifying reset lines connected to IP modules
>> +==============================================
>> +
>> +The system reset controller can be used to reset various set of
>> +peripherals. Device nodes that need access to reset lines should
>> +specify them as a reset phandle in their corresponding node as
>> +specified in reset.txt.
>> +
>> +Example:
>> +
>> +     pcie: pcie at 33800000 {
>> +
>> +             ...
>> +
>> +             resets = <&src IMX7_RESET_PCIEPHY>,
>> +                      <&src IMX7_RESET_PCIE_CTRL_APPS_EN>;
>> +             reset-names = "pciephy", "apps";
>> +
>> +             ...
>> +        };
>> +
>> +
>> +For list of all valid reset indicies see
>> +<dt-bindings/reset/imx7-reset.h>
>> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
>> index 172dc96..bea1800 100644
>> --- a/drivers/reset/Kconfig
>> +++ b/drivers/reset/Kconfig
>> @@ -27,6 +27,14 @@ config RESET_BERLIN
>>       help
>>         This enables the reset controller driver for Marvell Berlin SoCs.
>>
>> +config RESET_IMX7
>> +     bool "i.MX7 Reset Driver"
>> +     depends on SOC_IMX7D || COMPILE_TEST
>> +     select MFD_SYSCON
>> +     default SOC_IMX7D
>> +     help
>> +       This enables the reset controller driver for i.MX7 SoCs.
>> +
>>  config RESET_LPC18XX
>>       bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST
>>       default ARCH_LPC18XX
>> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
>> index 13b346e..a24aa80 100644
>> --- a/drivers/reset/Makefile
>> +++ b/drivers/reset/Makefile
>> @@ -4,6 +4,7 @@ obj-$(CONFIG_ARCH_STI) += sti/
>>  obj-$(CONFIG_ARCH_TEGRA) += tegra/
>>  obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
>>  obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
>> +obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
>>  obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
>>  obj-$(CONFIG_RESET_MESON) += reset-meson.o
>>  obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
>> @@ -14,3 +15,4 @@ obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
>>  obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
>>  obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
>>  obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
>> +
>> diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
>> new file mode 100644
>> index 0000000..6e26796
>> --- /dev/null
>> +++ b/drivers/reset/reset-imx7.c
>> @@ -0,0 +1,186 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * i.MX7 System Reset Controller (SRC) driver
>> + *
>> + * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/reset-controller.h>
>> +#include <linux/regmap.h>
>> +#include <dt-bindings/reset/imx7-reset.h>
>> +
>> +struct imx7_src {
>> +     struct reset_controller_dev rcdev;
>> +     struct regmap *regmap;
>> +};
>> +
>> +enum imx7_src_registers {
>> +     SRC_A7RCR0              = 0x0004,
>> +     SRC_M4RCR               = 0x000c,
>> +     SRC_ERCR                = 0x0014,
>> +     SRC_HSICPHY_RCR         = 0x001c,
>> +     SRC_USBOPHY1_RCR        = 0x0020,
>> +     SRC_USBOPHY2_RCR        = 0x0024,
>> +     SRC_MIPIPHY_RCR         = 0x0028,
>> +     SRC_PCIEPHY_RCR         = 0x002c,
>> +     SRC_DDRC_RCR            = 0x1000,
>> +
>> +     SRC_PCIEPHY_RCR_PCIEPHY_G_RST   = BIT(1),
>> +     SRC_PCIEPHY_RCR_PCIEPHY_BTN     = BIT(2),
>> +};
>> +
>> +struct imx7_src_signal {
>> +     unsigned int offset, bit;
>> +};
>> +
>> +static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
>> +     [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
>> +     [IMX7_RESET_A7_CORE_POR_RESET1] = { SRC_A7RCR0, BIT(1) },
>> +     [IMX7_RESET_A7_CORE_RESET0]     = { SRC_A7RCR0, BIT(4) },
>> +     [IMX7_RESET_A7_CORE_RESET1]     = { SRC_A7RCR0, BIT(5) },
>> +     [IMX7_RESET_A7_DBG_RESET0]      = { SRC_A7RCR0, BIT(8) },
>> +     [IMX7_RESET_A7_DBG_RESET1]      = { SRC_A7RCR0, BIT(9) },
>> +     [IMX7_RESET_A7_ETM_RESET0]      = { SRC_A7RCR0, BIT(12) },
>> +     [IMX7_RESET_A7_ETM_RESET1]      = { SRC_A7RCR0, BIT(13) },
>> +     [IMX7_RESET_A7_SOC_DBG_RESET]   = { SRC_A7RCR0, BIT(20) },
>> +     [IMX7_RESET_A7_L2RESET]         = { SRC_A7RCR0, BIT(21) },
>> +     [IMX7_RESET_SW_M4C_RST]         = { SRC_M4RCR, BIT(1) },
>> +     [IMX7_RESET_SW_M4P_RST]         = { SRC_M4RCR, BIT(2) },
>> +     [IMX7_RESET_EIM_RST]            = { SRC_ERCR, BIT(0) },
>> +     [IMX7_RESET_HSICPHY_PORT_RST]   = { SRC_HSICPHY_RCR, BIT(1) },
>> +     [IMX7_RESET_USBPHY1_POR]        = { SRC_USBOPHY1_RCR, BIT(0) },
>> +     [IMX7_RESET_USBPHY1_PORT_RST]   = { SRC_USBOPHY1_RCR, BIT(1) },
>> +     [IMX7_RESET_USBPHY2_POR]        = { SRC_USBOPHY2_RCR, BIT(0) },
>> +     [IMX7_RESET_USBPHY2_PORT_RST]   = { SRC_USBOPHY2_RCR, BIT(1) },
>> +     [IMX7_RESET_MIPI_PHY_MRST]      = { SRC_MIPIPHY_RCR, BIT(1) },
>> +     [IMX7_RESET_MIPI_PHY_SRST]      = { SRC_MIPIPHY_RCR, BIT(2) },
>> +     [IMX7_RESET_PCIEPHY]            = { /* Placeholder */ },
>> +     [IMX7_RESET_PCIEPHY_PERST]      = { SRC_PCIEPHY_RCR, BIT(3) },
>> +     [IMX7_RESET_PCIE_CTRL_APPS_EN]  = { SRC_PCIEPHY_RCR, BIT(6) },
>> +     [IMX7_RESET_DDRC_PRST]          = { SRC_DDRC_RCR, BIT(0) },
>> +     [IMX7_RESET_DDRC_CORE_RST]      = { SRC_DDRC_RCR, BIT(1) },
>> +};
>> +
>> +static struct imx7_src *to_imx7_src(struct reset_controller_dev *rcdev)
>> +{
>> +     return container_of(rcdev, struct imx7_src, rcdev);
>> +}
>> +
>> +static int imx7_reset_assert(struct reset_controller_dev *rcdev,
>> +                          unsigned long id)
>> +{
>> +     struct imx7_src *imx7src = to_imx7_src(rcdev);
>> +     const struct imx7_src_signal *signal = &imx7_src_signals[id];
>> +     unsigned int value = signal->bit;
>> +
>> +     switch (id) {
>> +     case IMX7_RESET_PCIEPHY:
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_G_RST,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_G_RST);
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_BTN,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_BTN);
>
> Is it possible to assert (and deassert) both bits at the same time?
> That would allow to use the default case here.

Good point and I am not sure, I'll do an experiment and see if they can.

>
>> +             break;
>> +
>> +     case IMX7_RESET_PCIE_CTRL_APPS_EN:
>> +             value = 0;
>> +     default:                /* FALLTHROUGH */
>> +             regmap_update_bits(imx7src->regmap,
>> +                                signal->offset, signal->bit, value);
>> +             break;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int imx7_reset_deassert(struct reset_controller_dev *rcdev,
>> +                            unsigned long id)
>> +{
>> +     struct imx7_src *imx7src = to_imx7_src(rcdev);
>> +     const struct imx7_src_signal *signal = &imx7_src_signals[id];
>> +     unsigned int value = 0;
>> +
>> +     switch (id) {
>> +     case IMX7_RESET_PCIEPHY:
>> +             /*
>> +              * wait for more than 10us to release phy g_rst and
>> +              * btnrst
>> +              */
>> +             udelay(10);
>
> What is the purpose of this delay?

That's how downstream PCIe driver is using those lines. I haven't seen
anything in datasheet that would explain the purpose of it.

>
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_G_RST, 0);
>> +             regmap_update_bits(imx7src->regmap,
>> +                                SRC_PCIEPHY_RCR,
>> +                                SRC_PCIEPHY_RCR_PCIEPHY_BTN, 0);
>
> Same as above. Assert and deassert using the same order makes me think
> that the order may not be important at all. If they do on the other hand
> have to be flipped in a certain order, it would be better to expose them
> separately.
>
>> +             break;
>> +     case IMX7_RESET_PCIE_CTRL_APPS_EN:
>> +             value = signal->bit;
>> +     default:                /* FALLTHROUGH */
>> +             regmap_update_bits(imx7src->regmap,
>> +                                signal->offset, signal->bit, value);
>> +
>> +             break;
>> +     };
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct reset_control_ops imx7_reset_ops = {
>> +     .assert         = imx7_reset_assert,
>> +     .deassert       = imx7_reset_deassert,
>> +};
>> +
>> +static int imx7_reset_probe(struct platform_device *pdev)
>> +{
>> +     struct imx7_src *imx7src;
>> +     struct device *dev = &pdev->dev;
>> +     struct regmap_config config = { .name = "src" };
>> +
>> +     imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
>> +     if (!imx7src)
>> +             return -ENOMEM;
>> +
>> +     imx7src->regmap = syscon_node_to_regmap(dev->of_node);
>> +     if (IS_ERR(imx7src->regmap)) {
>> +             dev_err(dev, "Unable to get imx7-src regmap");
>> +             return PTR_ERR(imx7src->regmap);
>> +     }
>> +     regmap_attach_dev(dev, imx7src->regmap, &config);
>> +
>> +     imx7src->rcdev.owner     = THIS_MODULE;
>> +     imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
>> +     imx7src->rcdev.ops       = &imx7_reset_ops;
>> +     imx7src->rcdev.of_node   = dev->of_node;
>> +
>> +     return devm_reset_controller_register(dev, &imx7src->rcdev);
>> +}
>> +
>> +static const struct of_device_id imx7_reset_dt_ids[] = {
>> +     { .compatible = "fsl,imx7d-src", },
>> +     { /* sentinel */ },
>> +};
>> +
>> +static struct platform_driver imx7_reset_driver = {
>> +     .probe  = imx7_reset_probe,
>> +     .driver = {
>> +             .name           = KBUILD_MODNAME,
>> +             .of_match_table = imx7_reset_dt_ids,
>> +     },
>> +};
>> +builtin_platform_driver(imx7_reset_driver);
>> diff --git a/include/dt-bindings/reset/imx7-reset.h b/include/dt-bindings/reset/imx7-reset.h
>> new file mode 100644
>> index 0000000..6394817
>> --- /dev/null
>> +++ b/include/dt-bindings/reset/imx7-reset.h
>> @@ -0,0 +1,62 @@
>> +/*
>> + * Copyright (C) 2017 Impinj, Inc.
>> + *
>> + * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef DT_BINDING_RESET_IMX7_H
>> +#define DT_BINDING_RESET_IMX7_H
>> +
>> +#define IMX7_RESET_A7_CORE_POR_RESET0        0
>> +#define IMX7_RESET_A7_CORE_POR_RESET1        1
>> +#define IMX7_RESET_A7_CORE_RESET0    2
>> +#define IMX7_RESET_A7_CORE_RESET1    3
>> +#define IMX7_RESET_A7_DBG_RESET0     4
>> +#define IMX7_RESET_A7_DBG_RESET1     5
>> +#define IMX7_RESET_A7_ETM_RESET0     6
>> +#define IMX7_RESET_A7_ETM_RESET1     7
>> +#define IMX7_RESET_A7_SOC_DBG_RESET  8
>> +#define IMX7_RESET_A7_L2RESET                9
>> +#define IMX7_RESET_SW_M4C_RST                10
>> +#define IMX7_RESET_SW_M4P_RST                11
>> +#define IMX7_RESET_EIM_RST           12
>> +#define IMX7_RESET_HSICPHY_PORT_RST  13
>> +#define IMX7_RESET_USBPHY1_POR               14
>> +#define IMX7_RESET_USBPHY1_PORT_RST  15
>> +#define IMX7_RESET_USBPHY2_POR               16
>> +#define IMX7_RESET_USBPHY2_PORT_RST  17
>> +#define IMX7_RESET_MIPI_PHY_MRST     18
>> +#define IMX7_RESET_MIPI_PHY_SRST     19
>> +
>> +/*
>> + * IMX7_RESET_PCIEPHY is a logical reset line combining PCIEPHY_BTN
>> + * and PCIEPHY_G_RST
>> + */
>> +#define IMX7_RESET_PCIEPHY           20
>> +#define IMX7_RESET_PCIEPHY_PERST     21
>> +
>> +/*
>> + * IMX7_RESET_PCIE_CTRL_APPS_EN is not strictly a reset line, but it
>> + * can be used to inhibit PCIe LTTSM, so, in a way, it can be thoguht
>> + * of as one
>> + */
>> +#define IMX7_RESET_PCIE_CTRL_APPS_EN 22
>> +#define IMX7_RESET_DDRC_PRST         23
>> +#define IMX7_RESET_DDRC_CORE_RST     24
>> +
>> +#define IMX7_RESET_NUM                       25
>> +
>> +#endif
>> +
>
> regards
> Philipp
>
>

  reply	other threads:[~2017-02-20 19:46 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-20 15:26 [PATCH v3] reset: Add i.MX7 SRC reset driver Andrey Smirnov
2017-02-20 15:26 ` Andrey Smirnov
2017-02-20 15:26 ` Andrey Smirnov
2017-02-20 16:11 ` Philipp Zabel
2017-02-20 16:11   ` Philipp Zabel
2017-02-20 16:11   ` Philipp Zabel
2017-02-20 19:46   ` Andrey Smirnov [this message]
2017-02-20 19:46     ` Andrey Smirnov
2017-02-20 19:46     ` Andrey Smirnov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAHQ1cqFKfez4mGS982mVUz7Sek9Ms2OAkqgd292aOh-RB3OQBg@mail.gmail.com \
    --to=andrew.smirnov@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=l.stach@pengutronix.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=p.zabel@pengutronix.de \
    --cc=robh+dt@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.