* [PATCH 1/8] ARM: dts: armada-370-rd: Utilize new DSA binding
From: Andrew Lunn @ 2017-01-03 16:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170102022249.10657-2-f.fainelli@gmail.com>
> +
> + switch: switch at 10 {
> + compatible = "marvell,mv88e6085";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <16>;
Hummm, a device tree question. switch at 10, reg = <16>. Is there an
implicit understanding that the 10 is hex?
Andrew
^ permalink raw reply
* [PATCH 3/4] arm64: dts: exynos: make tm2 and tm2e independent from each other
From: Krzysztof Kozlowski @ 2017-01-03 16:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170103102548.73jg6qddlcthe2mu@gangnam.samsung>
On Tue, Jan 03, 2017 at 07:25:48PM +0900, Andi Shyti wrote:
> > >> > Currently tm2e dts includes tm2 but there are some differences
> > >> > between the two boards and tm2 has some properties that tm2e
> > >> > doesn't have.
> > >> >
> > >> > That's why it's important to keep the two dts files independent
> > >> > and put all the commonalities in a tm2-common.dtsi file.
> > >> >
> > >> > Signed-off-by: Andi Shyti <andi.shyti@samsung.com>
> > >> > Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
> > >> > ---
> > >> > .../boot/dts/exynos/exynos5433-tm2-common.dtsi | 1046 ++++++++++++++++++++
> > >> > arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 1033 +------------------
> > >> > arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts | 2 +-
> > >> > 3 files changed, 1049 insertions(+), 1032 deletions(-)
> > >> > create mode 100644 arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
> > >>
> > >> I would like to see here the rename and diff from it. Not entire delta
> > >> (deletions and addons). It is not possible to compare it... I think
> > >> git supports it by default with similarity of 50%.
> > >
> > > I understand, it's indeed quite cryptic to understand. But all
> > > the diff algorithms (patience, minimal, histogram, myers) give
> > > the same result. I don't know how to make it better.
> > >
> > > I could split this patch, but this also means breaking tm2's
> > > functionality, which looks worse.
> > >
> > > Please tell me if you know a better way for generating the patch.
> >
> > git format-patch -M95%?
>
> Same thing with all M values.
>
> Because exynos5433-tm2.dts results modified, while
> exynos5433-tm2-common.dtsi is new. Even though I did:
>
> 1. mv exynos5433-tm2.dts exynos5433-tm2-common.dtsi
> 2. copied pieces from exynos5433-tm2-common.dtsi to a new
> exynos5433-tm2.dts
mv/etc won't help. You need to convince git format-patch that it is
rename. For that, you need -B so copy will be considered a rename
(otherwise rename will be detected only if a file is removed), so:
git format-patch -B50% -1
Please resend with this approach.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH] pwm: sunxi: wait for the READY bit
From: Alexandre Belloni @ 2017-01-03 16:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <73f5fc87-717f-2238-b653-1b117359cbb8@schinagl.nl>
On 03/01/2017 at 16:56:16 +0100, Olliver Schinagl wrote :
> Hey Alexandre,
>
> I've sent several patches regarding pwm a while ago, sadly you never
> responded [0]. So I guess this is a follow up from that?
>
Well, we had the issue and I just had a bit of time to look at it. As I
remembered you kind of had the same issue, I chose to Cc you.
> I couldn't quickly find the resubmitted version however.
>
Was there a new version?
> > clk_gate = val & BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
> > - if (clk_gate) {
> > - val &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
> > +
> > + if (sun4i_pwm->data->has_rdy && (val & PWM_RDY(pwm->hwpwm))) {
> > + val |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
> > sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG);
> > +
> > + err = readl_poll_timeout(sun4i_pwm->base + PWM_CTRL_REG, val,
> > + !(val & PWM_RDY(pwm->hwpwm)), 400,
> > + 500000);
> > + if (err)
> > + goto finish;
> > }
> >
> What happens on sun4i here? sun4i does not have the RDY flag, but it does
> need the PWM_CLK_GATING to be active.
>
Does it actually need it? The datasheet doesn't say anything about it.
I'm actually wondering what happens if the period is written twice in a
row without waiting. If the latest period is used, maybe we don't
actually care.
> maybe only the readl_poll_timeout() should be guarded by the has_rdy, where
> you poll the register as you do now, and in the else just have a 'known safe
> delay' to emulate the has_rdy behavior? I'm guessing a few clock cycles of
> the PWM block. I don't think the documentation states how long this
> could/should be.
>
My guess is that the IP is waiting for the current period to finish
before updating the period internally. That would be the sane way to do it but
maybe I'm an optimist.
> With my 'wait before disable' patch [1] I run into the same issue, I think.
> We do not know how long to wait before the hardware is ready.
>
Up to 196.8s if I'm right...
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH 4/4] arm64: dts: exynos: Add tm2 touchkey node
From: Krzysztof Kozlowski @ 2017-01-03 16:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483430237-26823-5-git-send-email-jcsing.lee@samsung.com>
On Tue, Jan 03, 2017 at 04:57:17PM +0900, Jaechul Lee wrote:
> Add DT node support for TM2 touchkey device.
>
> Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
> Signed-off-by: Beomho Seo <beomho.seo@samsung.com>
> Signed-off-by: Andi Shyti <andi.shyti@samsung.com>
The order of sign-offs should follow the order of "who touched it". I
assume that the real order was like this:
1. Initially create by Beomho,
2. Adjustments by Andi,
3. Final adjustments and sending by you.
If that is correct then the order should be 1->2->3.
Beside of that, patch looks good.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH RESEND] dmaengine: stm32-dma: Rework starting transfer management
From: M'boumba Cedric Madianga @ 2017-01-03 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170103035703.GE3573@localhost>
Hi Vinod,
> ah sorry, i missed to push topic/stm32-dma. can you rebase onnthis and
> resend again. Btw this fails as as well..
I have tried again and I don't have any issue.
Please see below my way of working and let me know if there is
something I don't understand:
slave-dma git://git.infradead.org/users/vkoul/slave-dma.git
$ git fetch slave-dma
$ git checkout -b dma-fixes slave-dma/topic/dma-fixes
$ git checkout -b dma-stm32 slave-dma/topic/stm32-dma
$ git rebase dma-fixes
First, rewinding head to replay your work on top of it...
Applying: dmaengine: stm32-dma: Fix typo in Kconfig
Applying: dt-bindings: stm32-dma: Fix typo regarding DMA client binding
Applying: dmaengine: stm32-dma: Rework starting transfer management
Applying: dmaengine: stm32-dma: Fix residue computation issue in cyclic mode
Applying: dmaengine: stm32-dma: Add synchronization support
Applying: dmaengine: stm32-dma: Add max_burst support
Best regards,
Cedric
^ permalink raw reply
* [RESEND 1/2] document: dt: add binding for Hi3660 SoC
From: Rob Herring @ 2017-01-03 16:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482744972-56622-1-git-send-email-puck.chen@hisilicon.com>
On Mon, Dec 26, 2016 at 05:36:11PM +0800, Chen Feng wrote:
> Add binding for hisilicon Hi3660 SoC and HiKey960 Board.
>
> Signed-off-by: Chen Feng <puck.chen@hisilicon.com>
> ---
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt | 4 ++++
> 1 file changed, 4 insertions(+)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 1/2] pwm: sunxi: allow the pwm to finish its pulse before disable
From: Alexandre Belloni @ 2017-01-03 16:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <627ddbeb-d199-e2df-2073-090216a9fb0b@schinagl.nl>
On 03/01/2017 at 16:59:57 +0100, Olliver Schinagl wrote :
> On 12-12-16 13:24, Maxime Ripard wrote:
> > On Thu, Dec 08, 2016 at 02:23:39PM +0100, Olliver Schinagl wrote:
> > > Hey Maxime,
> > >
> > > first off, also sorry for the slow delay :) (pun not intended)
> > >
> > > On 27-08-16 00:19, Maxime Ripard wrote:
> > > > On Thu, Aug 25, 2016 at 07:50:10PM +0200, Olliver Schinagl wrote:
> > > > > When we inform the PWM block to stop toggeling the output, we may end up
> > > > > in a state where the output is not what we would expect (e.g. not the
> > > > > low-pulse) but whatever the output was at when the clock got disabled.
> > > > >
> > > > > To counter this we have to wait for maximally the time of one whole
> > > > > period to ensure the pwm hardware was able to finish. Since we already
> > > > > told the PWM hardware to disable it self, it will not continue toggling
> > > > > but merly finish its current pulse.
> > > > >
> > > > > If a whole period is considered to much, it may be contemplated to use a
> > > > > half period + a little bit to ensure we get passed the transition.
> > > > >
> > > > > Signed-off-by: Olliver Schinagl<oliver@schinagl.nl>
> > > > > ---
> > > > > drivers/pwm/pwm-sun4i.c | 11 +++++++++++
> > > > > 1 file changed, 11 insertions(+)
> > > > >
> > > > > diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
> > > > > index 03a99a5..5e97c8a 100644
> > > > > --- a/drivers/pwm/pwm-sun4i.c
> > > > > +++ b/drivers/pwm/pwm-sun4i.c
> > > > > @@ -8,6 +8,7 @@
> > > > > #include <linux/bitops.h>
> > > > > #include <linux/clk.h>
> > > > > +#include <linux/delay.h>
> > > > > #include <linux/err.h>
> > > > > #include <linux/io.h>
> > > > > #include <linux/module.h>
> > > > > @@ -245,6 +246,16 @@ static void sun4i_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
> > > > > spin_lock(&sun4i_pwm->ctrl_lock);
> > > > > val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
> > > > > val &= ~BIT_CH(PWM_EN, pwm->hwpwm);
> > > > > + sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG);
> > > > > + spin_unlock(&sun4i_pwm->ctrl_lock);
> > > > > +
> > > > > + /* Allow for the PWM hardware to finish its last toggle. The pulse
> > > > > + * may have just started and thus we should wait a full period.
> > > > > + */
> > > > > + ndelay(pwm_get_period(pwm));
> > > > Can't that use the ready bit as well?
> > >
> > > I started to implement our earlier discussed suggestions, but I do not think
> > > they will work. The read bit is not to let the user know it is ready with
> > > all of its commands, but only if the period registers are ready. I think it
> > > is some write lock while it copies the data into its internal control loop.
> > > From the manual:
> > > PWM0 period register ready.
> > > 0: PWM0 period register is ready to write,
> > > 1: PWM0 period register is busy.
> > >
> > >
> > > So no, I don't think i can use the ready bit here at all. The only thing we
> > > can do here, but I doubt it's worth it, is to read the period register,
> > > caluclate a time from it, and then ndelay(pwm_get_period(pwm) - ran_time)
> > >
> > > The only 'win' then is that we could are potentially not waiting the full
> > > pwm period, but only a fraction of it. Since we are disabling the hardware
> > > (for power reasons) anyway, I don't think this is any significant win,
> > > except for extreme situations. E.g. we have a pwm period of 10 seconds, we
> > > disable it after 9.9 second, and now we have to wait for 10 seconds before
> > > the pwm_disable is finally done. So this could in that case be reduced to
> > > then only wait for 0.2 seconds since it is 'done' sooner.
> > >
> > > However that optimization is also not 'free'. We have to read the period
> > > register and calculate back the time. I suggest to do that when reworking
> > > this driver to work with atomic mode, and merge this patch 'as is' to
> > > atleast fix te bug where simply not finish properly.
> >
> > That whole discussion made me realise something that is really
> > bad. AFAIK, pwm_get_period returns a 32 bits register, which means a
> > theorical period of 4s. Busy looping during 4 seconds is already very
> > bad, as you basically kill one CPU during that time, but doing so in a
> > (potentially) atomic context is even worse.
> Well technically, isn't it a 16 bit register? (half for the period, other
> half for the duty cycle?) Anyway, I think the delay can be far exceeding 4
> seconds (though I haven't checked what the PWM delay max option is).
>
That's 196.8s.
But you can rely on the RDY bit because what you want to
achieve actually relies on the fact that the duty cycle will be set to 0
before disabling the channel.
> Anyway, you are right, we should absolutely not do this!
>
> >
> > NACK.
> Absolutely! But what do you suggest? Would usleep (or msleep) instead of the
> ndelay work properly?
>
We can probably set up a timer and disable the channel when it expires.
Obviously it will be necessary to cancel the timer if the channel is
reenabled in the mean time.
Or maybe we can make all the functions blocking and forget about
synchronizing both channels.
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH] coresight: etm4x: Fix enabling of cycle accurate tracing in perf.
From: Mathieu Poirier @ 2017-01-03 16:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483397719-22235-1-git-send-email-mike.leach@linaro.org>
On Mon, Jan 02, 2017 at 10:55:19PM +0000, Mike Leach wrote:
> Using perf record 'cyclacc' option in cs_etm event was not setting up cycle
> accurate trace correctly.
>
> Corrects bit set in TRCCONFIGR to enable cycle accurate trace.
> Programs TRCCCCTLR with a valid threshold value as required by ETMv4 spec.
This look good - just a tiny blip below.
>
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
> drivers/hwtracing/coresight/coresight-etm4x.c | 7 +++++--
> drivers/hwtracing/coresight/coresight-etm4x.h | 1 +
> 2 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
> index 4db8d6a..07be032 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.c
> @@ -216,8 +216,11 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,
> goto out;
>
> /* Go from generic option to ETMv4 specifics */
> - if (attr->config & BIT(ETM_OPT_CYCACC))
> - config->cfg |= ETMv4_MODE_CYCACC;
> + if (attr->config & BIT(ETM_OPT_CYCACC)) {
> + config->cfg |= BIT(4);
> + /* TRM: Must program this for cycacc to work */
> + config->ccctlr = ETM_CYC_THRESHOLD_DEFAULT;
> + }
> if (attr->config & BIT(ETM_OPT_TS))
> config->cfg |= ETMv4_MODE_TIMESTAMP;
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index ba8d3f8..8a62c6c 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -146,6 +146,7 @@
> #define ETM_ARCH_V4 0x40
> #define ETMv4_SYNC_MASK 0x1F
> #define ETM_CYC_THRESHOLD_MASK 0xFFF
> +#define ETM_CYC_THRESHOLD_DEFAULT 256
If only to be consistent with the rest of the defines, please write this value
in base-16.
Thanks,
Mathieu
> #define ETMv4_EVENT_MASK 0xFF
> #define ETM_CNTR_MAX_VAL 0xFFFF
> #define ETM_TRACEID_MASK 0x3f
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH 2/4] input: tm2-touchkey: Add touchkey driver support for TM2
From: Krzysztof Kozlowski @ 2017-01-03 16:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483430237-26823-3-git-send-email-jcsing.lee@samsung.com>
On Tue, Jan 03, 2017 at 04:57:15PM +0900, Jaechul Lee wrote:
> This patch adds support for the TM2 touch key and led
> functionlity.
>
> The driver interfaces with userspace through an input device and
> reports KEY_PHONE and KEY_BACK event types. LED brightness can be
> controlled by "/sys/class/leds/tm2-touchkey/brightness".
>
> Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
> Signed-off-by: Beomho Seo <beomho.seo@samsung.com>
> ---
> drivers/input/keyboard/Kconfig | 11 ++
> drivers/input/keyboard/Makefile | 1 +
> drivers/input/keyboard/tm2-touchkey.c | 326 ++++++++++++++++++++++++++++++++++
> 3 files changed, 338 insertions(+)
> create mode 100644 drivers/input/keyboard/tm2-touchkey.c
>
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index cbd75cf..72c0ba1 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -666,6 +666,17 @@ config KEYBOARD_TC3589X
> To compile this driver as a module, choose M here: the
> module will be called tc3589x-keypad.
>
> +config KEYBOARD_TM2_TOUCHKEY
> + tristate "tm2-touchkey support"
> + depends on I2C
> + help
> + Say Y here to enable the tm2-touchkey.
The ending full stop is not needed.
> + touchkey driver for tm2. This driver can enable
> + the interrupt and make input events and control led brightness.
This sentence needs improvements. How about just:
"Beside input device, this driver provides also brightness control for
LEDs on touch keys."
Best regards,
Krzysztof
^ permalink raw reply
* [v2, 1/4] ARM: davinci: da8xx-dt: Add ti-aemif lookup for clock matching
From: David Lechner @ 2017-01-03 17:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7dbaaf44-09b8-ad27-b829-afbfa50f7aa7@ti.com>
On 01/03/2017 02:58 AM, Sekhar Nori wrote:
> On Monday 02 January 2017 01:34 PM, Sekhar Nori wrote:
>> On Saturday 31 December 2016 06:22 AM, David Lechner wrote:
>>> On 08/10/2016 06:00 AM, Karl Beldan wrote:
>>>> Many davinci boards (da830 and da850 families) don't have their clocks
>>>> in DT yet and won't be successful in getting an unnamed aemif clock
>>>> without explicitly registering them via clk_lookups, failing the
>>>> ti-aemif memory driver probe.
>>>>
>>>> The current aemif lookup entry resolving to the same clock:
>>>> 'CLK(NULL, "aemif", &aemif_clk)'
>>>> remains, as it is currently used (davinci_nand is getting a named clock
>>>> "aemif").
>>>>
>>>> This change will allow to switch from the mach-davinci aemif code to
>>>> the ti-aemif memory driver.
>>>>
>>>> Signed-off-by: Karl Beldan <kbeldan@baylibre.com>
>>>> ---
>>>
>>> FYI, I can't boot LEGO MINDSTORMS EV3 (AM1908) with a v4.9 mainline
>>> kernel. I did a git bisect and traced it down to this patch. I'm
>>> guessing that simply reverting it will break other things.
>>>
>>> The problem is that &aemif_clk is a node in a linked list and points to
>>> itself, which creates an infinite loop when looking up the usb clocks
>>> that are later in the list.
>>>
>>> I thought there was a patch to fix this properly from one of the Bay
>>> Libre guys to fix this already, but I can't seem to find it at the
>>> moment. When it is found, it would be good to have it applied to the 4.9
>>> stable and 4.10 mainline trees.
>>
>> Yes, a patch was submitted. It is pending in my queue since I need to do
>> a few experiments myself to determine if its the best solution possible.
>> Thanks for the heads-up on need to mark it for v4.9 stable. Will do.
>
> The master branch of my tree should have the patch included. If you can
> test and confirm it works fine on the lego platform, it will be great.
>
Tested "ARM: davinci: da850: fix infinite loop in clk_set_rate()"
working on LEGO Mindstorms with a 4.9.0 kernel.
^ permalink raw reply
* [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc
From: Rob Herring @ 2017-01-03 17:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161227070611.14852-3-rogershimizu@gmail.com>
On Tue, Dec 27, 2016 at 04:06:10PM +0900, Roger Shimizu wrote:
> Add linkstation-reset doc to describe the newly added
> POWER_RESET_LINKSTATION driver, which controls magic command
> sending to UART1 to power-off Buffalo Linkstation / KuroBox
> and their variants.
>
> To: Sebastian Reichel <sre@kernel.org>
> To: Rob Herring <robh+dt@kernel.org>
> To: Mark Rutland <mark.rutland@arm.com>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Ryan Tandy <ryan@nardis.ca>
> Cc: linux-pm at vger.kernel.org
> Cc: devicetree at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
>
> Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
> ---
> .../bindings/power/reset/linkstation-reset.txt | 26 ++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
>
> diff --git a/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> new file mode 100644
> index 000000000000..815e340318f3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> @@ -0,0 +1,26 @@
> +* Buffalo Linkstation Reset Driver
> +
> +Power of some Buffalo Linkstation or KuroBox Pro is managed by
> +micro-controller, which connects to UART1. After being fed from UART1
> +by a few magic numbers, the so-called power-off command,
> +the micro-controller will turn power off the device.
This needs to model the uC connected to the UART rather than some node
that defines only some portion of the functionality. I'm working on
bindings and proper bus support for this[1], but it's not done yet.
Though, the binding side is pretty simple.
Rob
[1] https://git.kernel.org/cgit/linux/kernel/git/robh/linux.git/log/?h=serial-bus-v2
^ permalink raw reply
* [PATCH 1/9] irqchip/ls-scfg-msi: fix typo of MSI compatible strings
From: Rob Herring @ 2017-01-03 17:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482829985-24421-1-git-send-email-Minghuan.Lian@nxp.com>
On Tue, Dec 27, 2016 at 05:12:57PM +0800, Minghuan Lian wrote:
> The patch is to fix typo of the Layerscape SCFG MSI dts compatible
> strings. "1" is replaced by "l".
>
> Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
> ---
> .../devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt | 6 +++---
> drivers/irqchip/irq-ls-scfg-msi.c | 6 ++++--
> 2 files changed, 7 insertions(+), 5 deletions(-)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 6/9] arm64: dts: ls1046a: add MSI dts node
From: Rob Herring @ 2017-01-03 17:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482829985-24421-6-git-send-email-Minghuan.Lian@nxp.com>
On Tue, Dec 27, 2016 at 05:13:02PM +0800, Minghuan Lian wrote:
> LS1046a includes 3 MSI controllers.
> Each controller supports 128 interrupts.
>
> Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
> ---
> .../interrupt-controller/fsl,ls-scfg-msi.txt | 1 +
> arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 31 ++++++++++++++++++++++
> 2 files changed, 32 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
> index 2755cd1..54597b0 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
> +++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
> @@ -6,6 +6,7 @@ Required properties:
> Layerscape PCIe MSI controller block such as:
> "fsl,ls1021a-msi"
> "fsl,ls1043a-msi"
> + "fsl,ls1046a-msi"
Differing whitespace.
Otherwise,
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH v6 6/8] IIO: add STM32 timer trigger driver
From: Jonathan Cameron @ 2017-01-03 17:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CA+M3ks6jshX-rEsi7Qfo-65awzWcHsEMVBjm-baYy979V9187Q@mail.gmail.com>
On 3 January 2017 09:23:34 GMT+00:00, Benjamin Gaignard <benjamin.gaignard@linaro.org> wrote:
>2017-01-02 19:22 GMT+01:00 Jonathan Cameron <jic23@kernel.org>:
>> On 02/01/17 08:46, Benjamin Gaignard wrote:
>>> 2016-12-30 22:12 GMT+01:00 Jonathan Cameron <jic23@kernel.org>:
>>>> On 09/12/16 14:15, Benjamin Gaignard wrote:
>>>>> Timers IPs can be used to generate triggers for other IPs like
>>>>> DAC, ADC or other timers.
>>>>> Each trigger may result of timer internals signals like counter
>enable,
>>>>> reset or edge, this configuration could be done through
>"master_mode"
>>>>> device attribute.
>>>>>
>>>>> A timer device could be triggered by other timers, we use the
>trigger
>>>>> name and is_stm32_iio_timer_trigger() function to distinguish them
>>>>> and configure IP input switch.
>>>>>
>>>>> Timer may also decide on which event (edge, level) they could
>>>>> be activated by a trigger, this configuration is done by writing
>in
>>>>> "slave_mode" device attribute.
>>>>>
>>>>> Since triggers could also be used by DAC or ADC their names are
>defined
>>>>> in include/ nux/iio/timer/stm32-timer-trigger.h so those IPs will
>be able
>>>>> to configure themselves in valid_trigger function
>>>>>
>>>>> Trigger have a "sampling_frequency" attribute which allow to
>configure
>>>>> timer sampling frequency without using PWM interface
>>>>>
>>>>> version 5:
>>>>> - simplify tables of triggers
>>>>> - only create an IIO device when needed
>>>>>
>>>>> version 4:
>>>>> - get triggers configuration from "reg" in DT
>>>>> - add tables of triggers
>>>>> - sampling frequency is enable/disable when writing in trigger
>>>>> sampling_frequency attribute
>>>>> - no more use of interruptions
>>>>>
>>>>> version 3:
>>>>> - change compatible to "st,stm32-timer-trigger"
>>>>> - fix attributes access right
>>>>> - use string instead of int for master_mode and slave_mode
>>>>> - document device attributes in sysfs-bus-iio-timer-stm32
>>>>>
>>>>> version 2:
>>>>> - keep only one compatible
>>>>> - use st,input-triggers-names and st,output-triggers-names
>>>>> to know which triggers are accepted and/or create by the device
>>>> Firstly, sorry it has taken me so long to get back to this.
>>>>
>>>> I'm still not keen on this use of iio_device elements just to act
>as
>>>> glue between triggers. I think we need to work out a more light
>weight
>>>> way to do this. As you are only using them for validation and to
>provide
>>>> somewhere to hang the control attibutes off, there is nothing
>stopping us
>>>> moving that over to the iio_trigger instead which would avoid the
>messy
>>>> duality going on here.
>>>
>>> I have add an iio_device because each hardware can generate multiple
>>> triggers (up to 5: trgo, ch 1...4) and slave_mode attribute will
>impact all the
>>> triggers of a device. For me it was making sense to centralize that
>in an
>>> iio_device rather than having an attribute "shared" (from hardware
>>> point of view)
>>> on multiple triggers.
>>> Since master_mode attribute is only used by trgo and not impact
>ch1...4
>>> triggers I will move it to trigger instead of the iio_device.
>>>
>>> I also wanted to be able to connect triggers on a iio_device as I
>>> could do for an
>>> ADC with a command like 'echo "tim1_trgo" >
>iio_deviceX/trigger/current_trigger'
>> This is interesting, but with a bit of refactoring I would think it
>would
>> be possible to share some of that code thus allowing non IIO devices
>to
>> bind to triggers. Ultimately I want to be able to bind a trigger to
>> a trigger - I appreciate here the topology is more limited than that
>> so some complexity comes in.
>>
>> My gut feeling is that representing that topology explicitly is hard
>> to do in a remotely general way, but lets try it and see.
>> We run into this sort of interdependency issue between different bits
>of
>> the hardware all the time. Setting a value somewhere effects the
>configuration
>> elsewhere - often the best plan is to just let that happen and leave
>it up to
>> userspace to check for changes if it cares.
>
>okay
>
>>> If I change that to parent_trigger attribute it change this behavior
>>> and I will have to
>>> duplicated what is done in iio_trigger_write_current() to find and
>>> validate triggers.
>> I get the reasoning, but we still end up with something represented
>> by an IIO device that isn't providing any channels at all. It's
>simply
>> using some of the infrastructure. To my mind it is 'something else'
>> and should be represented as such. I have no problem at all with
>> you registering additional elements in /sysfs/bus/iio/ to represent
>> these shared elements - we already have drivers that do that to
>> provide some centralized infrastructure (e.g. the sysfs-trigger)
>
>My hardware block are timers maybe I can add a channel type "IIO_TIMER"
>and declare a channel with info_mask_separate =
>BIT(IIO_CHAN_INFO_SAMP_FREQ)
>so I will be able to write/read sampling frequency on IIO device.
Hmm stretching a point. There aren't really input or output channels.
Still not convinced there should be any IIO devices near this at all.
>
>> I'm worried about the scope spread we get for an IIO device
>otherwise.
>> They serve a well defined purpose at the moment, and that isn't what
>> is happening here.
>>
>> So my gut feeling is we are better deliberately not representing the
>> inter dependence and claiming all triggers we are creating are
>> independent. That way we can have a nice generic infrastructure
>> that will work in all cases (be it pushing the sanity checking to
>> userspace).
>>
>> So each trigger has direct access to what controls it. Changing
>anything
>> can effect other triggers in weird ways.
>>
>> I'm finding it hard to see anything else generalizing sufficiently
>> as we'll always get cases where we can't represent the topology
>without
>> diving into the complexity of something like the media controller
>> framework.
>>
>> Jonathan
>>>
>>>> I might still be missing something though!
>>>>
>>>> You would only I think need 3 attributes
>>>>
>>>> parrent_trigger
>>>> and something like your master_mode and slave_mode attributes.
>>>>
>>>> The parrent_trigger would need some validation etc, but if we keep
>it
>>>> within this driver initially that won't be hard to do. Checking the
>device
>>>> parent matches will do most of it.
>>>>
>>>> Jonathan
>>>>>
>>>>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
>>>>> ---
>>>>> .../ABI/testing/sysfs-bus-iio-timer-stm32 | 55 +++
>>>>> drivers/iio/Kconfig | 2 +-
>>>>> drivers/iio/Makefile | 1 +
>>>>> drivers/iio/timer/Kconfig | 13 +
>>>>> drivers/iio/timer/Makefile | 1 +
>>>>> drivers/iio/timer/stm32-timer-trigger.c | 466
>+++++++++++++++++++++
>>>>> drivers/iio/trigger/Kconfig | 1 -
>>>>> include/linux/iio/timer/stm32-timer-trigger.h | 62 +++
>>>>> 8 files changed, 599 insertions(+), 2 deletions(-)
>>>>> create mode 100644
>Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>>>>> create mode 100644 drivers/iio/timer/Kconfig
>>>>> create mode 100644 drivers/iio/timer/Makefile
>>>>> create mode 100644 drivers/iio/timer/stm32-timer-trigger.c
>>>>> create mode 100644 include/linux/iio/timer/stm32-timer-trigger.h
>>>>>
>>>>> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>>>>> new file mode 100644
>>>>> index 0000000..26583dd
>>>>> --- /dev/null
>>>>> +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>>>>> @@ -0,0 +1,55 @@
>>>>> +What:
>/sys/bus/iio/devices/iio:deviceX/master_mode_available
>>>>> +KernelVersion: 4.10
>>>>> +Contact: benjamin.gaignard at st.com
>>>>> +Description:
>>>>> + Reading returns the list possible master modes which
>are:
>>>>> + - "reset" : The UG bit from the TIMx_EGR
>register is used as trigger output (TRGO).
>>>>> + - "enable" : The Counter Enable signal CNT_EN is
>used as trigger output.
>>>>> + - "update" : The update event is selected as
>trigger output.
>>>>> + For instance a master timer can then
>be used as a prescaler for a slave timer.
>>>>> + - "compare_pulse" : The trigger output send a
>positive pulse when the CC1IF flag is to be set.
>>>>> + - "OC1REF" : OC1REF signal is used as trigger
>output.
>>>>> + - "OC2REF" : OC2REF signal is used as trigger
>output.
>>>>> + - "OC3REF" : OC3REF signal is used as trigger
>output.
>>>>> + - "OC4REF" : OC4REF signal is used as trigger
>output.
>>>>> +
>>>>> +What: /sys/bus/iio/devices/iio:deviceX/master_mode
>>>>> +KernelVersion: 4.10
>>>>> +Contact: benjamin.gaignard at st.com
>>>>> +Description:
>>>>> + Reading returns the current master modes.
>>>>> + Writing set the master mode
>>>>> +
>>>>> +What:
>/sys/bus/iio/devices/iio:deviceX/slave_mode_available
>>>>> +KernelVersion: 4.10
>>>>> +Contact: benjamin.gaignard at st.com
>>>>> +Description:
>>>>> + Reading returns the list possible slave modes which
>are:
>>>>> + - "disabled" : The prescaler is clocked directly by
>the internal clock.
>>>>> + - "encoder_1" : Counter counts up/down on TI2FP1
>edge depending on TI1FP2 level.
>>>>> + - "encoder_2" : Counter counts up/down on TI1FP2
>edge depending on TI2FP1 level.
>>>>> + - "encoder_3" : Counter counts up/down on both
>TI1FP1 and TI2FP2 edges depending
>>>>> + on the level of the other input.
>>>>> + - "reset" : Rising edge of the selected trigger
>input reinitializes the counter
>>>>> + and generates an update of the
>registers.
>>>>> + - "gated" : The counter clock is enabled when
>the trigger input is high.
>>>>> + The counter stops (but is not reset)
>as soon as the trigger becomes low.
>>>>> + Both start and stop of the counter
>are controlled.
>>>>> + - "trigger" : The counter starts at a rising edge
>of the trigger TRGI (but it is not
>>>>> + reset). Only the start of the
>counter is controlled.
>>>>> + - "external_clock": Rising edges of the selected
>trigger (TRGI) clock the counter.
>>>>> +
>>>>> +What: /sys/bus/iio/devices/iio:deviceX/slave_mode
>>>>> +KernelVersion: 4.10
>>>>> +Contact: benjamin.gaignard at st.com
>>>>> +Description:
>>>>> + Reading returns the current slave mode.
>>>>> + Writing set the slave mode
>>>>> +
>>>>> +What:
>/sys/bus/iio/devices/triggerX/sampling_frequency
>>>>> +KernelVersion: 4.10
>>>>> +Contact: benjamin.gaignard at st.com
>>>>> +Description:
>>>>> + Reading returns the current sampling frequency.
>>>>> + Writing an value different of 0 set and start
>sampling.
>>>>> + Writing 0 stop sampling.
>>>>> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
>>>>> index 6743b18..2de2a80 100644
>>>>> --- a/drivers/iio/Kconfig
>>>>> +++ b/drivers/iio/Kconfig
>>>>> @@ -90,5 +90,5 @@ source "drivers/iio/potentiometer/Kconfig"
>>>>> source "drivers/iio/pressure/Kconfig"
>>>>> source "drivers/iio/proximity/Kconfig"
>>>>> source "drivers/iio/temperature/Kconfig"
>>>>> -
>>>>> +source "drivers/iio/timer/Kconfig"
>>>>> endif # IIO
>>>>> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
>>>>> index 87e4c43..b797c08 100644
>>>>> --- a/drivers/iio/Makefile
>>>>> +++ b/drivers/iio/Makefile
>>>>> @@ -32,4 +32,5 @@ obj-y += potentiometer/
>>>>> obj-y += pressure/
>>>>> obj-y += proximity/
>>>>> obj-y += temperature/
>>>>> +obj-y += timer/
>>>>> obj-y += trigger/
>>>>> diff --git a/drivers/iio/timer/Kconfig b/drivers/iio/timer/Kconfig
>>>>> new file mode 100644
>>>>> index 0000000..e3c21f2
>>>>> --- /dev/null
>>>>> +++ b/drivers/iio/timer/Kconfig
>>>>> @@ -0,0 +1,13 @@
>>>>> +#
>>>>> +# Timers drivers
>>>>> +
>>>>> +menu "Timers"
>>>>> +
>>>>> +config IIO_STM32_TIMER_TRIGGER
>>>>> + tristate "STM32 Timer Trigger"
>>>>> + depends on (ARCH_STM32 && OF && MFD_STM32_TIMERS) ||
>COMPILE_TEST
>>>>> + select IIO_TRIGGERED_EVENT
>>>>> + help
>>>>> + Select this option to enable STM32 Timer Trigger
>>>>> +
>>>>> +endmenu
>>>>> diff --git a/drivers/iio/timer/Makefile
>b/drivers/iio/timer/Makefile
>>>>> new file mode 100644
>>>>> index 0000000..4ad95ec9
>>>>> --- /dev/null
>>>>> +++ b/drivers/iio/timer/Makefile
>>>>> @@ -0,0 +1 @@
>>>>> +obj-$(CONFIG_IIO_STM32_TIMER_TRIGGER) += stm32-timer-trigger.o
>>>>> diff --git a/drivers/iio/timer/stm32-timer-trigger.c
>b/drivers/iio/timer/stm32-timer-trigger.c
>>>>> new file mode 100644
>>>>> index 0000000..8d16e8f
>>>>> --- /dev/null
>>>>> +++ b/drivers/iio/timer/stm32-timer-trigger.c
>>>>> @@ -0,0 +1,466 @@
>>>>> +/*
>>>>> + * Copyright (C) STMicroelectronics 2016
>>>>> + *
>>>>> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
>>>>> + *
>>>>> + * License terms: GNU General Public License (GPL), version 2
>>>>> + */
>>>>> +
>>>>> +#include <linux/iio/iio.h>
>>>>> +#include <linux/iio/sysfs.h>
>>>>> +#include <linux/iio/timer/stm32-timer-trigger.h>
>>>>> +#include <linux/iio/trigger.h>
>>>>> +#include <linux/iio/triggered_event.h>
>>>>> +#include <linux/interrupt.h>
>>>>> +#include <linux/mfd/stm32-timers.h>
>>>>> +#include <linux/module.h>
>>>>> +#include <linux/platform_device.h>
>>>>> +
>>>>> +#define MAX_TRIGGERS 6
>>>>> +#define MAX_VALIDS 5
>>>>> +
>>>>> +/* List the triggers created by each timer */
>>>>> +static const void *triggers_table[][MAX_TRIGGERS] = {
>>>>> + { TIM1_TRGO, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,},
>>>>> + { TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,},
>>>>> + { TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,},
>>>>> + { TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,},
>>>>> + { TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,},
>>>>> + { TIM6_TRGO,},
>>>>> + { TIM7_TRGO,},
>>>>> + { TIM8_TRGO, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,},
>>>>> + { TIM9_TRGO, TIM9_CH1, TIM9_CH2,},
>>>>> + { TIM12_TRGO, TIM12_CH1, TIM12_CH2,},
>>>>> +};
>>>>> +
>>>>> +/* List the triggers accepted by each timer */
>>>>> +static const void *valids_table[][MAX_VALIDS] = {
>>>>> + { TIM5_TRGO, TIM2_TRGO, TIM4_TRGO, TIM3_TRGO,},
>>>>> + { TIM1_TRGO, TIM8_TRGO, TIM3_TRGO, TIM4_TRGO,},
>>>>> + { TIM1_TRGO, TIM8_TRGO, TIM5_TRGO, TIM4_TRGO,},
>>>>> + { TIM1_TRGO, TIM2_TRGO, TIM3_TRGO, TIM8_TRGO,},
>>>>> + { TIM2_TRGO, TIM3_TRGO, TIM4_TRGO, TIM8_TRGO,},
>>>>> + { }, /* timer 6 */
>>>>> + { }, /* timer 7 */
>>>>> + { TIM1_TRGO, TIM2_TRGO, TIM4_TRGO, TIM5_TRGO,},
>>>>> + { TIM2_TRGO, TIM3_TRGO,},
>>>>> + { TIM4_TRGO, TIM5_TRGO,},
>>>>> +};
>>>>> +
>>>>> +struct stm32_timer_trigger {
>>>>> + struct device *dev;
>>>>> + struct regmap *regmap;
>>>>> + struct clk *clk;
>>>>> + u32 max_arr;
>>>>> + const void *triggers;
>>>>> + const void *valids;
>>>>> +};
>>>>> +
>>>>> +static int stm32_timer_start(struct stm32_timer_trigger *priv,
>>>>> + unsigned int frequency)
>>>>> +{
>>>>> + unsigned long long prd, div;
>>>>> + int prescaler = 0;
>>>>> + u32 ccer, cr1;
>>>>> +
>>>>> + /* Period and prescaler values depends of clock rate */
>>>>> + div = (unsigned long long)clk_get_rate(priv->clk);
>>>>> +
>>>>> + do_div(div, frequency);
>>>>> +
>>>>> + prd = div;
>>>>> +
>>>>> + /*
>>>>> + * Increase prescaler value until we get a result that fit
>>>>> + * with auto reload register maximum value.
>>>>> + */
>>>>> + while (div > priv->max_arr) {
>>>>> + prescaler++;
>>>>> + div = prd;
>>>>> + do_div(div, (prescaler + 1));
>>>>> + }
>>>>> + prd = div;
>>>>> +
>>>>> + if (prescaler > MAX_TIM_PSC) {
>>>>> + dev_err(priv->dev, "prescaler exceeds the maximum
>value\n");
>>>>> + return -EINVAL;
>>>>> + }
>>>>> +
>>>>> + /* Check if nobody else use the timer */
>>>>> + regmap_read(priv->regmap, TIM_CCER, &ccer);
>>>>> + if (ccer & TIM_CCER_CCXE)
>>>>> + return -EBUSY;
>>>>> +
>>>>> + regmap_read(priv->regmap, TIM_CR1, &cr1);
>>>>> + if (!(cr1 & TIM_CR1_CEN))
>>>>> + clk_enable(priv->clk);
>>>>> +
>>>>> + regmap_write(priv->regmap, TIM_PSC, prescaler);
>>>>> + regmap_write(priv->regmap, TIM_ARR, prd - 1);
>>>>> + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE,
>TIM_CR1_ARPE);
>>>>> +
>>>>> + /* Force master mode to update mode */
>>>>> + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS,
>0x20);
>>>>> +
>>>>> + /* Make sure that registers are updated */
>>>>> + regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG,
>TIM_EGR_UG);
>>>>> +
>>>>> + /* Enable controller */
>>>>> + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
>TIM_CR1_CEN);
>>>>> +
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> +static void stm32_timer_stop(struct stm32_timer_trigger *priv)
>>>>> +{
>>>>> + u32 ccer, cr1;
>>>>> +
>>>>> + regmap_read(priv->regmap, TIM_CCER, &ccer);
>>>>> + if (ccer & TIM_CCER_CCXE)
>>>>> + return;
>>>>> +
>>>>> + regmap_read(priv->regmap, TIM_CR1, &cr1);
>>>>> + if (cr1 & TIM_CR1_CEN)
>>>>> + clk_disable(priv->clk);
>>>>> +
>>>>> + /* Stop timer */
>>>>> + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
>>>>> + regmap_write(priv->regmap, TIM_PSC, 0);
>>>>> + regmap_write(priv->regmap, TIM_ARR, 0);
>>>>> +}
>>>>> +
>>>>> +static ssize_t stm32_tt_store_frequency(struct device *dev,
>>>>> + struct device_attribute
>*attr,
>>>>> + const char *buf, size_t len)
>>>>> +{
>>>>> + struct iio_trigger *trig = to_iio_trigger(dev);
>>>>> + struct stm32_timer_trigger *priv =
>iio_trigger_get_drvdata(trig);
>>>>> + unsigned int freq;
>>>>> + int ret;
>>>>> +
>>>>> + ret = kstrtouint(buf, 10, &freq);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + if (freq == 0) {
>>>>> + stm32_timer_stop(priv);
>>>>> + } else {
>>>>> + ret = stm32_timer_start(priv, freq);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> + }
>>>>> +
>>>>> + return len;
>>>>> +}
>>>>> +
>>>>> +static ssize_t stm32_tt_read_frequency(struct device *dev,
>>>>> + struct device_attribute
>*attr, char *buf)
>>>>> +{
>>>>> + struct iio_trigger *trig = to_iio_trigger(dev);
>>>>> + struct stm32_timer_trigger *priv =
>iio_trigger_get_drvdata(trig);
>>>>> + u32 psc, arr, cr1;
>>>>> + unsigned long long freq = 0;
>>>>> +
>>>>> + regmap_read(priv->regmap, TIM_CR1, &cr1);
>>>>> + regmap_read(priv->regmap, TIM_PSC, &psc);
>>>>> + regmap_read(priv->regmap, TIM_ARR, &arr);
>>>>> +
>>>>> + if (psc && arr && (cr1 & TIM_CR1_CEN)) {
>>>>> + freq = (unsigned long long)clk_get_rate(priv->clk);
>>>>> + do_div(freq, psc);
>>>>> + do_div(freq, arr);
>>>>> + }
>>>>> +
>>>>> + return sprintf(buf, "%d\n", (unsigned int)freq);
>>>>> +}
>>>>> +
>>>>> +static IIO_DEV_ATTR_SAMP_FREQ(0660,
>>>>> + stm32_tt_read_frequency,
>>>>> + stm32_tt_store_frequency);
>>>>> +
>>>>> +static struct attribute *stm32_trigger_attrs[] = {
>>>>> + &iio_dev_attr_sampling_frequency.dev_attr.attr,
>>>>> + NULL,
>>>>> +};
>>>>> +
>>>>> +static const struct attribute_group stm32_trigger_attr_group = {
>>>>> + .attrs = stm32_trigger_attrs,
>>>>> +};
>>>>> +
>>>>> +static const struct attribute_group *stm32_trigger_attr_groups[]
>= {
>>>>> + &stm32_trigger_attr_group,
>>>>> + NULL,
>>>>> +};
>>>>> +
>>>>> +static char *master_mode_table[] = {
>>>>> + "reset",
>>>>> + "enable",
>>>>> + "update",
>>>>> + "compare_pulse",
>>>>> + "OC1REF",
>>>>> + "OC2REF",
>>>>> + "OC3REF",
>>>>> + "OC4REF"
>>>>> +};
>>>>> +
>>>>> +static ssize_t stm32_tt_show_master_mode(struct device *dev,
>>>>> + struct device_attribute
>*attr,
>>>>> + char *buf)
>>>>> +{
>>>>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>>>> + struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>> + u32 cr2;
>>>>> +
>>>>> + regmap_read(priv->regmap, TIM_CR2, &cr2);
>>>>> + cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT;
>>>>> +
>>>>> + return snprintf(buf, PAGE_SIZE, "%s\n",
>master_mode_table[cr2]);
>>>>> +}
>>>>> +
>>>>> +static ssize_t stm32_tt_store_master_mode(struct device *dev,
>>>>> + struct device_attribute
>*attr,
>>>>> + const char *buf, size_t
>len)
>>>>> +{
>>>>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>>>> + struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>> + int i;
>>>>> +
>>>>> + for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) {
>>>>> + if (!strncmp(master_mode_table[i], buf,
>>>>> + strlen(master_mode_table[i]))) {
>>>>> + regmap_update_bits(priv->regmap, TIM_CR2,
>>>>> + TIM_CR2_MMS, i <<
>TIM_CR2_MMS_SHIFT);
>>>>> + return len;
>>>>> + }
>>>>> + }
>>>>> +
>>>>> + return -EINVAL;
>>>>> +}
>>>>> +
>>>>> +static IIO_CONST_ATTR(master_mode_available,
>>>>> + "reset enable update compare_pulse OC1REF OC2REF OC3REF
>OC4REF");
>>>>> +
>>>>> +static IIO_DEVICE_ATTR(master_mode, 0660,
>>>>> + stm32_tt_show_master_mode,
>>>>> + stm32_tt_store_master_mode,
>>>>> + 0);
>>>>> +
>>>>> +static char *slave_mode_table[] = {
>>>>> + "disabled",
>>>>> + "encoder_1",
>>>>> + "encoder_2",
>>>>> + "encoder_3",
>>>>> + "reset",
>>>>> + "gated",
>>>>> + "trigger",
>>>>> + "external_clock",
>>>>> +};
>>>>> +
>>>>> +static ssize_t stm32_tt_show_slave_mode(struct device *dev,
>>>>> + struct device_attribute
>*attr,
>>>>> + char *buf)
>>>>> +{
>>>>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>>>> + struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>> + u32 smcr;
>>>>> +
>>>>> + regmap_read(priv->regmap, TIM_SMCR, &smcr);
>>>>> + smcr &= TIM_SMCR_SMS;
>>>>> +
>>>>> + return snprintf(buf, PAGE_SIZE, "%s\n",
>slave_mode_table[smcr]);
>>>>> +}
>>>>> +
>>>>> +static ssize_t stm32_tt_store_slave_mode(struct device *dev,
>>>>> + struct device_attribute
>*attr,
>>>>> + const char *buf, size_t
>len)
>>>>> +{
>>>>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>>>> + struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>> + int i;
>>>>> +
>>>>> + for (i = 0; i < ARRAY_SIZE(slave_mode_table); i++) {
>>>>> + if (!strncmp(slave_mode_table[i], buf,
>>>>> + strlen(slave_mode_table[i]))) {
>>>>> + regmap_update_bits(priv->regmap,
>>>>> + TIM_SMCR, TIM_SMCR_SMS,
>i);
>>>>> + return len;
>>>>> + }
>>>>> + }
>>>>> +
>>>>> + return -EINVAL;
>>>>> +}
>>>>> +
>>>>> +static IIO_CONST_ATTR(slave_mode_available,
>>>>> +"disabled encoder_1 encoder_2 encoder_3 reset gated trigger
>external_clock");
>>>>> +
>>>>> +static IIO_DEVICE_ATTR(slave_mode, 0660,
>>>>> + stm32_tt_show_slave_mode,
>>>>> + stm32_tt_store_slave_mode,
>>>>> + 0);
>>>>> +
>>>>> +static struct attribute *stm32_timer_attrs[] = {
>>>>> + &iio_dev_attr_master_mode.dev_attr.attr,
>>>>> + &iio_const_attr_master_mode_available.dev_attr.attr,
>>>>> + &iio_dev_attr_slave_mode.dev_attr.attr,
>>>>> + &iio_const_attr_slave_mode_available.dev_attr.attr,
>>>>> + NULL,
>>>>> +};
>>>>> +
>>>>> +static const struct attribute_group stm32_timer_attr_group = {
>>>>> + .attrs = stm32_timer_attrs,
>>>>> +};
>>>>> +
>>>>> +static const struct iio_trigger_ops timer_trigger_ops = {
>>>>> + .owner = THIS_MODULE,
>>>>> +};
>>>>> +
>>>>> +static int stm32_setup_iio_triggers(struct stm32_timer_trigger
>*priv)
>>>>> +{
>>>>> + int ret;
>>>>> + const char * const *cur = priv->triggers;
>>>>> +
>>>>> + while (cur && *cur) {
>>>>> + struct iio_trigger *trig;
>>>>> +
>>>>> + trig = devm_iio_trigger_alloc(priv->dev, "%s",
>*cur);
>>>>> + if (!trig)
>>>>> + return -ENOMEM;
>>>>> +
>>>>> + trig->dev.parent = priv->dev->parent;
>>>>> + trig->ops = &timer_trigger_ops;
>>>>> + trig->dev.groups = stm32_trigger_attr_groups;
>>>>> + iio_trigger_set_drvdata(trig, priv);
>>>>> +
>>>>> + ret = devm_iio_trigger_register(priv->dev, trig);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> + cur++;
>>>>> + }
>>>>> +
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> +/**
>>>>> + * is_stm32_timer_trigger
>>>>> + * @trig: trigger to be checked
>>>>> + *
>>>>> + * return true if the trigger is a valid stm32 iio timer trigger
>>>>> + * either return false
>>>>> + */
>>>>> +bool is_stm32_timer_trigger(struct iio_trigger *trig)
>>>>> +{
>>>>> + return (trig->ops == &timer_trigger_ops);
>>>>> +}
>>>>> +EXPORT_SYMBOL(is_stm32_timer_trigger);
>>>>> +
>>>>> +static int stm32_validate_trigger(struct iio_dev *indio_dev,
>>>>> + struct iio_trigger *trig)
>>>>> +{
>>>>> + struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>> + const char * const *cur = priv->valids;
>>>>> + unsigned int i = 0;
>>>>> +
>>>>> + if (!is_stm32_timer_trigger(trig))
>>>>> + return -EINVAL;
>>>>> +
>>>>> + while (cur && *cur) {
>>>>> + if (!strncmp(trig->name, *cur, strlen(trig->name)))
>{
>>>>> + regmap_update_bits(priv->regmap,
>>>>> + TIM_SMCR, TIM_SMCR_TS,
>>>>> + i << TIM_SMCR_TS_SHIFT);
>>>>> + return 0;
>>>>> + }
>>>>> + cur++;
>>>>> + i++;
>>>>> + }
>>>>> +
>>>>> + return -EINVAL;
>>>>> +}
>>>>> +
>>>>> +static const struct iio_info stm32_trigger_info = {
>>>>> + .driver_module = THIS_MODULE,
>>>>> + .validate_trigger = stm32_validate_trigger,
>>>>> + .attrs = &stm32_timer_attr_group,
>>>>> +};
>>>>> +
>>>>> +static struct stm32_timer_trigger *stm32_setup_iio_device(struct
>device *dev)
>>>>> +{
>>>>> + struct iio_dev *indio_dev;
>>>>> + int ret;
>>>>> +
>>>>> + indio_dev = devm_iio_device_alloc(dev,
>>>>> + sizeof(struct
>stm32_timer_trigger));
>>>>> + if (!indio_dev)
>>>>> + return NULL;
>>>>> +
>>>>> + indio_dev->name = dev_name(dev);
>>>>> + indio_dev->dev.parent = dev;
>>>>> + indio_dev->info = &stm32_trigger_info;
>>>>> + indio_dev->modes = INDIO_EVENT_TRIGGERED;
>>>>> + indio_dev->num_channels = 0;
>>>>> + indio_dev->dev.of_node = dev->of_node;
>>>>> +
>>>>> + ret = devm_iio_device_register(dev, indio_dev);
>>>>> + if (ret)
>>>>> + return NULL;
>>>>> +
>>>>> + return iio_priv(indio_dev);
>>>>> +}
>>>>> +
>>>>> +static int stm32_timer_trigger_probe(struct platform_device
>*pdev)
>>>>> +{
>>>>> + struct device *dev = &pdev->dev;
>>>>> + struct stm32_timer_trigger *priv;
>>>>> + struct stm32_timers *ddata =
>dev_get_drvdata(pdev->dev.parent);
>>>>> + unsigned int index;
>>>>> + int ret;
>>>>> +
>>>>> + if (of_property_read_u32(dev->of_node, "reg", &index))
>>>>> + return -EINVAL;
>>>>> +
>>>>> + if (index >= ARRAY_SIZE(triggers_table))
>>>>> + return -EINVAL;
>>>>> +
>>>>> + /* Create an IIO device only if we have triggers to be
>validated */
>>>>> + if (*valids_table[index])
>>>>> + priv = stm32_setup_iio_device(dev);
>>>>
>>>> I still don't like this. Really feels like we shouldn't be creating
>an
>>>> iio device with all the bagage that carries just to allow us to do
>the
>>>> trigger trees. We ought to have a much more light weight solution
>for this
>>>> functionality - we aren't typically even using the interrupt tree
>stuff
>>>> that the triggers for devices are all really about.
>>>>
>>>> A simpler approach of allowing each trigger the option of a parent
>seems like
>>>> it would be cleaner. Could be done entirely within this driver in
>the first
>>>> instance. Basically it would just look like your master and slave
>attributes
>>>> but have those under triggerX not iio:deviceX.
>>>>
>>>> We can work out how to make it more generic later - including
>perhaps the
>>>> option to trigger from triggers outside this driver, using some
>parallel
>>>> infrastructure to the device triggering.
>>>>
>>>>
>>>>> + else
>>>>> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>>>>> +
>>>>> + if (!priv)
>>>>> + return -ENOMEM;
>>>>> +
>>>>> + priv->dev = dev;
>>>>> + priv->regmap = ddata->regmap;
>>>>> + priv->clk = ddata->clk;
>>>>> + priv->max_arr = ddata->max_arr;
>>>>> + priv->triggers = triggers_table[index];
>>>>> + priv->valids = valids_table[index];
>>>>> +
>>>>> + ret = stm32_setup_iio_triggers(priv);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + platform_set_drvdata(pdev, priv);
>>>>> +
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> +static const struct of_device_id stm32_trig_of_match[] = {
>>>>> + { .compatible = "st,stm32-timer-trigger", },
>>>>> + { /* end node */ },
>>>>> +};
>>>>> +MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
>>>>> +
>>>>> +static struct platform_driver stm32_timer_trigger_driver = {
>>>>> + .probe = stm32_timer_trigger_probe,
>>>>> + .driver = {
>>>>> + .name = "stm32-timer-trigger",
>>>>> + .of_match_table = stm32_trig_of_match,
>>>>> + },
>>>>> +};
>>>>> +module_platform_driver(stm32_timer_trigger_driver);
>>>>> +
>>>>> +MODULE_ALIAS("platform: stm32-timer-trigger");
>>>>> +MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger
>driver");
>>>>> +MODULE_LICENSE("GPL v2");
>>>>> diff --git a/drivers/iio/trigger/Kconfig
>b/drivers/iio/trigger/Kconfig
>>>>> index 809b2e7..f2af4fe 100644
>>>>> --- a/drivers/iio/trigger/Kconfig
>>>>> +++ b/drivers/iio/trigger/Kconfig
>>>>> @@ -46,5 +46,4 @@ config IIO_SYSFS_TRIGGER
>>>>>
>>>>> To compile this driver as a module, choose M here: the
>>>>> module will be called iio-trig-sysfs.
>>>>> -
>>>> Clean this up.
>>>
>>> ok
>>>
>>>>> endmenu
>>>>> diff --git a/include/linux/iio/timer/stm32-timer-trigger.h
>b/include/linux/iio/timer/stm32-timer-trigger.h
>>>>> new file mode 100644
>>>>> index 0000000..55535ae
>>>>> --- /dev/null
>>>>> +++ b/include/linux/iio/timer/stm32-timer-trigger.h
>>>>> @@ -0,0 +1,62 @@
>>>>> +/*
>>>>> + * Copyright (C) STMicroelectronics 2016
>>>>> + *
>>>>> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
>>>>> + *
>>>>> + * License terms: GNU General Public License (GPL), version 2
>>>>> + */
>>>>> +
>>>>> +#ifndef _STM32_TIMER_TRIGGER_H_
>>>>> +#define _STM32_TIMER_TRIGGER_H_
>>>>> +
>>>>> +#define TIM1_TRGO "tim1_trgo"
>>>>> +#define TIM1_CH1 "tim1_ch1"
>>>>> +#define TIM1_CH2 "tim1_ch2"
>>>>> +#define TIM1_CH3 "tim1_ch3"
>>>>> +#define TIM1_CH4 "tim1_ch4"
>>>>> +
>>>>> +#define TIM2_TRGO "tim2_trgo"
>>>>> +#define TIM2_CH1 "tim2_ch1"
>>>>> +#define TIM2_CH2 "tim2_ch2"
>>>>> +#define TIM2_CH3 "tim2_ch3"
>>>>> +#define TIM2_CH4 "tim2_ch4"
>>>>> +
>>>>> +#define TIM3_TRGO "tim3_trgo"
>>>>> +#define TIM3_CH1 "tim3_ch1"
>>>>> +#define TIM3_CH2 "tim3_ch2"
>>>>> +#define TIM3_CH3 "tim3_ch3"
>>>>> +#define TIM3_CH4 "tim3_ch4"
>>>>> +
>>>>> +#define TIM4_TRGO "tim4_trgo"
>>>>> +#define TIM4_CH1 "tim4_ch1"
>>>>> +#define TIM4_CH2 "tim4_ch2"
>>>>> +#define TIM4_CH3 "tim4_ch3"
>>>>> +#define TIM4_CH4 "tim4_ch4"
>>>>> +
>>>>> +#define TIM5_TRGO "tim5_trgo"
>>>>> +#define TIM5_CH1 "tim5_ch1"
>>>>> +#define TIM5_CH2 "tim5_ch2"
>>>>> +#define TIM5_CH3 "tim5_ch3"
>>>>> +#define TIM5_CH4 "tim5_ch4"
>>>>> +
>>>>> +#define TIM6_TRGO "tim6_trgo"
>>>>> +
>>>>> +#define TIM7_TRGO "tim7_trgo"
>>>>> +
>>>>> +#define TIM8_TRGO "tim8_trgo"
>>>>> +#define TIM8_CH1 "tim8_ch1"
>>>>> +#define TIM8_CH2 "tim8_ch2"
>>>>> +#define TIM8_CH3 "tim8_ch3"
>>>>> +#define TIM8_CH4 "tim8_ch4"
>>>>> +
>>>>> +#define TIM9_TRGO "tim9_trgo"
>>>>> +#define TIM9_CH1 "tim9_ch1"
>>>>> +#define TIM9_CH2 "tim9_ch2"
>>>>> +
>>>>> +#define TIM12_TRGO "tim12_trgo"
>>>>> +#define TIM12_CH1 "tim12_ch1"
>>>>> +#define TIM12_CH2 "tim12_ch2"
>>>>> +
>>>>> +bool is_stm32_timer_trigger(struct iio_trigger *trig);
>>>>> +
>>>>> +#endif
>>>>>
>>>>
>>>
>>>
>>>
>>
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
^ permalink raw reply
* [PATCHv6 00/11] CONFIG_DEBUG_VIRTUAL for arm64
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
Happy New Year!
This is a very minor rebase from v5. It only moves a few headers around.
I think this series should be ready to be queued up for 4.11.
Thanks,
Laura
Laura Abbott (11):
lib/Kconfig.debug: Add ARCH_HAS_DEBUG_VIRTUAL
mm/cma: Cleanup highmem check
arm64: Move some macros under #ifndef __ASSEMBLY__
arm64: Add cast for virt_to_pfn
mm: Introduce lm_alias
arm64: Use __pa_symbol for kernel symbols
drivers: firmware: psci: Use __pa_symbol for kernel symbol
kexec: Switch to __pa_symbol
mm/kasan: Switch to using __pa_symbol and lm_alias
mm/usercopy: Switch to using lm_alias
arm64: Add support for CONFIG_DEBUG_VIRTUAL
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/kvm_mmu.h | 4 +-
arch/arm64/include/asm/memory.h | 66 +++++++++++++++++++++----------
arch/arm64/include/asm/mmu_context.h | 6 +--
arch/arm64/include/asm/pgtable.h | 2 +-
arch/arm64/kernel/acpi_parking_protocol.c | 3 +-
arch/arm64/kernel/cpu-reset.h | 2 +-
arch/arm64/kernel/cpufeature.c | 3 +-
arch/arm64/kernel/hibernate.c | 20 +++-------
arch/arm64/kernel/insn.c | 2 +-
arch/arm64/kernel/psci.c | 3 +-
arch/arm64/kernel/setup.c | 9 +++--
arch/arm64/kernel/smp_spin_table.c | 3 +-
arch/arm64/kernel/vdso.c | 8 +++-
arch/arm64/mm/Makefile | 2 +
arch/arm64/mm/init.c | 12 +++---
arch/arm64/mm/kasan_init.c | 22 +++++++----
arch/arm64/mm/mmu.c | 33 ++++++++++------
arch/arm64/mm/physaddr.c | 30 ++++++++++++++
arch/x86/Kconfig | 1 +
drivers/firmware/psci.c | 2 +-
include/linux/mm.h | 4 ++
kernel/kexec_core.c | 2 +-
lib/Kconfig.debug | 5 ++-
mm/cma.c | 15 +++----
mm/kasan/kasan_init.c | 15 +++----
mm/usercopy.c | 4 +-
27 files changed, 180 insertions(+), 99 deletions(-)
create mode 100644 arch/arm64/mm/physaddr.c
--
2.7.4
^ permalink raw reply
* [PATCHv6 01/11] lib/Kconfig.debug: Add ARCH_HAS_DEBUG_VIRTUAL
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
DEBUG_VIRTUAL currently depends on DEBUG_KERNEL && X86. arm64 is getting
the same support. Rather than add a list of architectures, switch this
to ARCH_HAS_DEBUG_VIRTUAL and let architectures select it as
appropriate.
Acked-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Suggested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
arch/x86/Kconfig | 1 +
lib/Kconfig.debug | 5 ++++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e487493..f1d4e8f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -46,6 +46,7 @@ config X86
select ARCH_CLOCKSOURCE_DATA
select ARCH_DISCARD_MEMBLOCK
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
+ select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_ELF_RANDOMIZE
select ARCH_HAS_FAST_MULTIPLIER
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index b06848a..2aed316 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -622,9 +622,12 @@ config DEBUG_VM_PGFLAGS
If unsure, say N.
+config ARCH_HAS_DEBUG_VIRTUAL
+ bool
+
config DEBUG_VIRTUAL
bool "Debug VM translations"
- depends on DEBUG_KERNEL && X86
+ depends on DEBUG_KERNEL && ARCH_HAS_DEBUG_VIRTUAL
help
Enable some costly sanity checks in virtual to page code. This can
catch mistakes with virt_to_page() and friends.
--
2.7.4
^ permalink raw reply related
* [PATCHv6 02/11] mm/cma: Cleanup highmem check
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
6b101e2a3ce4 ("mm/CMA: fix boot regression due to physical address of
high_memory") added checks to use __pa_nodebug on x86 since
CONFIG_DEBUG_VIRTUAL complains about high_memory not being linearlly
mapped. arm64 is now getting support for CONFIG_DEBUG_VIRTUAL as well.
Rather than add an explosion of arches to the #ifdef, switch to an
alternate method to calculate the physical start of highmem using
the page before highmem starts. This avoids the need for the #ifdef and
extra __pa_nodebug calls.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
mm/cma.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/mm/cma.c b/mm/cma.c
index c960459..94b3460 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -235,18 +235,13 @@ int __init cma_declare_contiguous(phys_addr_t base,
phys_addr_t highmem_start;
int ret = 0;
-#ifdef CONFIG_X86
/*
- * high_memory isn't direct mapped memory so retrieving its physical
- * address isn't appropriate. But it would be useful to check the
- * physical address of the highmem boundary so it's justifiable to get
- * the physical address from it. On x86 there is a validation check for
- * this case, so the following workaround is needed to avoid it.
+ * We can't use __pa(high_memory) directly, since high_memory
+ * isn't a valid direct map VA, and DEBUG_VIRTUAL will (validly)
+ * complain. Find the boundary by adding one to the last valid
+ * address.
*/
- highmem_start = __pa_nodebug(high_memory);
-#else
- highmem_start = __pa(high_memory);
-#endif
+ highmem_start = __pa(high_memory - 1) + 1;
pr_debug("%s(size %pa, base %pa, limit %pa alignment %pa)\n",
__func__, &size, &base, &limit, &alignment);
--
2.7.4
^ permalink raw reply related
* [PATCHv6 03/11] arm64: Move some macros under #ifndef __ASSEMBLY__
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
Several macros for various x_to_y exist outside the bounds of an
__ASSEMBLY__ guard. Move them in preparation for support for
CONFIG_DEBUG_VIRTUAL.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
arch/arm64/include/asm/memory.h | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index bfe6328..f80a8e4 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -102,25 +102,6 @@
#endif
/*
- * Physical vs virtual RAM address space conversion. These are
- * private definitions which should NOT be used outside memory.h
- * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
- */
-#define __virt_to_phys(x) ({ \
- phys_addr_t __x = (phys_addr_t)(x); \
- __x & BIT(VA_BITS - 1) ? (__x & ~PAGE_OFFSET) + PHYS_OFFSET : \
- (__x - kimage_voffset); })
-
-#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
-#define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset))
-
-/*
- * Convert a page to/from a physical address
- */
-#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
-#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
-
-/*
* Memory types available.
*/
#define MT_DEVICE_nGnRnE 0
@@ -187,6 +168,25 @@ static inline unsigned long kaslr_offset(void)
#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
/*
+ * Physical vs virtual RAM address space conversion. These are
+ * private definitions which should NOT be used outside memory.h
+ * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
+ */
+#define __virt_to_phys(x) ({ \
+ phys_addr_t __x = (phys_addr_t)(x); \
+ __x & BIT(VA_BITS - 1) ? (__x & ~PAGE_OFFSET) + PHYS_OFFSET : \
+ (__x - kimage_voffset); })
+
+#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
+#define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset))
+
+/*
+ * Convert a page to/from a physical address
+ */
+#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
+#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
+
+/*
* Note: Drivers should NOT use these. They are the wrong
* translation for translating DMA addresses. Use the driver
* DMA support - see dma-mapping.h.
--
2.7.4
^ permalink raw reply related
* [PATCHv6 04/11] arm64: Add cast for virt_to_pfn
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
virt_to_pfn lacks a cast at the top level. Don't rely on __virt_to_phys
and explicitly cast to unsigned long.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
arch/arm64/include/asm/memory.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index f80a8e4..cd6e3ee 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -209,7 +209,7 @@ static inline void *phys_to_virt(phys_addr_t x)
#define __pa(x) __virt_to_phys((unsigned long)(x))
#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys(x))
+#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys((unsigned long)(x)))
/*
* virt_to_page(k) convert a _valid_ virtual address to struct page *
--
2.7.4
^ permalink raw reply related
* [PATCHv6 05/11] mm: Introduce lm_alias
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
Certain architectures may have the kernel image mapped separately to
alias the linear map. Introduce a macro lm_alias to translate a kernel
image symbol into its linear alias. This is used in part with work to
add CONFIG_DEBUG_VIRTUAL support for arm64.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
include/linux/mm.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fe6b403..5dc9c46 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -76,6 +76,10 @@ extern int mmap_rnd_compat_bits __read_mostly;
#define page_to_virt(x) __va(PFN_PHYS(page_to_pfn(x)))
#endif
+#ifndef lm_alias
+#define lm_alias(x) __va(__pa_symbol(x))
+#endif
+
/*
* To prevent common memory management code establishing
* a zero page mapping on a read fault.
--
2.7.4
^ permalink raw reply related
* [PATCHv6 06/11] arm64: Use __pa_symbol for kernel symbols
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
__pa_symbol is technically the marcro that should be used for kernel
symbols. Switch to this as a pre-requisite for DEBUG_VIRTUAL which
will do bounds checking.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
arch/arm64/include/asm/kvm_mmu.h | 4 ++--
arch/arm64/include/asm/memory.h | 1 +
arch/arm64/include/asm/mmu_context.h | 6 +++---
arch/arm64/include/asm/pgtable.h | 2 +-
arch/arm64/kernel/acpi_parking_protocol.c | 3 ++-
arch/arm64/kernel/cpu-reset.h | 2 +-
arch/arm64/kernel/cpufeature.c | 3 ++-
arch/arm64/kernel/hibernate.c | 20 +++++--------------
arch/arm64/kernel/insn.c | 2 +-
arch/arm64/kernel/psci.c | 3 ++-
arch/arm64/kernel/setup.c | 9 +++++----
arch/arm64/kernel/smp_spin_table.c | 3 ++-
arch/arm64/kernel/vdso.c | 8 ++++++--
arch/arm64/mm/init.c | 12 ++++++-----
arch/arm64/mm/kasan_init.c | 22 ++++++++++++++-------
arch/arm64/mm/mmu.c | 33 ++++++++++++++++++++-----------
16 files changed, 76 insertions(+), 57 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6f72fe8..55772c1 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -47,7 +47,7 @@
* If the page is in the bottom half, we have to use the top half. If
* the page is in the top half, we have to use the bottom half:
*
- * T = __virt_to_phys(__hyp_idmap_text_start)
+ * T = __pa_symbol(__hyp_idmap_text_start)
* if (T & BIT(VA_BITS - 1))
* HYP_VA_MIN = 0 //idmap in upper half
* else
@@ -271,7 +271,7 @@ static inline void __kvm_flush_dcache_pud(pud_t pud)
kvm_flush_dcache_to_poc(page_address(page), PUD_SIZE);
}
-#define kvm_virt_to_phys(x) __virt_to_phys((unsigned long)(x))
+#define kvm_virt_to_phys(x) __pa_symbol(x)
void kvm_set_way_flush(struct kvm_vcpu *vcpu);
void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled);
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index cd6e3ee..0ff237a 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -210,6 +210,7 @@ static inline void *phys_to_virt(phys_addr_t x)
#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys((unsigned long)(x)))
+#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
/*
* virt_to_page(k) convert a _valid_ virtual address to struct page *
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index 0363fe8..63e9982 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -45,7 +45,7 @@ static inline void contextidr_thread_switch(struct task_struct *next)
*/
static inline void cpu_set_reserved_ttbr0(void)
{
- unsigned long ttbr = virt_to_phys(empty_zero_page);
+ unsigned long ttbr = __pa_symbol(empty_zero_page);
write_sysreg(ttbr, ttbr0_el1);
isb();
@@ -114,7 +114,7 @@ static inline void cpu_install_idmap(void)
local_flush_tlb_all();
cpu_set_idmap_tcr_t0sz();
- cpu_switch_mm(idmap_pg_dir, &init_mm);
+ cpu_switch_mm(lm_alias(idmap_pg_dir), &init_mm);
}
/*
@@ -129,7 +129,7 @@ static inline void cpu_replace_ttbr1(pgd_t *pgd)
phys_addr_t pgd_phys = virt_to_phys(pgd);
- replace_phys = (void *)virt_to_phys(idmap_cpu_replace_ttbr1);
+ replace_phys = (void *)__pa_symbol(idmap_cpu_replace_ttbr1);
cpu_install_idmap();
replace_phys(pgd_phys);
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index ffbb9a5..090134c 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -52,7 +52,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
* for zero-mapped memory areas etc..
*/
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) pfn_to_page(PHYS_PFN(__pa(empty_zero_page)))
+#define ZERO_PAGE(vaddr) phys_to_page(__pa_symbol(empty_zero_page))
#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte))
diff --git a/arch/arm64/kernel/acpi_parking_protocol.c b/arch/arm64/kernel/acpi_parking_protocol.c
index a32b401..1f5655c 100644
--- a/arch/arm64/kernel/acpi_parking_protocol.c
+++ b/arch/arm64/kernel/acpi_parking_protocol.c
@@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/acpi.h>
+#include <linux/mm.h>
#include <linux/types.h>
#include <asm/cpu_ops.h>
@@ -109,7 +110,7 @@ static int acpi_parking_protocol_cpu_boot(unsigned int cpu)
* that read this address need to convert this address to the
* Boot-Loader's endianness before jumping.
*/
- writeq_relaxed(__pa(secondary_entry), &mailbox->entry_point);
+ writeq_relaxed(__pa_symbol(secondary_entry), &mailbox->entry_point);
writel_relaxed(cpu_entry->gic_cpu_id, &mailbox->cpu_id);
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h
index d4e9ecb..6c2b1b4 100644
--- a/arch/arm64/kernel/cpu-reset.h
+++ b/arch/arm64/kernel/cpu-reset.h
@@ -24,7 +24,7 @@ static inline void __noreturn cpu_soft_restart(unsigned long el2_switch,
el2_switch = el2_switch && !is_kernel_in_hyp_mode() &&
is_hyp_mode_available();
- restart = (void *)virt_to_phys(__cpu_soft_restart);
+ restart = (void *)__pa_symbol(__cpu_soft_restart);
cpu_install_idmap();
restart(el2_switch, entry, arg0, arg1, arg2);
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index fdf8f04..0ec6a1e 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -23,6 +23,7 @@
#include <linux/sort.h>
#include <linux/stop_machine.h>
#include <linux/types.h>
+#include <linux/mm.h>
#include <asm/cpu.h>
#include <asm/cpufeature.h>
#include <asm/cpu_ops.h>
@@ -737,7 +738,7 @@ static bool runs_at_el2(const struct arm64_cpu_capabilities *entry, int __unused
static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry,
int __unused)
{
- phys_addr_t idmap_addr = virt_to_phys(__hyp_idmap_text_start);
+ phys_addr_t idmap_addr = __pa_symbol(__hyp_idmap_text_start);
/*
* Activate the lower HYP offset only if:
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index fe301cb..3e94a45 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -50,9 +50,6 @@
*/
extern int in_suspend;
-/* Find a symbols alias in the linear map */
-#define LMADDR(x) phys_to_virt(virt_to_phys(x))
-
/* Do we need to reset el2? */
#define el2_reset_needed() (is_hyp_mode_available() && !is_kernel_in_hyp_mode())
@@ -102,8 +99,8 @@ static inline void arch_hdr_invariants(struct arch_hibernate_hdr_invariants *i)
int pfn_is_nosave(unsigned long pfn)
{
- unsigned long nosave_begin_pfn = virt_to_pfn(&__nosave_begin);
- unsigned long nosave_end_pfn = virt_to_pfn(&__nosave_end - 1);
+ unsigned long nosave_begin_pfn = sym_to_pfn(&__nosave_begin);
+ unsigned long nosave_end_pfn = sym_to_pfn(&__nosave_end - 1);
return (pfn >= nosave_begin_pfn) && (pfn <= nosave_end_pfn);
}
@@ -125,12 +122,12 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
return -EOVERFLOW;
arch_hdr_invariants(&hdr->invariants);
- hdr->ttbr1_el1 = virt_to_phys(swapper_pg_dir);
+ hdr->ttbr1_el1 = __pa_symbol(swapper_pg_dir);
hdr->reenter_kernel = _cpu_resume;
/* We can't use __hyp_get_vectors() because kvm may still be loaded */
if (el2_reset_needed())
- hdr->__hyp_stub_vectors = virt_to_phys(__hyp_stub_vectors);
+ hdr->__hyp_stub_vectors = __pa_symbol(__hyp_stub_vectors);
else
hdr->__hyp_stub_vectors = 0;
@@ -460,7 +457,6 @@ int swsusp_arch_resume(void)
void *zero_page;
size_t exit_size;
pgd_t *tmp_pg_dir;
- void *lm_restore_pblist;
phys_addr_t phys_hibernate_exit;
void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *,
void *, phys_addr_t, phys_addr_t);
@@ -481,12 +477,6 @@ int swsusp_arch_resume(void)
goto out;
/*
- * Since we only copied the linear map, we need to find restore_pblist's
- * linear map address.
- */
- lm_restore_pblist = LMADDR(restore_pblist);
-
- /*
* We need a zero page that is zero before & after resume in order to
* to break before make on the ttbr1 page tables.
*/
@@ -537,7 +527,7 @@ int swsusp_arch_resume(void)
}
hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1,
- resume_hdr.reenter_kernel, lm_restore_pblist,
+ resume_hdr.reenter_kernel, restore_pblist,
resume_hdr.__hyp_stub_vectors, virt_to_phys(zero_page));
out:
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 94b62c1..682f1a6 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -96,7 +96,7 @@ static void __kprobes *patch_map(void *addr, int fixmap)
if (module && IS_ENABLED(CONFIG_DEBUG_SET_MODULE_RONX))
page = vmalloc_to_page(addr);
else if (!module)
- page = pfn_to_page(PHYS_PFN(__pa(addr)));
+ page = phys_to_page(__pa_symbol(addr));
else
return addr;
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 42816be..e8edbf1 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -20,6 +20,7 @@
#include <linux/smp.h>
#include <linux/delay.h>
#include <linux/psci.h>
+#include <linux/mm.h>
#include <uapi/linux/psci.h>
@@ -45,7 +46,7 @@ static int __init cpu_psci_cpu_prepare(unsigned int cpu)
static int cpu_psci_cpu_boot(unsigned int cpu)
{
- int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_entry));
+ int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa_symbol(secondary_entry));
if (err)
pr_err("failed to boot CPU%d (%d)\n", cpu, err);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index b051367..669fc9f 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -42,6 +42,7 @@
#include <linux/of_fdt.h>
#include <linux/efi.h>
#include <linux/psci.h>
+#include <linux/mm.h>
#include <asm/acpi.h>
#include <asm/fixmap.h>
@@ -199,10 +200,10 @@ static void __init request_standard_resources(void)
struct memblock_region *region;
struct resource *res;
- kernel_code.start = virt_to_phys(_text);
- kernel_code.end = virt_to_phys(__init_begin - 1);
- kernel_data.start = virt_to_phys(_sdata);
- kernel_data.end = virt_to_phys(_end - 1);
+ kernel_code.start = __pa_symbol(_text);
+ kernel_code.end = __pa_symbol(__init_begin - 1);
+ kernel_data.start = __pa_symbol(_sdata);
+ kernel_data.end = __pa_symbol(_end - 1);
for_each_memblock(memory, region) {
res = alloc_bootmem_low(sizeof(*res));
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 9a00eee..9303465 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/smp.h>
#include <linux/types.h>
+#include <linux/mm.h>
#include <asm/cacheflush.h>
#include <asm/cpu_ops.h>
@@ -98,7 +99,7 @@ static int smp_spin_table_cpu_prepare(unsigned int cpu)
* boot-loader's endianess before jumping. This is mandated by
* the boot protocol.
*/
- writeq_relaxed(__pa(secondary_holding_pen), release_addr);
+ writeq_relaxed(__pa_symbol(secondary_holding_pen), release_addr);
__flush_dcache_area((__force void *)release_addr,
sizeof(*release_addr));
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index a2c2478..41b6e31 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -123,6 +123,7 @@ static int __init vdso_init(void)
{
int i;
struct page **vdso_pagelist;
+ unsigned long pfn;
if (memcmp(&vdso_start, "\177ELF", 4)) {
pr_err("vDSO is not a valid ELF object!\n");
@@ -140,11 +141,14 @@ static int __init vdso_init(void)
return -ENOMEM;
/* Grab the vDSO data page. */
- vdso_pagelist[0] = pfn_to_page(PHYS_PFN(__pa(vdso_data)));
+ vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data));
+
/* Grab the vDSO code pages. */
+ pfn = sym_to_pfn(&vdso_start);
+
for (i = 0; i < vdso_pages; i++)
- vdso_pagelist[i + 1] = pfn_to_page(PHYS_PFN(__pa(&vdso_start)) + i);
+ vdso_pagelist[i + 1] = pfn_to_page(pfn + i);
vdso_spec[0].pages = &vdso_pagelist[0];
vdso_spec[1].pages = &vdso_pagelist[1];
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 212c4d1..8af2ad6 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -36,6 +36,7 @@
#include <linux/efi.h>
#include <linux/swiotlb.h>
#include <linux/vmalloc.h>
+#include <linux/mm.h>
#include <asm/boot.h>
#include <asm/fixmap.h>
@@ -209,8 +210,8 @@ void __init arm64_memblock_init(void)
* linear mapping. Take care not to clip the kernel which may be
* high in memory.
*/
- memblock_remove(max_t(u64, memstart_addr + linear_region_size, __pa(_end)),
- ULLONG_MAX);
+ memblock_remove(max_t(u64, memstart_addr + linear_region_size,
+ __pa_symbol(_end)), ULLONG_MAX);
if (memstart_addr + linear_region_size < memblock_end_of_DRAM()) {
/* ensure that memstart_addr remains sufficiently aligned */
memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size,
@@ -225,7 +226,7 @@ void __init arm64_memblock_init(void)
*/
if (memory_limit != (phys_addr_t)ULLONG_MAX) {
memblock_mem_limit_remove_map(memory_limit);
- memblock_add(__pa(_text), (u64)(_end - _text));
+ memblock_add(__pa_symbol(_text), (u64)(_end - _text));
}
if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
@@ -278,7 +279,7 @@ void __init arm64_memblock_init(void)
* Register the kernel text, kernel data, initrd, and initial
* pagetables with memblock.
*/
- memblock_reserve(__pa(_text), _end - _text);
+ memblock_reserve(__pa_symbol(_text), _end - _text);
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start) {
memblock_reserve(initrd_start, initrd_end - initrd_start);
@@ -483,7 +484,8 @@ void __init mem_init(void)
void free_initmem(void)
{
- free_reserved_area(__va(__pa(__init_begin)), __va(__pa(__init_end)),
+ free_reserved_area(lm_alias(__init_begin),
+ lm_alias(__init_end),
0, "unused kernel");
/*
* Unmap the __init region but leave the VM area in place. This
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index 757009d..201d918 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/memblock.h>
#include <linux/start_kernel.h>
+#include <linux/mm.h>
#include <asm/mmu_context.h>
#include <asm/kernel-pgtable.h>
@@ -26,6 +27,13 @@
static pgd_t tmp_pg_dir[PTRS_PER_PGD] __initdata __aligned(PGD_SIZE);
+/*
+ * The p*d_populate functions call virt_to_phys implicitly so they can't be used
+ * directly on kernel symbols (bm_p*d). All the early functions are called too
+ * early to use lm_alias so __p*d_populate functions must be used to populate
+ * with the physical address from __pa_symbol.
+ */
+
static void __init kasan_early_pte_populate(pmd_t *pmd, unsigned long addr,
unsigned long end)
{
@@ -33,12 +41,12 @@ static void __init kasan_early_pte_populate(pmd_t *pmd, unsigned long addr,
unsigned long next;
if (pmd_none(*pmd))
- pmd_populate_kernel(&init_mm, pmd, kasan_zero_pte);
+ __pmd_populate(pmd, __pa_symbol(kasan_zero_pte), PMD_TYPE_TABLE);
pte = pte_offset_kimg(pmd, addr);
do {
next = addr + PAGE_SIZE;
- set_pte(pte, pfn_pte(virt_to_pfn(kasan_zero_page),
+ set_pte(pte, pfn_pte(sym_to_pfn(kasan_zero_page),
PAGE_KERNEL));
} while (pte++, addr = next, addr != end && pte_none(*pte));
}
@@ -51,7 +59,7 @@ static void __init kasan_early_pmd_populate(pud_t *pud,
unsigned long next;
if (pud_none(*pud))
- pud_populate(&init_mm, pud, kasan_zero_pmd);
+ __pud_populate(pud, __pa_symbol(kasan_zero_pmd), PMD_TYPE_TABLE);
pmd = pmd_offset_kimg(pud, addr);
do {
@@ -68,7 +76,7 @@ static void __init kasan_early_pud_populate(pgd_t *pgd,
unsigned long next;
if (pgd_none(*pgd))
- pgd_populate(&init_mm, pgd, kasan_zero_pud);
+ __pgd_populate(pgd, __pa_symbol(kasan_zero_pud), PUD_TYPE_TABLE);
pud = pud_offset_kimg(pgd, addr);
do {
@@ -148,7 +156,7 @@ void __init kasan_init(void)
*/
memcpy(tmp_pg_dir, swapper_pg_dir, sizeof(tmp_pg_dir));
dsb(ishst);
- cpu_replace_ttbr1(tmp_pg_dir);
+ cpu_replace_ttbr1(lm_alias(tmp_pg_dir));
clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
@@ -199,10 +207,10 @@ void __init kasan_init(void)
*/
for (i = 0; i < PTRS_PER_PTE; i++)
set_pte(&kasan_zero_pte[i],
- pfn_pte(virt_to_pfn(kasan_zero_page), PAGE_KERNEL_RO));
+ pfn_pte(sym_to_pfn(kasan_zero_page), PAGE_KERNEL_RO));
memset(kasan_zero_page, 0, PAGE_SIZE);
- cpu_replace_ttbr1(swapper_pg_dir);
+ cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
/* At this point kasan is fully initialized. Enable error messages */
init_task.kasan_depth = 0;
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 17243e4..a434157 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -28,6 +28,7 @@
#include <linux/memblock.h>
#include <linux/fs.h>
#include <linux/io.h>
+#include <linux/mm.h>
#include <asm/barrier.h>
#include <asm/cputype.h>
@@ -359,8 +360,8 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt,
static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
{
- unsigned long kernel_start = __pa(_text);
- unsigned long kernel_end = __pa(__init_begin);
+ unsigned long kernel_start = __pa_symbol(_text);
+ unsigned long kernel_end = __pa_symbol(__init_begin);
/*
* Take care not to create a writable alias for the
@@ -427,14 +428,14 @@ void mark_rodata_ro(void)
unsigned long section_size;
section_size = (unsigned long)_etext - (unsigned long)_text;
- create_mapping_late(__pa(_text), (unsigned long)_text,
+ create_mapping_late(__pa_symbol(_text), (unsigned long)_text,
section_size, PAGE_KERNEL_ROX);
/*
* mark .rodata as read only. Use __init_begin rather than __end_rodata
* to cover NOTES and EXCEPTION_TABLE.
*/
section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata;
- create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata,
+ create_mapping_late(__pa_symbol(__start_rodata), (unsigned long)__start_rodata,
section_size, PAGE_KERNEL_RO);
/* flush the TLBs after updating live kernel mappings */
@@ -446,7 +447,7 @@ void mark_rodata_ro(void)
static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end,
pgprot_t prot, struct vm_struct *vma)
{
- phys_addr_t pa_start = __pa(va_start);
+ phys_addr_t pa_start = __pa_symbol(va_start);
unsigned long size = va_end - va_start;
BUG_ON(!PAGE_ALIGNED(pa_start));
@@ -494,7 +495,7 @@ static void __init map_kernel(pgd_t *pgd)
*/
BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
set_pud(pud_set_fixmap_offset(pgd, FIXADDR_START),
- __pud(__pa(bm_pmd) | PUD_TYPE_TABLE));
+ __pud(__pa_symbol(bm_pmd) | PUD_TYPE_TABLE));
pud_clear_fixmap();
} else {
BUG();
@@ -525,7 +526,7 @@ void __init paging_init(void)
*/
cpu_replace_ttbr1(__va(pgd_phys));
memcpy(swapper_pg_dir, pgd, PAGE_SIZE);
- cpu_replace_ttbr1(swapper_pg_dir);
+ cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
pgd_clear_fixmap();
memblock_free(pgd_phys, PAGE_SIZE);
@@ -534,7 +535,7 @@ void __init paging_init(void)
* We only reuse the PGD from the swapper_pg_dir, not the pud + pmd
* allocated with it.
*/
- memblock_free(__pa(swapper_pg_dir) + PAGE_SIZE,
+ memblock_free(__pa_symbol(swapper_pg_dir) + PAGE_SIZE,
SWAPPER_DIR_SIZE - PAGE_SIZE);
}
@@ -645,6 +646,12 @@ static inline pte_t * fixmap_pte(unsigned long addr)
return &bm_pte[pte_index(addr)];
}
+/*
+ * The p*d_populate functions call virt_to_phys implicitly so they can't be used
+ * directly on kernel symbols (bm_p*d). This function is called too early to use
+ * lm_alias so __p*d_populate functions must be used to populate with the
+ * physical address from __pa_symbol.
+ */
void __init early_fixmap_init(void)
{
pgd_t *pgd;
@@ -654,7 +661,7 @@ void __init early_fixmap_init(void)
pgd = pgd_offset_k(addr);
if (CONFIG_PGTABLE_LEVELS > 3 &&
- !(pgd_none(*pgd) || pgd_page_paddr(*pgd) == __pa(bm_pud))) {
+ !(pgd_none(*pgd) || pgd_page_paddr(*pgd) == __pa_symbol(bm_pud))) {
/*
* We only end up here if the kernel mapping and the fixmap
* share the top level pgd entry, which should only happen on
@@ -663,12 +670,14 @@ void __init early_fixmap_init(void)
BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
pud = pud_offset_kimg(pgd, addr);
} else {
- pgd_populate(&init_mm, pgd, bm_pud);
+ if (pgd_none(*pgd))
+ __pgd_populate(pgd, __pa_symbol(bm_pud), PUD_TYPE_TABLE);
pud = fixmap_pud(addr);
}
- pud_populate(&init_mm, pud, bm_pmd);
+ if (pud_none(*pud))
+ __pud_populate(pud, __pa_symbol(bm_pmd), PMD_TYPE_TABLE);
pmd = fixmap_pmd(addr);
- pmd_populate_kernel(&init_mm, pmd, bm_pte);
+ __pmd_populate(pmd, __pa_symbol(bm_pte), PMD_TYPE_TABLE);
/*
* The boot-ioremap range spans multiple pmds, for which
--
2.7.4
^ permalink raw reply related
* [PATCHv6 07/11] drivers: firmware: psci: Use __pa_symbol for kernel symbol
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
__pa_symbol is technically the macro that should be used for kernel
symbols. Switch to this as a pre-requisite for DEBUG_VIRTUAL which
will do bounds checking.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
drivers/firmware/psci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 6c60a50..66a8793 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -383,7 +383,7 @@ static int psci_suspend_finisher(unsigned long index)
u32 *state = __this_cpu_read(psci_power_state);
return psci_ops.cpu_suspend(state[index - 1],
- virt_to_phys(cpu_resume));
+ __pa_symbol(cpu_resume));
}
int psci_cpu_suspend_enter(unsigned long index)
--
2.7.4
^ permalink raw reply related
* [PATCHv6 08/11] kexec: Switch to __pa_symbol
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
__pa_symbol is the correct api to get the physical address of kernel
symbols. Switch to it to allow for better debug checking.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
kernel/kexec_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 5617cc4..a01974e 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -1399,7 +1399,7 @@ void __weak arch_crash_save_vmcoreinfo(void)
phys_addr_t __weak paddr_vmcoreinfo_note(void)
{
- return __pa((unsigned long)(char *)&vmcoreinfo_note);
+ return __pa_symbol((unsigned long)(char *)&vmcoreinfo_note);
}
static int __init crash_save_vmcoreinfo_init(void)
--
2.7.4
^ permalink raw reply related
* [PATCHv6 09/11] mm/kasan: Switch to using __pa_symbol and lm_alias
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
__pa_symbol is the correct API to find the physical address of symbols.
Switch to it to allow for debugging APIs to work correctly. Other
functions such as p*d_populate may call __pa internally. Ensure that the
address passed is in the linear region by calling lm_alias.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
mm/kasan/kasan_init.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/mm/kasan/kasan_init.c b/mm/kasan/kasan_init.c
index 3f9a41c..31238da 100644
--- a/mm/kasan/kasan_init.c
+++ b/mm/kasan/kasan_init.c
@@ -15,6 +15,7 @@
#include <linux/kasan.h>
#include <linux/kernel.h>
#include <linux/memblock.h>
+#include <linux/mm.h>
#include <linux/pfn.h>
#include <asm/page.h>
@@ -49,7 +50,7 @@ static void __init zero_pte_populate(pmd_t *pmd, unsigned long addr,
pte_t *pte = pte_offset_kernel(pmd, addr);
pte_t zero_pte;
- zero_pte = pfn_pte(PFN_DOWN(__pa(kasan_zero_page)), PAGE_KERNEL);
+ zero_pte = pfn_pte(PFN_DOWN(__pa_symbol(kasan_zero_page)), PAGE_KERNEL);
zero_pte = pte_wrprotect(zero_pte);
while (addr + PAGE_SIZE <= end) {
@@ -69,7 +70,7 @@ static void __init zero_pmd_populate(pud_t *pud, unsigned long addr,
next = pmd_addr_end(addr, end);
if (IS_ALIGNED(addr, PMD_SIZE) && end - addr >= PMD_SIZE) {
- pmd_populate_kernel(&init_mm, pmd, kasan_zero_pte);
+ pmd_populate_kernel(&init_mm, pmd, lm_alias(kasan_zero_pte));
continue;
}
@@ -92,9 +93,9 @@ static void __init zero_pud_populate(pgd_t *pgd, unsigned long addr,
if (IS_ALIGNED(addr, PUD_SIZE) && end - addr >= PUD_SIZE) {
pmd_t *pmd;
- pud_populate(&init_mm, pud, kasan_zero_pmd);
+ pud_populate(&init_mm, pud, lm_alias(kasan_zero_pmd));
pmd = pmd_offset(pud, addr);
- pmd_populate_kernel(&init_mm, pmd, kasan_zero_pte);
+ pmd_populate_kernel(&init_mm, pmd, lm_alias(kasan_zero_pte));
continue;
}
@@ -135,11 +136,11 @@ void __init kasan_populate_zero_shadow(const void *shadow_start,
* puds,pmds, so pgd_populate(), pud_populate()
* is noops.
*/
- pgd_populate(&init_mm, pgd, kasan_zero_pud);
+ pgd_populate(&init_mm, pgd, lm_alias(kasan_zero_pud));
pud = pud_offset(pgd, addr);
- pud_populate(&init_mm, pud, kasan_zero_pmd);
+ pud_populate(&init_mm, pud, lm_alias(kasan_zero_pmd));
pmd = pmd_offset(pud, addr);
- pmd_populate_kernel(&init_mm, pmd, kasan_zero_pte);
+ pmd_populate_kernel(&init_mm, pmd, lm_alias(kasan_zero_pte));
continue;
}
--
2.7.4
^ permalink raw reply related
* [PATCHv6 10/11] mm/usercopy: Switch to using lm_alias
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>
The usercopy checking code currently calls __va(__pa(...)) to check for
aliases on symbols. Switch to using lm_alias instead.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
mm/usercopy.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mm/usercopy.c b/mm/usercopy.c
index 3c8da0a..8345299 100644
--- a/mm/usercopy.c
+++ b/mm/usercopy.c
@@ -108,13 +108,13 @@ static inline const char *check_kernel_text_object(const void *ptr,
* __pa() is not just the reverse of __va(). This can be detected
* and checked:
*/
- textlow_linear = (unsigned long)__va(__pa(textlow));
+ textlow_linear = (unsigned long)lm_alias(textlow);
/* No different mapping: we're done. */
if (textlow_linear == textlow)
return NULL;
/* Check the secondary mapping... */
- texthigh_linear = (unsigned long)__va(__pa(texthigh));
+ texthigh_linear = (unsigned long)lm_alias(texthigh);
if (overlaps(ptr, n, textlow_linear, texthigh_linear))
return "<linear kernel text>";
--
2.7.4
^ permalink raw reply related
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