* Re: [PATCH v2 1/3] ARM: dts: imx6qdl-apalis: Do not rely on DDC I2C bus bitbang for HDMI
From: maitysanchayan-Re5JQEeQqe8AvxtiuMwx3w @ 2016-11-08 17:33 UTC (permalink / raw)
To: Shawn Guo
Cc: Vladimir Zapolskiy, marcel.ziswiler-2KBjVHiyJgBBDgjK7y7TUQ,
stefan-XLVq0VzYD2Y,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Philipp Zabel
In-Reply-To: <3d2b6dfd-c03c-e635-8dc1-2dc9ac454f5a-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
Hello Shawn,
On 16-10-22 15:43:04, Vladimir Zapolskiy wrote:
> Hi Shawn,
>
> On 10/22/2016 06:25 AM, Shawn Guo wrote:
> > On Mon, Sep 19, 2016 at 10:41:51AM +0530, Sanchayan Maity wrote:
> > > Remove the use of DDC I2C bus bitbang to support reading of EDID
> > > and rely on support from internal HDMI I2C master controller instead.
> > > As a result remove the device tree property ddc-i2c-bus.
> > >
> > > Signed-off-by: Sanchayan Maity <maitysanchayan-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >
> > I think that the dw-hdmi i2c support [1] is a prerequisite of this
> > patch. I do not see it lands on v4.9-rc1. Or am I missing something?
> >
> > Shawn
> >
> > [1] https://patchwork.kernel.org/patch/9296883/
> >
>
> I'm adding Philipp to Cc, since he is the last one who tested the change
> and helped me to push the change to the mainline:
>
> https://lists.freedesktop.org/archives/dri-devel/2016-September/118569.html
>
> The problem is that there is no official DW HDMI bridge maintainer, may be
> you can review the change, and if you find it satisfactory push it through
> ARM/iMX tree.
Shawn, is it okay if that patch goes through your ARM/iMX tree?
- Sanchayan.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v8 3/3] fpga: Add support for Lattice iCE40 FPGAs
From: Joel Holdsworth @ 2016-11-08 17:30 UTC (permalink / raw)
To: Moritz Fischer, Marek Vasut
Cc: Alan Tull, Geert Uytterhoeven, Rob Herring, Devicetree List,
Linux Kernel Mailing List, linux-spi-u79uwXL29TY76Z2rM5mHXA,
Clifford Wolf
In-Reply-To: <CAAtXAHe_pz=oUpeP+t-Fy0z88LMmTeSffkD2Cbun3r+uTnmGYw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
>>> On the whole, I don't think the zero-length transfers are too
>>> egregiously bad, and all the alternatives seem worse to me.
>>
>> So why not turn the CS line into GPIO and just toggle the GPIO?
>
> Does that work with *all* SPI controllers?
>
It does not - no. See my other email.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v8 3/3] fpga: Add support for Lattice iCE40 FPGAs
From: Joel Holdsworth @ 2016-11-08 17:13 UTC (permalink / raw)
To: Marek Vasut, atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx,
moritz.fischer-+aYTwkv1SeIAvxtiuMwx3w,
geert-Td1EMuHUCqxL1ZNQvxDV9g, robh-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-spi-u79uwXL29TY76Z2rM5mHXA, clifford-cPpHkPqGOEfk7+2FdBfRIA
In-Reply-To: <4bdba358-db18-48f1-3286-a7a7f4c30215-ynQEQJNshbs@public.gmane.org>
Hi Marek,
>>> Should be this way for the sake of readability, fix globally:
>>>
>>> struct spi_transfer assert_cs_then_reset_delay = {
>>> .cs_change = 1,
>>> .delay_usecs = ICE40_SPI_FPGAMGR_RESET_DELAY
>>> };
>>
>> Sure ok. Personally, I prefer it to be concise, but I'm happy to accept
>> the norms.
>
> I prefer it to be readable :)
>
I'll conform to what you're saying.
But I just want to point out that this...
spi_message_add_tail(&(struct spi_transfer){.cs_change = 1,
.delay_usecs = ICE40_SPI_FPGAMGR_RESET_DELAY}, &message);
...is clearly more readable than this...
struct spi_transfer assert_cs_then_reset_delay = {
.cs_change = 1,
.delay_usecs = ICE40_SPI_FPGAMGR_RESET_DELAY
};
....
<30 lines of unrelated code>
....
spi_message_add_tail(&assert_cs_then_reset_delay, &message);
...in my opinion anyway ;)
>> Previously I had a copy of spi_set_cs copy-pasted into my driver, but in
>> the end I decided to replace that with the zero-length transfers because
>> there's a danger that if the original spi_set_cs() gets rewritten some
>> time, my copy-paste code would leave around some nasty legacy.
>>
>> On the whole, I don't think the zero-length transfers are too
>> egregiously bad, and all the alternatives seem worse to me.
>
> So why not turn the CS line into GPIO and just toggle the GPIO?
>
Two reasons.
1. On some devices the CS line is built into the SPI master, rather than
being a normal GPIO.
2. The SPI driver stack addresses SPI devices in terms of which CS line
they are attached to. You can't have an spi_device in the kernel where
the SPI driver machinery doesn't have a CS line to control. Moreover it
needs to be possible for another SPI device to interrupt a running
transfer to the FPGA. Supporting this involves the SPI framework
managing the CS line.
Thanks
Joel
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Mark Rutland @ 2016-11-08 17:10 UTC (permalink / raw)
To: Arnd Bergmann
Cc: zhichang.yuan, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, olof-nZhT3qVonbNeoWH0uzbU5w,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
lorenzo.pieralisi-5wv7dgnIgG8,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linuxarm-hv44wF8Li93QT0dZR+AlfA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-pci-u79uwXL29TY76Z2rM5mHXA,
linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, liviu.dudau-5wv7dgnIgG8,
zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
john.garry-hv44wF8Li93QT0dZR+AlfA,
gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, marc.zyngier-5wv7dgnIgG8
In-Reply-To: <2368890.jTbyGqYR0M@wuerfel>
On Tue, Nov 08, 2016 at 05:19:54PM +0100, Arnd Bergmann wrote:
> On Tuesday, November 8, 2016 11:49:53 AM CET Mark Rutland wrote:
> > My understanding of ISA (which may be flawed) is that it's not part of
> > the PCI host bridge, but rather on x86 it happens to share the IO space
> > with PCI.
>
> On normal systems, ISA or LPC are behind a PCI bridge device, which
> passes down both low addresses of I/O space and memory space.
Ok, so the use of those address spaces is an artifact of the ISA
controller being a device under the PCI host bridge.
Given we can have multiple domains, surely that implies we can have
multiple ISA controllers in general?
> > I believe that we could theoretically have multiple independent LPC/ISA
> > busses, as is possible with PCI on !x86 systems. If the current ISA code
> > assumes a singleton bus, I think that's something that needs to be fixed
> > up more generically.
> >
> > I don't see why we should need any architecture-specific code here. Why
> > can we not fix up the ISA bus code in drivers/of/address.c such that it
> > handles multiple ISA bus instances, and translates all sub-device
> > addresses relative to the specific bus instance?
>
> I think it is a relatively safe assumption that there is only one
> ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> when talking to an ISA device, so having multiple instances is
> already problematic.
I'm worried that this might not be a safe assumption. Hardware these
days has a habit of pushing the boundaries of our expectations.
If we're going to assume that, I'd certainly want the kernel to verify
that it's true for all instanciated ISA/LPC devices. Otherwise, I can
imagine people relying on (or working around) that assumption in ACPI
tables and DTs, and that will be a nightmare (at best) to untangle in
future.
Thanks,
Mark.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v8 3/3] fpga: Add support for Lattice iCE40 FPGAs
From: Moritz Fischer @ 2016-11-08 17:06 UTC (permalink / raw)
To: Marek Vasut
Cc: Joel Holdsworth, Alan Tull, Geert Uytterhoeven, Rob Herring,
Devicetree List, Linux Kernel Mailing List, linux-spi,
Clifford Wolf
In-Reply-To: <4bdba358-db18-48f1-3286-a7a7f4c30215@denx.de>
Marek,
On Mon, Nov 7, 2016 at 10:53 AM, Marek Vasut <marex@denx.de> wrote:
>> On the whole, I don't think the zero-length transfers are too
>> egregiously bad, and all the alternatives seem worse to me.
>
> So why not turn the CS line into GPIO and just toggle the GPIO?
Does that work with *all* SPI controllers?
Cheers,
Moritz
^ permalink raw reply
* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: John Garry @ 2016-11-08 17:05 UTC (permalink / raw)
To: Will Deacon
Cc: zhichang.yuan, mark.rutland, devicetree, lorenzo.pieralisi, benh,
minyard, arnd, catalin.marinas, gabriele.paoloni, zhichang.yuan02,
liviu.dudau, linux-kernel, xuwei5, linuxarm, olof, robh+dt,
zourongrong, linux-serial, linux-pci, bhelgaas, kantyzc,
linux-arm-kernel
In-Reply-To: <20161108164948.GG20591@arm.com>
On 08/11/2016 16:49, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
>> On 08/11/2016 16:12, Will Deacon wrote:
>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>> +static inline void arm64_set_extops(struct extio_ops *ops)
>>>> +{
>>>> + if (ops)
>>>> + WRITE_ONCE(arm64_extio_ops, ops);
>>>
>>> Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
>>> side. Also, what if multiple drivers want to set different ops for distinct
>>> address ranges?
>>
>> I think that the idea here is that we only have possibly one master in the
>> system which offers indirectIO backend, so another one could not possibly
>> re-set this value.
>
> Why is that assumption valid, and why does WRITE_ONCE help there? It's not
> ONCE as in WARN_ONCE, more ONCE as in exactly-once-per-invocation.
It's only valid based on the inherent assumption that all indirectIO is
redirected to one backend master, i.e. LPC driver.
Anyway, right, I don't think that WRITE_ONCE is correct. Zhichang was
looking for something which would only allow the pointer to be written
once ever.
>
>>>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>>>> new file mode 100644
>>>> index 0000000..647b3fa
>>>> --- /dev/null
>>>> +++ b/arch/arm64/kernel/extio.c
>>>> @@ -0,0 +1,27 @@
>>>> +/*
>>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License version 2 as
>>>> + * published by the Free Software Foundation.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>>> + * GNU General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public License
>>>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>>>> + */
>>>> +
>>>> +#include <linux/io.h>
>>>> +
>>>> +struct extio_ops *arm64_extio_ops;
>>>> +
>>>> +
>>>> +BUILD_EXTIO(b, u8)
>>>> +
>>>> +BUILD_EXTIO(w, u16)
>>>> +
>>>> +BUILD_EXTIO(l, u32)
>>>
>>> Is there no way to make this slightly more generic, so that it can be
>>> re-used elsewhere? For example, if struct extio_ops was common, then
>>> you could have the singleton (which maybe should be an interval tree?),
>>> type definition, setter function and the BUILD_EXTIO invocations
>>> somewhere generic, rather than squirelled away in the arch backend.
>>>
>> The concern would be that some architecture which uses generic higher-level
>> ISA accessor ops, but have IO space, could be affected.
>
> You're already adding a Kconfig symbol for this stuff, so you can keep
> that if you don't want it on other architectures. I'm just arguing that
> plumbing drivers directly into arch code via arm64_set_extops is not
> something I'm particularly fond of, especially when it looks like it
> could be avoided with a small amount of effort.
We'll check this.
Cheers,
John
>
> Will
>
> .
>
^ permalink raw reply
* Re: [PATCH v4 8/8] iio: envelope-detector: ADC driver based on a DAC and a comparator
From: Peter Rosin @ 2016-11-08 17:03 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jonathan Cameron,
Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <alpine.DEB.2.20.1611081630450.3501@nanos>
On 2016-11-08 16:59, Thomas Gleixner wrote:
> On Tue, 8 Nov 2016, Peter Rosin wrote:
>> +/*
>> + * The envelope_detector_comp_latch function works together with the compare
>> + * interrupt service routine below (envelope_detector_comp_isr) as a latch
>> + * (one-bit memory) for if the interrupt has triggered since last calling
>> + * this function.
>> + * The ..._comp_isr function disables the interrupt so that the cpu does not
>> + * need to service a possible interrupt flood from the comparator when no-one
>> + * cares anyway, and this ..._comp_latch function reenables them again if
>> + * needed.
>> + */
>> +static int envelope_detector_comp_latch(struct envelope *env)
>> +{
>> + int comp;
>> +
>> + spin_lock_irq(&env->comp_lock);
>> + comp = env->comp;
>> + env->comp = 0;
>> + spin_unlock_irq(&env->comp_lock);
>> +
>> + if (!comp)
>> + return 0;
>> +
>> + /*
>> + * The irq was disabled, and is reenabled just now.
>> + * But there might have been a pending irq that
>> + * happened while the irq was disabled that fires
>> + * just as the irq is reenabled. That is not what
>> + * is desired.
>> + */
>> + enable_irq(env->comp_irq);
>> +
>> + /* So, synchronize this possibly pending irq... */
>> + synchronize_irq(env->comp_irq);
>> +
>> + /* ...and redo the whole dance. */
>> + spin_lock_irq(&env->comp_lock);
>> + comp = env->comp;
>> + env->comp = 0;
>> + spin_unlock_irq(&env->comp_lock);
>> +
>> + if (comp)
>> + enable_irq(env->comp_irq);
>
> So you need that whole dance including the delayed work because you cannot
> call iio_write_channel_raw() from hard interrupt context, right?
It's not the "cannot call from hard irq context" that made me do that, it's...
> So you might just register a threaded interrupt handler, which should make
> this whole thing way simpler.
>
> devm_request_threaded_irq(dev, irq, NULL, your_isr, IRQF_ONESHOT, ...);
>
> The core will mask the interrupt line until the threaded handler is
> finished. The threaded handler is invoked with preemption enabled, so you
> can sleep there as long as you want. So you can do everything in your
> handler and the above dance is just not required.
...that I couldn't work out how to reenable a oneshot irq once it had fired,
short of freeing the irq and requesting it again. That seemed entirely
bogus, the driver shouldn't risk losing a resource like that so I don't know
what I didn't see? Or maybe it was that I had a hard time resolving the race
between the irq and the timeout in a nice way. I honestly don't remember
why exactly I abandoned oneshot irqs, but this enable/sync/enable dance
was much nicer than what I came up with for the oneshot irq solution I
originally worked on.
Or maybe I had problems with the possibly pending irq also when using a
oneshot irq, but didn't realize it? That was something I discovered quite
late in the process, some time after moving away from oneshot irqs. Are
pending irqs cleared when requesting (or reenabling, however that is done)
a oneshot irq?
Anyway, I do not want the interrupt to be serviced when no one is interested,
since I'm afraid that nasty input might generate a flood of interrupts that
might disturb other things that the cpu is doing. Which means that I need
to enable/disable the interrupt as needed.
However, what *I* thought Jonathan wanted input on was the part where the
interrupt edge/level is flipped when requesting "inverted" signals in
envelope_store_invert(). That could perhaps be seen as unorthodox and in
need of more eyes?
Cheers,
Peter
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: Will Deacon @ 2016-11-08 16:49 UTC (permalink / raw)
To: John Garry
Cc: zhichang.yuan, mark.rutland, devicetree, lorenzo.pieralisi, benh,
minyard, arnd, catalin.marinas, gabriele.paoloni, zhichang.yuan02,
liviu.dudau, linux-kernel, xuwei5, linuxarm, olof, robh+dt,
zourongrong, linux-serial, linux-pci, bhelgaas, kantyzc,
linux-arm-kernel
In-Reply-To: <8adfe182-4939-479d-6013-25ec40021b20@huawei.com>
On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
> On 08/11/2016 16:12, Will Deacon wrote:
> >On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> >>+static inline void arm64_set_extops(struct extio_ops *ops)
> >>+{
> >>+ if (ops)
> >>+ WRITE_ONCE(arm64_extio_ops, ops);
> >
> >Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
> >side. Also, what if multiple drivers want to set different ops for distinct
> >address ranges?
>
> I think that the idea here is that we only have possibly one master in the
> system which offers indirectIO backend, so another one could not possibly
> re-set this value.
Why is that assumption valid, and why does WRITE_ONCE help there? It's not
ONCE as in WARN_ONCE, more ONCE as in exactly-once-per-invocation.
> >>diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> >>new file mode 100644
> >>index 0000000..647b3fa
> >>--- /dev/null
> >>+++ b/arch/arm64/kernel/extio.c
> >>@@ -0,0 +1,27 @@
> >>+/*
> >>+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> >>+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> >>+ *
> >>+ * This program is free software; you can redistribute it and/or modify
> >>+ * it under the terms of the GNU General Public License version 2 as
> >>+ * published by the Free Software Foundation.
> >>+ *
> >>+ * This program is distributed in the hope that it will be useful,
> >>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> >>+ * GNU General Public License for more details.
> >>+ *
> >>+ * You should have received a copy of the GNU General Public License
> >>+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
> >>+ */
> >>+
> >>+#include <linux/io.h>
> >>+
> >>+struct extio_ops *arm64_extio_ops;
> >>+
> >>+
> >>+BUILD_EXTIO(b, u8)
> >>+
> >>+BUILD_EXTIO(w, u16)
> >>+
> >>+BUILD_EXTIO(l, u32)
> >
> >Is there no way to make this slightly more generic, so that it can be
> >re-used elsewhere? For example, if struct extio_ops was common, then
> >you could have the singleton (which maybe should be an interval tree?),
> >type definition, setter function and the BUILD_EXTIO invocations
> >somewhere generic, rather than squirelled away in the arch backend.
> >
> The concern would be that some architecture which uses generic higher-level
> ISA accessor ops, but have IO space, could be affected.
You're already adding a Kconfig symbol for this stuff, so you can keep
that if you don't want it on other architectures. I'm just arguing that
plumbing drivers directly into arch code via arm64_set_extops is not
something I'm particularly fond of, especially when it looks like it
could be avoided with a small amount of effort.
Will
^ permalink raw reply
* Re: [PATCH v3 00/10] Add DT support for ohci-da8xx
From: Axel Haslam @ 2016-11-08 16:37 UTC (permalink / raw)
To: Alan Stern, Greg KH, Sekhar Nori, Kevin Hilman, David Lechner,
robh+dt
Cc: devicetree, linux-usb, linux-kernel, linux-arm-kernel,
Axel Haslam
In-Reply-To: <20161107203948.28324-1-ahaslam@baylibre.com>
Hi,
On Mon, Nov 7, 2016 at 9:39 PM, Axel Haslam <ahaslam@baylibre.com> wrote:
> The purpose of this patch series is to add DT support for the davinci
> ohci driver.
>
To make it easier to review. I will split the arch/arm and driver
patches into separate series.
Regards
Axel
> To be able to use device tree to probe the driver, we need to remove
> the platform callbacks that are handling vbus and over current.
>
> The first four patches prepare the stage by allowing to use a regulator
> instead of the callbacks.
>
> The next three patches convert the callback users to use a regulator
> instead and then remove the callbacks from the driver and platform code.
>
> Finally, we add device tree bindings and support in the driver.
>
> DEPENDENCIES:
> This series has depends on some patches currently under review
> but mostly accepted:
> 1. [PATCH 0/3] fix ohci phy name [1] (accepted)
> 2. [PATCH/RFC v2 0/3] regulator: handling of error conditions for usb drivers [2] (accepted)
> 3. [PATCH] gpio: davinci: Use unique labels for each gpio chip [3] (review pending)
>
> Also the current davinci baranches soon to be pulled to linux-next:
> davinci-for-v4.10/soc
> davinci-for-v4.10/dt
> davinci-for-v4.10/defconfig
> davinci-for-v4.10/cleanup
>
> A branch with all the dependencies can be found here [4].
>
> Changes form v2->v3
> * drop patches that have been integrated to arch/arm
> * drop regulator patches which will be integrated through regulator tree
> * use of the accepted regulator API to get over current status
> * better patch separation with the use of wrappers
>
> Changes from v1->v2
> * Rebased and added patch to make ohci a separate driver
> * Use a regulator instead of handling Gpios (David Lechner)
> * Add an over current mode to regulator framework
> * Fixed regulator is able to register for and over current irq
> * Added patch by Alexandre to remove build warnings
> * Moved global variables into private hcd structure.
>
> [1] https://lkml.org/lkml/2016/11/2/208
> [2] https://lkml.org/lkml/2016/11/3/188
> [3] http://www.spinics.net/lists/linux-gpio/msg17710.html
> [4] https://github.com/axelhaslamx/linux-axel/commits/ohci-da8xx-dt-v3
>
> Axel Haslam (10):
> USB: ohci: da8xx: use ohci priv data instead of globals
> USB: ohci: da8xx: Prepare to remove platform callbacks
> USB: ohci: da8xx: Allow a regulator to handle VBUS
> ARM: davinci: da830: Handle vbus with a regulator
> ARM: davinci: hawk: Remove vbus and over current gpios
> USB: ohci: da8xx: Remove ohci platform callbacks
> USB: ohci: da8xx: use a flag instead of mask for ocic
> USB: ohci: da8xx: Add devicetree bindings
> USB: ohci: da8xx: Allow probing from DT
> ARM: dts: da850: add usb device node
>
> .../devicetree/bindings/usb/ohci-da8xx.txt | 39 ++++
> arch/arm/boot/dts/da850-lcdk.dts | 8 +
> arch/arm/boot/dts/da850.dtsi | 8 +
> arch/arm/mach-davinci/board-da830-evm.c | 108 ++++-----
> arch/arm/mach-davinci/board-omapl138-hawk.c | 99 +-------
> arch/arm/mach-davinci/include/mach/da8xx.h | 2 +-
> arch/arm/mach-davinci/usb-da8xx.c | 3 +-
> drivers/usb/host/ohci-da8xx.c | 253 +++++++++++++++------
> include/linux/platform_data/usb-davinci.h | 20 --
> 9 files changed, 283 insertions(+), 257 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/usb/ohci-da8xx.txt
>
> --
> 2.10.1
>
^ permalink raw reply
* Re: [PATCH V2 3/4] regulator: pv88080: Update Regulator driver for MFD support
From: Mark Brown @ 2016-11-08 16:37 UTC (permalink / raw)
To: Eric Hyeung Dong Jeong
Cc: LINUX-KERNEL, Liam Girdwood, Alexandre Courbot, DEVICETREE,
LINUX-GPIO, Lee Jones, Linus Walleij, Mark Rutland, Rob Herring,
Support Opensource
In-Reply-To: <8FA4409277D6E54680546B8811D85410029DFAA2EA@NB-EX-MBX01.diasemi.com>
[-- Attachment #1: Type: text/plain, Size: 391 bytes --]
On Tue, Nov 08, 2016 at 05:59:41AM +0000, Eric Hyeung Dong Jeong wrote:
> Thank you for the comments.
> There was an internal request to release driver based on Kernel 3.18 for GPIO and MFD support.
> After that, the code has been kept. I will send a patch again after changes.
Please don't submit code for ancient kernels upstream, we can't merge
anything that isn't for current kernels.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: John Garry @ 2016-11-08 16:33 UTC (permalink / raw)
To: Will Deacon, zhichang.yuan
Cc: mark.rutland, devicetree, lorenzo.pieralisi, benh, minyard, arnd,
catalin.marinas, gabriele.paoloni, zhichang.yuan02, liviu.dudau,
linux-kernel, xuwei5, linuxarm, olof, robh+dt, zourongrong,
linux-serial, linux-pci, bhelgaas, kantyzc, linux-arm-kernel
In-Reply-To: <20161108161245.GD20591@arm.com>
On 08/11/2016 16:12, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>> ---
>> arch/arm64/Kconfig | 6 +++
>> arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>> arch/arm64/include/asm/io.h | 29 +++++++++++++
>> arch/arm64/kernel/Makefile | 1 +
>> arch/arm64/kernel/extio.c | 27 ++++++++++++
>> 5 files changed, 157 insertions(+)
>> create mode 100644 arch/arm64/include/asm/extio.h
>> create mode 100644 arch/arm64/kernel/extio.c
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 969ef88..b44070b 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>> config ARCH_MMAP_RND_COMPAT_BITS_MAX
>> default 16
>>
>> +config ARM64_INDIRECT_PIO
>> + bool "access peripherals with legacy I/O port"
>> + help
>> + Support special accessors for ISA I/O devices. This is needed for
>> + SoCs that do not support standard read/write for the ISA range.
>> +
>> config NO_IOPORT_MAP
>> def_bool y if !PCI
>>
>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>> new file mode 100644
>> index 0000000..6ae0787
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/extio.h
>> @@ -0,0 +1,94 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +struct extio_ops {
>> + unsigned long start;/* inclusive, sys io addr */
>> + unsigned long end;/* inclusive, sys io addr */
>> +
>> + u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
>> + void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>> + size_t dlen);
>> + u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>> + size_t dlen, unsigned int count);
>> + void (*pfouts)(void *devobj, unsigned long ptaddr,
>> + const void *outbuf, size_t dlen,
>> + unsigned int count);
>> + void *devpara;
>> +};
>> +
>> +extern struct extio_ops *arm64_extio_ops;
>> +
>> +#define DECLARE_EXTIO(bw, type) \
>> +extern type in##bw(unsigned long addr); \
>> +extern void out##bw(type value, unsigned long addr); \
>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>> +
>> +#define BUILD_EXTIO(bw, type) \
>> +type in##bw(unsigned long addr) \
>> +{ \
>> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
>> + arm64_extio_ops->end < addr) \
>> + return read##bw(PCI_IOBASE + addr); \
>> + return arm64_extio_ops->pfin ? \
>> + arm64_extio_ops->pfin(arm64_extio_ops->devpara, \
>> + addr, sizeof(type)) : -1; \
>> +} \
>> + \
>> +void out##bw(type value, unsigned long addr) \
>> +{ \
>> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
>> + arm64_extio_ops->end < addr) \
>> + write##bw(value, PCI_IOBASE + addr); \
>> + else \
>> + if (arm64_extio_ops->pfout) \
>> + arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>> + addr, value, sizeof(type)); \
>> +} \
>> + \
>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count) \
>> +{ \
>> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
>> + arm64_extio_ops->end < addr) \
>> + reads##bw(PCI_IOBASE + addr, buffer, count); \
>> + else \
>> + if (arm64_extio_ops->pfins) \
>> + arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>> + addr, buffer, sizeof(type), count); \
>> +} \
>> + \
>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count) \
>> +{ \
>> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
>> + arm64_extio_ops->end < addr) \
>> + writes##bw(PCI_IOBASE + addr, buffer, count); \
>> + else \
>> + if (arm64_extio_ops->pfouts) \
>> + arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>> + addr, buffer, sizeof(type), count); \
>> +}
>> +
>> +static inline void arm64_set_extops(struct extio_ops *ops)
>> +{
>> + if (ops)
>> + WRITE_ONCE(arm64_extio_ops, ops);
>
> Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
> side. Also, what if multiple drivers want to set different ops for distinct
> address ranges?
I think that the idea here is that we only have possibly one master in
the system which offers indirectIO backend, so another one could not
possibly re-set this value.
>
>> +}
>> +
>> +#endif /* __LINUX_EXTIO_H*/
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 0bba427..136735d 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -31,6 +31,7 @@
>> #include <asm/early_ioremap.h>
>> #include <asm/alternative.h>
>> #include <asm/cpufeature.h>
>> +#include <asm/extio.h>
>>
>> #include <xen/xen.h>
>>
>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>> #define IO_SPACE_LIMIT (PCI_IO_SIZE - 1)
>> #define PCI_IOBASE ((void __iomem *)PCI_IO_START)
>>
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#define inb inb
>> +#define outb outb
>> +#define insb insb
>> +#define outsb outsb
>> +/* external declaration */
>> +DECLARE_EXTIO(b, u8)
>> +
>> +#define inw inw
>> +#define outw outw
>> +#define insw insw
>> +#define outsw outsw
>> +
>> +DECLARE_EXTIO(w, u16)
>> +
>> +#define inl inl
>> +#define outl outl
>> +#define insl insl
>> +#define outsl outsl
>> +
>> +DECLARE_EXTIO(l, u32)
>> +#endif
>> +
>> +
>> /*
>> * String version of I/O memory access operations.
>> */
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 7d66bba..60e0482 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
>> sys_compat.o entry32.o
>> arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
>> arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>> arm64-obj-$(CONFIG_ARM64_MODULE_PLTS) += module-plts.o
>> arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
>> arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>> new file mode 100644
>> index 0000000..647b3fa
>> --- /dev/null
>> +++ b/arch/arm64/kernel/extio.c
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/io.h>
>> +
>> +struct extio_ops *arm64_extio_ops;
>> +
>> +
>> +BUILD_EXTIO(b, u8)
>> +
>> +BUILD_EXTIO(w, u16)
>> +
>> +BUILD_EXTIO(l, u32)
>
> Is there no way to make this slightly more generic, so that it can be
> re-used elsewhere? For example, if struct extio_ops was common, then
> you could have the singleton (which maybe should be an interval tree?),
> type definition, setter function and the BUILD_EXTIO invocations
> somewhere generic, rather than squirelled away in the arch backend.
>
> Will
The concern would be that some architecture which uses generic
higher-level ISA accessor ops, but have IO space, could be affected.
John
>
> .
>
^ permalink raw reply
* [PATCH 2/2] ARM: dts: apq8064: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-08 16:29 UTC (permalink / raw)
To: Lee Jones
Cc: Rob Herring, Andy Gross, devicetree, linux-kernel, linux-arm-msm,
linux-soc, linux-arm-kernel, bjorn.andersson, Srinivas Kandagatla
In-Reply-To: <1478622577-20699-1-git-send-email-srinivas.kandagatla@linaro.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
arch/arm/boot/dts/qcom-apq8064.dtsi | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 1dbe697..fde006c 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -627,6 +627,34 @@
clock-names = "core";
};
+ qcom,ssbi@c00000 {
+ compatible = "qcom,ssbi";
+ reg = <0x00c00000 0x1000>;
+ qcom,controller-type = "pmic-arbiter";
+
+ pmicintc2: pmic@1 {
+ compatible = "qcom,pm8821";
+ interrupt-parent = <&tlmm_pinmux>;
+ interrupts = <76 8>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8821_mpps: mpps@50 {
+
+ compatible = "qcom,pm8821-mpp", "qcom,ssbi-mpp";
+ reg = <0x50>;
+
+ interrupts = <24 1>, <25 1>, <26 1>,
+ <27 1>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+ };
+
qcom,ssbi@500000 {
compatible = "qcom,ssbi";
reg = <0x00500000 0x1000>;
--
2.10.1
^ permalink raw reply related
* [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-08 16:29 UTC (permalink / raw)
To: Lee Jones
Cc: Rob Herring, Andy Gross, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
linux-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A, Srinivas Kandagatla
This patch adds support to PM8821 PMIC and interrupt support.
PM8821 is companion device that supplements primary PMIC PM8921 IC.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
Tested this patch for MPP and IRQ functionality on IFC6410 and SD600 EVAL
board with mpps PM8821 and PM8921.
.../devicetree/bindings/mfd/qcom-pm8xxx.txt | 1 +
drivers/mfd/pm8921-core.c | 368 +++++++++++++++++++--
2 files changed, 340 insertions(+), 29 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
index 37a088f..8f1b4ec 100644
--- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
+++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
@@ -11,6 +11,7 @@ voltages and other various functionality to Qualcomm SoCs.
Definition: must be one of:
"qcom,pm8058"
"qcom,pm8921"
+ "qcom,pm8821"
- #address-cells:
Usage: required
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 0e3a2ea..28c2470 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -28,16 +28,26 @@
#include <linux/mfd/core.h>
#define SSBI_REG_ADDR_IRQ_BASE 0x1BB
-
-#define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0)
-#define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1)
-#define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2)
-#define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3)
-#define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4)
-#define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5)
-#define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6)
-#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
-#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
+#define SSBI_PM8821_REG_ADDR_IRQ_BASE 0x100
+
+#define SSBI_REG_ADDR_IRQ_ROOT (0)
+#define SSBI_REG_ADDR_IRQ_M_STATUS1 (1)
+#define SSBI_REG_ADDR_IRQ_M_STATUS2 (2)
+#define SSBI_REG_ADDR_IRQ_M_STATUS3 (3)
+#define SSBI_REG_ADDR_IRQ_M_STATUS4 (4)
+#define SSBI_REG_ADDR_IRQ_BLK_SEL (5)
+#define SSBI_REG_ADDR_IRQ_IT_STATUS (6)
+#define SSBI_REG_ADDR_IRQ_CONFIG (7)
+#define SSBI_REG_ADDR_IRQ_RT_STATUS (8)
+
+#define PM8821_TOTAL_IRQ_MASTERS 2
+#define PM8821_BLOCKS_PER_MASTER 7
+#define PM8821_IRQ_MASTER1_SET 0x01
+#define PM8821_IRQ_CLEAR_OFFSET 0x01
+#define PM8821_IRQ_RT_STATUS_OFFSET 0x0f
+#define PM8821_IRQ_MASK_REG_OFFSET 0x08
+#define SSBI_REG_ADDR_IRQ_MASTER0 0x30
+#define SSBI_REG_ADDR_IRQ_MASTER1 0xb0
#define PM_IRQF_LVL_SEL 0x01 /* level select */
#define PM_IRQF_MASK_FE 0x02 /* mask falling edge */
@@ -54,30 +64,41 @@
#define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */
#define PM8921_NR_IRQS 256
+#define PM8821_NR_IRQS 112
struct pm_irq_chip {
struct regmap *regmap;
spinlock_t pm_irq_lock;
struct irq_domain *irqdomain;
+ unsigned int irq_reg_base;
unsigned int num_irqs;
unsigned int num_blocks;
unsigned int num_masters;
u8 config[0];
};
+struct pm8xxx_data {
+ int num_irqs;
+ unsigned int irq_reg_base;
+ const struct irq_domain_ops *irq_domain_ops;
+ void (*irq_handler)(struct irq_desc *desc);
+};
+
static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
unsigned int *ip)
{
int rc;
spin_lock(&chip->pm_irq_lock);
- rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+ rc = regmap_write(chip->regmap,
+ chip->irq_reg_base + SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
if (rc) {
pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
goto bail;
}
- rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
+ rc = regmap_read(chip->regmap,
+ chip->irq_reg_base + SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
if (rc)
pr_err("Failed Reading Status rc=%d\n", rc);
bail:
@@ -91,14 +112,16 @@ pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp)
int rc;
spin_lock(&chip->pm_irq_lock);
- rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+ rc = regmap_write(chip->regmap,
+ chip->irq_reg_base + SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
if (rc) {
pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
goto bail;
}
cp |= PM_IRQF_WRITE;
- rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp);
+ rc = regmap_write(chip->regmap,
+ chip->irq_reg_base + SSBI_REG_ADDR_IRQ_CONFIG, cp);
if (rc)
pr_err("Failed Configuring IRQ rc=%d\n", rc);
bail:
@@ -137,8 +160,8 @@ static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
unsigned int blockbits;
int block_number, i, ret = 0;
- ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master,
- &blockbits);
+ ret = regmap_read(chip->regmap, chip->irq_reg_base +
+ SSBI_REG_ADDR_IRQ_M_STATUS1 + master, &blockbits);
if (ret) {
pr_err("Failed to read master %d ret=%d\n", master, ret);
return ret;
@@ -165,7 +188,8 @@ static void pm8xxx_irq_handler(struct irq_desc *desc)
chained_irq_enter(irq_chip, desc);
- ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
+ ret = regmap_read(chip->regmap,
+ chip->irq_reg_base + SSBI_REG_ADDR_IRQ_ROOT, &root);
if (ret) {
pr_err("Can't read root status ret=%d\n", ret);
return;
@@ -182,6 +206,122 @@ static void pm8xxx_irq_handler(struct irq_desc *desc)
chained_irq_exit(irq_chip, desc);
}
+static int pm8821_read_master_irq(const struct pm_irq_chip *chip,
+ int m, unsigned int *master)
+{
+ unsigned int base;
+
+ if (!m)
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
+ else
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
+
+ return regmap_read(chip->regmap, base, master);
+}
+
+static int pm8821_read_block_irq(struct pm_irq_chip *chip, int master,
+ u8 block, unsigned int *bits)
+{
+ int rc;
+
+ unsigned int base;
+
+ if (!master)
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
+ else
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
+
+ spin_lock(&chip->pm_irq_lock);
+
+ rc = regmap_read(chip->regmap, base + block, bits);
+ if (rc)
+ pr_err("Failed Reading Status rc=%d\n", rc);
+
+ spin_unlock(&chip->pm_irq_lock);
+ return rc;
+}
+
+static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
+ int master_number, int block)
+{
+ int pmirq, irq, i, ret;
+ unsigned int bits;
+
+ ret = pm8821_read_block_irq(chip, master_number, block, &bits);
+ if (ret) {
+ pr_err("Failed reading %d block ret=%d", block, ret);
+ return ret;
+ }
+ if (!bits) {
+ pr_err("block bit set in master but no irqs: %d", block);
+ return 0;
+ }
+
+ /* Convert block offset to global block number */
+ block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
+
+ /* Check IRQ bits */
+ for (i = 0; i < 8; i++) {
+ if (bits & BIT(i)) {
+ pmirq = block * 8 + i;
+ irq = irq_find_mapping(chip->irqdomain, pmirq);
+ generic_handle_irq(irq);
+ }
+ }
+
+ return 0;
+}
+
+static int pm8821_irq_read_master(struct pm_irq_chip *chip,
+ int master_number, u8 master_val)
+{
+ int ret = 0;
+ int block;
+
+ for (block = 1; block < 8; block++) {
+ if (master_val & BIT(block)) {
+ ret |= pm8821_irq_block_handler(chip,
+ master_number, block);
+ }
+ }
+
+ return ret;
+}
+
+static void pm8821_irq_handler(struct irq_desc *desc)
+{
+ struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+ struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+ int ret;
+ unsigned int master;
+
+ chained_irq_enter(irq_chip, desc);
+ /* check master 0 */
+ ret = pm8821_read_master_irq(chip, 0, &master);
+ if (ret) {
+ pr_err("Failed to re:Qad master 0 ret=%d\n", ret);
+ return;
+ }
+
+ if (master & ~PM8821_IRQ_MASTER1_SET)
+ pm8821_irq_read_master(chip, 0, master);
+
+ /* check master 1 */
+ if (!(master & PM8821_IRQ_MASTER1_SET))
+ goto done;
+
+ ret = pm8821_read_master_irq(chip, 1, &master);
+ if (ret) {
+ pr_err("Failed to read master 1 ret=%d\n", ret);
+ return;
+ }
+
+ pm8821_irq_read_master(chip, 1, master);
+
+done:
+ chained_irq_exit(irq_chip, desc);
+}
+
static void pm8xxx_irq_mask_ack(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
@@ -254,13 +394,15 @@ static int pm8xxx_irq_get_irqchip_state(struct irq_data *d,
irq_bit = pmirq % 8;
spin_lock(&chip->pm_irq_lock);
- rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
+ rc = regmap_write(chip->regmap, chip->irq_reg_base +
+ SSBI_REG_ADDR_IRQ_BLK_SEL, block);
if (rc) {
pr_err("Failed Selecting Block %d rc=%d\n", block, rc);
goto bail;
}
- rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
+ rc = regmap_read(chip->regmap, chip->irq_reg_base +
+ SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
if (rc) {
pr_err("Failed Reading Status rc=%d\n", rc);
goto bail;
@@ -299,6 +441,151 @@ static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
.map = pm8xxx_irq_domain_map,
};
+static void pm8821_irq_mask_ack(struct irq_data *d)
+{
+ struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int base, pmirq = irqd_to_hwirq(d);
+ u8 block, master;
+ int irq_bit, rc;
+
+ block = pmirq / 8;
+ master = block / PM8821_BLOCKS_PER_MASTER;
+ irq_bit = pmirq % 8;
+ block %= PM8821_BLOCKS_PER_MASTER;
+
+ if (!master)
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
+ else
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
+
+ spin_lock(&chip->pm_irq_lock);
+ rc = regmap_update_bits(chip->regmap,
+ base + PM8821_IRQ_MASK_REG_OFFSET + block,
+ BIT(irq_bit), BIT(irq_bit));
+
+ if (rc) {
+ pr_err("Failed to read/write mask IRQ:%d rc=%d\n", pmirq, rc);
+ goto fail;
+ }
+
+ rc = regmap_update_bits(chip->regmap,
+ base + PM8821_IRQ_CLEAR_OFFSET + block,
+ BIT(irq_bit), BIT(irq_bit));
+
+ if (rc) {
+ pr_err("Failed to read/write IT_CLEAR IRQ:%d rc=%d\n",
+ pmirq, rc);
+ }
+
+fail:
+ spin_unlock(&chip->pm_irq_lock);
+}
+
+static void pm8821_irq_unmask(struct irq_data *d)
+{
+ struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int base, pmirq = irqd_to_hwirq(d);
+ int irq_bit, rc;
+ u8 block, master;
+
+ block = pmirq / 8;
+ master = block / PM8821_BLOCKS_PER_MASTER;
+ irq_bit = pmirq % 8;
+ block %= PM8821_BLOCKS_PER_MASTER;
+
+ if (!master)
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
+ else
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
+
+ spin_lock(&chip->pm_irq_lock);
+
+ rc = regmap_update_bits(chip->regmap,
+ base + PM8821_IRQ_MASK_REG_OFFSET + block,
+ BIT(irq_bit), ~BIT(irq_bit));
+
+ if (rc)
+ pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
+
+ spin_unlock(&chip->pm_irq_lock);
+}
+
+static int pm8821_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+
+ /*
+ * PM8821 IRQ controller does not have explicit software support for
+ * IRQ flow type.
+ */
+ return 0;
+}
+
+static int pm8821_irq_get_irqchip_state(struct irq_data *d,
+ enum irqchip_irq_state which,
+ bool *state)
+{
+ struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+ int pmirq, rc;
+ u8 block, irq_bit, master;
+ unsigned int bits;
+ unsigned int base;
+ unsigned long flags;
+
+ pmirq = irqd_to_hwirq(d);
+
+ block = pmirq / 8;
+ master = block / PM8821_BLOCKS_PER_MASTER;
+ irq_bit = pmirq % 8;
+ block %= PM8821_BLOCKS_PER_MASTER;
+
+ if (!master)
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
+ else
+ base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
+
+ spin_lock_irqsave(&chip->pm_irq_lock, flags);
+
+ rc = regmap_read(chip->regmap,
+ base + PM8821_IRQ_RT_STATUS_OFFSET + block, &bits);
+ if (rc) {
+ pr_err("Failed Reading Status rc=%d\n", rc);
+ goto bail_out;
+ }
+
+ *state = !!(bits & BIT(irq_bit));
+
+bail_out:
+ spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
+
+ return rc;
+}
+
+static struct irq_chip pm8821_irq_chip = {
+ .name = "pm8821",
+ .irq_mask_ack = pm8821_irq_mask_ack,
+ .irq_unmask = pm8821_irq_unmask,
+ .irq_set_type = pm8821_irq_set_type,
+ .irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
+ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct pm_irq_chip *chip = d->host_data;
+
+ irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq);
+ irq_set_chip_data(irq, chip);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops pm8821_irq_domain_ops = {
+ .xlate = irq_domain_xlate_twocell,
+ .map = pm8821_irq_domain_map,
+};
+
static const struct regmap_config ssbi_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
@@ -308,10 +595,25 @@ static const struct regmap_config ssbi_regmap_config = {
.reg_write = ssbi_reg_write
};
+static const struct pm8xxx_data pm8xxx_data = {
+ .num_irqs = PM8921_NR_IRQS,
+ .irq_reg_base = SSBI_REG_ADDR_IRQ_BASE,
+ .irq_domain_ops = &pm8xxx_irq_domain_ops,
+ .irq_handler = pm8xxx_irq_handler,
+};
+
+static const struct pm8xxx_data pm8821_data = {
+ .num_irqs = PM8821_NR_IRQS,
+ .irq_reg_base = SSBI_PM8821_REG_ADDR_IRQ_BASE,
+ .irq_domain_ops = &pm8821_irq_domain_ops,
+ .irq_handler = pm8821_irq_handler,
+};
+
static const struct of_device_id pm8921_id_table[] = {
- { .compatible = "qcom,pm8018", },
- { .compatible = "qcom,pm8058", },
- { .compatible = "qcom,pm8921", },
+ { .compatible = "qcom,pm8018", .data = &pm8xxx_data},
+ { .compatible = "qcom,pm8058", .data = &pm8xxx_data},
+ { .compatible = "qcom,pm8821", .data = &pm8821_data},
+ { .compatible = "qcom,pm8921", .data = &pm8xxx_data},
{ }
};
MODULE_DEVICE_TABLE(of, pm8921_id_table);
@@ -319,11 +621,17 @@ MODULE_DEVICE_TABLE(of, pm8921_id_table);
static int pm8921_probe(struct platform_device *pdev)
{
struct regmap *regmap;
+ const struct pm8xxx_data *data;
int irq, rc;
unsigned int val;
u32 rev;
struct pm_irq_chip *chip;
- unsigned int nirqs = PM8921_NR_IRQS;
+
+ data = of_match_node(pm8921_id_table, pdev->dev.of_node)->data;
+ if (!data) {
+ dev_err(&pdev->dev, "No matching driver data found\n");
+ return -EINVAL;
+ }
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -354,25 +662,27 @@ static int pm8921_probe(struct platform_device *pdev)
rev |= val << BITS_PER_BYTE;
chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
- sizeof(chip->config[0]) * nirqs,
- GFP_KERNEL);
+ sizeof(chip->config[0]) * data->num_irqs,
+ GFP_KERNEL);
if (!chip)
return -ENOMEM;
platform_set_drvdata(pdev, chip);
chip->regmap = regmap;
- chip->num_irqs = nirqs;
+ chip->num_irqs = data->num_irqs;
+ chip->irq_reg_base = data->irq_reg_base;
chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
spin_lock_init(&chip->pm_irq_lock);
- chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
- &pm8xxx_irq_domain_ops,
+ chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
+ data->num_irqs,
+ data->irq_domain_ops,
chip);
if (!chip->irqdomain)
return -ENODEV;
- irq_set_chained_handler_and_data(irq, pm8xxx_irq_handler, chip);
+ irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
irq_set_irq_wake(irq, 1);
rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
--
2.10.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH 4/6] clk: stm32f4: Add I2S clock
From: Gabriel Fernandez @ 2016-11-08 16:26 UTC (permalink / raw)
To: Daniel Thompson, Rob Herring, Mark Rutland, Russell King,
Maxime Coquelin, Alexandre Torgue, Michael Turquette,
Stephen Boyd, Nicolas Pitre, Arnd Bergmann, andrea.merello
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-clk, kernel,
ludovic.barre, olivier.bideau, amelie.delaunay
In-Reply-To: <08ad0f8c-bcdf-4835-9f07-167e129604bd@linaro.org>
On 11/07/2016 03:14 PM, Daniel Thompson wrote:
> On 07/11/16 13:05, gabriel.fernandez@st.com wrote:
>> From: Gabriel Fernandez <gabriel.fernandez@st.com>
>>
>> This patch introduces I2S clock for stm32f4 soc.
>> The I2S clock could be derived from an external clock or from pll-i2s
>>
>> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
>> ---
>> drivers/clk/clk-stm32f4.c | 12 +++++++++++-
>> 1 file changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
>> index 5fa5d51..b7cb359 100644
>> --- a/drivers/clk/clk-stm32f4.c
>> +++ b/drivers/clk/clk-stm32f4.c
>> @@ -216,6 +216,7 @@ enum {
>> SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC,
>> PLL_VCO_I2S, PLL_VCO_SAI,
>> CLK_LCD,
>> + CLK_I2S,
>
> Sorry, this has just clicked and it applies to most of the other
> patches, but adding things to this list effectively extends the clock
> bindings (i.e. the list of valid "other" clocks access with a primary
> index of 1).
>
> This list if a list of "arbitrary" constants by which DT periphericals
> can be linked to specific clocks.
>
> So...
>
> 1) If a clock is introduced here we should update the clock binding
> documentations.
>
> 2) If no peripheral can connect to the clock (because it is internal
> to the clock gen logic and peripherals must connect to the gated
> version) it should not be included in this enum.
>
> 3) I failed to mention this when the four undocumented clocks
> (LSI, LSE, HSE_RTC and RTC) were added.
>
> 4) I *should* have added a comment explaining the above to the code.
>
>
ok i agree
>> END_PRIMARY_CLK
>> };
>>
>> @@ -967,6 +968,8 @@ static struct clk_hw *stm32_register_cclk(struct
>> device *dev, const char *name,
>>
>> static const char *sdmux_parents[2] = { "pll48", "sys" };
>>
>> +static const char *i2s_parents[2] = { "plli2s-r", NULL };
>> +
>> struct stm32f4_clk_data {
>> const struct stm32f4_gate_data *gates_data;
>> const u64 *gates_map;
>> @@ -1005,7 +1008,7 @@ struct stm32f4_clk_data {
>>
>> static void __init stm32f4_rcc_init(struct device_node *np)
>> {
>> - const char *hse_clk;
>> + const char *hse_clk, *i2s_in_clk;
>> int n;
>> const struct of_device_id *match;
>> const struct stm32f4_clk_data *data;
>> @@ -1038,6 +1041,7 @@ static void __init stm32f4_rcc_init(struct
>> device_node *np)
>> stm32f4_gate_map = data->gates_map;
>>
>> hse_clk = of_clk_get_parent_name(np, 0);
>> + i2s_in_clk = of_clk_get_parent_name(np, 1);
>
> Again this looks like a change to the DT bindings.
>
ok
> Also does the code work if i2s_in_clk is NULL or as you hoping to get
> away with a not-backwards compatible change?
>
>
yes it works if i2s_in_clk is NULL.
BR
Gabriel
> Daniel.
>
>
>>
>> clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
>> 16000000, 160000);
>> @@ -1053,6 +1057,12 @@ static void __init stm32f4_rcc_init(struct
>> device_node *np)
>> clks[PLL_VCO_SAI] = stm32f4_rcc_register_pll(pllsrc,
>> &data->pll_data[2], &stm32f4_clk_lock);
>>
>> + i2s_parents[1] = i2s_in_clk;
>> +
>> + clks[CLK_I2S] = clk_hw_register_mux_table(NULL, "i2s",
>> + i2s_parents, ARRAY_SIZE(i2s_parents), 0,
>> + base + STM32F4_RCC_CFGR, 23, 1, 0, NULL,
>> + &stm32f4_clk_lock);
>> sys_parents[1] = hse_clk;
>> clk_register_mux_table(
>> NULL, "sys", sys_parents, ARRAY_SIZE(sys_parents), 0,
>>
>
^ permalink raw reply
* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
From: Arnd Bergmann @ 2016-11-08 16:24 UTC (permalink / raw)
To: zhichang.yuan
Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
olof, linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
devicetree, linux-pci, linux-serial, minyard, benh, liviu.dudau,
zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
kantyzc, xuwei5
In-Reply-To: <1478576829-112707-4-git-send-email-yuanzhichang@hisilicon.com>
On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> + /*
> + * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
> + * It will separate indirectIO range from pci host bridge to
> + * avoid the possible PIO conflict.
> + * Set the indirectIO range directly here.
> + */
> + lpcdev->io_ops.start = 0;
> + lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> + lpcdev->io_ops.devpara = lpcdev;
> + lpcdev->io_ops.pfin = hisilpc_comm_in;
> + lpcdev->io_ops.pfout = hisilpc_comm_out;
> + lpcdev->io_ops.pfins = hisilpc_comm_ins;
> + lpcdev->io_ops.pfouts = hisilpc_comm_outs;
I have to look at patch 2 in more detail again, after missing a few review
rounds. I'm still a bit skeptical about hardcoding a logical I/O port
range here, and would hope that we can just go through the same
assignment of logical port ranges that we have for PCI buses, decoupling
the bus addresses from the linux-internal ones.
Arnd
^ permalink raw reply
* [PATCH 2/2] ASoC: axentia: tse850: add ASoC driver for the Axentia TSE-850
From: Peter Rosin @ 2016-11-08 16:20 UTC (permalink / raw)
To: linux-kernel
Cc: Mark Rutland, devicetree, alsa-devel, Takashi Iwai, Liam Girdwood,
Rob Herring, Mark Brown, Peter Rosin
In-Reply-To: <1478622057-12426-1-git-send-email-peda@axentia.se>
The TSE-850 is an FM Transmitter Station Equipment, designed to generate
baseband signals for FM, mainly the DARC subcarrier, but other signals
are also possible.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
MAINTAINERS | 1 +
sound/soc/Kconfig | 1 +
sound/soc/Makefile | 1 +
sound/soc/axentia/Kconfig | 10 +
sound/soc/axentia/Makefile | 3 +
sound/soc/axentia/tse850-pcm5142.c | 504 +++++++++++++++++++++++++++++++++++++
6 files changed, 520 insertions(+)
create mode 100644 sound/soc/axentia/Kconfig
create mode 100644 sound/soc/axentia/Makefile
create mode 100644 sound/soc/axentia/tse850-pcm5142.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 4f2ebf3ab51a..e966dfa79680 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2323,6 +2323,7 @@ M: Peter Rosin <peda@axentia.se>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/axentia,*
+F: sound/soc/axentia/
AZ6007 DVB DRIVER
M: Mauro Carvalho Chehab <mchehab@s-opensource.com>
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 182d92efc7c8..5e2f9e58710b 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -41,6 +41,7 @@ source "sound/soc/adi/Kconfig"
source "sound/soc/amd/Kconfig"
source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
+source "sound/soc/axentia/Kconfig"
source "sound/soc/bcm/Kconfig"
source "sound/soc/blackfin/Kconfig"
source "sound/soc/cirrus/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 9a30f21d16ee..dcdd41358e2a 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_SND_SOC) += adi/
obj-$(CONFIG_SND_SOC) += amd/
obj-$(CONFIG_SND_SOC) += atmel/
obj-$(CONFIG_SND_SOC) += au1x/
+obj-$(CONFIG_SND_SOC) += axentia/
obj-$(CONFIG_SND_SOC) += bcm/
obj-$(CONFIG_SND_SOC) += blackfin/
obj-$(CONFIG_SND_SOC) += cirrus/
diff --git a/sound/soc/axentia/Kconfig b/sound/soc/axentia/Kconfig
new file mode 100644
index 000000000000..7c760edd4bed
--- /dev/null
+++ b/sound/soc/axentia/Kconfig
@@ -0,0 +1,10 @@
+config SND_SOC_AXENTIA_TSE850_PCM5142
+ tristate "ASoC driver for the Axentia TSE-850"
+ depends on ARCH_AT91 && OF
+ select ATMEL_SSC
+ select SND_ATMEL_SOC
+ select SND_ATMEL_SOC_SSC_DMA
+ select SND_SOC_PCM512x_I2C
+ help
+ Say Y if you want to add support for the ASoC driver for the
+ Axentia TSE-850 with a PCM5142 codec.
diff --git a/sound/soc/axentia/Makefile b/sound/soc/axentia/Makefile
new file mode 100644
index 000000000000..d4ef52915809
--- /dev/null
+++ b/sound/soc/axentia/Makefile
@@ -0,0 +1,3 @@
+snd-soc-tse850-pcm5142-objs := tse850-pcm5142.o
+
+obj-$(CONFIG_SND_SOC_AXENTIA_TSE850_PCM5142) += snd-soc-tse850-pcm5142.o
diff --git a/sound/soc/axentia/tse850-pcm5142.c b/sound/soc/axentia/tse850-pcm5142.c
new file mode 100644
index 000000000000..1865f1eea554
--- /dev/null
+++ b/sound/soc/axentia/tse850-pcm5142.c
@@ -0,0 +1,504 @@
+/*
+ * TSE-850 audio - ASoC driver for the Axentia TSE-850 with a PCM5142 codec
+ *
+ * Copyright (C) 2016 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <peda@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * loop1 relays
+ * IN1 +---o +------------+ o---+ OUT1
+ * \ /
+ * + +
+ * | / |
+ * +--o +--. |
+ * | add | |
+ * | V |
+ * | .---. |
+ * DAC +----------->|Sum|---+
+ * | '---' |
+ * | |
+ * + +
+ *
+ * IN2 +---o--+------------+--o---+ OUT2
+ * loop2 relays
+ *
+ * The 'loop1' gpio pin controlls two relays, which are either in loop
+ * position, meaning that input and output are directly connected, or
+ * they are in mixer position, meaning that the signal is passed through
+ * the 'Sum' mixer. Similarly for 'loop2'.
+ *
+ * In the above, the 'loop1' relays are inactive, thus feeding IN1 to the
+ * mixer (if 'add' is active) and feeding the mixer output to OUT1. The
+ * 'loop2' relays are active, short-cutting the TSE-850 from channel 2.
+ * IN1, IN2, OUT1 and OUT2 are TSE-850 connectors and DAC is the PCB name
+ * of the (filtered) output from the PCM5142 codec.
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+#include "../atmel/atmel_ssc_dai.h"
+
+struct tse850_priv {
+ int ssc_id;
+
+ struct gpio_desc *add;
+ struct gpio_desc *loop1;
+ struct gpio_desc *loop2;
+
+ struct regulator *ana;
+};
+
+static int tse850_get_mux1(struct snd_kcontrol *kctrl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
+ struct snd_soc_card *card = dapm->card;
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ ret = gpiod_get_value(tse850->loop1);
+ if (ret < 0)
+ return ret;
+
+ ucontrol->value.enumerated.item[0] = ret;
+
+ return 0;
+}
+
+static int tse850_put_mux1(struct snd_kcontrol *kctrl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
+ struct snd_soc_card *card = dapm->card;
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+ struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
+ unsigned int val = ucontrol->value.enumerated.item[0];
+
+ if (val >= e->items)
+ return -EINVAL;
+
+ gpiod_set_value(tse850->loop1, val);
+
+ return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
+}
+
+static int tse850_get_mux2(struct snd_kcontrol *kctrl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
+ struct snd_soc_card *card = dapm->card;
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ ret = gpiod_get_value(tse850->loop2);
+ if (ret < 0)
+ return ret;
+
+ ucontrol->value.enumerated.item[0] = ret;
+
+ return 0;
+}
+
+static int tse850_put_mux2(struct snd_kcontrol *kctrl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
+ struct snd_soc_card *card = dapm->card;
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+ struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
+ unsigned int val = ucontrol->value.enumerated.item[0];
+
+ if (val >= e->items)
+ return -EINVAL;
+
+ gpiod_set_value(tse850->loop2, val);
+
+ return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
+}
+
+int tse850_get_mix(struct snd_kcontrol *kctrl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
+ struct snd_soc_card *card = dapm->card;
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ ret = gpiod_get_value(tse850->add);
+ if (ret < 0)
+ return ret;
+
+ ucontrol->value.enumerated.item[0] = ret;
+
+ return 0;
+}
+
+int tse850_put_mix(struct snd_kcontrol *kctrl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
+ struct snd_soc_card *card = dapm->card;
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+ int old;
+ int connect;
+
+ connect = !!ucontrol->value.integer.value[0];
+ old = gpiod_get_value(tse850->add);
+
+ if (old == connect)
+ return 0;
+
+ /*
+ * Hmmm, this gpiod_set_value call should probably happen
+ * inside snd_soc_dapm_mixer_update_power in the loop.
+ */
+ gpiod_set_value(tse850->add, connect);
+
+ snd_soc_dapm_mixer_update_power(dapm, kctrl, connect, NULL);
+ return 1;
+}
+
+int tse850_get_ana(struct snd_kcontrol *kctrl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
+ struct snd_soc_card *card = dapm->card;
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ ret = regulator_get_voltage(tse850->ana);
+ if (ret < 0)
+ return ret;
+
+ if (ret < 11000000)
+ ret = 11000000;
+ else if (ret > 20000000)
+ ret = 20000000;
+ ret -= 11000000;
+ ret = (ret + 500000) / 1000000;
+
+ ucontrol->value.enumerated.item[0] = ret;
+
+ return 0;
+}
+
+int tse850_put_ana(struct snd_kcontrol *kctrl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
+ struct snd_soc_card *card = dapm->card;
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+ struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
+ unsigned int uV = ucontrol->value.enumerated.item[0];
+ int ret;
+
+ if (uV >= e->items)
+ return -EINVAL;
+
+ /*
+ * Map enum zero (Low) to 2 volts on the regulator, do this since
+ * the ana regulator is supplied by the system 12V voltage and
+ * requesting anything below the system voltage causes the system
+ * voltage to be passed through the regulator. Also, the ana
+ * regulator induces noise when requesting voltages near the
+ * system voltage. So, by mapping Low to 2V, that noise is
+ * eliminated when all that is needed is 12V (the system voltage).
+ */
+ if (uV)
+ uV = 11000000 + (1000000 * uV);
+ else
+ uV = 2000000;
+
+ ret = regulator_set_voltage(tse850->ana, uV, uV);
+ if (ret < 0)
+ return ret;
+
+ return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
+}
+
+static const char * const mux_text[] = { "Mixer", "Loop" };
+
+static const struct soc_enum mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, mux_text);
+
+static const struct snd_kcontrol_new mux1 =
+ SOC_DAPM_ENUM_EXT("MUX1", mux_enum, tse850_get_mux1, tse850_put_mux1);
+
+static const struct snd_kcontrol_new mux2 =
+ SOC_DAPM_ENUM_EXT("MUX2", mux_enum, tse850_get_mux2, tse850_put_mux2);
+
+#define TSE850_DAPM_SINGLE_EXT(xname, reg, shift, max, invert, xget, xput) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_info_volsw, \
+ .get = xget, \
+ .put = xput, \
+ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
+
+static const struct snd_kcontrol_new mix[] = {
+ TSE850_DAPM_SINGLE_EXT("IN Switch", SND_SOC_NOPM, 0, 1, 0,
+ tse850_get_mix, tse850_put_mix),
+};
+
+static const char * const ana_text[] = {
+ "Low", "12V", "13V", "14V", "15V", "16V", "17V", "18V", "19V", "20V"
+};
+
+static const struct soc_enum ana_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 9, ana_text);
+
+static const struct snd_kcontrol_new out =
+ SOC_DAPM_ENUM_EXT("ANA", ana_enum, tse850_get_ana, tse850_put_ana);
+
+static const struct snd_soc_dapm_widget tse850_dapm_widgets[] = {
+ SND_SOC_DAPM_LINE("OUT1", NULL),
+ SND_SOC_DAPM_LINE("OUT2", NULL),
+ SND_SOC_DAPM_LINE("IN1", NULL),
+ SND_SOC_DAPM_LINE("IN2", NULL),
+ SND_SOC_DAPM_INPUT("DAC"),
+ SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0),
+ SOC_MIXER_ARRAY("MIX", SND_SOC_NOPM, 0, 0, mix),
+ SND_SOC_DAPM_MUX("MUX1", SND_SOC_NOPM, 0, 0, &mux1),
+ SND_SOC_DAPM_MUX("MUX2", SND_SOC_NOPM, 0, 0, &mux2),
+ SND_SOC_DAPM_OUT_DRV("OUT", SND_SOC_NOPM, 0, 0, &out, 1),
+};
+
+/*
+ * These connections are not entirely correct, since both IN1 and IN2
+ * are always fed to MIX (if the "IN switch" is set so), i.e. without
+ * regard to the loop1 and loop2 relays that according to this only
+ * control MUX1 and MUX2 but in fact also control how the input signals
+ * are routed.
+ * But, 1) I don't know how to do it right, and 2) it doesn't seem to
+ * matter in practice since nothing is powered in those sections anyway.
+ */
+static const struct snd_soc_dapm_route tse850_intercon[] = {
+ { "OUT1", NULL, "MUX1" },
+ { "OUT2", NULL, "MUX2" },
+
+ { "MUX1", "Loop", "IN1" },
+ { "MUX1", "Mixer", "OUT" },
+
+ { "MUX2", "Loop", "IN2" },
+ { "MUX2", "Mixer", "OUT" },
+
+ { "OUT", NULL, "MIX" },
+
+ { "MIX", NULL, "DAC" },
+ { "MIX", "IN Switch", "IN1" },
+ { "MIX", "IN Switch", "IN2" },
+
+ /* connect board input to the codec left channel output pin */
+ { "DAC", NULL, "OUTL" },
+};
+
+static int tse850_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct device *dev = rtd->dev;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int dir = substream->stream != SNDRV_PCM_STREAM_PLAYBACK;
+ int div_id = dir ? ATMEL_SSC_RCMR_PERIOD : ATMEL_SSC_TCMR_PERIOD;
+ int period = snd_soc_params_to_frame_size(params) / 2 - 1;
+ int ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, div_id, period);
+ if (ret < 0) {
+ dev_err(dev, "failed to set cpu dai lrclk %d divider\n", dir);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops tse850_ops = {
+ .hw_params = tse850_hw_params,
+};
+
+static int tse850_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
+
+ return snd_soc_dapm_add_routes(dapm, tse850_intercon,
+ ARRAY_SIZE(tse850_intercon));
+}
+
+static struct snd_soc_dai_link tse850_dailink = {
+ .name = "TSE-850",
+ .stream_name = "TSE-850-PCM",
+ .codec_dai_name = "pcm512x-hifi",
+ .dai_fmt = SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFS,
+ .init = tse850_init,
+ .ops = &tse850_ops,
+};
+
+static struct snd_soc_card tse850_card = {
+ .name = "TSE-850-ASoC",
+ .owner = THIS_MODULE,
+ .dai_link = &tse850_dailink,
+ .num_links = 1,
+ .dapm_widgets = tse850_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tse850_dapm_widgets),
+ .fully_routed = true,
+};
+
+static int tse850_dt_init(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *codec_np, *cpu_np;
+ struct snd_soc_card *card = &tse850_card;
+ struct snd_soc_dai_link *dailink = &tse850_dailink;
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+
+ if (!np) {
+ dev_err(&pdev->dev, "only device tree supported\n");
+ return -EINVAL;
+ }
+
+ cpu_np = of_parse_phandle(np, "axentia,ssc-controller", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "failed to get dai and pcm info\n");
+ return -EINVAL;
+ }
+ dailink->cpu_of_node = cpu_np;
+ dailink->platform_of_node = cpu_np;
+ tse850->ssc_id = of_alias_get_id(cpu_np, "ssc");
+ of_node_put(cpu_np);
+
+ codec_np = of_parse_phandle(np, "axentia,audio-codec", 0);
+ if (!codec_np) {
+ dev_err(&pdev->dev, "failed to get codec info\n");
+ return -EINVAL;
+ }
+ dailink->codec_of_node = codec_np;
+ of_node_put(codec_np);
+
+ return 0;
+}
+
+static int tse850_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &tse850_card;
+ struct device *dev = card->dev = &pdev->dev;
+ struct tse850_priv *tse850;
+ int ret;
+
+ tse850 = devm_kzalloc(dev, sizeof(*tse850), GFP_KERNEL);
+ if (!tse850)
+ return -ENOMEM;
+
+ snd_soc_card_set_drvdata(card, tse850);
+
+ ret = tse850_dt_init(pdev);
+ if (ret) {
+ dev_err(dev, "failed to init dt info\n");
+ return ret;
+ }
+
+ tse850->add = devm_gpiod_get(dev, "axentia,add", GPIOD_OUT_HIGH);
+ if (IS_ERR(tse850->add)) {
+ if (PTR_ERR(tse850->add) != -EPROBE_DEFER)
+ dev_err(dev, "failed to get 'add' gpio\n");
+ return PTR_ERR(tse850->add);
+ }
+
+ tse850->loop1 = devm_gpiod_get(dev, "axentia,loop1", GPIOD_OUT_HIGH);
+ if (IS_ERR(tse850->loop1)) {
+ if (PTR_ERR(tse850->loop1) != -EPROBE_DEFER)
+ dev_err(dev, "failed to get 'loop1' gpio\n");
+ return PTR_ERR(tse850->loop1);
+ }
+
+ tse850->loop2 = devm_gpiod_get(dev, "axentia,loop2", GPIOD_OUT_HIGH);
+ if (IS_ERR(tse850->loop2)) {
+ if (PTR_ERR(tse850->loop2) != -EPROBE_DEFER)
+ dev_err(dev, "failed to get 'loop2' gpio\n");
+ return PTR_ERR(tse850->loop2);
+ }
+
+ tse850->ana = devm_regulator_get(dev, "axentia,ana");
+ if (IS_ERR(tse850->ana)) {
+ if (PTR_ERR(tse850->ana) != -EPROBE_DEFER)
+ dev_err(dev, "failed to get 'ana' regulator\n");
+ return PTR_ERR(tse850->ana);
+ }
+
+ ret = regulator_enable(tse850->ana);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable the 'ana' regulator\n");
+ return ret;
+ }
+
+ ret = atmel_ssc_set_audio(tse850->ssc_id);
+ if (ret != 0) {
+ dev_err(dev,
+ "failed to set SSC %d for audio\n", tse850->ssc_id);
+ goto err_disable_ana;
+ }
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(dev, "snd_soc_register_card failed\n");
+ goto err_put_audio;
+ }
+
+ return 0;
+
+err_put_audio:
+ atmel_ssc_put_audio(tse850->ssc_id);
+err_disable_ana:
+ regulator_disable(tse850->ana);
+ return ret;
+}
+
+static int tse850_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
+
+ snd_soc_unregister_card(card);
+ atmel_ssc_put_audio(tse850->ssc_id);
+ regulator_disable(tse850->ana);
+
+ return 0;
+}
+
+static const struct of_device_id tse850_dt_ids[] = {
+ { .compatible = "axentia,tse850-pcm5142", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tse850_dt_ids);
+
+static struct platform_driver tse850_driver = {
+ .driver = {
+ .name = "axentia-tse850-pcm5142",
+ .of_match_table = of_match_ptr(tse850_dt_ids),
+ },
+ .probe = tse850_probe,
+ .remove = tse850_remove,
+};
+
+module_platform_driver(tse850_driver);
+
+/* Module information */
+MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
+MODULE_DESCRIPTION("ALSA SoC driver for TSE-850 with PCM5142 codec");
+MODULE_LICENSE("GPL");
--
2.1.4
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: sound: document axentia,tse850-pcm5142 bindings
From: Peter Rosin @ 2016-11-08 16:20 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
Jaroslav Kysela, Takashi Iwai, alsa-devel, devicetree
In-Reply-To: <1478622057-12426-1-git-send-email-peda@axentia.se>
The TSE-850 is an FM Transmitter Station Equipment, designed to generate
baseband signals for FM, mainly the DARC subcarrier, but other signals
are also possible.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
.../bindings/sound/axentia,tse850-pcm5142.txt | 88 ++++++++++++++++++++++
MAINTAINERS | 6 ++
2 files changed, 94 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt
diff --git a/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt b/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt
new file mode 100644
index 000000000000..0c2d44fda17e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt
@@ -0,0 +1,88 @@
+ASoC driver for the Axentia TSE-850 with a PCM5142 codec
+
+Required properties:
+ - compatible: "axentia,tse850-pcm5142"
+ - axentia,ssc-controller: The phandle of the atmel SSC controller used as
+ cpu dai.
+ - axentia,audio-codec: The phandle of the PCM5142 codec.
+ - axentia,add-gpios: gpio specifier that controls the mixer.
+ - axentia,loop1-gpios: gpio specifier that controls loop relays on channel 1.
+ - axentia,loop2-gpios: gpio specifier that controls loop relays on channel 2.
+ - axentia,ana-supply: Regulator that supplies the output amplifier. Must
+ support voltages in the 2V - 20V range, in 1V steps.
+
+The schematics explaining the gpios are as follows:
+
+ loop1 relays
+ IN1 +---o +------------+ o---+ OUT1
+ \ /
+ + +
+ | / |
+ +--o +--. |
+ | add | |
+ | V |
+ | .---. |
+ DAC +----------->|Sum|---+
+ | '---' |
+ | |
+ + +
+
+ IN2 +---o--+------------+--o---+ OUT2
+ loop2 relays
+
+The 'loop1' gpio pin controlls two relays, which are either in loop position,
+meaning that input and output are directly connected, or they are in mixer
+position, meaning that the signal is passed through the 'Sum' mixer. Similarly
+for 'loop2'.
+
+In the above, the 'loop1' relays are inactive, thus feeding IN1 to the mixer
+(if 'add' is active) and feeding the mixer output to OUT1. The 'loop2' relays
+are active, short-cutting the TSE-850 from channel 2. IN1, IN2, OUT1 and OUT2
+are TSE-850 connectors and DAC is the PCB name of the (filtered) output from
+the PCM5142 codec.
+
+Example:
+
+ &i2c {
+ codec: pcm5142@4c {
+ compatible = "ti,pcm5142";
+
+ reg = <0x4c>;
+
+ AVDD-supply = <®_3v3>;
+ DVDD-supply = <®_3v3>;
+ CPVDD-supply = <®_3v3>;
+
+ clocks = <&sck>;
+
+ pll-in = <3>;
+ pll-out = <6>;
+ };
+ };
+
+ ana: ana-reg {
+ compatible = "pwm-regulator";
+
+ regulator-name = "ANA";
+
+ pwms = <&pwm0 2 1000 PWM_POLARITY_INVERTED>;
+ pwm-dutycycle-unit = <1000>;
+ pwm-dutycycle-range = <100 1000>;
+
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <20000000>;
+ regulator-ramp-delay = <1000>;
+ };
+
+ sound {
+ compatible = "axentia,tse850-pcm5142";
+
+ axentia,ssc-controller = <&ssc0>;
+ axentia,audio-codec = <&codec>;
+
+ axentia,add-gpios = <&pioA 8 GPIO_ACTIVE_LOW>;
+ axentia,loop1-gpios = <&pioA 10 GPIO_ACTIVE_LOW>;
+ axentia,loop2-gpios = <&pioA 11 GPIO_ACTIVE_LOW>;
+
+ axentia,ana-supply = <&ana>;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 539b20baf791..4f2ebf3ab51a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2318,6 +2318,12 @@ F: include/uapi/linux/ax25.h
F: include/net/ax25.h
F: net/ax25/
+AXENTIA ASOC DRIVERS
+M: Peter Rosin <peda@axentia.se>
+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/sound/axentia,*
+
AZ6007 DVB DRIVER
M: Mauro Carvalho Chehab <mchehab@s-opensource.com>
M: Mauro Carvalho Chehab <mchehab@kernel.org>
--
2.1.4
^ permalink raw reply related
* [PATCH 0/2] ASoC driver for the TSE-850
From: Peter Rosin @ 2016-11-08 16:20 UTC (permalink / raw)
To: linux-kernel
Cc: Mark Rutland, devicetree, alsa-devel, Takashi Iwai, Liam Girdwood,
Rob Herring, Mark Brown, Peter Rosin
Hi!
The TSE-850 is an FM Transmitter Station Equipment, designed to generate
baseband signals for FM, mainly the DARC subcarrier, but other signals
are also possible.
This adds a driver for the "sound" bits of the device (quoted since it
is normally not used for normal sound output, but that works too of
course).
I have not provided a patch to add axentia as a devicetree vendor prefix,
since such a patch is already pending in an IIO series [1] that seems
close to being accepted.
However, there are a couple of points that I'm not 100% satisfied with
for this driver.
First, I do not know how to describe the relays that control if the
IN1/IN2 signals are directly routed towards OUT1/OUT2 or if they are
routed to the "add" switch. The dapm routing treats this as if the
IN1/IN2 signals are always routed to both the "add" switch and to
the muxes feeding OUT1/OUT2. This is fine with me since nothing is
powered in those sections anyway, so what dapm thinks does not really
matter. But it is a wart all the same.
Second, there's my comment in tse850_put_mix() when the "add" switch
is updated. I believe this update should really happen as a side
effect of the call to snd_soc_dapm_mixer_update_power(), so that it
happens at the right point compared to other stuff that is powered.
But I do not know how to hook that up and instead I flip the switch
before the call since it doesn't really matter. I.e., any noise
resulting from this badness is negligeble in practice.
Cheers,
Peter
[1] http://www.spinics.net/lists/devicetree/thrd3.html#147258
Peter Rosin (2):
dt-bindings: sound: document axentia,tse850-pcm5142 bindings
ASoC: axentia: tse850: add ASoC driver for the Axentia TSE-850
.../bindings/sound/axentia,tse850-pcm5142.txt | 88 ++++
MAINTAINERS | 7 +
sound/soc/Kconfig | 1 +
sound/soc/Makefile | 1 +
sound/soc/axentia/Kconfig | 10 +
sound/soc/axentia/Makefile | 3 +
sound/soc/axentia/tse850-pcm5142.c | 504 +++++++++++++++++++++
7 files changed, 614 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt
create mode 100644 sound/soc/axentia/Kconfig
create mode 100644 sound/soc/axentia/Makefile
create mode 100644 sound/soc/axentia/tse850-pcm5142.c
--
2.1.4
^ permalink raw reply
* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Arnd Bergmann @ 2016-11-08 16:19 UTC (permalink / raw)
To: Mark Rutland
Cc: gabriele.paoloni, benh, will.deacon, linuxarm, lorenzo.pieralisi,
xuwei5, linux-serial, catalin.marinas, devicetree, minyard,
marc.zyngier, liviu.dudau, john.garry, zourongrong, robh+dt,
bhelgaas, kantyzc, zhichang.yuan02, linux-arm-kernel, linux-pci,
linux-kernel, zhichang.yuan, olof
In-Reply-To: <20161108114953.GB15297@leverpostej>
On Tuesday, November 8, 2016 11:49:53 AM CET Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> > +Hisilicon Hip06 low-pin-count device
> > + Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> > + locate on LPC bus can be accessed direclty. But some SoCs have independent
> > + LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> > + Hisilicon Hip06 implements this LPC device.
>
> s/direclty/directly/
>
> My understanding of ISA (which may be flawed) is that it's not part of
> the PCI host bridge, but rather on x86 it happens to share the IO space
> with PCI.
On normal systems, ISA or LPC are behind a PCI bridge device, which
passes down both low addresses of I/O space and memory space.
> So, how about this becomes:
>
> Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
> provides access to some legacy ISA devices.
>
> I believe that we could theoretically have multiple independent LPC/ISA
> busses, as is possible with PCI on !x86 systems. If the current ISA code
> assumes a singleton bus, I think that's something that needs to be fixed
> up more generically.
>
> I don't see why we should need any architecture-specific code here. Why
> can we not fix up the ISA bus code in drivers/of/address.c such that it
> handles multiple ISA bus instances, and translates all sub-device
> addresses relative to the specific bus instance?
I think it is a relatively safe assumption that there is only one
ISA bridge. A lot of old drivers hardcode PIO or memory addresses
when talking to an ISA device, so having multiple instances is
already problematic.
What is odd about ARM64 here is that the PIO space is not shared among
all ISA and PCI buses in some cases.
Arnd
^ permalink raw reply
* Re: [PATCH 1/6] clk: stm32f4: Add PLL_I2S & PLL_SAI for STM32F429/469 boards
From: Gabriel Fernandez @ 2016-11-08 16:19 UTC (permalink / raw)
To: Radosław Pietrzyk
Cc: Rob Herring, Mark Rutland, Russell King, Maxime Coquelin,
Alexandre Torgue, Michael Turquette, Stephen Boyd, Nicolas Pitre,
Arnd Bergmann, Daniel Thompson, Andrea Merello, devicetree,
amelie.delaunay, kernel, olivier.bideau, linux-kernel, linux-clk,
ludovic.barre, linux-arm-kernel
In-Reply-To: <CAFvLkMSwwyoi8Vb_-+6dViB8PaBRUoCZYBcrzDjgX9EJnv_mvQ@mail.gmail.com>
On 11/08/2016 09:52 AM, Radosław Pietrzyk wrote:
> 2016-11-08 9:35 GMT+01:00 Gabriel Fernandez <gabriel.fernandez@st.com>:
>> Hi Radosław
>>
>> Many thanks for reviewing.
>>
>> On 11/07/2016 03:57 PM, Radosław Pietrzyk wrote:
>>>> +static struct clk_hw *clk_register_pll_div(const char *name,
>>>> + const char *parent_name, unsigned long flags,
>>>> + void __iomem *reg, u8 shift, u8 width,
>>>> + u8 clk_divider_flags, const struct clk_div_table *table,
>>>> + struct clk_hw *pll_hw, spinlock_t *lock)
>>>> +{
>>>> + struct stm32f4_pll_div *pll_div;
>>>> + struct clk_hw *hw;
>>>> + struct clk_init_data init;
>>>> + int ret;
>>>> +
>>>> + /* allocate the divider */
>>>> + pll_div = kzalloc(sizeof(*pll_div), GFP_KERNEL);
>>>> + if (!pll_div)
>>>> + return ERR_PTR(-ENOMEM);
>>>> +
>>>> + init.name = name;
>>>> + init.ops = &stm32f4_pll_div_ops;
>>>> + init.flags = flags;
>>> Maybe it's worth to have CLK_SET_RATE_PARENT here and the VCO clock
>>> should have CLK_SET_RATE_GATE flag and we can get rid of custom
>>> divider ops.
>> I don't want to offer the possibility to change the vco clock through the
>> divisor of the pll (only by a boot-loader or by DT).
>>
>> e.g. if i make a set rate on lcd-tft clock, i don't want to change the SAI
>> frequencies.
>>
>> I used same structure for internal divisors of the pll (p, q, r) and for
>> post divisors (plli2s-q-div, pllsai-q-div & pllsai-r-div).
>> That why the CLK_SET_RATE_PARENT flag is transmit by parameter.
>>
>> These divisors are similar because we have to switch off the pll before
>> changing the rate.
>>
> But changing pll and lcd dividers only may not be enough for getting
> very specific pixelclocks and that might require changing the VCO
> frequency itself. The rest of the SAI tree should be recalculated
> then.
I agree but it seems to be too much complicated to recalculate all PLL
divisors if we change the vco clock.
You mean to use Clock notifier callback ?
^ permalink raw reply
* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: Arnd Bergmann @ 2016-11-08 16:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Mark Rutland, catalin.marinas, gabriele.paoloni, benh,
will.deacon, linuxarm, lorenzo.pieralisi, xuwei5, linux-serial,
linux-pci, devicetree, minyard, marc.zyngier, liviu.dudau,
john.garry, olof, robh+dt, bhelgaas, kantyzc, zhichang.yuan02,
linux-kernel, zhichang.yuan, zourongrong
In-Reply-To: <13493313.OkuDZEY5WO@wuerfel>
On Tuesday, November 8, 2016 5:09:59 PM CET Arnd Bergmann wrote:
>
> I don't see a better alternative. I earlier suggested having these
> out of line so we don't grow the object code too much when it is
> enabled.
>
On second look, I see that they are all done out of line, I would
just move around the BUILD_EXTIO macro to the file that uses it
and remove and open-code the DECLARE_EXTIO() as that makes it easier
to grep.
Arnd
^ permalink raw reply
* Re: [PATCH 0/8] firmware: arm_scpi: add support for legacy SCPI protocol
From: Russell King - ARM Linux @ 2016-11-08 16:13 UTC (permalink / raw)
To: Sudeep Holla
Cc: Neil Armstrong, devicetree, linux-kernel, Olof Johansson,
linux-amlogic, linux-arm-kernel
In-Reply-To: <e83e8462-6d63-7253-f69c-afb507463bba@arm.com>
On Tue, Nov 08, 2016 at 04:08:38PM +0000, Sudeep Holla wrote:
> I will focus on this and see what's happening. I have issue with network
> on my setup with debug build and Linaro guys are not seeing it. I revert
> to release build of UEFI for that. Anyways one suggestion I have right
> now is to erase the second partition of NOR flash where the old UEFI
> config is placed and it could be conflicting with the new UEFI image.
>
> Cmd> flash
>
>
> Switching on main power...
> PMIC RAM configuration (pms_v105.bin)...
> IOFPGA config: PASSED
> Enabling usb remote...
>
>
> Flash> ERASERANGE 0x0BFC0000 0x0BFF0000
>
> I will looking into that further.
Still behaves the same, stopping at:
FV2 Hob 0xFE07B000 - 0xFE8253BF
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: Will Deacon @ 2016-11-08 16:12 UTC (permalink / raw)
To: zhichang.yuan
Cc: mark.rutland, gabriele.paoloni, benh, liviu.dudau, linuxarm,
lorenzo.pieralisi, arnd, xuwei5, linux-serial, catalin.marinas,
devicetree, minyard, john.garry, zourongrong, robh+dt, bhelgaas,
kantyzc, zhichang.yuan02, linux-arm-kernel, linux-pci,
linux-kernel, olof
In-Reply-To: <1478576829-112707-2-git-send-email-yuanzhichang@hisilicon.com>
On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
>
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
> arch/arm64/Kconfig | 6 +++
> arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
> arch/arm64/include/asm/io.h | 29 +++++++++++++
> arch/arm64/kernel/Makefile | 1 +
> arch/arm64/kernel/extio.c | 27 ++++++++++++
> 5 files changed, 157 insertions(+)
> create mode 100644 arch/arm64/include/asm/extio.h
> create mode 100644 arch/arm64/kernel/extio.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 969ef88..b44070b 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
> config ARCH_MMAP_RND_COMPAT_BITS_MAX
> default 16
>
> +config ARM64_INDIRECT_PIO
> + bool "access peripherals with legacy I/O port"
> + help
> + Support special accessors for ISA I/O devices. This is needed for
> + SoCs that do not support standard read/write for the ISA range.
> +
> config NO_IOPORT_MAP
> def_bool y if !PCI
>
> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +struct extio_ops {
> + unsigned long start;/* inclusive, sys io addr */
> + unsigned long end;/* inclusive, sys io addr */
> +
> + u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
> + void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
> + size_t dlen);
> + u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
> + size_t dlen, unsigned int count);
> + void (*pfouts)(void *devobj, unsigned long ptaddr,
> + const void *outbuf, size_t dlen,
> + unsigned int count);
> + void *devpara;
> +};
> +
> +extern struct extio_ops *arm64_extio_ops;
> +
> +#define DECLARE_EXTIO(bw, type) \
> +extern type in##bw(unsigned long addr); \
> +extern void out##bw(type value, unsigned long addr); \
> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
> +
> +#define BUILD_EXTIO(bw, type) \
> +type in##bw(unsigned long addr) \
> +{ \
> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
> + arm64_extio_ops->end < addr) \
> + return read##bw(PCI_IOBASE + addr); \
> + return arm64_extio_ops->pfin ? \
> + arm64_extio_ops->pfin(arm64_extio_ops->devpara, \
> + addr, sizeof(type)) : -1; \
> +} \
> + \
> +void out##bw(type value, unsigned long addr) \
> +{ \
> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
> + arm64_extio_ops->end < addr) \
> + write##bw(value, PCI_IOBASE + addr); \
> + else \
> + if (arm64_extio_ops->pfout) \
> + arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> + addr, value, sizeof(type)); \
> +} \
> + \
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count) \
> +{ \
> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
> + arm64_extio_ops->end < addr) \
> + reads##bw(PCI_IOBASE + addr, buffer, count); \
> + else \
> + if (arm64_extio_ops->pfins) \
> + arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> + addr, buffer, sizeof(type), count); \
> +} \
> + \
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count) \
> +{ \
> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
> + arm64_extio_ops->end < addr) \
> + writes##bw(PCI_IOBASE + addr, buffer, count); \
> + else \
> + if (arm64_extio_ops->pfouts) \
> + arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> + addr, buffer, sizeof(type), count); \
> +}
> +
> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> + if (ops)
> + WRITE_ONCE(arm64_extio_ops, ops);
Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
side. Also, what if multiple drivers want to set different ops for distinct
address ranges?
> +}
> +
> +#endif /* __LINUX_EXTIO_H*/
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 0bba427..136735d 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -31,6 +31,7 @@
> #include <asm/early_ioremap.h>
> #include <asm/alternative.h>
> #include <asm/cpufeature.h>
> +#include <asm/extio.h>
>
> #include <xen/xen.h>
>
> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
> #define IO_SPACE_LIMIT (PCI_IO_SIZE - 1)
> #define PCI_IOBASE ((void __iomem *)PCI_IO_START)
>
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#define inb inb
> +#define outb outb
> +#define insb insb
> +#define outsb outsb
> +/* external declaration */
> +DECLARE_EXTIO(b, u8)
> +
> +#define inw inw
> +#define outw outw
> +#define insw insw
> +#define outsw outsw
> +
> +DECLARE_EXTIO(w, u16)
> +
> +#define inl inl
> +#define outl outl
> +#define insl insl
> +#define outsl outsl
> +
> +DECLARE_EXTIO(l, u32)
> +#endif
> +
> +
> /*
> * String version of I/O memory access operations.
> */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 7d66bba..60e0482 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
> sys_compat.o entry32.o
> arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
> arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
> arm64-obj-$(CONFIG_ARM64_MODULE_PLTS) += module-plts.o
> arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
> arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> new file mode 100644
> index 0000000..647b3fa
> --- /dev/null
> +++ b/arch/arm64/kernel/extio.c
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +
> +struct extio_ops *arm64_extio_ops;
> +
> +
> +BUILD_EXTIO(b, u8)
> +
> +BUILD_EXTIO(w, u16)
> +
> +BUILD_EXTIO(l, u32)
Is there no way to make this slightly more generic, so that it can be
re-used elsewhere? For example, if struct extio_ops was common, then
you could have the singleton (which maybe should be an interval tree?),
type definition, setter function and the BUILD_EXTIO invocations
somewhere generic, rather than squirelled away in the arch backend.
Will
^ permalink raw reply
* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: Arnd Bergmann @ 2016-11-08 16:09 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Mark Rutland, catalin.marinas, gabriele.paoloni, benh,
will.deacon, linuxarm, lorenzo.pieralisi, xuwei5, linux-serial,
linux-pci, devicetree, minyard, marc.zyngier, liviu.dudau,
john.garry, olof, robh+dt, bhelgaas, kantyzc, zhichang.yuan02,
linux-kernel, zhichang.yuan, zourongrong
In-Reply-To: <20161108120323.GC15297@leverpostej>
On Tuesday, November 8, 2016 12:03:23 PM CET Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > For arm64, there is no I/O space as other architectural platforms, such as
> > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > known port addresses are used to control the corresponding target devices, for
> > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > normal MMIO mode in using.
>
> This has nothing to do with arm64. Hardware with this kind of indirect
> bus access could be integrated with a variety of CPU architectures. It
> simply hasn't been, yet.
Actually PowerPC has a vaguely similar mechanism.
> > To drive these devices, this patch introduces a method named indirect-IO.
> > In this method the in/out pair in arch/arm64/include/asm/io.h will be
> > redefined. When upper layer drivers call in/out with those known legacy port
> > addresses to access the peripherals, the hooking functions corrresponding to
> > those target peripherals will be called. Through this way, those upper layer
> > drivers which depend on in/out can run on Hip06 without any changes.
>
> As above, this has nothing to do with arm64, and as such, should live in
> generic code, exactly as we would do if we had higher-level ISA
> accessor ops.
>
> Regardless, given the multi-instance case, I don't think this is
> sufficient in general (and I think we need higher-level ISA accessors
> to handle the indirection).
I think it is rather unlikely that we have to deal with multiple
instances in the future, it's more likely that future platforms
won't have any I/O ports at all, which is why I was advocating for
simplicity here.
> > +type in##bw(unsigned long addr) \
> > +{ \
> > + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
> > + arm64_extio_ops->end < addr) \
> > + return read##bw(PCI_IOBASE + addr); \
> > + return arm64_extio_ops->pfin ? \
> > + arm64_extio_ops->pfin(arm64_extio_ops->devpara, \
> > + addr, sizeof(type)) : -1; \
> > +} \
> > + \
> > +void out##bw(type value, unsigned long addr) \
> > +{ \
> > + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
> > + arm64_extio_ops->end < addr) \
> > + write##bw(value, PCI_IOBASE + addr); \
> > + else \
> > + if (arm64_extio_ops->pfout) \
> > + arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > + addr, value, sizeof(type)); \
> > +} \
> > + \
> > +void ins##bw(unsigned long addr, void *buffer, unsigned int count) \
> > +{ \
> > + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
> > + arm64_extio_ops->end < addr) \
> > + reads##bw(PCI_IOBASE + addr, buffer, count); \
> > + else \
> > + if (arm64_extio_ops->pfins) \
> > + arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> > + addr, buffer, sizeof(type), count); \
> > +} \
> > + \
> > +void outs##bw(unsigned long addr, const void *buffer, unsigned int count) \
> > +{ \
> > + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
> > + arm64_extio_ops->end < addr) \
> > + writes##bw(PCI_IOBASE + addr, buffer, count); \
> > + else \
> > + if (arm64_extio_ops->pfouts) \
> > + arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> > + addr, buffer, sizeof(type), count); \
> > +}
> > +
>
> So all PCI I/O will be slowed down by irrelevant checks when this is
> enabled?
I don't see a better alternative. I earlier suggested having these
out of line so we don't grow the object code too much when it is
enabled.
Performance of PIO accessors is not an issue here though, any bus
access will by definition be orders of magnitude slower than the
added branches and dereferences here.
> [...]
>
> > +static inline void arm64_set_extops(struct extio_ops *ops)
> > +{
> > + if (ops)
> > + WRITE_ONCE(arm64_extio_ops, ops);
> > +}
>
> Why WRITE_ONCE()?
>
> Is this not protected/propagated by some synchronisation mechanism?
>
> WRITE_ONCE() is not sufficient to ensure that this is consistently
> observed by readers, and regardless, I don't see READ_ONCE() anywhere in
> this patch.
>
> This looks very suspicious.
Agreed, this looks wrong.
Arnd
^ permalink raw reply
* Re: [PATCH 0/8] firmware: arm_scpi: add support for legacy SCPI protocol
From: Sudeep Holla @ 2016-11-08 16:08 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Sudeep Holla, Neil Armstrong, devicetree, linux-kernel,
Olof Johansson, linux-amlogic, linux-arm-kernel
In-Reply-To: <20161108154038.GS1041@n2100.armlinux.org.uk>
On 08/11/16 15:40, Russell King - ARM Linux wrote:
> On Tue, Nov 08, 2016 at 03:11:07PM +0000, Sudeep Holla wrote:
>> On 08/11/16 14:51, Russell King - ARM Linux wrote:
>>> On Wed, Nov 02, 2016 at 10:52:03PM -0600, Sudeep Holla wrote:
>>>> This is minor rework of the series[1] from Neil Armstrong's to support
>>>> legacy SCPI protocol to make DT bindings more generic and move out all
>>>> the platform specific bindings out of the generic binding document.
>>>
>>> Is this what would be in my HBI0282B Juno?
>>>
>>
>> No, it's one on the AmLogic Meson GXBB platform. Juno never supported
>> that except that old firmware use it internally. By that I mean some
>> version of trusted firmware used legacy SCPI but they are generally
>> bundled together in fip, so you should not see any issue with upgrade.
>
> I was wondering whether it'd work with my existing 1st September 2014
> version of the trusted firmware. I've pretty much come to the
> conclusion that there's no way I can run the later firmware on this
> hardware.
>
No, we should be able to fix it. It's just some weird configuration
that has triggered this. Generally people just replace entire tarball
into uSD and hence it is not tested very well for such cases.
>> I am currently trying to run Linaro 16.10 release, I don't see any issue
>> except network boot from UEFI which is known and reported.
>
> Interesting - maybe the hardware is different then?
>
No, we have seen issues in past especially UEFI.
>> I will go through your logs in detail and try to replicate your issue.
>> I assume you have tried replacing the entry contents of the uSD with the
>> release. I will start with that now.
>
> I haven't wiped it and copied the entire contents of the zip file over.
> I instead backed up the old board.txt and images.txt files, and copied
> the HBI0282B directories on top of the others.
>
> This correctly causes all the various components to be updated when the
> board boots, updating the MBB BIOS, iofpga, and reprogramming the NOR
> flash with the updated images. I even diff'd what was on the uSD card
> and what was supplied in the zip file.
>
> That's one state I tested: it also allowed me to edit the board.txt and
> similar to wind back to what I have now on the board - which is all the
> old versions of the firmware except for the MBB BIOS.
>
> Anyway, I've wiped the uSD, and copied the contents of the 16.10 release
> over:
>
[...]
> Memory Allocation 0x00000004 0xFE07B000 - 0xFE826FFF
> Memory Allocation 0x00000004 0xFE03B000 - 0xFE07AFFF
> Memory Allocation 0x00000003 0xFE03B000 - 0xFE07AFFF
> FV Hob 0xE0000000 - 0xE00EFFFF
> FV Hob 0xFE07B000 - 0xFE8253BF
> FV2 Hob 0xFE07B000 - 0xFE8253BF
>
> which looks more hopeful... except it stops there.
>
Ah that's good, some progress.
> As it contains a zero sized Image and .dtb files, I tried copying my
> Image and .dtb over, and also copied my original config.txt (only
> change is AUTORUN: FALSE). It still doesn't appear to boot beyond
> this point.
>
I will focus on this and see what's happening. I have issue with network
on my setup with debug build and Linaro guys are not seeing it. I revert
to release build of UEFI for that. Anyways one suggestion I have right
now is to erase the second partition of NOR flash where the old UEFI
config is placed and it could be conflicting with the new UEFI image.
Cmd> flash
Switching on main power...
PMIC RAM configuration (pms_v105.bin)...
IOFPGA config: PASSED
Enabling usb remote...
Flash> ERASERANGE 0x0BFC0000 0x0BFF0000
I will looking into that further.
--
Regards,
Sudeep
^ 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