* [PATCH/RFT v2 07/17] ARM: davinci: da8xx: Enable the usb20 "per" clk on phy_clk_enable
From: Axel Haslam @ 2016-10-25 10:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <c2d31f5a-32c6-5e93-2d3d-d6ef75b697fc@lechnology.com>
On Tue, Oct 25, 2016 at 4:53 AM, David Lechner <david@lechnology.com> wrote:
> On 10/24/2016 11:46 AM, ahaslam at baylibre.com wrote:
>>
>> From: Axel Haslam <ahaslam@baylibre.com>
>>
>> While probing ochi phy with usb20 phy as a parent clock for usb11_phy,
>> the usb20_phy clock enable would time out. This is because the usb20
>> module clock needs to enabled while trying to lock the usb20_phy PLL.
>>
>> Call clk enable and get for the usb20 peripheral before trying to
>> enable the phy PLL.
>>
>> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
>> ---
>
>
>
> This patch can be combined with "ARM: davinci: da8xx: add usb phy clocks"
> since that patch has not been merged yet.
yes, agree, these should be merged.
>
> If you like, I can resubmit my patches from this series along with the
> changes from this patch.
Ok, if you can resubmit those patches with this change included
i can reference them and start making the series shorter.
i will also submit in separate patches the regulator changes, as requested
by Mark.
Regards
Axel.
>
^ permalink raw reply
* [PATCH] ARM: sti: stih410-clocks: Add PROC_STFE as a critical clock
From: Lee Jones @ 2016-10-25 10:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161025093926.GA3206@griffinp-ThinkPad-X1-Carbon-2nd>
On Tue, 25 Oct 2016, Peter Griffin wrote:
> Hi Lee,
>
> On Tue, 25 Oct 2016, Lee Jones wrote:
>
> > On Mon, 24 Oct 2016, Peter Griffin wrote:
> >
> > > Hi Lee,
> > >
> > > On Mon, 24 Oct 2016, Lee Jones wrote:
> > > > On Tue, 18 Oct 2016, Peter Griffin wrote:
> > > >
> > > > > Once the ST frontend demux HW IP has been enabled, the clock can't
> > > > > be disabled otherwise the system will hang and the board will
> > > > > be unserviceable.
> > > > >
> > > > > To allow balanced clock enable/disable calls in the driver we use
> > > > > the critical clock infrastructure to take an extra reference on the
> > > > > clock so the clock will never actually be disabled.
> > > >
> > > > This is an abuse of the critical-clocks framework, and is exactly the
> > > > type of hack I promised the clk guys I'd try to prevent.
> > >
> > > I expect the best way to do this would be to write some documentation on the
> > > clock-critical DT binding and/or CRITICAL_CLK flag. The only documentation I can
> > > find currently is with the initial patch series [1] and the comment in
> > > clk-provider.h of
> > >
> > > #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */
> > >
> > > Or the patch decription
> > >
> > > "Critical clocks are those which must not be gated, else undefined
> > > or catastrophic failure would occur. Here we have chosen to
> > > ensure the prepare/enable counts are correctly incremented, so as
> > > not to confuse users with enabled clocks with no visible users."
> > >
> > > Which is the functionality I want for this clock.
> >
> > No, that's not the functionality you want.
>
> Yes it is :)
No, it's the functionally that is most convenient.
> > You want for the clock not
> > to be RE-gated (big difference). Currently, the STFE clock will never
> > be gated, even when a) it's not used and b) can actually be disabled.
> > You're needlessly wasting power here.
>
> IMO it is *never* safe for Linux to gate this clock, as you have no idea
> on the state of the hardware from the primary and secondary bootloaders.
You can say that with any of the clocks on this platform.
> If the clock is enabled when Linux boots, the Linux clock framework *needs*
> to assume the hardware may have been used in previous boot stages, and it should
> not attempt to disable the clock.
None of the boot loaders we use do this.
I have never seen the STFE clock crash a platform.
> > Also, in your use-case there is a visible user, and the prepare/enable
> > counts will be correct.
>
> Your correct there is a visible user, but this is the same as CLK_EXT2F_A9 where
> there are multiple users of the clock (SPI, I2C, UART etc).
Right, but their clocks can not be turned off, ever. So all the boxes
are ticked for criticalness. Not the case with your clock.
> > > > If this, or
> > > > any other IP has some quirks (i.e. once enabled, if this clock is
> > > > subsequently disabled it will have a catastrophic effect on the
> > > > platform), then they should be worked around in the driver.
> > > >
> > > > The correct thing to do here is craft a clk-keep-on flag and ensure it
> > > > is set to true for the effected platform(s)' platform data.
> > >
> > > I'm always wary of creating a driver specific flag, especially when its
> > > purpose is to do the same thing as an existing mechanism provided by the
> > > subsystem of not gating the clock.
> >
> > Using existing sub-system supplied mechanisms in the way they were not
> > intended is sub-optimal (read "hacky").
>
> I think the scope of this flag has been defined in a very narrow way, which is
> making you want to suggest lots of hacks in the client driver.
The scope was narrowed intentionally, buy the maintainers. I am
merely reflecting their views. If you really wish to contend these,
you should take it up with them.
> > > I can see a couple of problems with what you propose:
> > >
> > > 1) You have to put the clk-keep-on flag in every driver which consumes the
> > > clock. IMO it is much better to have this knowledge in the SoC's
> > > clock driver so every consumer of the clock automatically benefits.
> >
> > That would also be fine(ish). The issue is that this problem is
> > board specific, so the platform clock driver would have to contain
> > board level knowledge.
>
> It is not board specific. It is a SoC HW bug, so by definition present on all
> boards which have this SoC.
Okay SoC specific. Is there a SoC specific clock driver?
> > Also, if you were to implement this, it would
> > too mess up reference counting in the core.
This still stands.
> > > 2) You don't benefit from the CLK_IS_CRITICAL reference counting logic in
> > > clk.c. So then each driver has to also work around that to get sensible reference
> > > counts. e.g.
> > >
> > > if (!__clk_is_enabled(clk) && pdata->clk-keep-on)
> > > clk_enable(clk)
> > >
> > > Which seems to me to be fighting against the subsystem. Given that the only use of
> > > _clk_is_enabled() outside drivers/clk is in an old arch/arm/mach-omap2/pm24xx.c
> > > driver I suspect its use is frowned upon, and it shouldn't really be an EXPORTED_SYMBOL.
> >
> > In this instance, since the STFE clock is only used by this IP, I
> > would choose to handle it in the driver.
>
> There are other IPs within this IP block for which upstream drivers don't yet exist.
If they are many and various, we can discuss alternative solutions.
What are they?
> > This can be done using a
> > single flag stored in pdata which should be fetched using
> > of_match_device(). This way there is no need for any more API abuse;
> > either by incorrectly identifying the STFE clock as critical OR
> > invoking any internal __clk_*() calls.
> >
> > Enable the clock once in .probe(), which you already do.
>
> But these drivers are by default built as modules, so when you rmmod, and insmod the
> driver you now have an ever increasing clock reference count. This is the
> problem I was describing in the previous email, and why what you propose is a
> bad idea.
Then the variable would have to be exported.
> > Then, whenever you do any power saving do:
> >
> > suspend()
> > {
> > if (!ddata->enable_clk_once)
> > clk_disable(clk);
> > }
> >
> > resume()
> > {
> > if (!ddata->enable_clk_once)
> > clk_enable(clk);
> > }
> >
> > However, looking at your driver, I think this point might even be
> > moot, since you don't have any power saving. The only time you
> > disable the clock is in the error path. Just replace that with a
> > comment about the platform's unfortunate errata.
>
> This is exactly what I want to avoid doing. The driver already has these
> hacks as it was waiting for the critical clock patches to land so I could remove
> them and fix the problem properly.
>
> Much like you did with the I2C and SPI drivers, where you removed similar hacks
> and added the clock to the critical clock list.
Right, see above.
> > > [1] https://lkml.org/lkml/2016/1/18/272
> >
> > I'm glad you mentioned this. Let's take a look:
> >
> > > Some platforms contain clocks which if gated, will cause undefined or
> > > catastrophic behaviours. As such they are not to be turned off, ever.
> >
> > Not the case here.
> >
> > This clock *can* be gated and can be turned off *sometimes*.
>
> See above, if the clock is on when Linux boots it can never be assumed that it
> is safe to disable it.
See above.
> > > Many of these such clocks do not have devices, thus device drivers
> > > where clocks may be enabled and references taken to ensure they stay
> > > enabled do not exist. Therefore, we must handle these such cases in
> > > the core.
> >
> > This clock *does* have a driver and correct references *can* be
> > taken.
>
> As above this is the same for CLK_EXT2F_A9, which has multiple users in the
> kernel.
>
> The point is we don't wish to have the knowledge in the individual drivers that
> this clock is critical and can destroy the system if it is disabled.
>
> >
> > [...]
> >
> > All I'm saying is, and it's the same thing I've said many times; these
> > types of issues do not exhibit the same set of symptoms as a critical
> > clock by definition. Critical clocks are those which references can
> > not be taken by any other means.
>
> That is not how you are using it currently. See CLK_EXT2F_A9 and
> CLK_TX_ICN_DMU.
>
> > Think of the critical clock
> > framework as a mechanism to circumvent the requirement of writing a
> > special driver which would *only* handle clocks i.e. an interconnect
> > driver in the ST case.
> >
>
> You didn't need a new flag for that. CLK_IGNORE_UNUSED already allowed you to not
> write a specical driver which only handled for example an interconnect clock and
> would ensure it wouldn't be gated by the disable_unused logic.
>
> IMO the point of the critical clock stuff, and what CLK_IGNORE_UNUSED *did not* allow
> you to do is for situations like CLK_EXT2F_A9, CLK_TX_ICN_DMU and PROC_STFE where users
> *do* exist in the kernel, but the SoC clock driver has *special* knowledge of the
> clock tree on the SoC and knows that despite what the drivers are doing with
> their enable/disable calls the clock should never be disabled.
>
> In fact out of what we currently mark as clock-critical on STi platform most
> of the clocks could have been handled perfectly fine with the CLK_IGNORE_UNUSED
> flag (apart from the fact that there is no way to set the flag from DT). It is
> only CLK_EXT2F_A9 and CLK_TX_ICN_DMU which *do* have kernel users where the
> extra functionality of critical clocks is required (we need the additional
> reference taken by the clk framework to avoid the kernel drivers from disabling
> the clock).
Probably best to take your special use-case up with the Clock
Maintainers. As the author of the critical-clocks patch-set, I would
say that your use-case does not tick all the boxes for use of the
critical-clock mechanism, but at the end of the day, it really isn't
my train-set.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH/RFT v2 13/17] USB: da8xx: use ohci priv data instead of globals
From: Axel Haslam @ 2016-10-25 9:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0cf6f211-90ba-2f7b-978f-f1cfa1b11554@lechnology.com>
On Tue, Oct 25, 2016 at 3:12 AM, David Lechner <david@lechnology.com> wrote:
> On 10/24/2016 11:46 AM, ahaslam at baylibre.com wrote:
>>
>> From: Axel Haslam <ahaslam@baylibre.com>
>> > static const struct ohci_driver_overrides da8xx_overrides __initconst =
>> > {
>> - .reset = ohci_da8xx_reset
>> + .reset = ohci_da8xx_reset,
>> + .extra_priv_size = sizeof(struct da8xx_ohci_hcd),
>
>
> nit: since you are changing both lines anyway, you might as well make the
> ='s line up.
ok, will do.
>
>> };
>>
>> /*
>>
>
^ permalink raw reply
* [PATCH/RFT v2 15/17] usb: host: ohci-da8xx: Add devicetree bindings documentation
From: Axel Haslam @ 2016-10-25 9:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <523928a1-a321-abb6-504f-a1053c88ce53@lechnology.com>
On Tue, Oct 25, 2016 at 3:02 AM, David Lechner <david@lechnology.com> wrote:
> On 10/24/2016 11:46 AM, ahaslam at baylibre.com wrote:
>>
>> From: Axel Haslam <ahaslam@baylibre.com>
>>
>> This patch documents the device tree bindings required for
>> the ohci controller found in TI da8xx family of SoC's
>>
>> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
>> ---
>> .../devicetree/bindings/usb/ohci-da8xx.txt | 39
>> ++++++++++++++++++++++
>> 1 file changed, 39 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/usb/ohci-da8xx.txt
>>
>> diff --git a/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
>> b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
>> new file mode 100644
>> index 0000000..4251c84
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
>> @@ -0,0 +1,39 @@
>> +DA8XX USB OHCI controller
>> +
>> +Required properties:
>> +
>> + - compatible: Should be "ti,da830-ohci"
>> + - reg: Should contain one register range i.e. start and length
>> + - interrupts: Description of the interrupt line
>> + - phys: Phandle for the PHY device
>> + - phy-names: Should be "usb-phy"
>> +
>> +Optional properties:
>> + - vbus-supply: Regulator that controls vbus power
>
>
>
> Isn't vbus-supply property required?
>
> If it is really supposed to be optional, the ohci driver needs to use
> devm_regulator_get_optional() and handle the case when there is no
> regulator.
>
> I don't see a problem with making it required though since one can just use
> a dummy supply if there is not a real one.
The regulator framework will use a dummy regulator if none is provided.
>
>> +
>> +Example for omap138-lck:
>> +
>> +vbus_fixed: fixed-regulator-vbus {
>> + compatible = "regulator-fixed";
>> + gpio = <&gpio 109 0>;
>> + oc-gpio = <&gpio 36 0>;
>> + regulator-boot-on;
>> + enable-active-high;
>> + regulator-name = "vbus";
>> + regulator-min-microvolt = <5000000>;
>> + regulator-max-microvolt = <5000000>;
>> +};
>> +
>> +usb_phy: usb-phy {
>> + compatible = "ti,da830-usb-phy";
>> + #phy-cells = <1>;
>> + status = "disabled";
>
>
> why disabled?
>
yes, i copied from the device tree im using, but
i should enable these for the example,
i will fix.
>> +};
>> +usb: usb at 0225000 {
>> + compatible = "ti,da830-ohci";
>> + reg = <0x225000 0x1000>;
>> + interrupts = <59>;
>> + phys = <&usb_phy 1>;
>> + phy-names = "usb-phy";
>
>
> missing vbus-supply property
>
>> + status = "disabled";
>
>
> why disabled?
>
>> +};
>>
>
^ permalink raw reply
* [PATCH v2 3/4] soc: ti: Add ti_sci_pm_domains driver
From: Ulf Hansson @ 2016-10-25 9:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161019203347.17893-4-d-gerlach@ti.com>
On 19 October 2016 at 22:33, Dave Gerlach <d-gerlach@ti.com> wrote:
> Introduce a ti_sci_pm_domains driver to act as a generic pm domain provider
> to allow each device to attach and associate it's ti-sci-id so that it can
> be controlled through the TI SCI protocol.
>
> This driver implements a simple genpd where each device node has
> a phandle to the power domain node and also must provide an index which
> represents the ID to be passed with TI SCI representing the device using a
> ti,sci-id property. Through this interface the genpd dev_ops start and
> stop hooks will use TI SCI to turn on and off each device as determined
> by pm_runtime usage.
>
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> Signed-off-by: Nishanth Menon <nm@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Looks good!
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Kind regards
Uffe
> ---
> MAINTAINERS | 1 +
> arch/arm/mach-keystone/Kconfig | 1 +
> drivers/soc/ti/Kconfig | 12 +++
> drivers/soc/ti/Makefile | 1 +
> drivers/soc/ti/ti_sci_pm_domains.c | 198 +++++++++++++++++++++++++++++++++++++
> 5 files changed, 213 insertions(+)
> create mode 100644 drivers/soc/ti/ti_sci_pm_domains.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d894873c2bff..3eaac5ede847 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11894,6 +11894,7 @@ F: drivers/firmware/ti_sci*
> F: include/linux/soc/ti/ti_sci_protocol.h
> F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
> F: include/dt-bindings/genpd/k2g.h
> +F: drivers/soc/ti/ti_sci_pm_domains.c
>
> THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
> M: Hans Verkuil <hverkuil@xs4all.nl>
> diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
> index 24bd64dabdfc..18d49465cafb 100644
> --- a/arch/arm/mach-keystone/Kconfig
> +++ b/arch/arm/mach-keystone/Kconfig
> @@ -9,6 +9,7 @@ config ARCH_KEYSTONE
> select ARCH_SUPPORTS_BIG_ENDIAN
> select ZONE_DMA if ARM_LPAE
> select PINCTRL
> + select PM_GENERIC_DOMAINS if PM
> help
> Support for boards based on the Texas Instruments Keystone family of
> SoCs.
> diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
> index 3557c5e32a93..39e152abe6b9 100644
> --- a/drivers/soc/ti/Kconfig
> +++ b/drivers/soc/ti/Kconfig
> @@ -38,4 +38,16 @@ config WKUP_M3_IPC
> to communicate and use the Wakeup M3 for PM features like suspend
> resume and boots it using wkup_m3_rproc driver.
>
> +config TI_SCI_PM_DOMAINS
> + tristate "TI SCI PM Domains Driver"
> + depends on TI_SCI_PROTOCOL
> + depends on PM_GENERIC_DOMAINS
> + help
> + Generic power domain implementation for TI device implementing
> + the TI SCI protocol.
> +
> + To compile this as a module, choose M here. The module will be
> + called ti_sci_pm_domains. Note this is needed early in boot before
> + rootfs may be available.
> +
> endif # SOC_TI
> diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile
> index 48ff3a79634f..7d572736c86e 100644
> --- a/drivers/soc/ti/Makefile
> +++ b/drivers/soc/ti/Makefile
> @@ -5,3 +5,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS) += knav_qmss.o
> knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o
> obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o
> obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o
> +obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o
> diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/soc/ti/ti_sci_pm_domains.c
> new file mode 100644
> index 000000000000..ec76215d64c7
> --- /dev/null
> +++ b/drivers/soc/ti/ti_sci_pm_domains.c
> @@ -0,0 +1,198 @@
> +/*
> + * TI SCI Generic Power Domain Driver
> + *
> + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
> + * J Keerthy <j-keerthy@ti.com>
> + * Dave Gerlach <d-gerlach@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * 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/err.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_domain.h>
> +#include <linux/slab.h>
> +#include <linux/soc/ti/ti_sci_protocol.h>
> +
> +/**
> + * struct ti_sci_genpd_dev_data: holds data needed for every device attached
> + * to this genpd
> + * @idx: index of the device that identifies it with the system
> + * control processor.
> + */
> +struct ti_sci_genpd_dev_data {
> + int idx;
> +};
> +
> +/**
> + * struct ti_sci_pm_domain: TI specific data needed for power domain
> + * @ti_sci: handle to TI SCI protocol driver that provides ops to
> + * communicate with system control processor.
> + * @dev: pointer to dev for the driver for devm allocs
> + * @pd: generic_pm_domain for use with the genpd framework
> + */
> +struct ti_sci_pm_domain {
> + const struct ti_sci_handle *ti_sci;
> + struct device *dev;
> + struct generic_pm_domain pd;
> +};
> +
> +#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)
> +
> +/**
> + * ti_sci_dev_id(): get prepopulated ti_sci id from struct dev
> + * @dev: pointer to device associated with this genpd
> + *
> + * Returns device_id stored from ti,sci_id property
> + */
> +static int ti_sci_dev_id(struct device *dev)
> +{
> + struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
> + struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
> +
> + return sci_dev_data->idx;
> +}
> +
> +/**
> + * ti_sci_dev_to_sci_handle(): get pointer to ti_sci_handle
> + * @dev: pointer to device associated with this genpd
> + *
> + * Returns ti_sci_handle to be used to communicate with system
> + * control processor.
> + */
> +static const struct ti_sci_handle *ti_sci_dev_to_sci_handle(struct device *dev)
> +{
> + struct generic_pm_domain *pd = pd_to_genpd(dev->pm_domain);
> + struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(pd);
> +
> + return ti_sci_genpd->ti_sci;
> +}
> +
> +/**
> + * ti_sci_dev_start(): genpd device start hook called to turn device on
> + * @dev: pointer to device associated with this genpd to be powered on
> + */
> +static int ti_sci_dev_start(struct device *dev)
> +{
> + const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
> + int idx = ti_sci_dev_id(dev);
> +
> + return ti_sci->ops.dev_ops.get_device(ti_sci, idx);
> +}
> +
> +/**
> + * ti_sci_dev_stop(): genpd device stop hook called to turn device off
> + * @dev: pointer to device associated with this genpd to be powered off
> + */
> +static int ti_sci_dev_stop(struct device *dev)
> +{
> + const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
> + int idx = ti_sci_dev_id(dev);
> +
> + return ti_sci->ops.dev_ops.put_device(ti_sci, idx);
> +}
> +
> +static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain,
> + struct device *dev)
> +{
> + struct device_node *np = dev->of_node;
> + struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(domain);
> + const struct ti_sci_handle *ti_sci = ti_sci_genpd->ti_sci;
> + struct ti_sci_genpd_dev_data *sci_dev_data;
> + struct generic_pm_domain_data *genpd_data;
> + int idx, ret = 0;
> +
> + ret = of_property_read_u32(np, "ti,sci-id", &idx);
> + if (ret) {
> + dev_err(ti_sci_genpd->dev, "Cannot find ti,sci-id for %s\n",
> + dev_name(dev));
> + return -ENODEV;
> + }
> +
> + /*
> + * Check the validity of the requested idx, if the index is not valid
> + * the PMMC will return a NAK here and we will not allocate it.
> + */
> + ret = ti_sci->ops.dev_ops.is_valid(ti_sci, idx);
> + if (ret)
> + return -EINVAL;
> +
> + sci_dev_data = kzalloc(sizeof(*sci_dev_data), GFP_KERNEL);
> + if (!sci_dev_data)
> + return -ENOMEM;
> +
> + sci_dev_data->idx = idx;
> +
> + genpd_data = dev_gpd_data(dev);
> + genpd_data->data = sci_dev_data;
> +
> + return 0;
> +}
> +
> +static void ti_sci_pd_detach_dev(struct generic_pm_domain *domain,
> + struct device *dev)
> +{
> + struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
> + struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
> +
> + kfree(sci_dev_data);
> + genpd_data->data = NULL;
> +}
> +
> +static const struct of_device_id ti_sci_pm_domain_matches[] = {
> + { .compatible = "ti,sci-pm-domain", },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches);
> +
> +static int ti_sci_pm_domain_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + struct ti_sci_pm_domain *ti_sci_pd;
> + int ret;
> +
> + ti_sci_pd = devm_kzalloc(dev, sizeof(*ti_sci_pd), GFP_KERNEL);
> + if (!ti_sci_pd)
> + return -ENOMEM;
> +
> + ti_sci_pd->ti_sci = devm_ti_sci_get_handle(dev);
> + if (IS_ERR(ti_sci_pd->ti_sci))
> + return PTR_ERR(ti_sci_pd->ti_sci);
> +
> + ti_sci_pd->dev = dev;
> +
> + ti_sci_pd->pd.attach_dev = ti_sci_pd_attach_dev;
> + ti_sci_pd->pd.detach_dev = ti_sci_pd_detach_dev;
> +
> + ti_sci_pd->pd.dev_ops.start = ti_sci_dev_start;
> + ti_sci_pd->pd.dev_ops.stop = ti_sci_dev_stop;
> +
> + pm_genpd_init(&ti_sci_pd->pd, NULL, true);
> +
> + ret = of_genpd_add_provider_simple(np, &ti_sci_pd->pd);
> +
> + return ret;
> +}
> +
> +static struct platform_driver ti_sci_pm_domains_driver = {
> + .probe = ti_sci_pm_domain_probe,
> + .driver = {
> + .name = "ti_sci_pm_domains",
> + .of_match_table = ti_sci_pm_domain_matches,
> + },
> +};
> +module_platform_driver(ti_sci_pm_domains_driver);
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver");
> +MODULE_AUTHOR("Dave Gerlach");
> --
> 2.9.3
>
^ permalink raw reply
* [PATCH v2 1/4] PM / Domains: Add generic data pointer to genpd data struct
From: Ulf Hansson @ 2016-10-25 9:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161019203347.17893-2-d-gerlach@ti.com>
On 19 October 2016 at 22:33, Dave Gerlach <d-gerlach@ti.com> wrote:
> Add a void *data pointer to struct generic_pm_domain_data. Because this
> exists for each device associated with a genpd it will allow us to
> assign per-device data if needed on a platform for control of that
> specific device.
>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Kind regards
Uffe
> ---
> include/linux/pm_domain.h | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
> index a09fe5c009c8..9c0a897fe605 100644
> --- a/include/linux/pm_domain.h
> +++ b/include/linux/pm_domain.h
> @@ -105,6 +105,7 @@ struct generic_pm_domain_data {
> struct pm_domain_data base;
> struct gpd_timing_data td;
> struct notifier_block nb;
> + void *data;
> };
>
> #ifdef CONFIG_PM_GENERIC_DOMAINS
> --
> 2.9.3
>
^ permalink raw reply
* [PATCH] ARM: sti: stih410-clocks: Add PROC_STFE as a critical clock
From: Peter Griffin @ 2016-10-25 9:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161025074257.GF8574@dell>
Hi Lee,
On Tue, 25 Oct 2016, Lee Jones wrote:
> On Mon, 24 Oct 2016, Peter Griffin wrote:
>
> > Hi Lee,
> >
> > On Mon, 24 Oct 2016, Lee Jones wrote:
> > > On Tue, 18 Oct 2016, Peter Griffin wrote:
> > >
> > > > Once the ST frontend demux HW IP has been enabled, the clock can't
> > > > be disabled otherwise the system will hang and the board will
> > > > be unserviceable.
> > > >
> > > > To allow balanced clock enable/disable calls in the driver we use
> > > > the critical clock infrastructure to take an extra reference on the
> > > > clock so the clock will never actually be disabled.
> > >
> > > This is an abuse of the critical-clocks framework, and is exactly the
> > > type of hack I promised the clk guys I'd try to prevent.
> >
> > I expect the best way to do this would be to write some documentation on the
> > clock-critical DT binding and/or CRITICAL_CLK flag. The only documentation I can
> > find currently is with the initial patch series [1] and the comment in
> > clk-provider.h of
> >
> > #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */
> >
> > Or the patch decription
> >
> > "Critical clocks are those which must not be gated, else undefined
> > or catastrophic failure would occur. Here we have chosen to
> > ensure the prepare/enable counts are correctly incremented, so as
> > not to confuse users with enabled clocks with no visible users."
> >
> > Which is the functionality I want for this clock.
>
> No, that's not the functionality you want.
Yes it is :)
> You want for the clock not
> to be RE-gated (big difference). Currently, the STFE clock will never
> be gated, even when a) it's not used and b) can actually be disabled.
> You're needlessly wasting power here.
IMO it is *never* safe for Linux to gate this clock, as you have no idea
on the state of the hardware from the primary and secondary bootloaders.
If the clock is enabled when Linux boots, the Linux clock framework *needs*
to assume the hardware may have been used in previous boot stages, and it should
not attempt to disable the clock.
>
> Also, in your use-case there is a visible user, and the prepare/enable
> counts will be correct.
Your correct there is a visible user, but this is the same as CLK_EXT2F_A9 where
there are multiple users of the clock (SPI, I2C, UART etc).
>
> > > If this, or
> > > any other IP has some quirks (i.e. once enabled, if this clock is
> > > subsequently disabled it will have a catastrophic effect on the
> > > platform), then they should be worked around in the driver.
> > >
> > > The correct thing to do here is craft a clk-keep-on flag and ensure it
> > > is set to true for the effected platform(s)' platform data.
> >
> > I'm always wary of creating a driver specific flag, especially when its
> > purpose is to do the same thing as an existing mechanism provided by the
> > subsystem of not gating the clock.
>
> Using existing sub-system supplied mechanisms in the way they were not
> intended is sub-optimal (read "hacky").
I think the scope of this flag has been defined in a very narrow way, which is
making you want to suggest lots of hacks in the client driver.
>
> > I can see a couple of problems with what you propose:
> >
> > 1) You have to put the clk-keep-on flag in every driver which consumes the
> > clock. IMO it is much better to have this knowledge in the SoC's
> > clock driver so every consumer of the clock automatically benefits.
>
> That would also be fine(ish). The issue is that this problem is
> board specific, so the platform clock driver would have to contain
> board level knowledge.
It is not board specific. It is a SoC HW bug, so by definition present on all
boards which have this SoC.
> Also, if you were to implement this, it would
> too mess up reference counting in the core.
>
> > 2) You don't benefit from the CLK_IS_CRITICAL reference counting logic in
> > clk.c. So then each driver has to also work around that to get sensible reference
> > counts. e.g.
> >
> > if (!__clk_is_enabled(clk) && pdata->clk-keep-on)
> > clk_enable(clk)
> >
> > Which seems to me to be fighting against the subsystem. Given that the only use of
> > _clk_is_enabled() outside drivers/clk is in an old arch/arm/mach-omap2/pm24xx.c
> > driver I suspect its use is frowned upon, and it shouldn't really be an EXPORTED_SYMBOL.
>
> In this instance, since the STFE clock is only used by this IP, I
> would choose to handle it in the driver.
There are other IPs within this IP block for which upstream drivers don't yet exist.
> This can be done using a
> single flag stored in pdata which should be fetched using
> of_match_device(). This way there is no need for any more API abuse;
> either by incorrectly identifying the STFE clock as critical OR
> invoking any internal __clk_*() calls.
>
> Enable the clock once in .probe(), which you already do.
But these drivers are by default built as modules, so when you rmmod, and insmod the
driver you now have an ever increasing clock reference count. This is the
problem I was describing in the previous email, and why what you propose is a
bad idea.
>
> Then, whenever you do any power saving do:
>
> suspend()
> {
> if (!ddata->enable_clk_once)
> clk_disable(clk);
> }
>
> resume()
> {
> if (!ddata->enable_clk_once)
> clk_enable(clk);
> }
>
> However, looking at your driver, I think this point might even be
> moot, since you don't have any power saving. The only time you
> disable the clock is in the error path. Just replace that with a
> comment about the platform's unfortunate errata.
This is exactly what I want to avoid doing. The driver already has these
hacks as it was waiting for the critical clock patches to land so I could remove
them and fix the problem properly.
Much like you did with the I2C and SPI drivers, where you removed similar hacks
and added the clock to the critical clock list.
>
> > [1] https://lkml.org/lkml/2016/1/18/272
>
> I'm glad you mentioned this. Let's take a look:
>
> > Some platforms contain clocks which if gated, will cause undefined or
> > catastrophic behaviours. As such they are not to be turned off, ever.
>
> Not the case here.
>
> This clock *can* be gated and can be turned off *sometimes*.
See above, if the clock is on when Linux boots it can never be assumed that it
is safe to disable it.
>
> > Many of these such clocks do not have devices, thus device drivers
> > where clocks may be enabled and references taken to ensure they stay
> > enabled do not exist. Therefore, we must handle these such cases in
> > the core.
>
> This clock *does* have a driver and correct references *can* be
> taken.
As above this is the same for CLK_EXT2F_A9, which has multiple users in the
kernel.
The point is we don't wish to have the knowledge in the individual drivers that
this clock is critical and can destroy the system if it is disabled.
>
> [...]
>
> All I'm saying is, and it's the same thing I've said many times; these
> types of issues do not exhibit the same set of symptoms as a critical
> clock by definition. Critical clocks are those which references can
> not be taken by any other means.
That is not how you are using it currently. See CLK_EXT2F_A9 and
CLK_TX_ICN_DMU.
> Think of the critical clock
> framework as a mechanism to circumvent the requirement of writing a
> special driver which would *only* handle clocks i.e. an interconnect
> driver in the ST case.
>
You didn't need a new flag for that. CLK_IGNORE_UNUSED already allowed you to not
write a specical driver which only handled for example an interconnect clock and
would ensure it wouldn't be gated by the disable_unused logic.
IMO the point of the critical clock stuff, and what CLK_IGNORE_UNUSED *did not* allow
you to do is for situations like CLK_EXT2F_A9, CLK_TX_ICN_DMU and PROC_STFE where users
*do* exist in the kernel, but the SoC clock driver has *special* knowledge of the
clock tree on the SoC and knows that despite what the drivers are doing with
their enable/disable calls the clock should never be disabled.
In fact out of what we currently mark as clock-critical on STi platform most
of the clocks could have been handled perfectly fine with the CLK_IGNORE_UNUSED
flag (apart from the fact that there is no way to set the flag from DT). It is
only CLK_EXT2F_A9 and CLK_TX_ICN_DMU which *do* have kernel users where the
extra functionality of critical clocks is required (we need the additional
reference taken by the clk framework to avoid the kernel drivers from disabling
the clock).
regards,
Peter.
^ permalink raw reply
* [PATCH v3 2/2] power/reset: at91-poweroff: timely shutdown LPDDR memories
From: Alexandre Belloni @ 2016-10-25 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161025093759.20913-1-alexandre.belloni@free-electrons.com>
LPDDR memories can only handle up to 400 uncontrolled power off. Ensure the
proper power off sequence is used before shutting down the platform.
Cc: <stable@vger.kernel.org> # 4.4+
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
drivers/power/reset/Kconfig | 2 +-
drivers/power/reset/at91-poweroff.c | 54 +++++++++++++++++++++++++++++++-
drivers/power/reset/at91-sama5d2_shdwc.c | 49 ++++++++++++++++++++++++++++-
3 files changed, 102 insertions(+), 3 deletions(-)
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index c74c3f67b8da..02e46bbcf45d 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -32,7 +32,7 @@ config POWER_RESET_AT91_RESET
config POWER_RESET_AT91_SAMA5D2_SHDWC
tristate "Atmel AT91 SAMA5D2-Compatible shutdown controller driver"
- depends on ARCH_AT91 || COMPILE_TEST
+ depends on ARCH_AT91
default SOC_SAMA5
help
This driver supports the alternate shutdown controller for some Atmel
diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c
index e9e24df35f26..2579f025b90b 100644
--- a/drivers/power/reset/at91-poweroff.c
+++ b/drivers/power/reset/at91-poweroff.c
@@ -14,9 +14,12 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/printk.h>
+#include <soc/at91/at91sam9_ddrsdr.h>
+
#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
#define AT91_SHDW_SHDW BIT(0) /* Shut Down command */
#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
@@ -50,6 +53,7 @@ static const char *shdwc_wakeup_modes[] = {
static void __iomem *at91_shdwc_base;
static struct clk *sclk;
+static void __iomem *mpddrc_base;
static void __init at91_wakeup_status(void)
{
@@ -73,6 +77,29 @@ static void at91_poweroff(void)
writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR);
}
+static void at91_lpddr_poweroff(void)
+{
+ asm volatile(
+ /* Align to cache lines */
+ ".balign 32\n\t"
+
+ /* Ensure AT91_SHDW_CR is in the TLB by reading it */
+ " ldr r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
+
+ /* Power down SDRAM0 */
+ " str %1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
+ /* Shutdown CPU */
+ " str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
+
+ " b .\n\t"
+ :
+ : "r" (mpddrc_base),
+ "r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF),
+ "r" (at91_shdwc_base),
+ "r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW)
+ : "r0");
+}
+
static int at91_poweroff_get_wakeup_mode(struct device_node *np)
{
const char *pm;
@@ -124,6 +151,8 @@ static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev)
static int __init at91_poweroff_probe(struct platform_device *pdev)
{
struct resource *res;
+ struct device_node *np;
+ u32 ddr_type;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -150,12 +179,30 @@ static int __init at91_poweroff_probe(struct platform_device *pdev)
pm_power_off = at91_poweroff;
+ np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc");
+ if (!np)
+ return 0;
+
+ mpddrc_base = of_iomap(np, 0);
+ of_node_put(np);
+
+ if (!mpddrc_base)
+ return 0;
+
+ ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD;
+ if ((ddr_type == AT91_DDRSDRC_MD_LPDDR2) ||
+ (ddr_type == AT91_DDRSDRC_MD_LPDDR3))
+ pm_power_off = at91_lpddr_poweroff;
+ else
+ iounmap(mpddrc_base);
+
return 0;
}
static int __exit at91_poweroff_remove(struct platform_device *pdev)
{
- if (pm_power_off == at91_poweroff)
+ if (pm_power_off == at91_poweroff ||
+ pm_power_off == at91_lpddr_poweroff)
pm_power_off = NULL;
clk_disable_unprepare(sclk);
@@ -163,6 +210,11 @@ static int __exit at91_poweroff_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id at91_ramc_of_match[] = {
+ { .compatible = "atmel,sama5d3-ddramc", },
+ { /* sentinel */ }
+};
+
static const struct of_device_id at91_poweroff_of_match[] = {
{ .compatible = "atmel,at91sam9260-shdwc", },
{ .compatible = "atmel,at91sam9rl-shdwc", },
diff --git a/drivers/power/reset/at91-sama5d2_shdwc.c b/drivers/power/reset/at91-sama5d2_shdwc.c
index 8a5ac9706c9c..90b0b5a70ce5 100644
--- a/drivers/power/reset/at91-sama5d2_shdwc.c
+++ b/drivers/power/reset/at91-sama5d2_shdwc.c
@@ -22,9 +22,12 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/printk.h>
+#include <soc/at91/at91sam9_ddrsdr.h>
+
#define SLOW_CLOCK_FREQ 32768
#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
@@ -75,6 +78,7 @@ struct shdwc {
*/
static struct shdwc *at91_shdwc;
static struct clk *sclk;
+static void __iomem *mpddrc_base;
static const unsigned long long sdwc_dbc_period[] = {
0, 3, 32, 512, 4096, 32768,
@@ -108,6 +112,29 @@ static void at91_poweroff(void)
at91_shdwc->at91_shdwc_base + AT91_SHDW_CR);
}
+static void at91_lpddr_poweroff(void)
+{
+ asm volatile(
+ /* Align to cache lines */
+ ".balign 32\n\t"
+
+ /* Ensure AT91_SHDW_CR is in the TLB by reading it */
+ " ldr r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
+
+ /* Power down SDRAM0 */
+ " str %1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
+ /* Shutdown CPU */
+ " str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
+
+ " b .\n\t"
+ :
+ : "r" (mpddrc_base),
+ "r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF),
+ "r" (at91_shdwc->at91_shdwc_base),
+ "r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW)
+ : "r0");
+}
+
static u32 at91_shdwc_debouncer_value(struct platform_device *pdev,
u32 in_period_us)
{
@@ -212,6 +239,8 @@ static int __init at91_shdwc_probe(struct platform_device *pdev)
{
struct resource *res;
const struct of_device_id *match;
+ struct device_node *np;
+ u32 ddr_type;
int ret;
if (!pdev->dev.of_node)
@@ -249,6 +278,23 @@ static int __init at91_shdwc_probe(struct platform_device *pdev)
pm_power_off = at91_poweroff;
+ np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc");
+ if (!np)
+ return 0;
+
+ mpddrc_base = of_iomap(np, 0);
+ of_node_put(np);
+
+ if (!mpddrc_base)
+ return 0;
+
+ ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD;
+ if ((ddr_type == AT91_DDRSDRC_MD_LPDDR2) ||
+ (ddr_type == AT91_DDRSDRC_MD_LPDDR3))
+ pm_power_off = at91_lpddr_poweroff;
+ else
+ iounmap(mpddrc_base);
+
return 0;
}
@@ -256,7 +302,8 @@ static int __exit at91_shdwc_remove(struct platform_device *pdev)
{
struct shdwc *shdw = platform_get_drvdata(pdev);
- if (pm_power_off == at91_poweroff)
+ if (pm_power_off == at91_poweroff ||
+ pm_power_off == at91_lpddr_poweroff)
pm_power_off = NULL;
/* Reset values to disable wake-up features */
--
2.9.3
^ permalink raw reply related
* [PATCH v3 1/2] ARM: at91: define LPDDR types
From: Alexandre Belloni @ 2016-10-25 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161025093759.20913-1-alexandre.belloni@free-electrons.com>
The Atmel MPDDR controller support LPDDR2 and LPDDR3 memories, add their
types.
Cc: <stable@vger.kernel.org> # 4.4+
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
include/soc/at91/at91sam9_ddrsdr.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/soc/at91/at91sam9_ddrsdr.h b/include/soc/at91/at91sam9_ddrsdr.h
index dc10c52e0e91..393362bdb860 100644
--- a/include/soc/at91/at91sam9_ddrsdr.h
+++ b/include/soc/at91/at91sam9_ddrsdr.h
@@ -81,6 +81,7 @@
#define AT91_DDRSDRC_LPCB_POWER_DOWN 2
#define AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN 3
#define AT91_DDRSDRC_CLKFR (1 << 2) /* Clock Frozen */
+#define AT91_DDRSDRC_LPDDR2_PWOFF (1 << 3) /* LPDDR Power Off */
#define AT91_DDRSDRC_PASR (7 << 4) /* Partial Array Self Refresh */
#define AT91_DDRSDRC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */
#define AT91_DDRSDRC_DS (3 << 10) /* Drive Strength */
@@ -96,7 +97,9 @@
#define AT91_DDRSDRC_MD_SDR 0
#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1
#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3
+#define AT91_DDRSDRC_MD_LPDDR3 5
#define AT91_DDRSDRC_MD_DDR2 6 /* [SAM9 Only] */
+#define AT91_DDRSDRC_MD_LPDDR2 7
#define AT91_DDRSDRC_DBW (1 << 4) /* Data Bus Width */
#define AT91_DDRSDRC_DBW_32BITS (0 << 4)
#define AT91_DDRSDRC_DBW_16BITS (1 << 4)
--
2.9.3
^ permalink raw reply related
* [PATCH v3 0/2] ARM: at91: properly handle LPDDR poweroff
From: Alexandre Belloni @ 2016-10-25 9:37 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This patch set improves LPDDR support on SoCs using the Atmel MPDDR controller.
LPDDR memories can only handle up to 400 uncontrolled power offs in their
life. The proper power off sequence has to be applied before shutting down the
SoC.
I'm not too happy with the code duplication but this is a design choice
that has been made before because both shutdown controllers are really
different apart from the shutdown itself.
I guess it is still better than slowly killing the LPDDR.
Changes in v3:
- removed COMPILE_TEST for sama5d2_shdwc as it is now ARM specific
Changes in v2:
- Fix typos
- Add a comment for the dummy read access of AT91_SHDW_CR
- Properly set up pm_power_off in at91_poweroff_probe()
Alexandre Belloni (2):
ARM: at91: define LPDDR types
power/reset: at91-poweroff: timely shutdown LPDDR memories
drivers/power/reset/Kconfig | 2 +-
drivers/power/reset/at91-poweroff.c | 54 +++++++++++++++++++++++++++++++-
drivers/power/reset/at91-sama5d2_shdwc.c | 49 ++++++++++++++++++++++++++++-
include/soc/at91/at91sam9_ddrsdr.h | 3 ++
4 files changed, 105 insertions(+), 3 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH/RFT v2 03/17] ARM: davinci: da8xx: Add USB PHY platform declaration
From: Axel Haslam @ 2016-10-25 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4129f1be-42f6-f182-c8a2-84befe01d298@ti.com>
On Tue, Oct 25, 2016 at 11:18 AM, Sekhar Nori <nsekhar@ti.com> wrote:
> On Monday 24 October 2016 10:16 PM, ahaslam at baylibre.com wrote:
>> +static struct platform_device da8xx_usb_phy = {
>> + .name = "da8xx-usb-phy",
>> + .id = 0,
>
> There is a single phy control in the system for both 1.1 and 2.0 PHYs.
> so this can be a singular device (id -1).
>
Ok.
> Thanks,
> Sekhar
>
^ permalink raw reply
* [PATCH/RFT v2 02/17] ARM: davinci: da8xx: Add CFGCHIP syscon platform declaration.
From: Axel Haslam @ 2016-10-25 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7f9efe9d-0912-e10a-3e45-24c5d2b455ab@ti.com>
Hi Sekar,
On Tue, Oct 25, 2016 at 10:10 AM, Sekhar Nori <nsekhar@ti.com> wrote:
> On Monday 24 October 2016 10:16 PM, ahaslam at baylibre.com wrote:
>> From: David Lechner <david@lechnology.com>
>>
>> The CFGCHIP registers are used by a number of devices, so using a syscon
>> device to share them. The first consumer of this will by the phy-da8xx-usb
>> driver.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> [Axel: minor fix: change id to -1]
>
> Can you please clarify this change? There could be other syscon devices
> on the chip for other common registers. Why use the singular device-id?
>
in the case of non DT boot, the phy driver is looking for "syscon" :
d_phy->regmap = syscon_regmap_lookup_by_pdevname("syscon");
if we register the syscon driver with id = 0, the actual name of the syscon
device will be "syscon.0" and the phy driver will fail to probe, because
the strncmp match in the syscon driver (syscon_match_pdevname)
will fail.
should i change the phy driver instead?
Regards,
Axel.
>> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
>
> Thanks,
> Sekhar
>
^ permalink raw reply
* [PATCH 0/4] i2c: Fix module autoload for some i2c busses platform drivers
From: Wolfram Sang @ 2016-10-25 9:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476824508-4679-1-git-send-email-javier@osg.samsung.com>
On Tue, Oct 18, 2016 at 06:01:44PM -0300, Javier Martinez Canillas wrote:
> Hello Wolfram,
>
> I noticed that module autoload won't be working in some of the i2c
> busses drivers. This patch series contains the fixes for these.
>
> Best regards,
> Javier
Applied to for-current, thank you very much for doing this
subsystem-wide!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161025/a53437d0/attachment.sig>
^ permalink raw reply
* [PATCH] ahci: use pci_alloc_irq_vectors
From: Robert Richter @ 2016-10-25 9:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161022141123.GA25500@lst.de>
On 22.10.16 16:11:23, Christoph Hellwig wrote:
> Hi Robert,
>
> is this a controller that's using MSI-X?
>
> If so can you try the patch below?
Great, that fixes the issue. Thanks.
Tested-by: Robert Richter <rrichter@cavium.com>
>
> diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
> index ba5f11c..5fe852d 100644
> --- a/drivers/ata/ahci.c
> +++ b/drivers/ata/ahci.c
> @@ -1617,7 +1617,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
> /* legacy intx interrupts */
> pci_intx(pdev, 1);
> }
> - hpriv->irq = pdev->irq;
> + hpriv->irq = pci_irq_vector(pdev, 0);
>
> if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
> host->flags |= ATA_HOST_PARALLEL_SCAN;
^ permalink raw reply
* Disabling an interrupt in the handler locks the system up
From: Thomas Gleixner @ 2016-10-25 9:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <580F17E7.5060603@laposte.net>
On Tue, 25 Oct 2016, Sebastian Frias wrote:
> On 10/24/2016 06:55 PM, Thomas Gleixner wrote:
> > On Mon, 24 Oct 2016, Mason wrote:
> >>
> >> For the record, setting the IRQ_DISABLE_UNLAZY flag for this device
> >> makes the system lock-up disappear.
> >
> > The way how lazy irq disabling works is:
> >
> > 1) Interrupt is marked disabled in software, but the hardware is not masked
> >
> > 2) If the interrupt fires befor the interrupt is reenabled, then it's
> > masked at the hardware level in the low level interrupt flow handler.
> >
> Would you mind explaining what is the intention behind?
> Because it does not seem obvious why there isn't a direct map between
> "disable_irq*()" and "mask_irq()"
Two reasons for this:
1) If you mask edge type interrupts then you might race with an incoming
interrupt which then gets lost and eventually you won't get another
interrupt from that device. Even if there is no race, then on many irq
chips edge type interrupts are not latched when the interrupt line is
masked. That also can result in a stale interrupt line.
With the lazy disabling we mask only if an interrupt fires while it's
disabled in software. We note that it is pending and resend it when the
interrupt gets reenabled.
2) Accessing irq chip hardware can be slow and we have situations where
interrupts are disabled/enabled fast. So it's an optimization to avoid
the hardware access, which is sensible as we do not expect an interrupt
to fire in most cases. If it fires then we mask it when the interrupt
handler sees the disabled flag.
That should really work on any hardware and the IRQ_DISABLE_UNLAZY flag is
just there to deal with devices which are known to keep the (level based)
irq line active. In that case we know that we always take an interrupt to
mask it right away, so we can avoid the overhead.
Though you should not set that flag on edge type interrupts, unless your
hardware guarantees to avoid the issues described in #1.
Hope that helps.
Thanks,
tglx
^ permalink raw reply
* [PATCH/RFT v2 03/17] ARM: davinci: da8xx: Add USB PHY platform declaration
From: Sekhar Nori @ 2016-10-25 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161024164634.4330-4-ahaslam@baylibre.com>
On Monday 24 October 2016 10:16 PM, ahaslam at baylibre.com wrote:
> +static struct platform_device da8xx_usb_phy = {
> + .name = "da8xx-usb-phy",
> + .id = 0,
There is a single phy control in the system for both 1.1 and 2.0 PHYs.
so this can be a singular device (id -1).
Thanks,
Sekhar
^ permalink raw reply
* [PATCH 4/9] pinctrl: meson: allow gpio to request irq
From: Linus Walleij @ 2016-10-25 9:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477040798.15560.96.camel@baylibre.com>
On Fri, Oct 21, 2016 at 11:06 AM, Jerome Brunet <jbrunet@baylibre.com> wrote:
>> Isn't this usecase (also as described in the cover letter) a textbook
>> example of when you should be using hierarchical irqdomain?
>>
>> Please check with Marc et al on hierarchical irqdomains.
>
> Linus,
> Do you mean I should create a new hierarchical irqdomains in each of
> the two pinctrl instances we have in these SoC, these domains being
> stacked on the one I just added for controller in irqchip ?
>
> I did not understand this is what you meant when I asked you the
> question at ELCE.
Honestly, I do not understand when and where to properly use
hierarchical irqdomain, even after Marc's talk at ELC-E.
Which is problematic since quite a few GPIO drivers now
need to use them.
I will review his slides, in the meantime I would say: whatever
Marc ACKs is fine with me. I trust this guy 100%. So I guess I
could ask that he ACK the entire chain of patches
from GIC->specialchip->GPIO.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] i2c: rk3x: Give the tuning value 0 during rk3x_i2c_v0_calc_timings
From: Wolfram Sang @ 2016-10-25 9:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477125822-30644-1-git-send-email-david.wu@rock-chips.com>
On Sat, Oct 22, 2016 at 04:43:42PM +0800, David Wu wrote:
> We found a bug that i2c transfer sometimes failed on 3066a board with
> stabel-4.8, the con register would be updated by uninitialized tuning
> value, it made the i2c transfer failed.
>
> So give the tuning value to be zero during rk3x_i2c_v0_calc_timings.
>
> Signed-off-by: David Wu <david.wu@rock-chips.com>
Added stable and applied to for-current, thanks!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161025/0184c0eb/attachment.sig>
^ permalink raw reply
* [PATCH 2/3] ARM: convert to generated system call tables
From: Michael Cree @ 2016-10-25 9:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3851270.xZRcP9hae0@wuerfel>
On Fri, Oct 21, 2016 at 03:06:45PM +0200, Arnd Bergmann wrote:
> I see your point, but I think there are serious issues with the current
> approach as well:
>
> - a lot of the less common architectures just don't get updated
> in time, out of 22 architectures that don't use asm-generic/unistd.h,
> only 12 have pwritev2 in linux-next, and only three have pkey_mprotect
>
> - some architectures that add all syscalls sometimes make a mistake
> and forget one, e.g. alpha apparently never added __NR_bpf, but it
> did add the later __NR_execveat.
__NR_bpf was not forgotten on Alpha. It was not wired up because
extra architecture support is needed which has not been implemented.
But maybe we should just wire it up to sys_ni_syscall in the meantime
so a syscall number is reserved for it, and user space can call it to
get -ENOSYS returned.
Cheers
Michael.
^ permalink raw reply
* [PATCH 3/3 v2] RFC: mmc: mmci: add qcom specific program end support
From: Linus Walleij @ 2016-10-25 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477386367-18514-1-git-send-email-linus.walleij@linaro.org>
From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
This patch adds support to programend interrupt which is very
specific to QCOM integration. This interrupt is use as busy signal
when a command forces the card to enter into programming state
like CMD6 writing to ext_csd registers.
Hopefully, this also fixes the __mmc_switch timeout issue reproted
with latest versions of the eMMC used on DB600c board.
This patch is based on a WIP patch from Srinivas Kandagatla and
augmented by Linus Walleij for another approach.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Rebase on new register naming.
Srinivas: please test to see if this fixes your problems. Sadly
it does *NOT* solve my APQ8060 issues, but it would be nice if
the common code path works for the busy detection on your
DB600c.
---
drivers/mmc/host/mmci.c | 21 +++++++++++++++++++--
drivers/mmc/host/mmci.h | 6 ++++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 7f68fa7a961e..580ca89d33dc 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -72,7 +72,10 @@ static unsigned int fmax = 515633;
* @signal_direction: input/out direction of bus signals can be indicated
* @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
* @busy_detect: true if the variant supports busy detection on DAT0.
- * @busy_dpsm_flag: bitmask enabling busy detection in the DPSM
+ * @busy_cpsm_flag: bitmask enabling busy detection in the CPSM (command
+ * path state machine)
+ * @busy_dpsm_flag: bitmask enabling busy detection in the DPSM (data path
+ * state machine)
* @busy_detect_flag: bitmask identifying the bit in the MMCISTATUS register
* indicating that the card is busy
* @busy_detect_mask: bitmask identifying the bit in the MMCIMASK0 to mask for
@@ -103,6 +106,7 @@ struct variant_data {
bool signal_direction;
bool pwrreg_clkgate;
bool busy_detect;
+ u32 busy_cpsm_flag;
u32 busy_dpsm_flag;
u32 busy_detect_flag;
u32 busy_detect_mask;
@@ -229,6 +233,10 @@ static struct variant_data variant_qcom = {
.datalength_bits = 24,
.pwrreg_powerup = MCI_PWR_UP,
.f_max = 208000000,
+ .busy_detect = true,
+ .busy_cpsm_flag = MCI_CPSM_QCOM_PROGENA,
+ .busy_detect_flag = MCI_QCOM_PROGDONE,
+ .busy_detect_mask = MCI_QCOM_PROGDONEMASK,
.explicit_mclk_control = true,
.qcom_fifo = true,
.qcom_dml = true,
@@ -903,6 +911,15 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
if (/*interrupt*/0)
c |= MCI_CPSM_INTERRUPT;
+ /*
+ * Enable the program end interrupt for specific commands
+ * used for busy detection.
+ */
+ if (host->variant->busy_detect &&
+ (cmd->flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
+ c |= host->variant->busy_cpsm_flag;
+ }
+
if (mmc_cmd_type(cmd) == MMC_CMD_ADTC)
c |= host->variant->data_cmd_enable;
@@ -1005,7 +1022,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
return;
/*
- * ST Micro variant: handle busy detection.
+ * ST Micro and Qualcomm variants: handle busy detection.
*/
if (host->variant->busy_detect) {
bool busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 56322c6afba4..355259b0a24b 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -130,6 +130,8 @@
#define MCI_ST_SDIOIT (1 << 22)
#define MCI_ST_CEATAEND (1 << 23)
#define MCI_ST_CARDBUSY (1 << 24)
+/* Extended status bits for the QCOM variants */
+#define MCI_QCOM_PROGDONE (1 << 23)
#define MMCICLEAR 0x038
#define MCI_CMDCRCFAILCLR (1 << 0)
@@ -147,6 +149,8 @@
#define MCI_ST_SDIOITC (1 << 22)
#define MCI_ST_CEATAENDC (1 << 23)
#define MCI_ST_BUSYENDC (1 << 24)
+/* Extended status bits for the QCOM variants */
+#define MCI_QCOM_PROGDONECLR (1 << 23)
#define MMCIMASK0 0x03c
#define MCI_CMDCRCFAILMASK (1 << 0)
@@ -175,6 +179,8 @@
#define MCI_ST_SDIOITMASK (1 << 22)
#define MCI_ST_CEATAENDMASK (1 << 23)
#define MCI_ST_BUSYENDMASK (1 << 24)
+/* Extended status bits for the Qualcomm variants */
+#define MCI_QCOM_PROGDONEMASK (1 << 23)
#define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x048
--
2.7.4
^ permalink raw reply related
* [PATCH 2/3 v2] mmc: mmci: refactor ST Micro busy detection
From: Linus Walleij @ 2016-10-25 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477386367-18514-1-git-send-email-linus.walleij@linaro.org>
The ST Micro-specific busy detection was made after the assumption
that only this variant supports busy detection. So when doing busy
detection, the host immediately tries to use some ST-specific
register bits.
Since the qualcomm variant also supports some busy detection
schemes, encapsulate the variant flags better in the variant struct
and prepare to add more variants by just providing some bitmasks
to the logic.
Put the entire busy detection logic within an if()-clause in the
mmci_cmd_irq() function so the code is only executed when busy
detection is enabled, and so that it is kept in (almost) one
place, and add comments describing what is going on so the
code can be understood.
Tested on the Ux500 by introducing some prints in the busy
detection path and noticing how the IRQ is enabled, used and
disabled successfully.
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Rebase on new register naming.
---
drivers/mmc/host/mmci.c | 113 +++++++++++++++++++++++++++++++++++-------------
drivers/mmc/host/mmci.h | 2 +-
2 files changed, 85 insertions(+), 30 deletions(-)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 6a8ea9c633d4..7f68fa7a961e 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -71,7 +71,12 @@ static unsigned int fmax = 515633;
* @f_max: maximum clk frequency supported by the controller.
* @signal_direction: input/out direction of bus signals can be indicated
* @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
- * @busy_detect: true if busy detection on dat0 is supported
+ * @busy_detect: true if the variant supports busy detection on DAT0.
+ * @busy_dpsm_flag: bitmask enabling busy detection in the DPSM
+ * @busy_detect_flag: bitmask identifying the bit in the MMCISTATUS register
+ * indicating that the card is busy
+ * @busy_detect_mask: bitmask identifying the bit in the MMCIMASK0 to mask for
+ * getting busy end detection interrupts
* @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply
* @explicit_mclk_control: enable explicit mclk control in driver.
* @qcom_fifo: enables qcom specific fifo pio read logic.
@@ -98,6 +103,9 @@ struct variant_data {
bool signal_direction;
bool pwrreg_clkgate;
bool busy_detect;
+ u32 busy_dpsm_flag;
+ u32 busy_detect_flag;
+ u32 busy_detect_mask;
bool pwrreg_nopower;
bool explicit_mclk_control;
bool qcom_fifo;
@@ -178,6 +186,9 @@ static struct variant_data variant_ux500 = {
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
+ .busy_dpsm_flag = MCI_DPSM_ST_BUSYMODE,
+ .busy_detect_flag = MCI_ST_CARDBUSY,
+ .busy_detect_mask = MCI_ST_BUSYENDMASK,
.pwrreg_nopower = true,
};
@@ -199,6 +210,9 @@ static struct variant_data variant_ux500v2 = {
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
+ .busy_dpsm_flag = MCI_DPSM_ST_BUSYMODE,
+ .busy_detect_flag = MCI_ST_CARDBUSY,
+ .busy_detect_mask = MCI_ST_BUSYENDMASK,
.pwrreg_nopower = true,
};
@@ -220,6 +234,7 @@ static struct variant_data variant_qcom = {
.qcom_dml = true,
};
+/* Busy detection for the ST Micro variant */
static int mmci_card_busy(struct mmc_host *mmc)
{
struct mmci_host *host = mmc_priv(mmc);
@@ -227,7 +242,7 @@ static int mmci_card_busy(struct mmc_host *mmc)
int busy = 0;
spin_lock_irqsave(&host->lock, flags);
- if (readl(host->base + MMCISTATUS) & MCI_ST_CARDBUSY)
+ if (readl(host->base + MMCISTATUS) & host->variant->busy_detect_flag)
busy = 1;
spin_unlock_irqrestore(&host->lock, flags);
@@ -294,8 +309,8 @@ static void mmci_write_pwrreg(struct mmci_host *host, u32 pwr)
*/
static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl)
{
- /* Keep ST Micro busy mode if enabled */
- datactrl |= host->datactrl_reg & MCI_DPSM_ST_BUSYMODE;
+ /* Keep busy mode in DPSM if enabled */
+ datactrl |= host->datactrl_reg & host->variant->busy_dpsm_flag;
if (host->datactrl_reg != datactrl) {
host->datactrl_reg = datactrl;
@@ -973,37 +988,66 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
unsigned int status)
{
void __iomem *base = host->base;
- bool sbc, busy_resp;
+ bool sbc;
if (!cmd)
return;
sbc = (cmd == host->mrq->sbc);
- busy_resp = host->variant->busy_detect && (cmd->flags & MMC_RSP_BUSY);
- if (!((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
- MCI_CMDSENT|MCI_CMDRESPEND)))
+ /*
+ * We need to be one of these interrupts to be considered worth
+ * handling. Note that we tag on any latent IRQs postponed
+ * due to waiting for busy status.
+ */
+ if (!((status|host->busy_status) &
+ (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND)))
return;
- /* Check if we need to wait for busy completion. */
- if (host->busy_status && (status & MCI_ST_CARDBUSY))
- return;
+ /*
+ * ST Micro variant: handle busy detection.
+ */
+ if (host->variant->busy_detect) {
+ bool busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
- /* Enable busy completion if needed and supported. */
- if (!host->busy_status && busy_resp &&
- !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
- (readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) {
- writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND,
- base + MMCIMASK0);
- host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND);
- return;
- }
+ /* We are busy with a command, return */
+ if (host->busy_status &&
+ (status & host->variant->busy_detect_flag))
+ return;
+
+ /*
+ * We were not busy, but we now got a busy response on
+ * something that was not an error, and we double-check
+ * that the special busy status bit is still set before
+ * proceeding.
+ */
+ if (!host->busy_status && busy_resp &&
+ !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
+ (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) {
+ /* Unmask the busy IRQ */
+ writel(readl(base + MMCIMASK0) |
+ host->variant->busy_detect_mask,
+ base + MMCIMASK0);
+ /*
+ * Now cache the last response status code (until
+ * the busy bit goes low), and return.
+ */
+ host->busy_status =
+ status & (MCI_CMDSENT|MCI_CMDRESPEND);
+ return;
+ }
- /* At busy completion, mask the IRQ and complete the request. */
- if (host->busy_status) {
- writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND,
- base + MMCIMASK0);
- host->busy_status = 0;
+ /*
+ * At this point we are not busy with a command, we have
+ * not recieved a new busy request, mask the busy IRQ and
+ * fall through to process the IRQ.
+ */
+ if (host->busy_status) {
+ writel(readl(base + MMCIMASK0) &
+ ~host->variant->busy_detect_mask,
+ base + MMCIMASK0);
+ host->busy_status = 0;
+ }
}
host->cmd = NULL;
@@ -1257,9 +1301,11 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
mmci_data_irq(host, host->data, status);
}
- /* Don't poll for busy completion in irq context. */
- if (host->busy_status)
- status &= ~MCI_ST_CARDBUSY;
+ /*
+ * Don't poll for busy completion in irq context.
+ */
+ if (host->variant->busy_detect && host->busy_status)
+ status &= ~host->variant->busy_detect_flag;
ret = 1;
} while (status);
@@ -1612,9 +1658,18 @@ static int mmci_probe(struct amba_device *dev,
/* We support these capabilities. */
mmc->caps |= MMC_CAP_CMD23;
+ /*
+ * Enable busy detection.
+ */
if (variant->busy_detect) {
mmci_ops.card_busy = mmci_card_busy;
- mmci_write_datactrlreg(host, MCI_DPSM_ST_BUSYMODE);
+ /*
+ * Not all variants have a flag to enable busy detection
+ * in the DPSM, but if they do, set it here.
+ */
+ if (variant->busy_dpsm_flag)
+ mmci_write_datactrlreg(host,
+ host->variant->busy_dpsm_flag);
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
mmc->max_busy_timeout = 0;
}
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 7cabf270050b..56322c6afba4 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -174,7 +174,7 @@
/* Extended status bits for the ST Micro variants */
#define MCI_ST_SDIOITMASK (1 << 22)
#define MCI_ST_CEATAENDMASK (1 << 23)
-#define MCI_ST_BUSYEND (1 << 24)
+#define MCI_ST_BUSYENDMASK (1 << 24)
#define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x048
--
2.7.4
^ permalink raw reply related
* [PATCH 1/3 v2] mmc: mmci: clean up header defines
From: Linus Walleij @ 2016-10-25 9:06 UTC (permalink / raw)
To: linux-arm-kernel
There was some confusion in the CPSM (Command Path State Machine)
and DPSM (Data Path State Machine) regarding the naming of the
registers, clarify the meaning of this acronym so the naming is
understandable, and consistently use BIT() to define these fields.
Consequently name the register bit defines MCI_[C|D]PSM_* and
adjust the driver as well.
Include new definitions for a few bits found in a patch from
Srinivas Kandagatla.
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Use more consequent register naming.
---
drivers/mmc/host/mmci.c | 16 ++++++------
drivers/mmc/host/mmci.h | 69 +++++++++++++++++++++++++++----------------------
2 files changed, 46 insertions(+), 39 deletions(-)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index df990bb8c873..6a8ea9c633d4 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -137,7 +137,7 @@ static struct variant_data variant_u300 = {
.clkreg_enable = MCI_ST_U300_HWFCEN,
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.datalength_bits = 16,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.pwrreg_powerup = MCI_PWR_ON,
.f_max = 100000000,
@@ -152,7 +152,7 @@ static struct variant_data variant_nomadik = {
.clkreg = MCI_CLK_ENABLE,
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.datalength_bits = 24,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.st_clkdiv = true,
.pwrreg_powerup = MCI_PWR_ON,
@@ -170,7 +170,7 @@ static struct variant_data variant_ux500 = {
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.clkreg_neg_edge_enable = MCI_ST_UX500_NEG_EDGE,
.datalength_bits = 24,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.st_clkdiv = true,
.pwrreg_powerup = MCI_PWR_ON,
@@ -188,9 +188,9 @@ static struct variant_data variant_ux500v2 = {
.clkreg_enable = MCI_ST_UX500_HWFCEN,
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.clkreg_neg_edge_enable = MCI_ST_UX500_NEG_EDGE,
- .datactrl_mask_ddrmode = MCI_ST_DPSM_DDRMODE,
+ .datactrl_mask_ddrmode = MCI_DPSM_ST_DDRMODE,
.datalength_bits = 24,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.st_clkdiv = true,
.blksz_datactrl16 = true,
@@ -210,7 +210,7 @@ static struct variant_data variant_qcom = {
MCI_QCOM_CLK_SELECT_IN_FBCLK,
.clkreg_8bit_bus_enable = MCI_QCOM_CLK_WIDEBUS_8,
.datactrl_mask_ddrmode = MCI_QCOM_CLK_SELECT_IN_DDR_MODE,
- .data_cmd_enable = MCI_QCOM_CSPM_DATCMD,
+ .data_cmd_enable = MCI_CPSM_QCOM_DATCMD,
.blksz_datactrl4 = true,
.datalength_bits = 24,
.pwrreg_powerup = MCI_PWR_UP,
@@ -295,7 +295,7 @@ static void mmci_write_pwrreg(struct mmci_host *host, u32 pwr)
static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl)
{
/* Keep ST Micro busy mode if enabled */
- datactrl |= host->datactrl_reg & MCI_ST_DPSM_BUSYMODE;
+ datactrl |= host->datactrl_reg & MCI_DPSM_ST_BUSYMODE;
if (host->datactrl_reg != datactrl) {
host->datactrl_reg = datactrl;
@@ -1614,7 +1614,7 @@ static int mmci_probe(struct amba_device *dev,
if (variant->busy_detect) {
mmci_ops.card_busy = mmci_card_busy;
- mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
+ mmci_write_datactrlreg(host, MCI_DPSM_ST_BUSYMODE);
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
mmc->max_busy_timeout = 0;
}
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index a1f5e4f49e2a..7cabf270050b 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -51,25 +51,27 @@
#define MCI_QCOM_CLK_SELECT_IN_DDR_MODE (BIT(14) | BIT(15))
#define MMCIARGUMENT 0x008
-#define MMCICOMMAND 0x00c
-#define MCI_CPSM_RESPONSE (1 << 6)
-#define MCI_CPSM_LONGRSP (1 << 7)
-#define MCI_CPSM_INTERRUPT (1 << 8)
-#define MCI_CPSM_PENDING (1 << 9)
-#define MCI_CPSM_ENABLE (1 << 10)
-/* Argument flag extenstions in the ST Micro versions */
-#define MCI_ST_SDIO_SUSP (1 << 11)
-#define MCI_ST_ENCMD_COMPL (1 << 12)
-#define MCI_ST_NIEN (1 << 13)
-#define MCI_ST_CE_ATACMD (1 << 14)
-/* Modified on Qualcomm Integrations */
-#define MCI_QCOM_CSPM_DATCMD BIT(12)
-#define MCI_QCOM_CSPM_MCIABORT BIT(13)
-#define MCI_QCOM_CSPM_CCSENABLE BIT(14)
-#define MCI_QCOM_CSPM_CCSDISABLE BIT(15)
-#define MCI_QCOM_CSPM_AUTO_CMD19 BIT(16)
-#define MCI_QCOM_CSPM_AUTO_CMD21 BIT(21)
+/* The command register controls the Command Path State Machine (CPSM) */
+#define MMCICOMMAND 0x00c
+#define MCI_CPSM_RESPONSE BIT(6)
+#define MCI_CPSM_LONGRSP BIT(7)
+#define MCI_CPSM_INTERRUPT BIT(8)
+#define MCI_CPSM_PENDING BIT(9)
+#define MCI_CPSM_ENABLE BIT(10)
+/* Command register flag extenstions in the ST Micro versions */
+#define MCI_CPSM_ST_SDIO_SUSP BIT(11)
+#define MCI_CPSM_ST_ENCMD_COMPL BIT(12)
+#define MCI_CPSM_ST_NIEN BIT(13)
+#define MCI_CPSM_ST_CE_ATACMD BIT(14)
+/* Command register flag extensions in the Qualcomm versions */
+#define MCI_CPSM_QCOM_PROGENA BIT(11)
+#define MCI_CPSM_QCOM_DATCMD BIT(12)
+#define MCI_CPSM_QCOM_MCIABORT BIT(13)
+#define MCI_CPSM_QCOM_CCSENABLE BIT(14)
+#define MCI_CPSM_QCOM_CCSDISABLE BIT(15)
+#define MCI_CPSM_QCOM_AUTO_CMD19 BIT(16)
+#define MCI_CPSM_QCOM_AUTO_CMD21 BIT(21)
#define MMCIRESPCMD 0x010
#define MMCIRESPONSE0 0x014
@@ -78,22 +80,27 @@
#define MMCIRESPONSE3 0x020
#define MMCIDATATIMER 0x024
#define MMCIDATALENGTH 0x028
+
+/* The data control register controls the Data Path State Machine (DPSM) */
#define MMCIDATACTRL 0x02c
-#define MCI_DPSM_ENABLE (1 << 0)
-#define MCI_DPSM_DIRECTION (1 << 1)
-#define MCI_DPSM_MODE (1 << 2)
-#define MCI_DPSM_DMAENABLE (1 << 3)
-#define MCI_DPSM_BLOCKSIZE (1 << 4)
+#define MCI_DPSM_ENABLE BIT(0)
+#define MCI_DPSM_DIRECTION BIT(1)
+#define MCI_DPSM_MODE BIT(2)
+#define MCI_DPSM_DMAENABLE BIT(3)
+#define MCI_DPSM_BLOCKSIZE BIT(4)
/* Control register extensions in the ST Micro U300 and Ux500 versions */
-#define MCI_ST_DPSM_RWSTART (1 << 8)
-#define MCI_ST_DPSM_RWSTOP (1 << 9)
-#define MCI_ST_DPSM_RWMOD (1 << 10)
-#define MCI_ST_DPSM_SDIOEN (1 << 11)
+#define MCI_DPSM_ST_RWSTART BIT(8)
+#define MCI_DPSM_ST_RWSTOP BIT(9)
+#define MCI_DPSM_ST_RWMOD BIT(10)
+#define MCI_DPSM_ST_SDIOEN BIT(11)
/* Control register extensions in the ST Micro Ux500 versions */
-#define MCI_ST_DPSM_DMAREQCTL (1 << 12)
-#define MCI_ST_DPSM_DBOOTMODEEN (1 << 13)
-#define MCI_ST_DPSM_BUSYMODE (1 << 14)
-#define MCI_ST_DPSM_DDRMODE (1 << 15)
+#define MCI_DPSM_ST_DMAREQCTL BIT(12)
+#define MCI_DPSM_ST_DBOOTMODEEN BIT(13)
+#define MCI_DPSM_ST_BUSYMODE BIT(14)
+#define MCI_DPSM_ST_DDRMODE BIT(15)
+/* Control register extensions in the Qualcomm versions */
+#define MCI_DPSM_QCOM_DATA_PEND BIT(17)
+#define MCI_DPSM_QCOM_RX_DATA_PEND BIT(20)
#define MMCIDATACNT 0x030
#define MMCISTATUS 0x034
--
2.7.4
^ permalink raw reply related
* [PATCH v2 1/8] drm/bridge: rgb-to-vga: Support an enable GPIO
From: Chen-Yu Tsai @ 2016-10-25 8:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0b5fbe8e-e51b-c874-e1a3-0b88dc65e361@codeaurora.org>
On Tue, Oct 25, 2016 at 4:09 PM, Archit Taneja <architt@codeaurora.org> wrote:
> Hi,
>
> On 10/20/2016 09:13 AM, Chen-Yu Tsai wrote:
>>
>> Some rgb-to-vga bridges have an enable GPIO, either directly tied to
>> an enable pin on the bridge IC, or indirectly controlling a power
>> switch.
>>
>> Add support for it.
>
>
> Does the bridge on your platform have an active/passive DAC, or is it a
> smarter encoder chip that is capable of doing more? If so, it might be
> good to have a separate DT compatible string to it, like what's done
> in the patch titled:
>
> drm: bridge: vga-dac: Add adi,adv7123 compatible string
>
> so that we can switch to a different driver later if needed.
The chip is GM7123. It is not configurable. It just takes the LCD RGB/SYNC
signals and converts them to analog. The only things you can change are
putting it into sleep mode and tweaking the output drive strength by
changing the external reference resistor. The latter would be a hardware
design decision. I would say this qualifies as "dumb".
I revisited the board schematics, and the enable GPIO actually toggles
an external LDO regulator. So this might be better modeled as a regulator
supply?
Thanks
ChenYu
>
> Thanks,
> Archit
>
>
>>
>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> .../bindings/display/bridge/dumb-vga-dac.txt | 2 ++
>> drivers/gpu/drm/bridge/dumb-vga-dac.c | 28
>> ++++++++++++++++++++++
>> 2 files changed, 30 insertions(+)
>>
>> diff --git
>> a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>> b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>> index 003bc246a270..d3484822bf77 100644
>> --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>> @@ -16,6 +16,8 @@ graph bindings specified in
>> Documentation/devicetree/bindings/graph.txt.
>> - Video port 0 for RGB input
>> - Video port 1 for VGA output
>>
>> +Optional properties:
>> +- enable-gpios: GPIO pin to enable or disable the bridge
>>
>> Example
>> -------
>> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>> b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>> index afec232185a7..b487e5e9b56d 100644
>> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>> @@ -10,6 +10,7 @@
>> * the License, or (at your option) any later version.
>> */
>>
>> +#include <linux/gpio/consumer.h>
>> #include <linux/module.h>
>> #include <linux/of_graph.h>
>>
>> @@ -23,6 +24,7 @@ struct dumb_vga {
>> struct drm_connector connector;
>>
>> struct i2c_adapter *ddc;
>> + struct gpio_desc *enable_gpio;
>> };
>>
>> static inline struct dumb_vga *
>> @@ -124,8 +126,26 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
>> return 0;
>> }
>>
>> +static void dumb_vga_enable(struct drm_bridge *bridge)
>> +{
>> + struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>> +
>> + if (vga->enable_gpio)
>> + gpiod_set_value_cansleep(vga->enable_gpio, 1);
>> +}
>> +
>> +static void dumb_vga_disable(struct drm_bridge *bridge)
>> +{
>> + struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>> +
>> + if (vga->enable_gpio)
>> + gpiod_set_value_cansleep(vga->enable_gpio, 0);
>> +}
>> +
>> static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
>> .attach = dumb_vga_attach,
>> + .enable = dumb_vga_enable,
>> + .disable = dumb_vga_disable,
>> };
>>
>> static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
>> @@ -169,6 +189,14 @@ static int dumb_vga_probe(struct platform_device
>> *pdev)
>> return -ENOMEM;
>> platform_set_drvdata(pdev, vga);
>>
>> + vga->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
>> + GPIOD_OUT_LOW);
>> + if (IS_ERR(vga->enable_gpio)) {
>> + ret = PTR_ERR(vga->enable_gpio);
>> + dev_err(&pdev->dev, "failed to request GPIO: %d\n", ret);
>> + return ret;
>> + }
>> +
>> vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
>> if (IS_ERR(vga->ddc)) {
>> if (PTR_ERR(vga->ddc) == -ENODEV) {
>>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH v3 0/5] Add runtime PM support for clocks (on Exynos SoC example)
From: Marek Szyprowski @ 2016-10-25 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477311130-6534-1-git-send-email-m.szyprowski@samsung.com>
Dear All,
On 2016-10-24 14:12, Marek Szyprowski wrote:
> This patchset adds runtime PM support to common clock framework. This is an
> attempt to implement support for clock controllers, which belongs to a power
> domain. This approach works surprisingly well on Exynos 4412 and 5433 SoCs,
> what allowed us to solve various freeze/crash issues related to power
> management.
>
> The main idea behind this patchset is to keep clock's controller power domain
> enabled every time when at least one of its clock is enabled or access to its
> registers is being made. Clock controller driver (clock provider) can
> supply a struct device pointer, which is the used by clock core for tracking and
> managing clock's controller runtime pm state. Each clk_prepare() operation will
> first call pm_runtime_get_sync() on the supplied device, while clk_unprepare()
> will do pm_runtime_put() at the end.
>
> This runtime PM feature has been tested with Exynos4412 and Exynos5433 clocks
> drivers. Both have some clocks, which belongs to respective power domains and
> need special handling during power on/off procedures. Till now it wasn't handled
> at all, what caused various problems.
>
> Patches for exynos 4412 and 5433 clocks drivers change the way the clock
> provider is initialized. Instead of CLK_OF_DECLARE based initialization, a
> complete platform device driver infrastructure is being used. This is needed to
> let driver to use runtime pm feature and integrate with generic power domains.
> The side-effect of this change is a delay in clock provider registeration
> during system boot, so early initialized drivers might get EPROBEDEFER error
> when requesting their clocks. This is an issue for IOMMU drivers, so
> this patchset will be fully functional once the deferred probe for IOMMU
> will be merged.
>
> The side-effect of this patchset is the one can finally read
> /sys/kernel/debug/clk/clk_summary on all Exynos4412 boards without any freeze.
>
> If one wants to test this patchset (on Exynos4412 Trats2 device with FIMC-IS
> driver), I've provided a branch with all needed patches (fixes for Exynos,
> FIMC-IS driver and IOMMU deferred probe):
> https://git.linaro.org/people/marek.szyprowski/linux-srpol.git v4.9-clocks-pm-v3
>
> Patches are based on vanilla v4.9-rc1 kernel.
If one want to test this patchset together with my recently posted
Exynos IOMMU
runtime PM patches (V5:
http://www.mail-archive.com/linux-kernel at vger.kernel.org/msg1253432.html),
I prepared a single branch with both patchsets and all their prerequisites:
https://git.linaro.org/people/marek.szyprowski/linux-srpol.git v4.9-iommu-pm-v5-clocks-pm-v3
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* [PATCH v2 8/8] ARM: dts: sun6i: hummingbird-a31: Enable display output through VGA bridge
From: Chen-Yu Tsai @ 2016-10-25 8:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <bac9a59f-df97-245b-f349-bed57dec6aad@codeaurora.org>
On Tue, Oct 25, 2016 at 4:13 PM, Archit Taneja <architt@codeaurora.org> wrote:
>
>
> On 10/20/2016 09:13 AM, Chen-Yu Tsai wrote:
>>
>> The Hummingbird A31 board has a RGB-to-VGA bridge which converts RGB
>> output from the LCD interface to VGA signals.
>>
>> Enable this part of the display pipeline.
>
>
> I couldn't find the enable-gpios binding for the bridge that you
> introduced in the previous patch. Is that intentional?
Error on my part. Thanks for spotting that.
ChenYu
>
> Thanks,
> Archit
>
>
>>
>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 56
>> +++++++++++++++++++++++++++++
>> 1 file changed, 56 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
>> b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
>> index 9a74637f677f..05a49b2147f1 100644
>> --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
>> +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
>> @@ -63,6 +63,49 @@
>> stdout-path = "serial0:115200n8";
>> };
>>
>> + bridge {
>> + compatible = "dumb-vga-dac";
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> +
>> + ports {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> +
>> + port at 0 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + reg = <0>;
>> +
>> + vga_bridge_in: endpoint at 0 {
>> + reg = <0>;
>> + remote-endpoint =
>> <&tcon0_out_vga>;
>> + };
>> + };
>> +
>> + port at 1 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + reg = <1>;
>> +
>> + vga_bridge_out: endpoint at 0 {
>> + reg = <0>;
>> + remote-endpoint = <&vga_con_in>;
>> + };
>> + };
>> + };
>> + };
>> +
>> + vga {
>> + compatible = "vga-connector";
>> +
>> + port {
>> + vga_con_in: endpoint {
>> + remote-endpoint = <&vga_bridge_out>;
>> + };
>> + };
>> + };
>> +
>> wifi_pwrseq: wifi_pwrseq {
>> compatible = "mmc-pwrseq-simple";
>> reset-gpios = <&pio 6 10 GPIO_ACTIVE_LOW>; /* PG10 */
>> @@ -245,6 +288,19 @@
>> status = "okay";
>> };
>>
>> +&tcon0 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&lcd0_rgb888_pins>;
>> + status = "okay";
>> +};
>> +
>> +&tcon0_out {
>> + tcon0_out_vga: endpoint at 0 {
>> + reg = <0>;
>> + remote-endpoint = <&vga_bridge_in>;
>> + };
>> +};
>> +
>> &uart0 {
>> pinctrl-names = "default";
>> pinctrl-0 = <&uart0_pins_a>;
>>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox