* [PATCH v2] arm64: dts: qcom: msm8996: Move UFS_GDSC to UFS HCD
From: Bjorn Andersson @ 2018-05-25 18:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524223122.12601-1-bjorn.andersson@linaro.org>
The UFS_GDSC backs the resources needed by the UFS HCD, rather than the
PHY. This results in the UFS HCD occationally failing to enable some of
its clocks.
Move the UFS_GDSC reference to the UFS HCD node instead, to correct
this.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
Changes since v1:
- Dropped UFS_GDSC from phy node
arch/arm64/boot/dts/qcom/msm8996.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 380e14591686..8c7f9ca25b53 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -654,8 +654,6 @@
clocks = <&rpmcc RPM_SMD_LN_BB_CLK>,
<&gcc GCC_UFS_CLKREF_CLK>;
status = "disabled";
-
- power-domains = <&gcc UFS_GDSC>;
};
ufshc at 624000 {
@@ -674,6 +672,8 @@
vccq-max-microamp = <450000>;
vccq2-max-microamp = <450000>;
+ power-domains = <&gcc UFS_GDSC>;
+
clock-names =
"core_clk_src",
"core_clk",
--
2.17.0
^ permalink raw reply related
* [PATCH 1/6] coresight: remove CORESIGHT_LINKS_AND_SINKS dependencies and selections
From: Kim Phillips @ 2018-05-25 18:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANLsYkwZtAptXtLK0HaDwmXbdAx24X+PEFVggakxe31nkH111g@mail.gmail.com>
On Fri, 25 May 2018 09:27:09 -0600
Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
> On 24 May 2018 at 17:30, Kim Phillips <kim.phillips@arm.com> wrote:
> > On Thu, 24 May 2018 09:32:48 -0600
> > Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
> >
> >> On 23 May 2018 at 13:51, Kim Phillips <kim.phillips@arm.com> wrote:
> >> > On Tue, 22 May 2018 11:31:40 -0600
> >> > Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
> >> >
> >> >> On Thu, May 17, 2018 at 08:20:19PM -0500, Kim Phillips wrote:
> >> >> > A coresight topology doesn't need to include links, i.e., a source can
> >> >> > be directly connected to a sink. As such, selecting and/or depending on
> >> >> > LINKS_AND_SINKS is no longer needed.
> >> >>
> >> >> I'm good with this patch but now the help text for CORESIGHT_LINKS_AND_SINKS no
> >> >> longer match what the config does. I see two ways to fix this:
> >> >
> >> > This patch doesn't change what the config does, it just changes what
> >> > other config options depend on it.
> >> >
> >> >> 1) Rework the help text.
> >> >
> >> > I don't see how, given the above. Here's the text:
> >> >
> >> > config CORESIGHT_LINKS_AND_SINKS
> >> > bool "CoreSight Link and Sink drivers"
> >> > help
> >> > This enables support for CoreSight link and sink drivers that are
> >> > responsible for transporting and collecting the trace data
> >> > respectively. Link and sinks are dynamically aggregated with a trace
> >> > entity at run time to form a complete trace path.
> >> >
> >> > What part of that becomes invalid with this patch?
> >>
> >> Looking at the new Kconfig, what sink component depend on
> >> CORESIGHT_LINKS_AND_SINKS?
> >
> > How does that affect the description text? The description text
> > doesn't insinuate any implicit dependencies or non-.
>
> Now that the depends are gone there is no correlation between this
> config and sinks.
There never was: LINKS_AND_SINKS got introduced here:
commit 6e21e3451556af6ada01e2206d5949fc654d75e1
Author: Pratik Patel <pratikp@codeaurora.org>
Date: Mon Nov 3 11:07:39 2014 -0700
coresight-funnel: add CoreSight Funnel driver
This driver manages CoreSight Funnel which acts as a link.
Funnels have multiple input ports (typically 8) each of which
represents an input trace data stream. These multiple input trace
data streams are interleaved into a single output stream coming
out of the Funnel.
Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 4c43dade4c14..05b8a1c75f73 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_OF) += of_coresight.o
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
+obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o
Then the replicator driver (again, not a sink), got tacked on to be
built under LINKS_AND_SINKS here:
commit ceacc1d9b7ae41e4be185596306be17537682fb1
Author: Pratik Patel <pratikp@codeaurora.org>
Date: Mon Nov 3 11:07:40 2014 -0700
coresight-replicator: add CoreSight Replicator driver
This driver manages non-configurable CoreSight Replicator that
takes a single input trace data stream and replicates it to
produce two identical trace data output streams. Replicators
are typically used to route single interleaved trace data
stream to two or more sinks.
Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 05b8a1c75f73..574d5fa496fa 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_OF) += of_coresight.o
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
-obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o
+obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
+ coresight-replicator.o
Then, finally, the first 'depends on' came with the introduction of the
first TMC driver, which used the config symbol
CORESIGHT_LINK_AND_SINK_TMC, because the TMC can be configured as a
link or as a sink:
commit bc4bf7fe98daf4e64cc5ffc6cdc0e820f4d99c14
Author: Pratik Patel <pratikp@codeaurora.org>
Date: Mon Nov 3 11:07:36 2014 -0700
coresight-tmc: add CoreSight TMC driver
This driver manages CoreSight TMC (Trace Memory Controller) which
can act as a link or a sink depending upon its configuration. It
can present itself as an ETF (Embedded Trace FIFO) or ETR
(Embedded Trace Router).
ETF when configured in circular buffer mode acts as a trace
collection sink. When configured in HW fifo mode it acts as link.
ETR always acts as a sink and can be used to route data to memory
allocated in RAM.
Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index cd3890e3110e..092b6728af55 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1340,4 +1340,24 @@ menuconfig CORESIGHT
a topological view of the CoreSight components based on a DT
specification and configure the right serie of components when a
trace source gets enabled.
+
+if CORESIGHT
+config CORESIGHT_LINKS_AND_SINKS
+ bool "CoreSight Link and Sink drivers"
+ help
+ This enables support for CoreSight link and sink drivers that are
+ responsible for transporting and collecting the trace data
+ respectively. Link and sinks are dynamically aggregated with a trace
+ entity at run time to form a complete trace path.
+
+config CORESIGHT_LINK_AND_SINK_TMC
+ bool "Coresight generic TMC driver"
+ depends on CORESIGHT_LINKS_AND_SINKS
+ help
+ This enables support for the Trace Memory Controller driver. Depending
+ on its configuration the device can act as a link (embedded trace router
+ - ETR) or sink (embedded trace FIFO). The driver complies with the
+ generic implementation of the component without special enhancement or
+ added features.
+endif
endmenu
So LINKS_AND_SINKS never actually built a sink driver by itself. Since
all the above commits appear to come from the same series, I'm guessing
the CORESIGHT_LINKS_AND_SINKS name was from a decision made during
development, where indeed sinks may have been built under the name.
We can argue semantics over the 'depends on' causality, but the original
text description suggests that sink drivers were indeed being build
under the name, because it never explicitly said that sink drivers need
to depend on it.
So I don't think the rename change is warranted due to the lift of the
'depends on' clauses. I think the LINKS_AND_SINKS name was initially
incorrect, and is a remnant of an oversight when cleaning up a
development version for submission upstream. A rename patch to fix
it can be done, but I think it adds undue complication, and is
completely unrelated to this modularization series.
> >> config CORESIGHT_LINKS
> >
> > Please, not another gratuitous config name change, I've already
> > experienced usage regressions from the CORESIGHT_QCOM_REPLICATOR =>
> > CORESIGHT_DYNAMIC_REPLICATOR change:
>
> Defines within subsystems are bound to change as they evolves. Most
> of the CoreSight subsystem was developed on the OMAP3 based
> beagleboard. Since then new topologies have emerged and new IP blocks
> came along. It is only normal that we adjust configuration options to
> reflect the reality of the HW the subsystem is managing. I can guide
> you through the history of the replicator config name change if you
> want - it is quite logical. Other than that and until this patchset,
> we haven't modified a single configuration in the 5 years the
> subsystem has existed. Not bad for all the churn and new IP blocks
> that came in.
>
> >
> > https://patchwork.kernel.org/patch/10206023/
> >
> >> bool "CoreSight Link drivers"
> >> help
> >> This enables support for CoreSight link drivers that are responsible
> >> for transporting trace data from source to sink. Links are
> >> dynamically
> >> aggregated with other traces entities at run time to form a
> >> complete trace
> >> path.
> >
> > Oh, I see, so your point is that LINKS_AND_SINKS doesn't technically
> > build any sink drivers? That's completely orthogonal to removing a
> > dependency chain: that just tells me the name was a poor choice in the
> > first place maybe? I don't see where the Makefile may have built a
> > sink, but it may be before the move to drivers/hwtracing/coresight, or
> > some other reorganization.
>
> Because of the depends property carried by the sink drivers (which we
> are now removing), defining CORESIGHT_LINKS_AND_SINKS was mandatory to
> build sink drivers. That was accurate 5 years ago with the topologies
> that were available at that time. Now there is no point in having the
> define, which is why I'm asking you to make this modification.
See above for my own analysis of the history; it should have been
CORESIGHT_LINKS from the very beginning, and the description was
inaccurate also from the beginning. Lifting the 'depends on' doesn't
necessitate globbing in a gratuitous naming and description fix in this
patch.
> >> >> 2) Rework CORESIGHT_LINKS_AND_SINKS to be CORESIGHT_FUNNEL and move
> >> >> coresight-replicator.o under CORESIGHT_DYNAMIC_REPLICATOR in the Makefile. I
> >> >> really liked your idea of making the replicator driver intelligent enough to
> >> >> deal with both DT and platform declaration, which merges two driver into one.
> >> >>
> >> >> I'm obviously favouring the second option but recognise it doesn't have to be
> >> >> part of this patchet. So for this set please rework the help text for
> >> >> CORESIGHT_LINKS_AND_SINKS. Once we've dealt with this topic we can refactor the
> >> >> replicator driver.
> >> >
> >> > I'd really like to just focus on getting CoreSight to load as modules,
> >> > something for which this patch isn't technically required...
> >>
> >> The only thing I'm asking is that the config description and help text
> >> reflect what the Makefile does.
> >
> > argh, wellll, it's a completely different change, and we're now
> > completely off the modularization topic, and I'm uncomfortable doing
>
> I don't agree with you. This is a very simple change and I even wrote
> down what needed to be modified.
>
> > reorgs on things I don't understand, renaming CONFIG_s, esp. when
> > others such as the REPLICATOR, since as far as I know, that's also a
> > link??
>
> Correct, a replicator is a link and completely removed from this conversation.
>
> If this is so hard for you then simply don't make the modification - I
> will do it myself, something that will take me about 10 minutes
> (including writing the changelog).
OK, cool, thanks and sorry, but, like I said, I don't think the rename
belongs in either this 'depends on' lift one-off patch (that I'm already
uncomfortable with), let alone in this modularization series.
Because I consider it gratuitous, I think the rename ought to come at a
time where another more purposeful rename occurs, i.e., in addition to
e.g., a replicator driver reorg.
Just my 2c.
Kim
^ permalink raw reply related
* [PATCH 1/6] coresight: remove CORESIGHT_LINKS_AND_SINKS dependencies and selections
From: Mathieu Poirier @ 2018-05-25 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525135227.ca286a1ba942bc7a28bb5686@arm.com>
On 25 May 2018 at 12:52, Kim Phillips <kim.phillips@arm.com> wrote:
> On Fri, 25 May 2018 09:27:09 -0600
> Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
>
>> On 24 May 2018 at 17:30, Kim Phillips <kim.phillips@arm.com> wrote:
>> > On Thu, 24 May 2018 09:32:48 -0600
>> > Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
>> >
>> >> On 23 May 2018 at 13:51, Kim Phillips <kim.phillips@arm.com> wrote:
>> >> > On Tue, 22 May 2018 11:31:40 -0600
>> >> > Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
>> >> >
>> >> >> On Thu, May 17, 2018 at 08:20:19PM -0500, Kim Phillips wrote:
>> >> >> > A coresight topology doesn't need to include links, i.e., a source can
>> >> >> > be directly connected to a sink. As such, selecting and/or depending on
>> >> >> > LINKS_AND_SINKS is no longer needed.
>> >> >>
>> >> >> I'm good with this patch but now the help text for CORESIGHT_LINKS_AND_SINKS no
>> >> >> longer match what the config does. I see two ways to fix this:
>> >> >
>> >> > This patch doesn't change what the config does, it just changes what
>> >> > other config options depend on it.
>> >> >
>> >> >> 1) Rework the help text.
>> >> >
>> >> > I don't see how, given the above. Here's the text:
>> >> >
>> >> > config CORESIGHT_LINKS_AND_SINKS
>> >> > bool "CoreSight Link and Sink drivers"
>> >> > help
>> >> > This enables support for CoreSight link and sink drivers that are
>> >> > responsible for transporting and collecting the trace data
>> >> > respectively. Link and sinks are dynamically aggregated with a trace
>> >> > entity at run time to form a complete trace path.
>> >> >
>> >> > What part of that becomes invalid with this patch?
>> >>
>> >> Looking at the new Kconfig, what sink component depend on
>> >> CORESIGHT_LINKS_AND_SINKS?
>> >
>> > How does that affect the description text? The description text
>> > doesn't insinuate any implicit dependencies or non-.
>>
>> Now that the depends are gone there is no correlation between this
>> config and sinks.
>
> There never was: LINKS_AND_SINKS got introduced here:
>
> commit 6e21e3451556af6ada01e2206d5949fc654d75e1
> Author: Pratik Patel <pratikp@codeaurora.org>
> Date: Mon Nov 3 11:07:39 2014 -0700
>
> coresight-funnel: add CoreSight Funnel driver
>
> This driver manages CoreSight Funnel which acts as a link.
> Funnels have multiple input ports (typically 8) each of which
> represents an input trace data stream. These multiple input trace
> data streams are interleaved into a single output stream coming
> out of the Funnel.
>
> Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
> index 4c43dade4c14..05b8a1c75f73 100644
> --- a/drivers/coresight/Makefile
> +++ b/drivers/coresight/Makefile
> @@ -6,3 +6,4 @@ obj-$(CONFIG_OF) += of_coresight.o
> obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
> obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
> obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
> +obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o
>
> Then the replicator driver (again, not a sink), got tacked on to be
> built under LINKS_AND_SINKS here:
>
> commit ceacc1d9b7ae41e4be185596306be17537682fb1
> Author: Pratik Patel <pratikp@codeaurora.org>
> Date: Mon Nov 3 11:07:40 2014 -0700
>
> coresight-replicator: add CoreSight Replicator driver
>
> This driver manages non-configurable CoreSight Replicator that
> takes a single input trace data stream and replicates it to
> produce two identical trace data output streams. Replicators
> are typically used to route single interleaved trace data
> stream to two or more sinks.
>
> Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
> index 05b8a1c75f73..574d5fa496fa 100644
> --- a/drivers/coresight/Makefile
> +++ b/drivers/coresight/Makefile
> @@ -6,4 +6,5 @@ obj-$(CONFIG_OF) += of_coresight.o
> obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
> obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
> obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
> -obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o
> +obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
> + coresight-replicator.o
>
> Then, finally, the first 'depends on' came with the introduction of the
> first TMC driver, which used the config symbol
> CORESIGHT_LINK_AND_SINK_TMC, because the TMC can be configured as a
> link or as a sink:
>
> commit bc4bf7fe98daf4e64cc5ffc6cdc0e820f4d99c14
> Author: Pratik Patel <pratikp@codeaurora.org>
> Date: Mon Nov 3 11:07:36 2014 -0700
>
> coresight-tmc: add CoreSight TMC driver
>
> This driver manages CoreSight TMC (Trace Memory Controller) which
> can act as a link or a sink depending upon its configuration. It
> can present itself as an ETF (Embedded Trace FIFO) or ETR
> (Embedded Trace Router).
>
> ETF when configured in circular buffer mode acts as a trace
> collection sink. When configured in HW fifo mode it acts as link.
> ETR always acts as a sink and can be used to route data to memory
> allocated in RAM.
>
> Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
> index cd3890e3110e..092b6728af55 100644
> --- a/arch/arm/Kconfig.debug
> +++ b/arch/arm/Kconfig.debug
> @@ -1340,4 +1340,24 @@ menuconfig CORESIGHT
> a topological view of the CoreSight components based on a DT
> specification and configure the right serie of components when a
> trace source gets enabled.
> +
> +if CORESIGHT
> +config CORESIGHT_LINKS_AND_SINKS
> + bool "CoreSight Link and Sink drivers"
> + help
> + This enables support for CoreSight link and sink drivers that are
> + responsible for transporting and collecting the trace data
> + respectively. Link and sinks are dynamically aggregated with a trace
> + entity at run time to form a complete trace path.
> +
> +config CORESIGHT_LINK_AND_SINK_TMC
> + bool "Coresight generic TMC driver"
> + depends on CORESIGHT_LINKS_AND_SINKS
> + help
> + This enables support for the Trace Memory Controller driver. Depending
> + on its configuration the device can act as a link (embedded trace router
> + - ETR) or sink (embedded trace FIFO). The driver complies with the
> + generic implementation of the component without special enhancement or
> + added features.
> +endif
> endmenu
>
> So LINKS_AND_SINKS never actually built a sink driver by itself. Since
> all the above commits appear to come from the same series, I'm guessing
> the CORESIGHT_LINKS_AND_SINKS name was from a decision made during
> development, where indeed sinks may have been built under the name.
Sinks were never built under that config. It is there to highlight
the fact that sinks can't operate without links. But that was under
previous designs where sources were never directly connected to sinks.
>
> We can argue semantics over the 'depends on' causality, but the original
> text description suggests that sink drivers were indeed being build
> under the name, because it never explicitly said that sink drivers need
> to depend on it.
>
> So I don't think the rename change is warranted due to the lift of the
> 'depends on' clauses. I think the LINKS_AND_SINKS name was initially
> incorrect, and is a remnant of an oversight when cleaning up a
> development version for submission upstream. A rename patch to fix
> it can be done, but I think it adds undue complication, and is
> completely unrelated to this modularization series.
>
>> >> config CORESIGHT_LINKS
>> >
>> > Please, not another gratuitous config name change, I've already
>> > experienced usage regressions from the CORESIGHT_QCOM_REPLICATOR =>
>> > CORESIGHT_DYNAMIC_REPLICATOR change:
>>
>> Defines within subsystems are bound to change as they evolves. Most
>> of the CoreSight subsystem was developed on the OMAP3 based
>> beagleboard. Since then new topologies have emerged and new IP blocks
>> came along. It is only normal that we adjust configuration options to
>> reflect the reality of the HW the subsystem is managing. I can guide
>> you through the history of the replicator config name change if you
>> want - it is quite logical. Other than that and until this patchset,
>> we haven't modified a single configuration in the 5 years the
>> subsystem has existed. Not bad for all the churn and new IP blocks
>> that came in.
>>
>> >
>> > https://patchwork.kernel.org/patch/10206023/
>> >
>> >> bool "CoreSight Link drivers"
>> >> help
>> >> This enables support for CoreSight link drivers that are responsible
>> >> for transporting trace data from source to sink. Links are
>> >> dynamically
>> >> aggregated with other traces entities at run time to form a
>> >> complete trace
>> >> path.
>> >
>> > Oh, I see, so your point is that LINKS_AND_SINKS doesn't technically
>> > build any sink drivers? That's completely orthogonal to removing a
>> > dependency chain: that just tells me the name was a poor choice in the
>> > first place maybe? I don't see where the Makefile may have built a
>> > sink, but it may be before the move to drivers/hwtracing/coresight, or
>> > some other reorganization.
>>
>> Because of the depends property carried by the sink drivers (which we
>> are now removing), defining CORESIGHT_LINKS_AND_SINKS was mandatory to
>> build sink drivers. That was accurate 5 years ago with the topologies
>> that were available at that time. Now there is no point in having the
>> define, which is why I'm asking you to make this modification.
>
> See above for my own analysis of the history; it should have been
> CORESIGHT_LINKS from the very beginning, and the description was
> inaccurate also from the beginning. Lifting the 'depends on' doesn't
> necessitate globbing in a gratuitous naming and description fix in this
> patch.
>
>> >> >> 2) Rework CORESIGHT_LINKS_AND_SINKS to be CORESIGHT_FUNNEL and move
>> >> >> coresight-replicator.o under CORESIGHT_DYNAMIC_REPLICATOR in the Makefile. I
>> >> >> really liked your idea of making the replicator driver intelligent enough to
>> >> >> deal with both DT and platform declaration, which merges two driver into one.
>> >> >>
>> >> >> I'm obviously favouring the second option but recognise it doesn't have to be
>> >> >> part of this patchet. So for this set please rework the help text for
>> >> >> CORESIGHT_LINKS_AND_SINKS. Once we've dealt with this topic we can refactor the
>> >> >> replicator driver.
>> >> >
>> >> > I'd really like to just focus on getting CoreSight to load as modules,
>> >> > something for which this patch isn't technically required...
>> >>
>> >> The only thing I'm asking is that the config description and help text
>> >> reflect what the Makefile does.
>> >
>> > argh, wellll, it's a completely different change, and we're now
>> > completely off the modularization topic, and I'm uncomfortable doing
>>
>> I don't agree with you. This is a very simple change and I even wrote
>> down what needed to be modified.
>>
>> > reorgs on things I don't understand, renaming CONFIG_s, esp. when
>> > others such as the REPLICATOR, since as far as I know, that's also a
>> > link??
>>
>> Correct, a replicator is a link and completely removed from this conversation.
>>
>> If this is so hard for you then simply don't make the modification - I
>> will do it myself, something that will take me about 10 minutes
>> (including writing the changelog).
>
> OK, cool, thanks and sorry, but, like I said, I don't think the rename
> belongs in either this 'depends on' lift one-off patch (that I'm already
> uncomfortable with), let alone in this modularization series.
Don't do anything, just leave things the way they are - I will deal with it.
>
> Because I consider it gratuitous, I think the rename ought to come at a
> time where another more purposeful rename occurs, i.e., in addition to
> e.g., a replicator driver reorg.
>
> Just my 2c.
>
> Kim
^ permalink raw reply
* [PATCH 2/2] ARM: shmobile: only call secure_cntvoff_init on SMP builds
From: Geert Uytterhoeven @ 2018-05-25 19:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525161051.187324-2-arnd@arndb.de>
Hi Arnd,
On Fri, May 25, 2018 at 6:10 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> The secure_cntvoff_init() function is not available without CONFIG_SMP,
> leading to a link error on shmobile:
>
> arch/arm/mach-shmobile/setup-rcar-gen2.o: In function `rcar_gen2_timer_init':
> setup-rcar-gen2.c:(.init.text+0x18): undefined reference to `secure_cntvoff_init'
>
> From the description in commit 3fd45a136ff6 ("ARM: shmobile: rcar-gen2:
> Make sure CNTVOFF is initialized on CA7/15"), I understand that we
> don't need to call it on non-SMP builds because the boot CPU is always
> initialized by common code, so we can simply avoid the reference by
> checking for CONFIG_SMP.
>
> Fixes: cad160ed0a94 ("ARM: shmobile: Convert file to use cntvoff")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
NAKed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c
> +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
> @@ -71,7 +71,8 @@ void __init rcar_gen2_timer_init(void)
> void __iomem *base;
> u32 freq;
>
> - secure_cntvoff_init();
> + if (IS_ENABLED(CONFIG_SMP))
> + secure_cntvoff_init();
The call here is for the boot CPU, since commit 9ce3fa6816c2fb59 ("ARM:
shmobile: rcar-gen2: Add CA7 arch_timer initialization for r8a7794"), and
modified and consolidated in commit 3fd45a136ff6 mentioned above.
The call for secondary CPUs is in arch/arm/mach-shmobile/headsmp-apmu.S.
>
> if (of_machine_is_compatible("renesas,r8a7745") ||
> of_machine_is_compatible("renesas,r8a77470") ||
So the proper fix is to build arch/arm/common/secure_cntvoff.o
unconditionally.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH v6 09/11] firmware: xilinx: Add debugfs for clock control APIs
From: Jolly Shah @ 2018-05-25 19:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6579fdce-6845-70d5-1dc1-64d52debef19@arm.com>
Hi Sudeep,
> -----Original Message-----
> From: Sudeep Holla [mailto:sudeep.holla at arm.com]
> Sent: Tuesday, May 15, 2018 1:58 AM
> To: Jolly Shah <JOLLYS@xilinx.com>; ard.biesheuvel at linaro.org;
> mingo at kernel.org; gregkh at linuxfoundation.org; matt at codeblueprint.co.uk;
> hkallweit1 at gmail.com; keescook at chromium.org;
> dmitry.torokhov at gmail.com; mturquette at baylibre.com;
> sboyd at codeaurora.org; michal.simek at xilinx.com; robh+dt at kernel.org;
> mark.rutland at arm.com; linux-clk at vger.kernel.org
> Cc: Sudeep Holla <sudeep.holla@arm.com>; Rajan Vaja <RAJANV@xilinx.com>;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> devicetree at vger.kernel.org
> Subject: Re: [PATCH v6 09/11] firmware: xilinx: Add debugfs for clock control
> APIs
>
>
>
> On 14/05/18 20:18, Jolly Shah wrote:
> > Hi Sudeep,
>
> [..]
>
> >>
> >> As I mentioned in earlier patch, I don't see the need for this
> >> debugfs interface. Clock lay has read-only interface in debugfs
> >> already. Also if you want to debug clocks, you can do so using the
> >> driver which uses these clocks. Do you really want to manage clocks
> >> in user-space ? The whole idea of EEMI kind of interface is to
> >> abstract and hide the fine details even from non-trusted rich OS like
> >> Linux kernel, but by providing this you are doing exactly opposite.
> >
> > No we don't want to manage clocks in user-space. This debugfs is meant
> > for developer who wants to debug APIs behavior in case something
> > doesn't work as expected. Debugfs should be off by default in
> > production images.
> >
>
> Good that it's not used in production image. The clock layer has
> *sufficient* debugfs support that will *help in debugging*. So please drop this
> Xilinx specific clock debugfs.
>
> --
> Regards,
> Sudeep
Ok. Will remove them in next version. Let me know if rest changes look ok and I can submit final version with suggested minor changes.
Thanks,
Jolly Shah
^ permalink raw reply
* [PATCH V3 0/6] hwmon: Add support for Raspberry Pi voltage sensor
From: Stefan Wahren @ 2018-05-25 19:24 UTC (permalink / raw)
To: linux-arm-kernel
A common issue for the Raspberry Pi is an inadequate power supply.
Noralf Tr?nnes started a discussion [1] about writing such undervoltage
conditions into the kernel log.
Changes in V3:
- rebase
- simplify probing
Changes in V2:
- simplified Kconfig dependency suggested by Robin Murphy
- replace dt-binding by probing from firmware driver
- add hwmon documentation
- minor improvements suggested by Guenter Roeck
[1] - https://github.com/raspberrypi/linux/issues/2367
Stefan Wahren (6):
ARM: bcm2835: Add GET_THROTTLED firmware property
hwmon: Add support for RPi voltage sensor
firmware: raspberrypi: Register hwmon driver
ARM: bcm2835_defconfig: Enable RPi voltage sensor
ARM: multi_v7_defconfig: Enable RPi voltage sensor
arm64: defconfig: Enable RPi voltage sensor
Documentation/hwmon/raspberrypi-hwmon | 22 ++++
arch/arm/configs/bcm2835_defconfig | 2 +-
arch/arm/configs/multi_v7_defconfig | 1 +
arch/arm64/configs/defconfig | 1 +
drivers/firmware/raspberrypi.c | 19 ++++
drivers/hwmon/Kconfig | 10 ++
drivers/hwmon/Makefile | 1 +
drivers/hwmon/raspberrypi-hwmon.c | 166 +++++++++++++++++++++++++++++
include/soc/bcm2835/raspberrypi-firmware.h | 1 +
9 files changed, 222 insertions(+), 1 deletion(-)
create mode 100644 Documentation/hwmon/raspberrypi-hwmon
create mode 100644 drivers/hwmon/raspberrypi-hwmon.c
--
2.7.4
^ permalink raw reply
* [PATCH V3 1/6] ARM: bcm2835: Add GET_THROTTLED firmware property
From: Stefan Wahren @ 2018-05-25 19:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527276279-23876-1-git-send-email-stefan.wahren@i2se.com>
Recent Raspberry Pi firmware provides a mailbox property to detect
under-voltage conditions. Here is the current definition.
The u32 value returned by the firmware is divided into 2 parts:
- lower 16-bits are the live value
- upper 16-bits are the history or sticky value
Bits:
0: undervoltage
1: arm frequency capped
2: currently throttled
16: undervoltage has occurred
17: arm frequency capped has occurred
18: throttling has occurred
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
include/soc/bcm2835/raspberrypi-firmware.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index 8ee8991..c4a5c9e 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -75,6 +75,7 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020,
RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
+ RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001,
RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002,
RPI_FIRMWARE_SET_VOLTAGE = 0x00038003,
--
2.7.4
^ permalink raw reply related
* [PATCH V3 2/6] hwmon: Add support for RPi voltage sensor
From: Stefan Wahren @ 2018-05-25 19:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527276279-23876-1-git-send-email-stefan.wahren@i2se.com>
Currently there is no easy way to detect undervoltage conditions on a
remote Raspberry Pi. This hwmon driver retrieves the state of the
undervoltage sensor via mailbox interface. The handling based on
Noralf's modifications to the downstream firmware driver. In case of
an undervoltage condition only an entry is written to the kernel log.
CC: "Noralf Tr?nnes" <noralf@tronnes.org>
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
Documentation/hwmon/raspberrypi-hwmon | 22 +++++
drivers/hwmon/Kconfig | 10 ++
drivers/hwmon/Makefile | 1 +
drivers/hwmon/raspberrypi-hwmon.c | 166 ++++++++++++++++++++++++++++++++++
4 files changed, 199 insertions(+)
create mode 100644 Documentation/hwmon/raspberrypi-hwmon
create mode 100644 drivers/hwmon/raspberrypi-hwmon.c
diff --git a/Documentation/hwmon/raspberrypi-hwmon b/Documentation/hwmon/raspberrypi-hwmon
new file mode 100644
index 0000000..3c92e2c
--- /dev/null
+++ b/Documentation/hwmon/raspberrypi-hwmon
@@ -0,0 +1,22 @@
+Kernel driver raspberrypi-hwmon
+===============================
+
+Supported boards:
+ * Raspberry Pi A+ (via GPIO on SoC)
+ * Raspberry Pi B+ (via GPIO on SoC)
+ * Raspberry Pi 2 B (via GPIO on SoC)
+ * Raspberry Pi 3 B (via GPIO on port expander)
+ * Raspberry Pi 3 B+ (via PMIC)
+
+Author: Stefan Wahren <stefan.wahren@i2se.com>
+
+Description
+-----------
+
+This driver periodically polls a mailbox property of the VC4 firmware to detect
+undervoltage conditions.
+
+Sysfs entries
+-------------
+
+in0_lcrit_alarm Undervoltage alarm
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f10840a..fdaab82 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1298,6 +1298,16 @@ config SENSORS_PWM_FAN
This driver can also be built as a module. If so, the module
will be called pwm-fan.
+config SENSORS_RASPBERRYPI_HWMON
+ tristate "Raspberry Pi voltage monitor"
+ depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
+ help
+ If you say yes here you get support for voltage sensor on the
+ Raspberry Pi.
+
+ This driver can also be built as a module. If so, the module
+ will be called raspberrypi-hwmon.
+
config SENSORS_SHT15
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
depends on GPIOLIB || COMPILE_TEST
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index e7d52a3..a929770 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -141,6 +141,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
+obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
new file mode 100644
index 0000000..fb4e4a6
--- /dev/null
+++ b/drivers/hwmon/raspberrypi-hwmon.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Raspberry Pi voltage sensor driver
+ *
+ * Based on firmware/raspberrypi.c by Noralf Tr?nnes
+ *
+ * Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com>
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+#define UNDERVOLTAGE_STICKY_BIT BIT(16)
+
+struct rpi_hwmon_data {
+ struct device *hwmon_dev;
+ struct rpi_firmware *fw;
+ u32 last_throttled;
+ struct delayed_work get_values_poll_work;
+};
+
+static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
+{
+ u32 new_uv, old_uv, value;
+ int ret;
+
+ /* Request firmware to clear sticky bits */
+ value = 0xffff;
+
+ ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+ &value, sizeof(value));
+ if (ret) {
+ dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n",
+ ret);
+ return;
+ }
+
+ new_uv = value & UNDERVOLTAGE_STICKY_BIT;
+ old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT;
+ data->last_throttled = value;
+
+ if (new_uv == old_uv)
+ return;
+
+ if (new_uv)
+ dev_crit(data->hwmon_dev, "Undervoltage detected!\n");
+ else
+ dev_info(data->hwmon_dev, "Voltage normalised\n");
+
+ sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm");
+}
+
+static void get_values_poll(struct work_struct *work)
+{
+ struct rpi_hwmon_data *data;
+
+ data = container_of(work, struct rpi_hwmon_data,
+ get_values_poll_work.work);
+
+ rpi_firmware_get_throttled(data);
+
+ /*
+ * We can't run faster than the sticky shift (100ms) since we get
+ * flipping in the sticky bits that are cleared.
+ */
+ schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+}
+
+static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct rpi_hwmon_data *data = dev_get_drvdata(dev);
+
+ *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
+ return 0;
+}
+
+static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ return 0444;
+}
+
+static const u32 rpi_in_config[] = {
+ HWMON_I_LCRIT_ALARM,
+ 0
+};
+
+static const struct hwmon_channel_info rpi_in = {
+ .type = hwmon_in,
+ .config = rpi_in_config,
+};
+
+static const struct hwmon_channel_info *rpi_info[] = {
+ &rpi_in,
+ NULL
+};
+
+static const struct hwmon_ops rpi_hwmon_ops = {
+ .is_visible = rpi_is_visible,
+ .read = rpi_read,
+};
+
+static const struct hwmon_chip_info rpi_chip_info = {
+ .ops = &rpi_hwmon_ops,
+ .info = rpi_info,
+};
+
+static int rpi_hwmon_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rpi_hwmon_data *data;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* Parent driver assure that firmware is correct */
+ data->fw = dev_get_drvdata(dev->parent);
+
+ /* Init throttled */
+ ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+ &data->last_throttled,
+ sizeof(data->last_throttled));
+
+ data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",
+ data,
+ &rpi_chip_info,
+ NULL);
+
+ INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll);
+ platform_set_drvdata(pdev, data);
+
+ if (!PTR_ERR_OR_ZERO(data->hwmon_dev))
+ schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+
+ return PTR_ERR_OR_ZERO(data->hwmon_dev);
+}
+
+static int rpi_hwmon_remove(struct platform_device *pdev)
+{
+ struct rpi_hwmon_data *data = platform_get_drvdata(pdev);
+
+ cancel_delayed_work_sync(&data->get_values_poll_work);
+
+ return 0;
+}
+
+static struct platform_driver rpi_hwmon_driver = {
+ .probe = rpi_hwmon_probe,
+ .remove = rpi_hwmon_remove,
+ .driver = {
+ .name = "raspberrypi-hwmon",
+ },
+};
+module_platform_driver(rpi_hwmon_driver);
+
+MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
+MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related
* [PATCH V3 3/6] firmware: raspberrypi: Register hwmon driver
From: Stefan Wahren @ 2018-05-25 19:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527276279-23876-1-git-send-email-stefan.wahren@i2se.com>
Since the raspberrypi-hwmon driver is tied to the VC4 firmware instead of
particular hardware its registration should be in the firmware driver.
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
drivers/firmware/raspberrypi.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 6692888f..0602626 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -21,6 +21,8 @@
#define MBOX_DATA28(msg) ((msg) & ~0xf)
#define MBOX_CHAN_PROPERTY 8
+static struct platform_device *rpi_hwmon;
+
struct rpi_firmware {
struct mbox_client cl;
struct mbox_chan *chan; /* The property channel. */
@@ -183,6 +185,20 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
}
}
+static void
+rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
+{
+ u32 packet;
+ int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED,
+ &packet, sizeof(packet));
+
+ if (ret)
+ return;
+
+ rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon",
+ -1, NULL, 0);
+}
+
static int rpi_firmware_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -209,6 +225,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, fw);
rpi_firmware_print_firmware_revision(fw);
+ rpi_register_hwmon_driver(dev, fw);
return 0;
}
@@ -217,6 +234,8 @@ static int rpi_firmware_remove(struct platform_device *pdev)
{
struct rpi_firmware *fw = platform_get_drvdata(pdev);
+ platform_device_unregister(rpi_hwmon);
+ rpi_hwmon = NULL;
mbox_free_channel(fw->chan);
return 0;
--
2.7.4
^ permalink raw reply related
* [PATCH V3 4/6] ARM: bcm2835_defconfig: Enable RPi voltage sensor
From: Stefan Wahren @ 2018-05-25 19:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527276279-23876-1-git-send-email-stefan.wahren@i2se.com>
The patch enables the hwmon driver for the Raspberry Pi.
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
arch/arm/configs/bcm2835_defconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index e4d188f..e9bc889 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -86,7 +86,7 @@ CONFIG_SPI=y
CONFIG_SPI_BCM2835=y
CONFIG_SPI_BCM2835AUX=y
CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
CONFIG_THERMAL=y
CONFIG_BCM2835_THERMAL=y
CONFIG_WATCHDOG=y
--
2.7.4
^ permalink raw reply related
* [PATCH V3 5/6] ARM: multi_v7_defconfig: Enable RPi voltage sensor
From: Stefan Wahren @ 2018-05-25 19:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527276279-23876-1-git-send-email-stefan.wahren@i2se.com>
The patch enables the hwmon driver for the Raspberry Pi.
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
arch/arm/configs/multi_v7_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 7b2283a..2af46fd 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -449,6 +449,7 @@ CONFIG_SENSORS_LM90=y
CONFIG_SENSORS_LM95245=y
CONFIG_SENSORS_NTC_THERMISTOR=m
CONFIG_SENSORS_PWM_FAN=m
+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
CONFIG_SENSORS_INA2XX=m
CONFIG_CPU_THERMAL=y
CONFIG_IMX_THERMAL=y
--
2.7.4
^ permalink raw reply related
* [PATCH V3 6/6] arm64: defconfig: Enable RPi voltage sensor
From: Stefan Wahren @ 2018-05-25 19:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527276279-23876-1-git-send-email-stefan.wahren@i2se.com>
The patch enables the hwmon driver for the Raspberry Pi.
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3299505..e5c7198 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -353,6 +353,7 @@ CONFIG_BATTERY_BQ27XXX=y
CONFIG_SENSORS_ARM_SCPI=y
CONFIG_SENSORS_LM90=m
CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_THERMAL_EMULATION=y
--
2.7.4
^ permalink raw reply related
* [PATCH] arm64: defconfig: Enable PCIe on msm8996 and db820c
From: Bjorn Andersson @ 2018-05-25 19:25 UTC (permalink / raw)
To: linux-arm-kernel
The msm8996 PCIe sits behind the "agnoc0", which is represented as a
simple-pm-bus, so enable support for this. Then enable the QMP phy
driver.
Also enable the atl1c ethernet driver and ath10k wlan driver to support
these components on the DragonBoard820c.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
arch/arm64/configs/defconfig | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 895b2d92124d..e3687afdd64c 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -173,6 +173,7 @@ CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_SIMPLE_PM_BUS=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_M25P80=y
@@ -213,6 +214,7 @@ CONFIG_VETH=m
CONFIG_VIRTIO_NET=y
CONFIG_AMD_XGBE=y
CONFIG_NET_XGENE=y
+CONFIG_ATL1C=m
CONFIG_MACB=y
CONFIG_THUNDER_NIC_PF=y
CONFIG_HNS_DSAF=y
@@ -254,6 +256,8 @@ CONFIG_USB_NET_SMSC75XX=m
CONFIG_USB_NET_SMSC95XX=m
CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
+CONFIG_ATH10K=m
+CONFIG_ATH10K_PCI=m
CONFIG_BRCMFMAC=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_PCIE=m
@@ -615,6 +619,7 @@ CONFIG_PHY_HI6220_USB=y
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PHY_MVEBU_CP110_COMPHY=y
+CONFIG_PHY_QCOM_QMP=m
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_EMMC=y
CONFIG_PHY_ROCKCHIP_PCIE=m
--
2.17.0
^ permalink raw reply related
* [PATCH] arm64: dts: fix regulator property name for wlan pcie endpoint
From: Bjorn Andersson @ 2018-05-25 19:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180522195758.24607-1-niklas.cassel@linaro.org>
On Tue 22 May 12:57 PDT 2018, Niklas Cassel wrote:
> The property name vddpe-supply is not included in
> Documentation/devicetree/bindings/pci/qcom,pcie.txt
> nor in the pcie-qcom PCIe Root Complex driver.
>
> This property name was used in an initial patchset for pcie-qcom,
> but was renamed in a later revision.
>
> Therefore, the regulator is currently never enabled, leaving us with
> unoperational wlan.
>
> Fix this by using the correct regulator property name, so that wlan
> comes up correctly.
>
> Fixes: 1c8ca74a2ea1 ("arm64: dts: apq8096-db820c: Enable wlan and bt en pins")
> Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Regards,
Bjorn
> ---
> Bluetooth needs a similar patch, but since bluetooth needs some more
> work, submit this right now, so we at least have working wlan.
>
> arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> index 818bf0efd501..804268f54f37 100644
> --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> @@ -203,7 +203,7 @@
> pcie at 600000 {
> status = "okay";
> perst-gpio = <&msmgpio 35 GPIO_ACTIVE_LOW>;
> - vddpe-supply = <&wlan_en>;
> + vddpe-3v3-supply = <&wlan_en>;
> vddpe1-supply = <&bt_en>;
> };
>
> --
> 2.17.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH V3 2/6] hwmon: Add support for RPi voltage sensor
From: Guenter Roeck @ 2018-05-25 19:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527276279-23876-3-git-send-email-stefan.wahren@i2se.com>
On Fri, May 25, 2018 at 09:24:35PM +0200, Stefan Wahren wrote:
> Currently there is no easy way to detect undervoltage conditions on a
> remote Raspberry Pi. This hwmon driver retrieves the state of the
> undervoltage sensor via mailbox interface. The handling based on
> Noralf's modifications to the downstream firmware driver. In case of
> an undervoltage condition only an entry is written to the kernel log.
>
> CC: "Noralf Tr?nnes" <noralf@tronnes.org>
> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
... assuming this will go through some arm tree.
> ---
> Documentation/hwmon/raspberrypi-hwmon | 22 +++++
> drivers/hwmon/Kconfig | 10 ++
> drivers/hwmon/Makefile | 1 +
> drivers/hwmon/raspberrypi-hwmon.c | 166 ++++++++++++++++++++++++++++++++++
> 4 files changed, 199 insertions(+)
> create mode 100644 Documentation/hwmon/raspberrypi-hwmon
> create mode 100644 drivers/hwmon/raspberrypi-hwmon.c
>
> diff --git a/Documentation/hwmon/raspberrypi-hwmon b/Documentation/hwmon/raspberrypi-hwmon
> new file mode 100644
> index 0000000..3c92e2c
> --- /dev/null
> +++ b/Documentation/hwmon/raspberrypi-hwmon
> @@ -0,0 +1,22 @@
> +Kernel driver raspberrypi-hwmon
> +===============================
> +
> +Supported boards:
> + * Raspberry Pi A+ (via GPIO on SoC)
> + * Raspberry Pi B+ (via GPIO on SoC)
> + * Raspberry Pi 2 B (via GPIO on SoC)
> + * Raspberry Pi 3 B (via GPIO on port expander)
> + * Raspberry Pi 3 B+ (via PMIC)
> +
> +Author: Stefan Wahren <stefan.wahren@i2se.com>
> +
> +Description
> +-----------
> +
> +This driver periodically polls a mailbox property of the VC4 firmware to detect
> +undervoltage conditions.
> +
> +Sysfs entries
> +-------------
> +
> +in0_lcrit_alarm Undervoltage alarm
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index f10840a..fdaab82 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -1298,6 +1298,16 @@ config SENSORS_PWM_FAN
> This driver can also be built as a module. If so, the module
> will be called pwm-fan.
>
> +config SENSORS_RASPBERRYPI_HWMON
> + tristate "Raspberry Pi voltage monitor"
> + depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
> + help
> + If you say yes here you get support for voltage sensor on the
> + Raspberry Pi.
> +
> + This driver can also be built as a module. If so, the module
> + will be called raspberrypi-hwmon.
> +
> config SENSORS_SHT15
> tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
> depends on GPIOLIB || COMPILE_TEST
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index e7d52a3..a929770 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -141,6 +141,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
> obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
> obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
> obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
> +obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
> obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
> obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
> obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
> diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
> new file mode 100644
> index 0000000..fb4e4a6
> --- /dev/null
> +++ b/drivers/hwmon/raspberrypi-hwmon.c
> @@ -0,0 +1,166 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Raspberry Pi voltage sensor driver
> + *
> + * Based on firmware/raspberrypi.c by Noralf Tr?nnes
> + *
> + * Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com>
> + */
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/hwmon.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/workqueue.h>
> +#include <soc/bcm2835/raspberrypi-firmware.h>
> +
> +#define UNDERVOLTAGE_STICKY_BIT BIT(16)
> +
> +struct rpi_hwmon_data {
> + struct device *hwmon_dev;
> + struct rpi_firmware *fw;
> + u32 last_throttled;
> + struct delayed_work get_values_poll_work;
> +};
> +
> +static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
> +{
> + u32 new_uv, old_uv, value;
> + int ret;
> +
> + /* Request firmware to clear sticky bits */
> + value = 0xffff;
> +
> + ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
> + &value, sizeof(value));
> + if (ret) {
> + dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n",
> + ret);
> + return;
> + }
> +
> + new_uv = value & UNDERVOLTAGE_STICKY_BIT;
> + old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT;
> + data->last_throttled = value;
> +
> + if (new_uv == old_uv)
> + return;
> +
> + if (new_uv)
> + dev_crit(data->hwmon_dev, "Undervoltage detected!\n");
> + else
> + dev_info(data->hwmon_dev, "Voltage normalised\n");
> +
> + sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm");
> +}
> +
> +static void get_values_poll(struct work_struct *work)
> +{
> + struct rpi_hwmon_data *data;
> +
> + data = container_of(work, struct rpi_hwmon_data,
> + get_values_poll_work.work);
> +
> + rpi_firmware_get_throttled(data);
> +
> + /*
> + * We can't run faster than the sticky shift (100ms) since we get
> + * flipping in the sticky bits that are cleared.
> + */
> + schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
> +}
> +
> +static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
> + u32 attr, int channel, long *val)
> +{
> + struct rpi_hwmon_data *data = dev_get_drvdata(dev);
> +
> + *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
> + return 0;
> +}
> +
> +static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
> + u32 attr, int channel)
> +{
> + return 0444;
> +}
> +
> +static const u32 rpi_in_config[] = {
> + HWMON_I_LCRIT_ALARM,
> + 0
> +};
> +
> +static const struct hwmon_channel_info rpi_in = {
> + .type = hwmon_in,
> + .config = rpi_in_config,
> +};
> +
> +static const struct hwmon_channel_info *rpi_info[] = {
> + &rpi_in,
> + NULL
> +};
> +
> +static const struct hwmon_ops rpi_hwmon_ops = {
> + .is_visible = rpi_is_visible,
> + .read = rpi_read,
> +};
> +
> +static const struct hwmon_chip_info rpi_chip_info = {
> + .ops = &rpi_hwmon_ops,
> + .info = rpi_info,
> +};
> +
> +static int rpi_hwmon_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct rpi_hwmon_data *data;
> + int ret;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + /* Parent driver assure that firmware is correct */
> + data->fw = dev_get_drvdata(dev->parent);
> +
> + /* Init throttled */
> + ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
> + &data->last_throttled,
> + sizeof(data->last_throttled));
> +
> + data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",
> + data,
> + &rpi_chip_info,
> + NULL);
> +
> + INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll);
> + platform_set_drvdata(pdev, data);
> +
> + if (!PTR_ERR_OR_ZERO(data->hwmon_dev))
> + schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
> +
> + return PTR_ERR_OR_ZERO(data->hwmon_dev);
> +}
> +
> +static int rpi_hwmon_remove(struct platform_device *pdev)
> +{
> + struct rpi_hwmon_data *data = platform_get_drvdata(pdev);
> +
> + cancel_delayed_work_sync(&data->get_values_poll_work);
> +
> + return 0;
> +}
> +
> +static struct platform_driver rpi_hwmon_driver = {
> + .probe = rpi_hwmon_probe,
> + .remove = rpi_hwmon_remove,
> + .driver = {
> + .name = "raspberrypi-hwmon",
> + },
> +};
> +module_platform_driver(rpi_hwmon_driver);
> +
> +MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
> +MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH] dmaengine: pxa: add a default requestor policy
From: Robert Jarzmik @ 2018-05-25 19:56 UTC (permalink / raw)
To: linux-arm-kernel
As what former drcmr -1 value meant, add a this as a default to each
channel, ie. that by default no requestor line is used.
This is specifically used for network drivers smc91x and smc911x, and
needed for their port to slave maps.
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
drivers/dma/pxa_dma.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
index 9505334f9c6e..4edc8f927641 100644
--- a/drivers/dma/pxa_dma.c
+++ b/drivers/dma/pxa_dma.c
@@ -762,6 +762,8 @@ static void pxad_free_chan_resources(struct dma_chan *dchan)
dma_pool_destroy(chan->desc_pool);
chan->desc_pool = NULL;
+ chan->drcmr = (u32)-1;
+ chan->prio = PXAD_PRIO_LOWEST;
}
static void pxad_free_desc(struct virt_dma_desc *vd)
@@ -1386,6 +1388,8 @@ static int pxad_init_dmadev(struct platform_device *op,
c = devm_kzalloc(&op->dev, sizeof(*c), GFP_KERNEL);
if (!c)
return -ENOMEM;
+ c->drcmr = (u32)-1;
+ c->prio = PXAD_PRIO_LOWEST;
c->vc.desc_free = pxad_free_desc;
vchan_init(&c->vc, &pdev->slave);
init_waitqueue_head(&c->wq_state);
--
2.11.0
^ permalink raw reply related
* [RFC][PATCH] ARM: shmobile: Rework the PMIC IRQ line quirk
From: Marek Vasut @ 2018-05-25 20:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMuHMdVz=Wut4qaER=75w41jdqLXpgBw-PQW9oQ+4dSveK-CXg@mail.gmail.com>
On 05/25/2018 09:40 AM, Geert Uytterhoeven wrote:
> Hi Marek,
Hi,
> On Fri, May 25, 2018 at 2:30 AM, Marek Vasut <marek.vasut@gmail.com> wrote:
>> On 02/26/2018 11:39 AM, Geert Uytterhoeven wrote:
>>> On Mon, Feb 26, 2018 at 11:17 AM, Marek Vasut <marek.vasut@gmail.com> wrote:
>>>> Rather than hard-coding the quirk topology, which stopped scaling,
>>>> parse the information from DT. The code looks for all compatible
>>>> PMICs -- da9036 and da9210 -- and checks if their IRQ line is tied
>>>> to the same pin. If so, the code sends a matching sequence to the
>>>> PMIC to deassert the IRQ.
>>>>
>>>> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
>>>
>>> Thanks for your patch!
>>>
>>> At first sight, the probing part looks good to me. I'll have a closer look,
>>> and will give it a try later.
>>>
>>> A few early comment below.
>>>
>>>> --- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
>>>> +++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
>>>
>>>> @@ -88,17 +103,21 @@ static int regulator_quirk_notify(struct notifier_block *nb,
>>>> client = to_i2c_client(dev);
>>>> dev_dbg(dev, "Detected %s\n", client->name);
>>>>
>>>> - if ((client->addr == 0x58 && !strcmp(client->name, "da9063")) ||
>>>> - (client->addr == 0x68 && !strcmp(client->name, "da9210")) ||
>>>> - (client->addr == 0x70 && !strcmp(client->name, "da9210"))) {
>>>> - int ret, len;
>>>> + list_for_each_entry(pos, &quirk_list, list) {
>>>> + if (pos->i2c_msg.addr != client->addr)
>>>> + continue;
>>>>
>>>> - /* There are two DA9210 on Stout, one on the other boards. */
>>>> - len = of_machine_is_compatible("renesas,stout") ? 3 : 2;
>>>> + if (!of_device_is_compatible(dev->of_node, pos->id->compatible))
>>>> + continue;
>>>>
>>>> - dev_info(&client->dev, "clearing da9063/da9210 interrupts\n");
>>>> - ret = i2c_transfer(client->adapter, da9xxx_msgs, len);
>>>> - if (ret != ARRAY_SIZE(da9xxx_msgs))
>>>> + if (!pos->shared)
>>>> + continue;
>>>> +
>>>> + dev_info(&client->dev, "clearing %s at 0x%02x interrupts\n",
>>>> + pos->id->compatible, pos->i2c_msg.addr);
>>>> +
>>>> + ret = i2c_transfer(client->adapter, &pos->i2c_msg, 1);
>>>> + if (ret != 1)
>>>> dev_err(&client->dev, "i2c error %d\n", ret);
>>>> }
>>>
>>> The loop above sents a clear message to a single device only, right?
>>> That won't work, as that will clear the interrupt for that single device only.
>>> All other devices may still have their interrupts asserted.
>>> Next step in probing will be binding the da9210 or da9063 driver, which will
>>> enable the shared irq, and boom!
>>>
>>> Upon detecting the first affected device, you really have to send clear
>>> messages to all devices in the list for which shared == true.
>>
>> This is even worse, the single-device part can be easily fixed. But what
>> if the devices are on different i2c bus ? Do we care about that case or
>> do we assume they are on the same bus (they are in the configurations we
>> know of).
>
> Until we have to support boards where the offenders are on different buses,
> we can limit it to the same bus.
Let's add comment about that.
>>>> @@ -122,7 +146,14 @@ static struct notifier_block regulator_quirk_nb = {
>>>>
>>>> static int __init rcar_gen2_regulator_quirk(void)
>>>> {
>>>> - u32 mon;
>>>> + struct device_node *np;
>>>> + const struct of_device_id *id;
>>>> + struct regulator_quirk *quirk;
>>>> + struct regulator_quirk *pos;
>>>> + struct of_phandle_args *argsa, *argsb;
>>>> + u32 mon, addr, i;
>>>> + bool match;
>>>> + int ret;
>>>>
>>>> if (!of_machine_is_compatible("renesas,koelsch") &&
>>>> !of_machine_is_compatible("renesas,lager") &&
>>>
>>>> @@ -130,6 +161,51 @@ static int __init rcar_gen2_regulator_quirk(void)
>>>> !of_machine_is_compatible("renesas,gose"))
>>>> return -ENODEV;
>>>
>>> We might drop the checks above, to handle other platforms based on the
>>> Renesas reference designs.
>>
>> Are you sure that's a good idea ?
>
> Why not? Would it hurt?
If someone were to design a board which has DA9xxx PMICs on different
I2C busses, sharing the same IRQ line, this quirk won't work. I think
I'd like to have better control over when/where this quirk is applied.
--
Best regards,
Marek Vasut
^ permalink raw reply
* [PATCH V2] ARM: shmobile: Rework the PMIC IRQ line quirk
From: Marek Vasut @ 2018-05-25 20:05 UTC (permalink / raw)
To: linux-arm-kernel
Rather than hard-coding the quirk topology, which stopped scaling,
parse the information from DT. The code looks for all compatible
PMICs -- da9036 and da9210 -- and checks if their IRQ line is tied
to the same pin. If so, the code sends a matching sequence to the
PMIC to deassert the IRQ.
Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa+renesas@sang-engineering.com>
Cc: linux-renesas-soc at vger.kernel.org
---
V2: - Replace the DT shared IRQ check loop with memcmp()
- Send the I2C message to deassert the IRQ line to all PMICs
in the list with shared IRQ line instead of just one
- Add comment that this works only in case all the PMICs are
on the same I2C bus
---
arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c | 117 ++++++++++++++++-----
1 file changed, 93 insertions(+), 24 deletions(-)
diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
index 93f628acfd94..4db8d9ea5f97 100644
--- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
@@ -31,8 +31,10 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/mfd/da9063/registers.h>
@@ -44,34 +46,47 @@
/* start of DA9210 System Control and Event Registers */
#define DA9210_REG_MASK_A 0x54
+struct regulator_quirk {
+ struct list_head list;
+ const struct of_device_id *id;
+ struct of_phandle_args irq_args;
+ struct i2c_msg i2c_msg;
+ bool shared; /* IRQ line is shared */
+};
+
+static LIST_HEAD(quirk_list);
static void __iomem *irqc;
/* first byte sets the memory pointer, following are consecutive reg values */
static u8 da9063_irq_clr[] = { DA9063_REG_IRQ_MASK_A, 0xff, 0xff, 0xff, 0xff };
static u8 da9210_irq_clr[] = { DA9210_REG_MASK_A, 0xff, 0xff };
-static struct i2c_msg da9xxx_msgs[3] = {
- {
- .addr = 0x58,
- .len = ARRAY_SIZE(da9063_irq_clr),
- .buf = da9063_irq_clr,
- }, {
- .addr = 0x68,
- .len = ARRAY_SIZE(da9210_irq_clr),
- .buf = da9210_irq_clr,
- }, {
- .addr = 0x70,
- .len = ARRAY_SIZE(da9210_irq_clr),
- .buf = da9210_irq_clr,
- },
+static struct i2c_msg da9063_msgs = {
+ .addr = 0x00,
+ .len = ARRAY_SIZE(da9063_irq_clr),
+ .buf = da9063_irq_clr,
+};
+
+static struct i2c_msg da9210_msgs = {
+ .addr = 0x00,
+ .len = ARRAY_SIZE(da9210_irq_clr),
+ .buf = da9210_irq_clr,
+};
+
+static const struct of_device_id rcar_gen2_quirk_match[] = {
+ { .compatible = "dlg,da9063", .data = &da9063_msgs },
+ { .compatible = "dlg,da9210", .data = &da9210_msgs },
+ {},
};
static int regulator_quirk_notify(struct notifier_block *nb,
unsigned long action, void *data)
{
+ struct regulator_quirk *pos, *tmp;
struct device *dev = data;
struct i2c_client *client;
static bool done;
+ int ret;
u32 mon;
if (done)
@@ -88,17 +103,20 @@ static int regulator_quirk_notify(struct notifier_block *nb,
client = to_i2c_client(dev);
dev_dbg(dev, "Detected %s\n", client->name);
- if ((client->addr == 0x58 && !strcmp(client->name, "da9063")) ||
- (client->addr == 0x68 && !strcmp(client->name, "da9210")) ||
- (client->addr == 0x70 && !strcmp(client->name, "da9210"))) {
- int ret, len;
+ /*
+ * Send message to all PMICs that share an IRQ line to deassert it.
+ *
+ * WARNING: This works only if all the PMICs are on the same I2C bus.
+ */
+ list_for_each_entry(pos, &quirk_list, list) {
+ if (!pos->shared)
+ continue;
- /* There are two DA9210 on Stout, one on the other boards. */
- len = of_machine_is_compatible("renesas,stout") ? 3 : 2;
+ dev_info(&client->dev, "clearing %s at 0x%02x interrupts\n",
+ pos->id->compatible, pos->i2c_msg.addr);
- dev_info(&client->dev, "clearing da9063/da9210 interrupts\n");
- ret = i2c_transfer(client->adapter, da9xxx_msgs, len);
- if (ret != len)
+ ret = i2c_transfer(client->adapter, &pos->i2c_msg, 1);
+ if (ret != 1)
dev_err(&client->dev, "i2c error %d\n", ret);
}
@@ -111,6 +129,11 @@ static int regulator_quirk_notify(struct notifier_block *nb,
remove:
dev_info(dev, "IRQ2 is not asserted, removing quirk\n");
+ list_for_each_entry_safe(pos, tmp, &quirk_list, list) {
+ list_del(&pos->list);
+ kfree(pos);
+ }
+
done = true;
iounmap(irqc);
return 0;
@@ -122,7 +145,13 @@ static struct notifier_block regulator_quirk_nb = {
static int __init rcar_gen2_regulator_quirk(void)
{
- u32 mon;
+ struct device_node *np;
+ const struct of_device_id *id;
+ struct regulator_quirk *quirk;
+ struct regulator_quirk *pos;
+ struct of_phandle_args *argsa, *argsb;
+ u32 mon, addr;
+ int ret;
if (!of_machine_is_compatible("renesas,koelsch") &&
!of_machine_is_compatible("renesas,lager") &&
@@ -130,6 +159,46 @@ static int __init rcar_gen2_regulator_quirk(void)
!of_machine_is_compatible("renesas,gose"))
return -ENODEV;
+ for_each_matching_node_and_match(np, rcar_gen2_quirk_match, &id) {
+ if (!np || !of_device_is_available(np))
+ break;
+
+ quirk = kzalloc(sizeof(*quirk), GFP_KERNEL);
+
+ argsa = &quirk->irq_args;
+ memcpy(&quirk->i2c_msg, id->data, sizeof(quirk->i2c_msg));
+
+ ret = of_property_read_u32(np, "reg", &addr);
+ if (ret)
+ return ret;
+
+ quirk->id = id;
+ quirk->i2c_msg.addr = addr;
+ quirk->shared = false;
+
+ ret = of_irq_parse_one(np, 0, &quirk->irq_args);
+ if (ret)
+ return ret;
+
+ list_for_each_entry(pos, &quirk_list, list) {
+ argsa = &quirk->irq_args;
+ argsb = &pos->irq_args;
+
+ if (argsa->args_count != argsb->args_count)
+ continue;
+
+ ret = memcmp(argsa->args, argsb->args,
+ argsa->args_count *
+ sizeof(argsa->args[0]));
+ if (!ret) {
+ pos->shared = true;
+ quirk->shared = true;
+ }
+ }
+
+ list_add_tail(&quirk->list, &quirk_list);
+ }
+
irqc = ioremap(IRQC_BASE, PAGE_SIZE);
if (!irqc)
return -ENOMEM;
--
2.16.2
^ permalink raw reply related
* [PATCH] ARM: dts: pxa3xx: fix MMC clocks
From: Robert Jarzmik @ 2018-05-25 20:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524174339.12236-1-daniel@zonque.org>
Daniel Mack <daniel@zonque.org> writes:
> The clocks for the 3 MMC controllers on pxa3xx platforms are CLK_MMC1,
> CLK_MMC2 and CLK_MMC3. CLK_MMC is only for pxa2xx.
>
> Signed-off-by: Daniel Mack <daniel@zonque.org>
Very true.
Queued to pxa/dt.
--
Cheers.
^ permalink raw reply
* [PATCH v2 1/4] soc: Add TmFifo driver for Mellanox BlueField Soc
From: Liming Sun @ 2018-05-25 20:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b143b40446c1870fb8d422b364ead95d54552be9.1527264077.git.lsun@mellanox.com>
This commit adds the TmFifo driver for Mellanox BlueField Soc.
TmFifo is a shared FIFO which enables external host machine to
exchange data with the SoC via USB or PCIe. The driver is based on
virtio framework and has console and network access enabled.
Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/mellanox/Kconfig | 18 +
drivers/soc/mellanox/Makefile | 5 +
drivers/soc/mellanox/tmfifo.c | 1239 ++++++++++++++++++++++++++++++++++++
drivers/soc/mellanox/tmfifo_regs.h | 75 +++
6 files changed, 1339 insertions(+)
create mode 100644 drivers/soc/mellanox/Kconfig
create mode 100644 drivers/soc/mellanox/Makefile
create mode 100644 drivers/soc/mellanox/tmfifo.c
create mode 100644 drivers/soc/mellanox/tmfifo_regs.h
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index c07b4a8..fa87dc8 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -7,6 +7,7 @@ source "drivers/soc/bcm/Kconfig"
source "drivers/soc/fsl/Kconfig"
source "drivers/soc/imx/Kconfig"
source "drivers/soc/mediatek/Kconfig"
+source "drivers/soc/mellanox/Kconfig"
source "drivers/soc/qcom/Kconfig"
source "drivers/soc/renesas/Kconfig"
source "drivers/soc/rockchip/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 4052357..868163f 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_GEMINI) += gemini/
obj-$(CONFIG_ARCH_MXC) += imx/
obj-$(CONFIG_SOC_XWAY) += lantiq/
obj-y += mediatek/
+obj-$(CONFIG_SOC_MLNX) += mellanox/
obj-$(CONFIG_ARCH_MESON) += amlogic/
obj-$(CONFIG_ARCH_QCOM) += qcom/
obj-y += renesas/
diff --git a/drivers/soc/mellanox/Kconfig b/drivers/soc/mellanox/Kconfig
new file mode 100644
index 0000000..d88efa1
--- /dev/null
+++ b/drivers/soc/mellanox/Kconfig
@@ -0,0 +1,18 @@
+menuconfig SOC_MLNX
+ bool "Mellanox SoC drivers"
+ default y if ARCH_MLNX_BLUEFIELD
+
+if ARCH_MLNX_BLUEFIELD || COMPILE_TEST
+
+config MLNX_BLUEFIELD_TMFIFO
+ tristate "Mellanox BlueField SoC TmFifo driver"
+ depends on ARM64
+ default m
+ select VIRTIO_CONSOLE
+ select VIRTIO_NET
+ help
+ Say y here to enable TmFifo support. The TmFifo driver provides the
+ virtio driver framework for the TMFIFO of Mellanox BlueField SoC and
+ the implementation of a console and network driver.
+
+endif # ARCH_MLNX_BLUEFIELD
diff --git a/drivers/soc/mellanox/Makefile b/drivers/soc/mellanox/Makefile
new file mode 100644
index 0000000..c44c0e2
--- /dev/null
+++ b/drivers/soc/mellanox/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Mellanox SoC drivers.
+#
+obj-$(CONFIG_MLNX_BLUEFIELD_TMFIFO) += tmfifo.o
diff --git a/drivers/soc/mellanox/tmfifo.c b/drivers/soc/mellanox/tmfifo.c
new file mode 100644
index 0000000..5647cb6
--- /dev/null
+++ b/drivers/soc/mellanox/tmfifo.c
@@ -0,0 +1,1239 @@
+/*
+ * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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/acpi.h>
+#include <linux/bitfield.h>
+#include <linux/cache.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/efi.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_console.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_net.h>
+#include <linux/virtio_ring.h>
+#include <asm/byteorder.h>
+
+#include "tmfifo_regs.h"
+
+#define TMFIFO_GET_FIELD(reg, mask) FIELD_GET(mask, reg)
+
+#define TMFIFO_SET_FIELD(reg, mask, value) \
+ ((reg & ~mask) | FIELD_PREP(mask, value))
+
+/* Vring size. */
+#define TMFIFO_VRING_SIZE 1024
+
+/* Console Tx buffer size. */
+#define TMFIFO_CONS_TX_BUF_SIZE (32 * 1024)
+
+/* Use a timer for house-keeping. */
+static int tmfifo_timer_interval = HZ / 10;
+
+/* Global lock. */
+static struct mutex tmfifo_lock;
+
+/* Virtio ring size. */
+static int tmfifo_vring_size = TMFIFO_VRING_SIZE;
+module_param(tmfifo_vring_size, int, 0444);
+MODULE_PARM_DESC(tmfifo_vring_size, "Size of the vring.");
+
+struct tmfifo;
+
+/* A flag to indicate TmFifo ready. */
+static bool tmfifo_ready;
+
+/* Virtual devices sharing the TM FIFO. */
+#define TMFIFO_VDEV_MAX (VIRTIO_ID_CONSOLE + 1)
+
+/* Spin lock. */
+static DEFINE_SPINLOCK(tmfifo_spin_lock);
+
+/* Structure to maintain the ring state. */
+struct tmfifo_vring {
+ void *va; /* virtual address */
+ dma_addr_t dma; /* dma address */
+ struct virtqueue *vq; /* virtqueue pointer */
+ struct vring_desc *desc; /* current desc */
+ struct vring_desc *desc_head; /* current desc head */
+ int cur_len; /* processed len in current desc */
+ int rem_len; /* remaining length to be processed */
+ int size; /* vring size */
+ int align; /* vring alignment */
+ int id; /* vring id */
+ int vdev_id; /* TMFIFO_VDEV_xxx */
+ u32 pkt_len; /* packet total length */
+ __virtio16 next_avail; /* next avail desc id */
+ struct tmfifo *fifo; /* pointer back to the tmfifo */
+};
+
+/* Interrupt types. */
+enum {
+ TM_RX_LWM_IRQ, /* Rx low water mark irq */
+ TM_RX_HWM_IRQ, /* Rx high water mark irq */
+ TM_TX_LWM_IRQ, /* Tx low water mark irq */
+ TM_TX_HWM_IRQ, /* Tx high water mark irq */
+ TM_IRQ_CNT
+};
+
+/* Ring types (Rx & Tx). */
+enum {
+ TMFIFO_VRING_RX, /* Rx ring */
+ TMFIFO_VRING_TX, /* Tx ring */
+ TMFIFO_VRING_NUM
+};
+
+struct tmfifo_vdev {
+ struct virtio_device vdev; /* virtual device */
+ u8 status;
+ u64 features;
+ union { /* virtio config space */
+ struct virtio_console_config cons;
+ struct virtio_net_config net;
+ } config;
+ struct tmfifo_vring vrings[TMFIFO_VRING_NUM];
+ u8 *tx_buf; /* tx buffer */
+ u32 tx_head; /* tx buffer head */
+ u32 tx_tail; /* tx buffer tail */
+};
+
+#define TMFIFO_VDEV_TX_BUF_AVAIL(vdev) \
+ (((vdev)->tx_tail >= (vdev)->tx_head) ? \
+ (TMFIFO_CONS_TX_BUF_SIZE - 8 - ((vdev)->tx_tail - (vdev)->tx_head)) : \
+ ((vdev)->tx_head - (vdev)->tx_tail - 8))
+
+#define TMFIFO_VDEV_TX_BUF_PUSH(vdev, len) do { \
+ (vdev)->tx_tail += (len); \
+ if ((vdev)->tx_tail >= TMFIFO_CONS_TX_BUF_SIZE) \
+ (vdev)->tx_tail -= TMFIFO_CONS_TX_BUF_SIZE; \
+} while (0)
+
+#define TMFIFO_VDEV_TX_BUF_POP(vdev, len) do { \
+ (vdev)->tx_head += (len); \
+ if ((vdev)->tx_head >= TMFIFO_CONS_TX_BUF_SIZE) \
+ (vdev)->tx_head -= TMFIFO_CONS_TX_BUF_SIZE; \
+} while (0)
+
+/* TMFIFO device structure */
+struct tmfifo {
+ struct tmfifo_vdev *vdev[TMFIFO_VDEV_MAX]; /* virtual devices */
+ struct platform_device *pdev; /* platform device */
+ struct mutex lock;
+ void __iomem *rx_base; /* mapped register base */
+ void __iomem *tx_base; /* mapped register base */
+ int tx_fifo_size; /* number of entries of the Tx FIFO */
+ int rx_fifo_size; /* number of entries of the Rx FIFO */
+ unsigned long pend_events; /* pending bits for deferred process */
+ int irq[TM_IRQ_CNT]; /* irq numbers */
+ struct work_struct work; /* work struct for deferred process */
+ struct timer_list timer; /* keepalive timer */
+ struct tmfifo_vring *vring[2]; /* current Tx/Rx ring */
+};
+
+union tmfifo_msg_hdr {
+ struct {
+ u8 type; /* message type */
+ __be16 len; /* payload length */
+ u8 unused[5]; /* reserved, set to 0 */
+ } __packed;
+ u64 data;
+};
+
+/*
+ * Default MAC.
+ * This MAC address will be read from EFI persistent variable if configured.
+ * It can also be reconfigured with standard Linux tools.
+ */
+static u8 tmfifo_net_default_mac[6] = {0x00, 0x1A, 0xCA, 0xFF, 0xFF, 0x01};
+
+/* MTU setting of the virtio-net interface. */
+#define TMFIFO_NET_MTU 1500
+
+/* Supported virtio-net features. */
+#define TMFIFO_NET_FEATURES ((1UL << VIRTIO_NET_F_MTU) | \
+ (1UL << VIRTIO_NET_F_STATUS) | \
+ (1UL << VIRTIO_NET_F_MAC))
+
+/* Forward declaration. */
+static void tmfifo_virtio_rxtx(struct virtqueue *vq, bool is_rx);
+static void tmfifo_release_pkt(struct virtio_device *vdev,
+ struct tmfifo_vring *vring,
+ struct vring_desc **desc);
+
+/* Allocate vrings for the fifo. */
+static int tmfifo_alloc_vrings(struct tmfifo *fifo,
+ struct tmfifo_vdev *tm_vdev, int vdev_id)
+{
+ dma_addr_t dma;
+ void *va;
+ int i, size;
+ struct tmfifo_vring *vring;
+
+ for (i = 0; i < ARRAY_SIZE(tm_vdev->vrings); i++) {
+ vring = &tm_vdev->vrings[i];
+ vring->fifo = fifo;
+ vring->size = tmfifo_vring_size;
+ vring->align = SMP_CACHE_BYTES;
+ vring->id = i;
+ vring->vdev_id = vdev_id;
+
+ size = PAGE_ALIGN(vring_size(vring->size, vring->align));
+ va = dma_alloc_coherent(tm_vdev->vdev.dev.parent, size, &dma,
+ GFP_KERNEL);
+ if (!va) {
+ dev_err(tm_vdev->vdev.dev.parent,
+ "vring allocation failed\n");
+ return -EINVAL;
+ }
+
+ vring->va = va;
+ vring->dma = dma;
+ }
+
+ return 0;
+}
+
+/* Free vrings of the fifo device. */
+static void tmfifo_free_vrings(struct tmfifo *fifo, int vdev_id)
+{
+ int i, size;
+ struct tmfifo_vring *vring;
+ struct tmfifo_vdev *tm_vdev = fifo->vdev[vdev_id];
+
+ for (i = 0; i < ARRAY_SIZE(tm_vdev->vrings); i++) {
+ vring = &tm_vdev->vrings[i];
+
+ size = PAGE_ALIGN(vring_size(vring->size, vring->align));
+ if (vring->va) {
+ dma_free_coherent(tm_vdev->vdev.dev.parent, size,
+ vring->va, vring->dma);
+ vring->va = NULL;
+ if (vring->vq) {
+ vring_del_virtqueue(vring->vq);
+ vring->vq = NULL;
+ }
+ }
+ }
+}
+
+/* Free interrupts of the fifo device. */
+static void tmfifo_free_irqs(struct tmfifo *fifo)
+{
+ int i, irq;
+
+ for (i = 0; i < TM_IRQ_CNT; i++) {
+ irq = fifo->irq[i];
+ if (irq) {
+ fifo->irq[i] = 0;
+ disable_irq(irq);
+ free_irq(irq, (u8 *)fifo + i);
+ }
+ }
+}
+
+/* Work handler for Rx, Tx or activity monitoring. */
+static void tmfifo_work_handler(struct work_struct *work)
+{
+ int i;
+ struct tmfifo_vdev *tm_vdev;
+ struct tmfifo *fifo = container_of(work, struct tmfifo, work);
+
+ if (!tmfifo_ready)
+ return;
+
+ mutex_lock(&fifo->lock);
+
+ /* Tx. */
+ if (test_and_clear_bit(TM_TX_LWM_IRQ, &fifo->pend_events) &&
+ fifo->irq[TM_TX_LWM_IRQ]) {
+ for (i = 0; i < TMFIFO_VDEV_MAX; i++) {
+ tm_vdev = fifo->vdev[i];
+ if (tm_vdev != NULL) {
+ tmfifo_virtio_rxtx(
+ tm_vdev->vrings[TMFIFO_VRING_TX].vq,
+ false);
+ }
+ }
+ }
+
+ /* Rx. */
+ if (test_and_clear_bit(TM_RX_HWM_IRQ, &fifo->pend_events) &&
+ fifo->irq[TM_RX_HWM_IRQ]) {
+ for (i = 0; i < TMFIFO_VDEV_MAX; i++) {
+ tm_vdev = fifo->vdev[i];
+ if (tm_vdev != NULL) {
+ tmfifo_virtio_rxtx(
+ tm_vdev->vrings[TMFIFO_VRING_RX].vq,
+ true);
+ }
+ }
+ }
+
+ mutex_unlock(&fifo->lock);
+}
+
+/* Interrupt handler. */
+static irqreturn_t tmfifo_irq_handler(int irq, void *dev_id)
+{
+ int i = (uintptr_t)dev_id % sizeof(void *);
+ struct tmfifo *fifo = dev_id - i;
+
+ if (i < TM_IRQ_CNT && !test_and_set_bit(i, &fifo->pend_events))
+ schedule_work(&fifo->work);
+
+ return IRQ_HANDLED;
+}
+
+/* Nothing to do for now. */
+static void tmfifo_virtio_dev_release(struct device *dev)
+{
+}
+
+/* Get the next packet descriptor from the vring. */
+static inline struct vring_desc *
+tmfifo_virtio_get_next_desc(struct virtqueue *vq)
+{
+ unsigned int idx, head;
+ struct vring *vr = (struct vring *)virtqueue_get_vring(vq);
+ struct tmfifo_vring *vring = (struct tmfifo_vring *)vq->priv;
+
+ if (!vr || vring->next_avail == vr->avail->idx)
+ return NULL;
+
+ idx = vring->next_avail % vr->num;
+ head = vr->avail->ring[idx];
+ BUG_ON(head >= vr->num);
+ vring->next_avail++;
+ return &vr->desc[head];
+}
+
+static inline void tmfifo_virtio_release_desc(struct virtio_device *vdev,
+ struct vring *vr,
+ struct vring_desc *desc, u32 len)
+{
+ unsigned int idx;
+
+ idx = vr->used->idx % vr->num;
+ vr->used->ring[idx].id = desc - vr->desc;
+ vr->used->ring[idx].len = cpu_to_virtio32(vdev, len);
+
+ /* Virtio could poll and check the 'idx' to decide
+ * whether the desc is done or not. Add a memory
+ * barrier here to make sure the update above completes
+ * before updating the idx.
+ */
+ mb();
+ vr->used->idx++;
+}
+
+/* Get the total length of a descriptor chain. */
+static inline u32 tmfifo_virtio_get_pkt_len(struct virtio_device *vdev,
+ struct vring_desc *desc, struct vring *vr)
+{
+ u32 len = 0, idx;
+
+ while (desc) {
+ len += virtio32_to_cpu(vdev, desc->len);
+ if (!(virtio16_to_cpu(vdev, desc->flags) & VRING_DESC_F_NEXT))
+ break;
+ idx = virtio16_to_cpu(vdev, desc->next);
+ desc = &vr->desc[idx];
+ }
+
+ return len;
+}
+
+static void tmfifo_release_pkt(struct virtio_device *vdev,
+ struct tmfifo_vring *vring,
+ struct vring_desc **desc)
+{
+ struct vring *vr = (struct vring *)virtqueue_get_vring(vring->vq);
+ struct vring_desc *desc_head;
+ uint32_t pkt_len = 0;
+
+ if (!vr)
+ return;
+
+ if (desc != NULL && *desc != NULL && vring->desc_head != NULL) {
+ desc_head = vring->desc_head;
+ pkt_len = vring->pkt_len;
+ } else {
+ desc_head = tmfifo_virtio_get_next_desc(vring->vq);
+ if (desc_head != NULL) {
+ pkt_len = tmfifo_virtio_get_pkt_len(vdev,
+ desc_head, vr);
+ }
+ }
+
+ if (desc_head != NULL)
+ tmfifo_virtio_release_desc(vdev, vr, desc_head, pkt_len);
+
+ if (desc != NULL)
+ *desc = NULL;
+ vring->pkt_len = 0;
+}
+
+/* House-keeping timer. */
+static void tmfifo_timer(struct timer_list *arg)
+{
+ struct tmfifo *fifo = container_of(arg, struct tmfifo, timer);
+
+ /*
+ * Wake up the work handler to poll the Rx FIFO in case interrupt
+ * missing or any leftover bytes stuck in the FIFO.
+ */
+ test_and_set_bit(TM_RX_HWM_IRQ, &fifo->pend_events);
+
+ /*
+ * Wake up Tx handler in case virtio has queued too many packets
+ * and are waiting for buffer return.
+ */
+ test_and_set_bit(TM_TX_LWM_IRQ, &fifo->pend_events);
+
+ schedule_work(&fifo->work);
+
+ mod_timer(&fifo->timer, jiffies + tmfifo_timer_interval);
+}
+
+/* Buffer the console output. */
+static void tmfifo_console_output(struct tmfifo_vdev *cons,
+ struct virtqueue *vq)
+{
+ u32 len, pkt_len, idx;
+ struct vring_desc *head_desc, *desc = NULL;
+ struct vring *vr = (struct vring *)virtqueue_get_vring(vq);
+ struct virtio_device *vdev = &cons->vdev;
+ void *addr;
+ union tmfifo_msg_hdr *hdr;
+
+ for (;;) {
+ head_desc = tmfifo_virtio_get_next_desc(vq);
+ if (head_desc == NULL)
+ break;
+
+ /* Release the packet if no more space. */
+ pkt_len = tmfifo_virtio_get_pkt_len(vdev, head_desc, vr);
+ if (pkt_len + sizeof(*hdr) > TMFIFO_VDEV_TX_BUF_AVAIL(cons)) {
+ tmfifo_virtio_release_desc(vdev, vr, head_desc,
+ pkt_len);
+ break;
+ }
+
+ hdr = (union tmfifo_msg_hdr *)&cons->tx_buf[cons->tx_tail];
+ hdr->data = 0;
+ hdr->type = VIRTIO_ID_CONSOLE;
+ hdr->len = htons(pkt_len);
+
+ TMFIFO_VDEV_TX_BUF_PUSH(cons, sizeof(*hdr));
+ desc = head_desc;
+
+ while (desc != NULL) {
+ addr = phys_to_virt(virtio64_to_cpu(vdev, desc->addr));
+ len = virtio32_to_cpu(vdev, desc->len);
+
+ if (len <= TMFIFO_CONS_TX_BUF_SIZE - cons->tx_tail) {
+ memcpy(cons->tx_buf + cons->tx_tail, addr, len);
+ } else {
+ u32 seg;
+
+ seg = TMFIFO_CONS_TX_BUF_SIZE - cons->tx_tail;
+ memcpy(cons->tx_buf + cons->tx_tail, addr, seg);
+ addr += seg;
+ memcpy(cons->tx_buf, addr, len - seg);
+ }
+ TMFIFO_VDEV_TX_BUF_PUSH(cons, len);
+
+ if (!(virtio16_to_cpu(vdev, desc->flags) &
+ VRING_DESC_F_NEXT))
+ break;
+ idx = virtio16_to_cpu(vdev, desc->next);
+ desc = &vr->desc[idx];
+ }
+
+ /* Make each packet 8-byte aligned. */
+ TMFIFO_VDEV_TX_BUF_PUSH(cons, ((pkt_len + 7) & -8) - pkt_len);
+
+ tmfifo_virtio_release_desc(vdev, vr, head_desc, pkt_len);
+ }
+}
+
+/* Rx & Tx processing of a virtual queue. */
+static void tmfifo_virtio_rxtx(struct virtqueue *vq, bool is_rx)
+{
+ struct tmfifo_vring *vring;
+ struct tmfifo *fifo;
+ struct vring *vr;
+ struct virtio_device *vdev;
+ u64 sts, data;
+ int num_avail = 0, hdr_len, tx_reserve;
+ void *addr;
+ u32 len, idx;
+ struct vring_desc *desc;
+ unsigned long flags;
+ struct tmfifo_vdev *cons;
+
+ if (!vq)
+ return;
+
+ vring = (struct tmfifo_vring *)vq->priv;
+ fifo = vring->fifo;
+ vr = (struct vring *)virtqueue_get_vring(vq);
+
+ if (!fifo->vdev[vring->vdev_id])
+ return;
+ vdev = &fifo->vdev[vring->vdev_id]->vdev;
+ cons = fifo->vdev[VIRTIO_ID_CONSOLE];
+
+ /* Don't continue if another vring is running. */
+ if (fifo->vring[is_rx] != NULL && fifo->vring[is_rx] != vring)
+ return;
+
+ /* tx_reserve is used to reserved some room in FIFO for console. */
+ if (vring->vdev_id == VIRTIO_ID_NET) {
+ hdr_len = sizeof(struct virtio_net_hdr);
+ tx_reserve = fifo->tx_fifo_size / 16;
+ } else {
+ BUG_ON(vring->vdev_id != VIRTIO_ID_CONSOLE);
+ hdr_len = 0;
+ tx_reserve = 1;
+ }
+
+ desc = vring->desc;
+
+again:
+ while (1) {
+ /* Get available FIFO space. */
+ if (num_avail == 0) {
+ if (is_rx) {
+ /* Get the number of available words in FIFO. */
+ sts = readq(fifo->rx_base + TMFIFO_RX_STS);
+ num_avail = TMFIFO_GET_FIELD(sts,
+ TMFIFO_RX_STS__COUNT_MASK);
+
+ /* Don't continue if nothing in FIFO. */
+ if (num_avail <= 0)
+ break;
+ } else {
+ /* Get available space in FIFO. */
+ sts = readq(fifo->tx_base + TMFIFO_TX_STS);
+ num_avail = fifo->tx_fifo_size - tx_reserve -
+ TMFIFO_GET_FIELD(sts,
+ TMFIFO_TX_STS__COUNT_MASK);
+
+ if (num_avail <= 0)
+ break;
+ }
+ }
+
+ /* Console output always comes from the Tx buffer. */
+ if (!is_rx && vring->vdev_id == VIRTIO_ID_CONSOLE &&
+ cons != NULL && cons->tx_buf != NULL) {
+ for (;;) {
+ spin_lock_irqsave(&tmfifo_spin_lock, flags);
+ if (cons->tx_head == cons->tx_tail) {
+ spin_unlock_irqrestore(
+ &tmfifo_spin_lock, flags);
+ return;
+ }
+ addr = cons->tx_buf + cons->tx_head;
+ writeq(cpu_to_le64(*(u64 *)addr),
+ fifo->tx_base + TMFIFO_TX_DATA);
+ TMFIFO_VDEV_TX_BUF_POP(cons, sizeof(u64));
+ spin_unlock_irqrestore(&tmfifo_spin_lock,
+ flags);
+ if (--num_avail <= 0)
+ goto again;
+ }
+ }
+
+ /* Get the desc of next packet. */
+ if (!desc) {
+ /* Save the head desc of the chain. */
+ vring->desc_head = tmfifo_virtio_get_next_desc(vq);
+ if (!vring->desc_head) {
+ vring->desc = NULL;
+ return;
+ }
+ desc = vring->desc_head;
+ vring->desc = desc;
+
+ if (is_rx && vring->vdev_id == VIRTIO_ID_NET) {
+ struct virtio_net_hdr *net_hdr;
+
+ /* Initialize the packet header. */
+ net_hdr = (struct virtio_net_hdr *)
+ phys_to_virt(virtio64_to_cpu(
+ vdev, desc->addr));
+ memset(net_hdr, 0, sizeof(*net_hdr));
+ }
+ }
+
+ /* Beginning of each packet. */
+ if (vring->pkt_len == 0) {
+ int vdev_id, vring_change = 0;
+ union tmfifo_msg_hdr hdr;
+
+ num_avail--;
+
+ /* Read/Write packet length. */
+ if (is_rx) {
+ hdr.data = readq(fifo->rx_base +
+ TMFIFO_RX_DATA);
+ hdr.data = le64_to_cpu(hdr.data);
+
+ /* Skip the length 0 packet (keepalive). */
+ if (hdr.len == 0)
+ continue;
+
+ /* Check packet type. */
+ if (hdr.type == VIRTIO_ID_NET) {
+ vdev_id = VIRTIO_ID_NET;
+ hdr_len = sizeof(struct virtio_net_hdr);
+ } else if (hdr.type == VIRTIO_ID_CONSOLE) {
+ vdev_id = VIRTIO_ID_CONSOLE;
+ hdr_len = 0;
+ } else {
+ continue;
+ }
+
+ /*
+ * Check whether the new packet still belongs
+ * to this vring or not. If not, update the
+ * pkt_len of the new vring and return.
+ */
+ if (vdev_id != vring->vdev_id) {
+ struct tmfifo_vdev *dev2 =
+ fifo->vdev[vdev_id];
+
+ if (!dev2)
+ break;
+ vring->desc = desc;
+ vring = &dev2->vrings[TMFIFO_VRING_RX];
+ vring_change = 1;
+ }
+ vring->pkt_len = ntohs(hdr.len) + hdr_len;
+ } else {
+ vring->pkt_len = tmfifo_virtio_get_pkt_len(
+ vdev, desc, vr);
+
+ hdr.data = 0;
+ hdr.type = (vring->vdev_id == VIRTIO_ID_NET) ?
+ VIRTIO_ID_NET :
+ VIRTIO_ID_CONSOLE;
+ hdr.len = htons(vring->pkt_len - hdr_len);
+ writeq(cpu_to_le64(hdr.data),
+ fifo->tx_base + TMFIFO_TX_DATA);
+ }
+
+ vring->cur_len = hdr_len;
+ vring->rem_len = vring->pkt_len;
+ fifo->vring[is_rx] = vring;
+
+ if (vring_change)
+ return;
+ continue;
+ }
+
+ /* Check available space in this desc. */
+ len = virtio32_to_cpu(vdev, desc->len);
+ if (len > vring->rem_len)
+ len = vring->rem_len;
+
+ /* Check if the current desc is already done. */
+ if (vring->cur_len == len)
+ goto check_done;
+
+ addr = phys_to_virt(virtio64_to_cpu(vdev, desc->addr));
+
+ /* Read a word from FIFO for Rx. */
+ if (is_rx) {
+ data = readq(fifo->rx_base + TMFIFO_RX_DATA);
+ data = le64_to_cpu(data);
+ }
+
+ if (vring->cur_len + sizeof(u64) <= len) {
+ /* The whole word. */
+ if (is_rx) {
+ memcpy(addr + vring->cur_len, &data,
+ sizeof(u64));
+ } else {
+ memcpy(&data, addr + vring->cur_len,
+ sizeof(u64));
+ }
+ vring->cur_len += sizeof(u64);
+ } else {
+ /* Leftover bytes. */
+ BUG_ON(vring->cur_len > len);
+ if (is_rx) {
+ memcpy(addr + vring->cur_len, &data,
+ len - vring->cur_len);
+ } else {
+ memcpy(&data, addr + vring->cur_len,
+ len - vring->cur_len);
+ }
+ vring->cur_len = len;
+ }
+
+ /* Write the word into FIFO for Tx. */
+ if (!is_rx) {
+ writeq(cpu_to_le64(data),
+ fifo->tx_base + TMFIFO_TX_DATA);
+ }
+
+ num_avail--;
+
+check_done:
+ /* Check whether this desc is full or completed. */
+ if (vring->cur_len == len) {
+ vring->cur_len = 0;
+ vring->rem_len -= len;
+
+ /* Get the next desc on the chain. */
+ if (vring->rem_len > 0 &&
+ (virtio16_to_cpu(vdev, desc->flags) &
+ VRING_DESC_F_NEXT)) {
+ idx = virtio16_to_cpu(vdev, desc->next);
+ desc = &vr->desc[idx];
+ continue;
+ }
+
+ /* Done and release the desc. */
+ tmfifo_release_pkt(vdev, vring, &desc);
+ fifo->vring[is_rx] = NULL;
+
+ /* Notify upper layer that packet is done. */
+ spin_lock_irqsave(&tmfifo_spin_lock, flags);
+ vring_interrupt(0, vq);
+ spin_unlock_irqrestore(&tmfifo_spin_lock, flags);
+ continue;
+ }
+ }
+
+ /* Save the current desc. */
+ vring->desc = desc;
+}
+
+/* The notify function is called when new buffers are posted. */
+static bool tmfifo_virtio_notify(struct virtqueue *vq)
+{
+ struct tmfifo_vring *vring = (struct tmfifo_vring *)vq->priv;
+ struct tmfifo *fifo = vring->fifo;
+ unsigned long flags;
+
+ /*
+ * Virtio maintains vrings in pairs, even number ring for Rx
+ * and odd number ring for Tx.
+ */
+ if (!(vring->id & 1)) {
+ /* Set the RX HWM bit to start Rx. */
+ if (!test_and_set_bit(TM_RX_HWM_IRQ, &fifo->pend_events))
+ schedule_work(&fifo->work);
+ } else {
+ /*
+ * Console could make blocking call with interrupts disabled.
+ * In such case, the vring needs to be served right away. For
+ * other cases, just set the TX LWM bit to start Tx in the
+ * worker handler.
+ */
+ if (vring->vdev_id == VIRTIO_ID_CONSOLE) {
+ spin_lock_irqsave(&tmfifo_spin_lock, flags);
+ tmfifo_console_output(fifo->vdev[VIRTIO_ID_CONSOLE],
+ vq);
+ spin_unlock_irqrestore(&tmfifo_spin_lock, flags);
+ schedule_work(&fifo->work);
+ } else if (!test_and_set_bit(TM_TX_LWM_IRQ, &fifo->pend_events))
+ schedule_work(&fifo->work);
+ }
+
+ return true;
+}
+
+/* Get the array of feature bits for this device. */
+static u64 tmfifo_virtio_get_features(struct virtio_device *vdev)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ return tm_vdev->features;
+}
+
+/* Confirm device features to use. */
+static int tmfifo_virtio_finalize_features(struct virtio_device *vdev)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ tm_vdev->features = vdev->features;
+ return 0;
+}
+
+/* Free virtqueues found by find_vqs(). */
+static void tmfifo_virtio_del_vqs(struct virtio_device *vdev)
+{
+ int i;
+ struct tmfifo_vring *vring;
+ struct virtqueue *vq;
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ for (i = 0; i < ARRAY_SIZE(tm_vdev->vrings); i++) {
+ vring = &tm_vdev->vrings[i];
+
+ /* Release the pending packet. */
+ if (vring->desc != NULL)
+ tmfifo_release_pkt(&tm_vdev->vdev, vring, &vring->desc);
+
+ vq = vring->vq;
+ if (vq) {
+ vring->vq = NULL;
+ vring_del_virtqueue(vq);
+ }
+ }
+}
+
+/* Create and initialize the virtual queues. */
+static int tmfifo_virtio_find_vqs(struct virtio_device *vdev,
+ unsigned int nvqs,
+ struct virtqueue *vqs[],
+ vq_callback_t *callbacks[],
+ const char * const names[],
+ const bool *ctx,
+ struct irq_affinity *desc)
+{
+ int i, ret = -EINVAL, size;
+ struct tmfifo_vring *vring;
+ struct virtqueue *vq;
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ if (nvqs > ARRAY_SIZE(tm_vdev->vrings))
+ return -EINVAL;
+
+ for (i = 0; i < nvqs; ++i) {
+ if (!names[i])
+ goto error;
+ vring = &tm_vdev->vrings[i];
+
+ /* zero vring */
+ size = vring_size(vring->size, vring->align);
+ memset(vring->va, 0, size);
+ vq = vring_new_virtqueue(i, vring->size, vring->align, vdev,
+ false, false, vring->va,
+ tmfifo_virtio_notify,
+ callbacks[i], names[i]);
+ if (!vq) {
+ dev_err(&vdev->dev, "vring_new_virtqueue failed\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ vqs[i] = vq;
+ vring->vq = vq;
+ vq->priv = vring;
+ }
+
+ return 0;
+
+error:
+ tmfifo_virtio_del_vqs(vdev);
+ return ret;
+}
+
+/* Read the status byte. */
+static u8 tmfifo_virtio_get_status(struct virtio_device *vdev)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ return tm_vdev->status;
+}
+
+/* Write the status byte. */
+static void tmfifo_virtio_set_status(struct virtio_device *vdev, u8 status)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ tm_vdev->status = status;
+}
+
+/* Reset the device. Not much here for now. */
+static void tmfifo_virtio_reset(struct virtio_device *vdev)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ tm_vdev->status = 0;
+}
+
+/* Read the value of a configuration field. */
+static void tmfifo_virtio_get(struct virtio_device *vdev,
+ unsigned int offset,
+ void *buf,
+ unsigned int len)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ if (offset + len > sizeof(tm_vdev->config) || offset + len < len) {
+ dev_err(vdev->dev.parent, "virtio_get access out of bounds\n");
+ return;
+ }
+
+ memcpy(buf, (u8 *)&tm_vdev->config + offset, len);
+}
+
+/* Write the value of a configuration field. */
+static void tmfifo_virtio_set(struct virtio_device *vdev,
+ unsigned int offset,
+ const void *buf,
+ unsigned int len)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ if (offset + len > sizeof(tm_vdev->config) || offset + len < len) {
+ dev_err(vdev->dev.parent, "virtio_get access out of bounds\n");
+ return;
+ }
+
+ memcpy((u8 *)&tm_vdev->config + offset, buf, len);
+}
+
+/* Virtio config operations. */
+static const struct virtio_config_ops tmfifo_virtio_config_ops = {
+ .get_features = tmfifo_virtio_get_features,
+ .finalize_features = tmfifo_virtio_finalize_features,
+ .find_vqs = tmfifo_virtio_find_vqs,
+ .del_vqs = tmfifo_virtio_del_vqs,
+ .reset = tmfifo_virtio_reset,
+ .set_status = tmfifo_virtio_set_status,
+ .get_status = tmfifo_virtio_get_status,
+ .get = tmfifo_virtio_get,
+ .set = tmfifo_virtio_set,
+};
+
+/* Create vdev type in a tmfifo. */
+int tmfifo_create_vdev(struct tmfifo *fifo, int vdev_id, u64 features,
+ void *config, u32 size)
+{
+ struct tmfifo_vdev *tm_vdev;
+ int ret = 0;
+
+ mutex_lock(&fifo->lock);
+
+ tm_vdev = fifo->vdev[vdev_id];
+ if (tm_vdev != NULL) {
+ pr_err("vdev %d already exists\n", vdev_id);
+ ret = -EEXIST;
+ goto already_exist;
+ }
+
+ tm_vdev = kzalloc(sizeof(*tm_vdev), GFP_KERNEL);
+ if (!tm_vdev) {
+ ret = -ENOMEM;
+ goto already_exist;
+ }
+
+ tm_vdev->vdev.id.device = vdev_id;
+ tm_vdev->vdev.config = &tmfifo_virtio_config_ops;
+ tm_vdev->vdev.dev.parent = &fifo->pdev->dev;
+ tm_vdev->vdev.dev.release = tmfifo_virtio_dev_release;
+ tm_vdev->features = features;
+ if (config)
+ memcpy(&tm_vdev->config, config, size);
+ if (tmfifo_alloc_vrings(fifo, tm_vdev, vdev_id)) {
+ pr_err("Unable to allocate vring\n");
+ ret = -ENOMEM;
+ goto alloc_vring_fail;
+ }
+ if (vdev_id == VIRTIO_ID_CONSOLE) {
+ tm_vdev->tx_buf = kmalloc(TMFIFO_CONS_TX_BUF_SIZE,
+ GFP_KERNEL);
+ }
+ fifo->vdev[vdev_id] = tm_vdev;
+
+ /* Register the virtio device. */
+ ret = register_virtio_device(&tm_vdev->vdev);
+ if (ret) {
+ dev_err(&fifo->pdev->dev, "register_virtio_device() failed\n");
+ goto register_fail;
+ }
+
+ mutex_unlock(&fifo->lock);
+ return 0;
+
+register_fail:
+ tmfifo_free_vrings(fifo, vdev_id);
+ fifo->vdev[vdev_id] = NULL;
+alloc_vring_fail:
+ kfree(tm_vdev);
+already_exist:
+ mutex_unlock(&fifo->lock);
+ return ret;
+}
+
+/* Delete vdev type from a tmfifo. */
+int tmfifo_delete_vdev(struct tmfifo *fifo, int vdev_id)
+{
+ struct tmfifo_vdev *tm_vdev;
+
+ mutex_lock(&fifo->lock);
+
+ /* Unregister vdev. */
+ tm_vdev = fifo->vdev[vdev_id];
+ if (tm_vdev) {
+ unregister_virtio_device(&tm_vdev->vdev);
+ tmfifo_free_vrings(fifo, vdev_id);
+ kfree(tm_vdev->tx_buf);
+ kfree(tm_vdev);
+ fifo->vdev[vdev_id] = NULL;
+ }
+
+ mutex_unlock(&fifo->lock);
+
+ return 0;
+}
+
+/* Device remove function. */
+static int tmfifo_remove(struct platform_device *pdev)
+{
+ int i;
+ struct tmfifo *fifo = platform_get_drvdata(pdev);
+ struct resource *rx_res, *tx_res;
+
+ tmfifo_ready = false;
+
+ if (fifo) {
+ mutex_lock(&tmfifo_lock);
+
+ /* Stop the timer. */
+ del_timer_sync(&fifo->timer);
+
+ /* Release interrupts. */
+ tmfifo_free_irqs(fifo);
+
+ /* Cancel the pending work. */
+ cancel_work_sync(&fifo->work);
+
+ for (i = 0; i < TMFIFO_VDEV_MAX; i++)
+ tmfifo_delete_vdev(fifo, i);
+
+ /* Release IO resources. */
+ if (fifo->rx_base)
+ iounmap(fifo->rx_base);
+ if (fifo->tx_base)
+ iounmap(fifo->tx_base);
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(fifo);
+
+ mutex_unlock(&tmfifo_lock);
+ }
+
+ rx_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (rx_res)
+ release_mem_region(rx_res->start, resource_size(rx_res));
+ tx_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (tx_res)
+ release_mem_region(tx_res->start, resource_size(tx_res));
+
+ return 0;
+}
+
+/* Read the configured network MAC address from efi variable. */
+static void tmfifo_get_cfg_mac(u8 *mac)
+{
+ u8 buf[6];
+ efi_status_t status;
+ unsigned long size = sizeof(buf);
+ efi_char16_t name[] = { 'R', 's', 'h', 'i', 'm', 'M', 'a', 'c',
+ 'A', 'd', 'd', 'r', 0 };
+ efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID;
+
+ status = efi.get_variable(name, &guid, NULL, &size, buf);
+ if (status == EFI_SUCCESS && size == sizeof(buf))
+ memcpy(mac, buf, sizeof(buf));
+}
+
+/* Probe the TMFIFO. */
+static int tmfifo_probe(struct platform_device *pdev)
+{
+ u64 ctl;
+ struct tmfifo *fifo;
+ struct resource *rx_res, *tx_res;
+ struct virtio_net_config net_config;
+ int i, ret;
+
+ /* Get the resource of the Rx & Tx FIFO. */
+ rx_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ tx_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!rx_res || !tx_res) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (request_mem_region(rx_res->start,
+ resource_size(rx_res), "bf-tmfifo") == NULL) {
+ ret = -EBUSY;
+ goto early_err;
+ }
+
+ if (request_mem_region(tx_res->start,
+ resource_size(tx_res), "bf-tmfifo") == NULL) {
+ release_mem_region(rx_res->start, resource_size(rx_res));
+ ret = -EBUSY;
+ goto early_err;
+ }
+
+ ret = -ENOMEM;
+ fifo = kzalloc(sizeof(struct tmfifo), GFP_KERNEL);
+ if (!fifo)
+ goto err;
+
+ fifo->pdev = pdev;
+ platform_set_drvdata(pdev, fifo);
+
+ INIT_WORK(&fifo->work, tmfifo_work_handler);
+
+ timer_setup(&fifo->timer, tmfifo_timer, 0);
+ fifo->timer.function = tmfifo_timer;
+
+ for (i = 0; i < TM_IRQ_CNT; i++) {
+ fifo->irq[i] = platform_get_irq(pdev, i);
+ ret = request_irq(fifo->irq[i], tmfifo_irq_handler, 0,
+ "tmfifo", (u8 *)fifo + i);
+ if (ret) {
+ pr_err("Unable to request irq\n");
+ fifo->irq[i] = 0;
+ goto err;
+ }
+ }
+
+ fifo->rx_base = ioremap(rx_res->start, resource_size(rx_res));
+ if (!fifo->rx_base)
+ goto err;
+
+ fifo->tx_base = ioremap(tx_res->start, resource_size(tx_res));
+ if (!fifo->tx_base)
+ goto err;
+
+ /* Get Tx FIFO size and set the low/high watermark. */
+ ctl = readq(fifo->tx_base + TMFIFO_TX_CTL);
+ fifo->tx_fifo_size =
+ TMFIFO_GET_FIELD(ctl, TMFIFO_TX_CTL__MAX_ENTRIES_MASK);
+ ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_TX_CTL__LWM_MASK,
+ fifo->tx_fifo_size / 2);
+ ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_TX_CTL__HWM_MASK,
+ fifo->tx_fifo_size - 1);
+ writeq(ctl, fifo->tx_base + TMFIFO_TX_CTL);
+
+ /* Get Rx FIFO size and set the low/high watermark. */
+ ctl = readq(fifo->rx_base + TMFIFO_RX_CTL);
+ fifo->rx_fifo_size =
+ TMFIFO_GET_FIELD(ctl, TMFIFO_RX_CTL__MAX_ENTRIES_MASK);
+ ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_RX_CTL__LWM_MASK, 0);
+ ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_RX_CTL__HWM_MASK, 1);
+ writeq(ctl, fifo->rx_base + TMFIFO_RX_CTL);
+
+ mutex_init(&fifo->lock);
+
+ /* Create the console vdev. */
+ ret = tmfifo_create_vdev(fifo, VIRTIO_ID_CONSOLE, 0, NULL, 0);
+ if (ret)
+ goto err;
+
+ /* Create the network vdev. */
+ memset(&net_config, 0, sizeof(net_config));
+ net_config.mtu = TMFIFO_NET_MTU;
+ net_config.status = VIRTIO_NET_S_LINK_UP;
+ memcpy(net_config.mac, tmfifo_net_default_mac, 6);
+ tmfifo_get_cfg_mac(net_config.mac);
+ ret = tmfifo_create_vdev(fifo, VIRTIO_ID_NET, TMFIFO_NET_FEATURES,
+ &net_config, sizeof(net_config));
+ if (ret)
+ goto err;
+
+ mod_timer(&fifo->timer, jiffies + tmfifo_timer_interval);
+
+ tmfifo_ready = true;
+
+ return 0;
+
+err:
+ tmfifo_remove(pdev);
+early_err:
+ dev_err(&pdev->dev, "Probe Failed\n");
+ return ret;
+}
+
+static const struct of_device_id tmfifo_match[] = {
+ { .compatible = "mellanox,bf-tmfifo" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tmfifo_match);
+
+static const struct acpi_device_id bf_tmfifo_acpi_match[] = {
+ { "MLNXBF01", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, bf_tmfifo_acpi_match);
+
+static struct platform_driver tmfifo_driver = {
+ .probe = tmfifo_probe,
+ .remove = tmfifo_remove,
+ .driver = {
+ .name = "bf-tmfifo",
+ .of_match_table = tmfifo_match,
+ .acpi_match_table = ACPI_PTR(bf_tmfifo_acpi_match),
+ },
+};
+
+static int __init tmfifo_init(void)
+{
+ int ret;
+
+ mutex_init(&tmfifo_lock);
+
+ ret = platform_driver_register(&tmfifo_driver);
+ if (ret)
+ pr_err("Failed to register tmfifo driver.\n");
+
+ return ret;
+}
+
+static void __exit tmfifo_exit(void)
+{
+ platform_driver_unregister(&tmfifo_driver);
+}
+
+module_init(tmfifo_init);
+module_exit(tmfifo_exit);
+
+MODULE_DESCRIPTION("Mellanox BlueField SoC TMFIFO Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Mellanox Technologies");
diff --git a/drivers/soc/mellanox/tmfifo_regs.h b/drivers/soc/mellanox/tmfifo_regs.h
new file mode 100644
index 0000000..f42c9d6
--- /dev/null
+++ b/drivers/soc/mellanox/tmfifo_regs.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ */
+
+#ifndef __TMFIFO_REGS_H__
+#define __TMFIFO_REGS_H__
+
+#include <linux/types.h>
+
+#define TMFIFO_TX_DATA 0x0
+
+#define TMFIFO_TX_STS 0x8
+#define TMFIFO_TX_STS__LENGTH 0x0001
+#define TMFIFO_TX_STS__COUNT_SHIFT 0
+#define TMFIFO_TX_STS__COUNT_WIDTH 9
+#define TMFIFO_TX_STS__COUNT_RESET_VAL 0
+#define TMFIFO_TX_STS__COUNT_RMASK 0x1ff
+#define TMFIFO_TX_STS__COUNT_MASK 0x1ff
+
+#define TMFIFO_TX_CTL 0x10
+#define TMFIFO_TX_CTL__LENGTH 0x0001
+#define TMFIFO_TX_CTL__LWM_SHIFT 0
+#define TMFIFO_TX_CTL__LWM_WIDTH 8
+#define TMFIFO_TX_CTL__LWM_RESET_VAL 128
+#define TMFIFO_TX_CTL__LWM_RMASK 0xff
+#define TMFIFO_TX_CTL__LWM_MASK 0xff
+#define TMFIFO_TX_CTL__HWM_SHIFT 8
+#define TMFIFO_TX_CTL__HWM_WIDTH 8
+#define TMFIFO_TX_CTL__HWM_RESET_VAL 128
+#define TMFIFO_TX_CTL__HWM_RMASK 0xff
+#define TMFIFO_TX_CTL__HWM_MASK 0xff00
+#define TMFIFO_TX_CTL__MAX_ENTRIES_SHIFT 32
+#define TMFIFO_TX_CTL__MAX_ENTRIES_WIDTH 9
+#define TMFIFO_TX_CTL__MAX_ENTRIES_RESET_VAL 256
+#define TMFIFO_TX_CTL__MAX_ENTRIES_RMASK 0x1ff
+#define TMFIFO_TX_CTL__MAX_ENTRIES_MASK 0x1ff00000000ULL
+
+#define TMFIFO_RX_DATA 0x0
+
+#define TMFIFO_RX_STS 0x8
+#define TMFIFO_RX_STS__LENGTH 0x0001
+#define TMFIFO_RX_STS__COUNT_SHIFT 0
+#define TMFIFO_RX_STS__COUNT_WIDTH 9
+#define TMFIFO_RX_STS__COUNT_RESET_VAL 0
+#define TMFIFO_RX_STS__COUNT_RMASK 0x1ff
+#define TMFIFO_RX_STS__COUNT_MASK 0x1ff
+
+#define TMFIFO_RX_CTL 0x10
+#define TMFIFO_RX_CTL__LENGTH 0x0001
+#define TMFIFO_RX_CTL__LWM_SHIFT 0
+#define TMFIFO_RX_CTL__LWM_WIDTH 8
+#define TMFIFO_RX_CTL__LWM_RESET_VAL 128
+#define TMFIFO_RX_CTL__LWM_RMASK 0xff
+#define TMFIFO_RX_CTL__LWM_MASK 0xff
+#define TMFIFO_RX_CTL__HWM_SHIFT 8
+#define TMFIFO_RX_CTL__HWM_WIDTH 8
+#define TMFIFO_RX_CTL__HWM_RESET_VAL 128
+#define TMFIFO_RX_CTL__HWM_RMASK 0xff
+#define TMFIFO_RX_CTL__HWM_MASK 0xff00
+#define TMFIFO_RX_CTL__MAX_ENTRIES_SHIFT 32
+#define TMFIFO_RX_CTL__MAX_ENTRIES_WIDTH 9
+#define TMFIFO_RX_CTL__MAX_ENTRIES_RESET_VAL 256
+#define TMFIFO_RX_CTL__MAX_ENTRIES_RMASK 0x1ff
+#define TMFIFO_RX_CTL__MAX_ENTRIES_MASK 0x1ff00000000ULL
+
+#endif /* !defined(__TMFIFO_REGS_H__) */
--
1.8.3.1
^ permalink raw reply related
* [PATCH v2 2/4] arm64: Add Mellanox BlueField SoC config option
From: Liming Sun @ 2018-05-25 20:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527279436-14773-1-git-send-email-lsun@mellanox.com>
This commit introduces config option for Mellanox BlueField SoC,
which can be used to build the SoC specific drivers, and enables
it by default in configs/defconfig.
Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
arch/arm64/Kconfig.platforms | 6 ++++++
arch/arm64/configs/defconfig | 1 +
2 files changed, 7 insertions(+)
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 2b1535c..74ad03f 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -110,6 +110,12 @@ config ARCH_MESON
help
This enables support for the Amlogic S905 SoCs.
+config ARCH_MLNX_BLUEFIELD
+ bool "Mellanox BlueField SoC Family"
+ select SOC_MLNX
+ help
+ This enables support for the Mellanox BlueField SoC.
+
config ARCH_MVEBU
bool "Marvell EBU SoC Family"
select ARMADA_AP806_SYSCON
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1c98939..842f607 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -43,6 +43,7 @@ CONFIG_ARCH_LG1K=y
CONFIG_ARCH_HISI=y
CONFIG_ARCH_MEDIATEK=y
CONFIG_ARCH_MESON=y
+CONFIG_ARCH_MLNX_BLUEFIELD=y
CONFIG_ARCH_MVEBU=y
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_ROCKCHIP=y
--
1.8.3.1
^ permalink raw reply related
* [PATCH v2 3/4] dt-bindings: soc: Add TmFifo binding for Mellanox BlueField SoC
From: Liming Sun @ 2018-05-25 20:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527279436-14773-1-git-send-email-lsun@mellanox.com>
Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
.../devicetree/bindings/soc/mellanox/tmfifo.txt | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
diff --git a/Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt b/Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
new file mode 100644
index 0000000..0a362f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
@@ -0,0 +1,20 @@
+* Mellanox BlueField SoC TmFifo
+
+BlueField TmFifo provides a shared FIFO between the target and the
+external host machine, which can be accessed via USB or PCIe.
+
+Required properties:
+
+- compatible: Should be "mellanox,bf-tmfifo"
+- reg: Physical base address and length of Rx/Tx block
+- interrupts: The interrupt number of Rx low water mark, Rx high water mark
+ Tx low water mark, Tx high water mark respectively.
+
+Example:
+
+tmfifo at 800a20 {
+ compatible = "mellanox,bf-tmfifo";
+ reg = <0x00800a20 0x00000018
+ 0x00800a40 0x00000018>;
+ interrupts = <41, 42, 43, 44>;
+};
--
1.8.3.1
^ permalink raw reply related
* [PATCH v2 4/4] MAINTAINERS: Add entry for Mellanox Bluefield Soc
From: Liming Sun @ 2018-05-25 20:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527279436-14773-1-git-send-email-lsun@mellanox.com>
Add maintainer information for Mellanox BlueField SoC.
Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 58b9861..85d5639 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1636,6 +1636,14 @@ L: linux-mediatek at lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/phy/mediatek/phy-mtk-tphy.c
+ARM/Mellanox BlueField SoC support
+M: David Woods <dwoods@mellanox.com>
+M: Liming Sun <lsun@mellanox.com>
+L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: drivers/soc/mellanox/*
+F: Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
+
ARM/MICREL KS8695 ARCHITECTURE
M: Greg Ungerer <gerg@uclinux.org>
L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v1 1/4] soc: Add TmFifo driver for Mellanox BlueField Soc
From: Liming Sun @ 2018-05-25 20:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <8c2bfde9-5dd2-c1f9-a7f1-503c6eb8b0fe@arm.com>
Thanks for the comments! Uploaded patch series v2.
Please also see response inline.
- Liming
> -----Original Message-----
> From: Robin Murphy [mailto:robin.murphy at arm.com]
> Sent: Friday, May 25, 2018 1:15 PM
> To: Liming Sun <lsun@mellanox.com>; Olof Johansson <olof@lixom.net>;
> Arnd Bergmann <arnd@arndb.de>; David Woods <dwoods@mellanox.com>
> Cc: devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH v1 1/4] soc: Add TmFifo driver for Mellanox BlueField Soc
>
> On 25/05/18 17:06, Liming Sun wrote:
> [...]
> > diff --git a/drivers/soc/mellanox/tmfifo.c b/drivers/soc/mellanox/tmfifo.c
> > new file mode 100644
> > index 0000000..a3303d1
> > --- /dev/null
> > +++ b/drivers/soc/mellanox/tmfifo.c
> > @@ -0,0 +1,1265 @@
> > +// SPDX-License-Identifier: GPL-2.0
>
> This tag doesn't match the included license text...
Fixed in patch v2-1/4.
>
> > +/*
> > + * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
> > + *
> > + * This software is available to you under a choice of one of two
> > + * licenses. You may choose to be licensed under the terms of the GNU
> > + * General Public License (GPL) Version 2, available from the file
> > + * COPYING in the main directory of this source tree, or the
> > + * OpenIB.org BSD license below:
> > + *
> > + * Redistribution and use in source and binary forms, with or
> > + * without modification, are permitted provided that the following
> > + * conditions are met:
> > + *
> > + * - Redistributions of source code must retain the above
> > + * copyright notice, this list of conditions and the following
> > + * disclaimer.
> > + *
> > + * - Redistributions in binary form must reproduce the above
> > + * copyright notice, this list of conditions and the following
> > + * disclaimer in the documentation and/or other materials
> > + * provided with the distribution.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> > + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
> WARRANTIES OF
> > + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> > + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
> COPYRIGHT HOLDERS
> > + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
> AN
> > + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
> OR IN
> > + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> IN THE
> > + * SOFTWARE.
> > + */
>
> [...]
> > +/* Several utility macros to get/set the register fields. */
> > +#define TMFIFO_GET_FIELD(reg, field) \
> > + (((reg) >> field##_SHIFT) & ((1UL << field##_WIDTH) - 1))
> > +
> > +#define TMFIFO_SET_FIELD(reg, field, value) ({ \
> > + u64 _mask = ((1UL << field##_WIDTH) - 1) << field##_SHIFT; \
> > + ((reg) & ~_mask) | (((value) << field##_SHIFT) & _mask); \
> > +})
>
> There's no need to reinvent <linux/bitfield.h>
Updated in patch v2-1/4.
>
> [...]
> > +MODULE_DESCRIPTION("Mellanox BlueField SoC TMFIFO Driver");
> > +MODULE_AUTHOR("Mellanox Technologies, Ltd");
> > +MODULE_LICENSE("GPL");
>
> ...and this implies yet another different license (since it indicates
> "GPLv2 or later")
Fixed in patch v2-1/4.
>
> > +MODULE_VERSION("0.7");
> > diff --git a/drivers/soc/mellanox/tmfifo_regs.h
> b/drivers/soc/mellanox/tmfifo_regs.h
> > new file mode 100644
> > index 0000000..b07f353
> > --- /dev/null
> > +++ b/drivers/soc/mellanox/tmfifo_regs.h
> > @@ -0,0 +1,112 @@
> > +// SPDX-License-Identifier: GPL-2.0
>
> Again, this doesn't match the included text. Also, the SPDX comment
> style is /* */ for headers.
Updated in patch v2-1/4.
>
> > +/*
> > + * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
> > + *
> > + * This software is available to you under a choice of one of two
> > + * licenses. You may choose to be licensed under the terms of the GNU
> > + * General Public License (GPL) Version 2, available from the file
> > + * COPYING in the main directory of this source tree, or the
> > + * OpenIB.org BSD license below:
> > + *
> > + * Redistribution and use in source and binary forms, with or
> > + * without modification, are permitted provided that the following
> > + * conditions are met:
> > + *
> > + * - Redistributions of source code must retain the above
> > + * copyright notice, this list of conditions and the following
> > + * disclaimer.
> > + *
> > + * - Redistributions in binary form must reproduce the above
> > + * copyright notice, this list of conditions and the following
> > + * disclaimer in the documentation and/or other materials
> > + * provided with the distribution.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> > + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
> WARRANTIES OF
> > + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> > + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
> COPYRIGHT HOLDERS
> > + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
> AN
> > + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
> OR IN
> > + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> IN THE
> > + * SOFTWARE.
> > + */
>
> [...]
> > +#ifdef __ASSEMBLER__
> > +#define _64bit(x) x
> > +#else /* __ASSEMBLER__ */
> > +#ifdef __tile__
> > +#define _64bit(x) x ## UL
> > +#else /* __tile__ */
> > +#define _64bit(x) x ## ULL
> > +#endif /* __tile__ */
> > +#endif /* __ASSEMBLER */
> > +
> > +#ifdef __KERNEL__
> > +#include <linux/types.h>
> > +#else
> > +#include <stdint.h>
> > +#endif
> > +
> > +#ifndef __DOXYGEN__
>
> Given that this is a private header under drivers/, is any of that lot
> necessary?
Simplified and updated it in patch v2-1/4.
>
> Robin.
^ permalink raw reply
* [PATCH] ARM: pxa3xx: enable external wakeup pins
From: Robert Jarzmik @ 2018-05-25 20:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524204046.21494-1-daniel@zonque.org>
Daniel Mack <daniel@zonque.org> writes:
> The PXA3xx SoCs feature dedicated pins for wakeup functionality. These pins
> have no alternate functions, so let's always enable them as wakeup source on
> DT enabled boards. The WAKEUP1 pin is only available on PXA320.
>
> Signed-off-by: Daniel Mack <daniel@zonque.org>
That looks correct. Is it tested on any board ?
Cheers.
--
Robert
^ 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