* [PATCH] drm: hdlcd: Work properly in big-endian mode
From: Daniel Vetter @ 2016-12-07 15:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f484518775c0bf063ae0a6f1e6c11bb404a7acc9.1481124156.git.robin.murphy@arm.com>
On Wed, Dec 07, 2016 at 03:31:40PM +0000, Robin Murphy wrote:
> Under a big-endian kernel, colours on the framebuffer all come out a
> delightful shade of wrong, since we fail to take the reversed byte
> order into account. Fortunately, the HDLCD has a control bit to make it
> automatically byteswap big-endian data; let's use it as appropriate.
>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
fourcc codes (and the drm fourcc codes) are supposed to be little-endian.
All of them. So either we fix up the drivers and userspace to set that
flag correctly (which would mean hdlcd should expose twice as many
formats, each one with the little and big endian mode).
Or we nuke the big endian flag from drm fourcc. Adding AMD folks who afaik
are the only other ones who ever cared about big endian in drm.
-Daniel
> ---
> drivers/gpu/drm/arm/hdlcd_crtc.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
> index 28341b32067f..eceb7bed5dd0 100644
> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
> @@ -63,6 +63,7 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
> uint32_t pixel_format;
> struct simplefb_format *format = NULL;
> int i;
> + u32 reg;
>
> pixel_format = crtc->primary->state->fb->pixel_format;
>
> @@ -76,7 +77,11 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
>
> /* HDLCD uses 'bytes per pixel', zero means 1 byte */
> btpp = (format->bits_per_pixel + 7) / 8;
> - hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, (btpp - 1) << 3);
> + reg = (btpp - 1) << 3;
> +#ifdef __BIG_ENDIAN
> + reg |= HDLCD_PIXEL_FMT_BIG_ENDIAN;
> +#endif
> + hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, reg);
>
> /*
> * The format of the HDLCD_REG_<color>_SELECT register is:
> --
> 2.10.2.dirty
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
^ permalink raw reply
* [PATCH v4 1/4] [media] davinci: vpif_capture: don't lock over s_stream
From: Kevin Hilman @ 2016-12-07 16:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4999781.kd7ueUSsQd@avalon>
Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes:
> Hi Kevin,
>
> On Tuesday 06 Dec 2016 08:49:38 Kevin Hilman wrote:
>> Laurent Pinchart writes:
>> > On Tuesday 29 Nov 2016 15:57:09 Kevin Hilman wrote:
>> >> Video capture subdevs may be over I2C and may sleep during xfer, so we
>> >> cannot do IRQ-disabled locking when calling the subdev.
>> >>
>> >> Signed-off-by: Kevin Hilman <khilman@baylibre.com>
>> >> ---
>> >> drivers/media/platform/davinci/vpif_capture.c | 3 +++
>> >> 1 file changed, 3 insertions(+)
>> >>
>> >> diff --git a/drivers/media/platform/davinci/vpif_capture.c
>> >> b/drivers/media/platform/davinci/vpif_capture.c index
>> >> 5104cc0ee40e..9f8f41c0f251 100644
>> >> --- a/drivers/media/platform/davinci/vpif_capture.c
>> >> +++ b/drivers/media/platform/davinci/vpif_capture.c
>> >> @@ -193,7 +193,10 @@ static int vpif_start_streaming(struct vb2_queue
>> >> *vq, unsigned int count)
>> >> }
>> >> }
>> >>
>> >> + spin_unlock_irqrestore(&common->irqlock, flags);
>> >> ret = v4l2_subdev_call(ch->sd, video, s_stream, 1);
>> >> + spin_lock_irqsave(&common->irqlock, flags);
>> >
>> > I always get anxious when I see a spinlock being released randomly with an
>> > operation in the middle of a protected section. Looking at the code it
>> > looks like the spinlock is abused here. irqlock should only protect the
>> > dma_queue and should thus only be taken around the following code:
>> >
>> > spin_lock_irqsave(&common->irqlock, flags);
>> > /* Get the next frame from the buffer queue */
>> > common->cur_frm = common->next_frm = list_entry(common->dma_queue.next,
>> > struct vpif_cap_buffer, list);
>> >
>> > /* Remove buffer from the buffer queue */
>> > list_del(&common->cur_frm->list);
>> > spin_unlock_irqrestore(&common->irqlock, flags);
>>
>> Yes, that looks correct. Will update.
>>
>> > The code that is currently protected by the lock in the start and stop
>> > streaming functions should be protected by a mutex instead.
>>
>> I tried taking the mutex here, but lockdep pointed out a deadlock. I
>> may not be fully understanding the V4L2 internals here, but it seems
>> that the ioctl is already taking a mutex, so taking it again in
>> start/stop streaming is a deadlock. Unless you think the locking should
>> be nested here, it seems to me that the mutex isn't needed.
>
> The V4L2 core can lock all ioctls using struct video_device::lock. For buffer-
> related ioctls, it can optionally use a separate lock from struct
> vb2_queue::lock. See v4l2_ioctl_get_lock() in drivers/media/v4l2-core/v4l2-
> ioctl.c.
>
> The vpif-capture driver sets both the video_device and vb2_queue locks to the
> same lock (which would have the same effect as leaving the vb2_queue lock
> NULL). All ioctls are thus serialized. You would only need to handle locking
> in start_streaming and stop_streaming manually if you didn't rely on the core
> serializing the ioctls.
OK, thanks for clarifying how that works.
Kevin
^ permalink raw reply
* [PATCH 6/7] arm: Add livepatch to build if CONFIG_LIVEPATCH
From: Abel Vesa @ 2016-12-07 16:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161207150525.GD13288@linux.suse>
On Wed, Dec 07, 2016 at 04:05:25PM +0100, Petr Mladek wrote:
> On Tue 2016-12-06 17:06:06, Abel Vesa wrote:
> > Necessary livepatch file added to makefile.
> >
> > Signed-off-by: Abel Vesa <abelvesa@linux.com>
> > ---
> > arch/arm/kernel/Makefile | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> > index ad325a8..9e70220 100644
> > --- a/arch/arm/kernel/Makefile
> > +++ b/arch/arm/kernel/Makefile
> > @@ -48,6 +48,7 @@ obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
> > obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
> > obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o
> > obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
> > +obj-$(CONFIG_LIVEPATCH) += livepatch.o
>
> It is strange that you add a source file in one patch and make it
> build in a much later patch.
>
> I suggest to restructure the entire patchset a bit. Please, first
> add support for FTRACE_WITH_REGS. It makes sense on its own.
> Then add the livepatch support on top of it.
>
> Otherwise, it is not necessary to send v2 immediately for such
> non-trivial code. There might be more people that would want
> to look at it and it might take days until they find a time.
> It is always better to collect some feedback, think about it
> over night(s). Every question often opens many other questions
> and it usually takes some time until all settles down into
> a good picture again.
>
> Best Regards,
> Petr
You're right, I should send this into two steps. One patchset that
adds FTRACE_WITH_REGS and then a second one that implements the
livepatch and is based on the first one.
Will do that.
Thanks.
^ permalink raw reply
* [PATCH] drm: hdlcd: Work properly in big-endian mode
From: liviu.dudau at arm.com @ 2016-12-07 16:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f484518775c0bf063ae0a6f1e6c11bb404a7acc9.1481124156.git.robin.murphy@arm.com>
On Wed, Dec 07, 2016 at 03:31:40PM +0000, Robin Murphy wrote:
> Under a big-endian kernel, colours on the framebuffer all come out a
> delightful shade of wrong,
So you are saying that wrong is only a 1 bit value?
> since we fail to take the reversed byte
> order into account. Fortunately, the HDLCD has a control bit to make it
> automatically byteswap big-endian data; let's use it as appropriate.
>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Change looks good to me, but as Daniel has mentioned, we should have failed
the modesetting as the buffer we are passed should be in the wrong fourcc format.
Any way I can play with a big-endian filesystem that you can share?
Best regards,
Liviu
> ---
> drivers/gpu/drm/arm/hdlcd_crtc.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
> index 28341b32067f..eceb7bed5dd0 100644
> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
> @@ -63,6 +63,7 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
> uint32_t pixel_format;
> struct simplefb_format *format = NULL;
> int i;
> + u32 reg;
>
> pixel_format = crtc->primary->state->fb->pixel_format;
>
> @@ -76,7 +77,11 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
>
> /* HDLCD uses 'bytes per pixel', zero means 1 byte */
> btpp = (format->bits_per_pixel + 7) / 8;
> - hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, (btpp - 1) << 3);
> + reg = (btpp - 1) << 3;
> +#ifdef __BIG_ENDIAN
> + reg |= HDLCD_PIXEL_FMT_BIG_ENDIAN;
> +#endif
> + hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, reg);
>
> /*
> * The format of the HDLCD_REG_<color>_SELECT register is:
> --
> 2.10.2.dirty
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
?\_(?)_/?
^ permalink raw reply
* [PATCH v3 2/5] spi: armada-3700: Add support for the FIFO mode
From: Romain Perier @ 2016-12-07 16:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205133728.sza2pt4tfkywu35k@sirena.org.uk>
Hello,
Le 05/12/2016 ? 14:37, Mark Brown a ?crit :
> On Thu, Dec 01, 2016 at 11:27:16AM +0100, Romain Perier wrote:
>
>> Changes in v3:
>> - Don't enable the fifo mode based on the compatible string, we introduce
>> a module parameter "pio_mode". By default this option is set to zero, so
>> the fifo mode is enabled. Pass pio_mode=1 to the driver enables the PIO
>> mode.
>
> Why? If the hardware supports a more efficient mode of operation it
> doesn't seem sensible not to use it.
That's just that our customer want to keep both modes, this is why I
decided to use the more efficient mode by default and disable it via a
module parameter. Previously the more efficient mode was always enabled,
based on the "compatible string" of the DT (the PIO mode was simply
useless in this case and dead code)
>
>> - int i;
>> + int i, ret = 0;
>
> Coding style - don't combine initialized and non-initalized variables on
> one line.
Ok
>
>> static int a3700_spi_transfer_one(struct spi_master *master,
>> struct spi_device *spi,
>> struct spi_transfer *xfer)
>> {
>> struct a3700_spi *a3700_spi = spi_master_get_devdata(master);
>> - int ret = 0;
>> + int ret;
>>
>> a3700_spi_transfer_setup(spi, xfer);
>>
>> @@ -505,6 +737,151 @@ static int a3700_spi_transfer_one(struct spi_master *master,
>> return ret;
>> }
>
> This appears to be a random unrelated change, should probably be part of
> the initial driver commit.
Good catch
>
>> +static int a3700_spi_fifo_transfer_one(struct spi_master *master,
>> + struct spi_device *spi,
>> + struct spi_transfer *xfer)
>> +{
>> + struct a3700_spi *a3700_spi = spi_master_get_devdata(master);
>> + int ret = 0, timeout = A3700_SPI_TIMEOUT;
>> + unsigned int nbits = 0;
>> + u32 val;
>> +
>> + a3700_spi_transfer_setup(spi, xfer);
>> +
>> + a3700_spi->tx_buf = xfer->tx_buf;
>> + a3700_spi->rx_buf = xfer->rx_buf;
>> + a3700_spi->buf_len = xfer->len;
>> +
>> + /* SPI transfer headers */
>> + a3700_spi_header_set(a3700_spi);
>> +
>> + if (xfer->tx_buf)
>> + nbits = xfer->tx_nbits;
>> + else if (xfer->rx_buf)
>> + nbits = xfer->rx_nbits;
>> +
>> + a3700_spi_pin_mode_set(a3700_spi, nbits);
>> +
>> + if (xfer->rx_buf) {
>> + /* Set read data length */
>> + spireg_write(a3700_spi, A3700_SPI_IF_DIN_CNT_REG,
>> + a3700_spi->buf_len);
>> + /* Start READ transfer */
>> + val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG);
>> + val &= ~A3700_SPI_RW_EN;
>> + val |= A3700_SPI_XFER_START;
>> + spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val);
>> + } else if (xfer->tx_buf) {
>> + /* Start Write transfer */
>
> So this only supports single duplex transfers but there doesn't seem to
> be anything that enforces this.
>
A flag or a capability, typically? I will investigate
Thanks,
Romain
--
Romain Perier, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH] i2c: rk3x: keep i2c irq ON in suspend
From: Grygorii Strashko @ 2016-12-07 16:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a6694d7d-6fca-e5ef-7bbd-9956562132a2@rock-chips.com>
On 12/06/2016 09:37 PM, David.Wu wrote:
> Hi Doug,
>
> ? 2016/12/7 0:31, Doug Anderson ??:
>> Hi,
>>
>> On Tue, Dec 6, 2016 at 12:12 AM, David.Wu <david.wu@rock-chips.com>
>> wrote:
>>> Hi Heiko,
>>>
>>> ? 2016/12/5 18:54, Heiko Stuebner ??:
>>>>
>>>> Hi David,
>>>>
>>>> Am Montag, 5. Dezember 2016, 16:02:59 CET schrieb David Wu:
>>>>>
>>>>> During suspend there may still be some i2c access happening.
>>>>> And if we don't keep i2c irq ON, there may be i2c access timeout if
>>>>> i2c is in irq mode of operation.
>>>>
>>>>
>>>> can you describe the issue you're trying to fix a bit more please?
>>>
>>>
>>> Sometimes we could see the i2c timeout errors during suspend/resume,
>>> which
>>> makes the duration of suspend/resume too longer.
>>>
>>> [ 484.171541] CPU4: Booted secondary processor [410fd082]
>>> [ 485.172777] rk3x-i2c ff3c0000.i2c: timeout, ipd: 0x10, state: 1
>>> [ 486.172760] rk3x-i2c ff3c0000.i2c: timeout, ipd: 0x10, state: 1
>>> [ 487.172759] rk3x-i2c ff3c0000.i2c: timeout, ipd: 0x10, state: 1
>>> [ 487.172840] cpu cpu4: _set_opp_voltage: failed to set voltage (800000
>>> 800000 800000 mV): -110
>>> [ 487.172874] cpu cpu4: failed to set volt 800000
>>>
>>>>
>>>> I.e. I'd think the i2c-core does suspend i2c-client devices first,
>>>> so that
>>>> these should be able to finish up their ongoing transfers and not start
>>>> any
>>>> new ones instead?
>>>>
>>>> Your irq can still happen slightly after the system started going to
>>>> actually
>>>> sleep, so to me it looks like you just widened the window where irqs
>>>> can
>>>> be
>>>> handled. Especially as your irq could also just simply stem from the
>>>> start
>>>> state, so you cannot even be sure if your transaction actually is
>>>> finished.
>>>
>>>
>>> Okay, you are right. I want to give it a double insurance at first,
>>> but it
>>> may hide the unhappend issue.
>>>
>>>>
>>>> So to me it looks like the i2c-connected device driver should be fixed
>>>> instead?
>>>
>>>
>>> I tell them to fix it in rk808 driver.
>>
>> To me it seems like perhaps cpufreq should not be changing frequencies
>> until it is resumed properly. Presumably if all the ordering is done
>> right then cpufreq should be resumed _after_ the i2c regulator so you
>> should be OK. ...or am I somehow confused about that?
>
> yes?the cpufreq and regulator should start i2c job after they resume
> properly.
>
>>
>> Also note that previous i2c busses I worked with simply returned -EIO
>> in the case where they were called when suspended. See
>> "i2c-exynos5.c" and "i2c-s3c2410.c".
>
> In "i2c-exynos5.c", it seems that using the "i2c->suspended" to protect
> i2c transfer works most of the time. Of course it could prevent the next
> new i2c transfer to start. But in one case, if the current i2c job was
> not finished until the i2c irq was disabled by system suspend, the i2c
> timeout error would also happen, as the current i2c job may have a large
> data to transfer and it lasts from a long time.
And this means you have bug in some of I2C client drivers which do not stop
their activities during suspend properly (most usual case - driver uses work
and this work still active during suspend and can run on one CPU while suspend
runs on another).
At the moment .suspend_noirq() callback is called there should be no active
I2C transactions in general.
>
> So is it necessary to add a mutex lock to wait the current job to be
> finished before the "i2c->suspended" is changed in i2c_suspend_noirq()?
>
You need to catch and fix all driver who will try to access I2C after your
I2C bus driver passes suspend_noirq stage. Smth, like [1], uses i2c_lock_adapter().
[1] https://git.ti.com/android-sdk/kernel-omap/commit/125ef8f7016e7b205886f93862288a45a312b1d8
--
regards,
-grygorii
^ permalink raw reply
* [Question] New mmap64 syscall?
From: Catalin Marinas @ 2016-12-07 16:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161207123944.GA11799@yury-N73SV>
On Wed, Dec 07, 2016 at 06:09:44PM +0530, Yury Norov wrote:
> On Wed, Dec 07, 2016 at 12:07:24PM +0100, Dr.Philipp Tomsich wrote:
> > [Resend, as my mail-client had insisted on using the wrong MIME type?]
> >
> > > On 07 Dec 2016, at 11:34, Yury Norov <ynorov@caviumnetworks.com> wrote:
> > >
> > >> If there is a use case for larger than 16TB offsets, we should add
> > >> the call on all architectures, probably using your approach 3. I don't
> > >> think that we should treat it as anything special for arm64 though.
> > >
> > > From this point of view, 16+TB offset is a matter of 16+TB storage,
> > > and it's more than real. The other consideration to add it is that
> > > we have 64-bit support for offsets in syscalls like sys_llseek().
> > > So mmap64() will simply extend this support.
> >
> > I believe the question is rather if the 16TB offset is a real use-case for ILP32.
>
> This is not for ilp32, but for all 32-bit architectures - both native
> and compat. And because the scope is so generic, I think it's the
> strong reason for us to support true 64-bit offset in mmap().
When I mentioned it, I didn't realise that we already use 6 registers
for mmap(). While we can go up to 8 on AArch64/ILP32, I think Arnd has a
point that we don't want this to diverge from other new 32-bit
architectures. I don't really have a strong opinion either way here,
just a remark that AArch64/ILP32 already diverged from _current_ 32-bit
architectures by introducing 64-bit off_t in a 32-bit world. Introducing
an mmap64() at the same time wouldn't look too bad either.
> > This seems to bring the discussion full-circle, as this would indicate that 64bit is the
> > preferred bit-width for all sizes, offsets, etc. throughout all filesystem-related calls
> > (i.e. stat, seek, etc.).
>
> AARCH64/ILP32 (and all new arches) exposes ino_t, off_t, blkcnt_t,
> fsblkcnt_t, fsfilcnt_t and rlim_t as 64-bit types. (Size_t should
> be 32-bit of course, because it's the same lengths as pointer.)
>
> It allows to make syscalls that pass it support 64-bit values, refer
> Documentation/arm64/ilp32.txt for details. Stat and seek are both
> supporting 64-bit types. From this point of view, mmap() is the (only?)
> exception in current ILP32 ABI.
I thought ILP32 will use llseek() which has its own explicit way of
passing a 64-bit offset and the result written back by the kernel. We
wouldn't be able to use lseek() because of the return type.
> > But if that is the case, then we should have gone with 64bit arguments in a single
> > register for our ILP32 definition on AArch64.
>
> There are 2 unrelated matters - the size of types, and the size of
> register. Most of 32-bit architectures has hardware limitation on
> register size (consider aarch32). And it doesn't mean that they are
> forced to stuck with 32-bit off_t etc. This is still opened question
> how to pass 64-bit parameters in aarch64/ilp32 because there we have
> the choice (the reason why it's RFC). If you have new ideas - welcome
> to that discussion. This topic also covers architectures that has to
> pass 64-bit parameters in a pair.
We've discussed this a few times already and the only sane option from
the _kernel_ perspective seemed to be either (a) close to native ABI for
ILP32 (and breaking POSIX) or (b) just a standard 32-bit ABI. The latter
implies splitting 64-bit values in register pairs, especially to avoid a
lot of annotations/wrapping in the generic kernel unistd.h file. IIRC,
we decided to go with option (b), so I don't think it's worth re-opening
that discussion.
> > In other words: Why not keep ILP32 simple an ask users that need a 16TB+ offset
> > to use LP64? It seems much more consistent with the other choices takes so far.
>
> If user can switch to lp64, he doesn't need ilp32 at all, right? :)
> Also, I don't understand how true 64-bit offset in mmap64() would
> complicate this port.
It's more like the user wanting a quick transition from code that was
only ever compiled for AArch32 (or other 32-bit architecture) with a
goal of full LP64 transition on the long run. I have yet to see
convincing benchmarks showing ILP32 as an advantage over LP64 (of
course, I hear the argument of reading a pointer a loop is twice as fast
with a half-size pointer but I don't consider such benchmarks relevant).
--
Catalin
^ permalink raw reply
* [PATCH v3 2/5] spi: armada-3700: Add support for the FIFO mode
From: Mark Brown @ 2016-12-07 16:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a9b86043-b631-8154-edc8-5abe49e47114@free-electrons.com>
On Wed, Dec 07, 2016 at 05:19:57PM +0100, Romain Perier wrote:
> Le 05/12/2016 ? 14:37, Mark Brown a ?crit :
> > Why? If the hardware supports a more efficient mode of operation it
> > doesn't seem sensible not to use it.
> That's just that our customer want to keep both modes, this is why I decided
> to use the more efficient mode by default and disable it via a module
> parameter. Previously the more efficient mode was always enabled, based on
> the "compatible string" of the DT (the PIO mode was simply useless in this
> case and dead code)
Keep that out of tree, if the user wants to do silly things then let
them pay the cost.
> > > + if (xfer->rx_buf) {
> > > + /* Set read data length */
> > > + spireg_write(a3700_spi, A3700_SPI_IF_DIN_CNT_REG,
> > > + a3700_spi->buf_len);
> > > + /* Start READ transfer */
> > > + val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG);
> > > + val &= ~A3700_SPI_RW_EN;
> > > + val |= A3700_SPI_XFER_START;
> > > + spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val);
> > > + } else if (xfer->tx_buf) {
> > > + /* Start Write transfer */
> > So this only supports single duplex transfers but there doesn't seem to
> > be anything that enforces this.
> A flag or a capability, typically? I will investigate
SPI_MASTER_HALF_DUPLEX.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161207/af74c861/attachment.sig>
^ permalink raw reply
* Tearing down DMA transfer setup after DMA client has finished
From: Vinod Koul @ 2016-12-07 16:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5846B237.8060409@free.fr>
On Tue, Dec 06, 2016 at 01:42:31PM +0100, Mason wrote:
> On 06/12/2016 06:12, Vinod Koul wrote:
>
> > On Tue, Nov 29, 2016 at 07:25:02PM +0100, Mason wrote:
> >
> >> Is there a way to write a driver within the existing framework?
> >
> > I think so, looking back at comments from Russell, I do tend to agree with
> > that. Is there a specific reason why sbox can't be tied to alloc and free
> > channels?
>
> Here's a recap of the situation.
>
> The "SBOX+MBUS" HW is used in several iterations of the tango SoC:
btw is SBOX setup dependent upon the peripheral connected to?
>
> tango3
> 2 memory channels available
> 6 devices ("clients"?) may request an MBUS channel
But only 2 can get a channel at any time..
>
> tango4 (one more channel)
> 3 memory channels available
> 7 devices may request an MBUS channel :
> NFC0, NFC1, SATA0, SATA1, memcpy, (IDE0, IDE1)
Same here
Only thing is users shouldn't hold on to channel and freeup when not in use.
> Notes:
> The current NFC driver supports only one controller.
> IDE is mostly obsolete at this point.
>
> tango5 (SATA gets own dedicated MBUS channel pair)
> 3 memory channels available
> 5 devices may request an MBUS channel :
> NFC0, NFC1, memcpy, (IDE0, IDE1)
>
>
> If I understand the current DMA driver (written by Mans), client
> drivers are instructed to use a specific channel in the DT, and
> the DMA driver muxes access to that channel. The DMA driver
> manages a per-channel queue of outstanding DMA transfer requests,
> and a new transfer is started friom within the DMA ISR
> (modulo the fact that the interrupt does not signal completion
> of the transfer, as explained else-thread).
>
> What you're proposing, Vinod, is to make a channel exclusive
> to a driver, as long as the driver has not explicitly released
> the channel, via dma_release_channel(), right?
Precisely, but yes the downside of that is concurrent access are limited, but
am not sure if driver implements virtual channels and allows that..
Thanks
--
~Vinod
^ permalink raw reply
* [PATCH] drm: hdlcd: Work properly in big-endian mode
From: Robin Murphy @ 2016-12-07 16:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161207155714.ldmshptddwvhsdop@phenom.ffwll.local>
On 07/12/16 15:57, Daniel Vetter wrote:
> On Wed, Dec 07, 2016 at 03:31:40PM +0000, Robin Murphy wrote:
>> Under a big-endian kernel, colours on the framebuffer all come out a
>> delightful shade of wrong, since we fail to take the reversed byte
>> order into account. Fortunately, the HDLCD has a control bit to make it
>> automatically byteswap big-endian data; let's use it as appropriate.
>>
>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>
> fourcc codes (and the drm fourcc codes) are supposed to be little-endian.
> All of them. So either we fix up the drivers and userspace to set that
> flag correctly (which would mean hdlcd should expose twice as many
> formats, each one with the little and big endian mode).
AFAICS, SIMPLEFB_FORMATS *is* supposed to be explicitly little-endian
modes. I see that DRM_FORMAT_BIG_ENDIAN exists, but nothing in-tree ever
sets it :/
My vague (and probably wrong) assumption was that the HDLCD is still
expecting little-endian data, but the the CPU is writing framebuffer
data as host-endian words, hence what the HDLCD thinks is xRGB is
actually RGBx under a big-endian kernel - It's certainly consistent
between kernel (fbcon) and userspace (fb-test[1]): white is yellow, blue
is black, green is red and red is green. I don't know how to test
"proper" DRM (I've failed to get X to work with the Arch Linux ARM
distro I have on there at the moment).
Once again I'm somewhat out of my depth here - I just found a thing that
seemed appropriate and visibly resolved the immediate problem :)
By comparison, the same use-cases (fbcon and fb-test) under the same
big-endian kernel do *not* show the same problem with nouveau driving a
PCIe 7600GT card, which led me to believe it was HDLCD-specific.
Robin.
[1]:https://github.com/prpplague/fb-test-app
> Or we nuke the big endian flag from drm fourcc. Adding AMD folks who afaik
> are the only other ones who ever cared about big endian in drm.
> -Daniel
>
>> ---
>> drivers/gpu/drm/arm/hdlcd_crtc.c | 7 ++++++-
>> 1 file changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
>> index 28341b32067f..eceb7bed5dd0 100644
>> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
>> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
>> @@ -63,6 +63,7 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
>> uint32_t pixel_format;
>> struct simplefb_format *format = NULL;
>> int i;
>> + u32 reg;
>>
>> pixel_format = crtc->primary->state->fb->pixel_format;
>>
>> @@ -76,7 +77,11 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
>>
>> /* HDLCD uses 'bytes per pixel', zero means 1 byte */
>> btpp = (format->bits_per_pixel + 7) / 8;
>> - hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, (btpp - 1) << 3);
>> + reg = (btpp - 1) << 3;
>> +#ifdef __BIG_ENDIAN
>> + reg |= HDLCD_PIXEL_FMT_BIG_ENDIAN;
>> +#endif
>> + hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, reg);
>>
>> /*
>> * The format of the HDLCD_REG_<color>_SELECT register is:
>> --
>> 2.10.2.dirty
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
^ permalink raw reply
* [Question] New mmap64 syscall?
From: Dr. Philipp Tomsich @ 2016-12-07 16:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161207163210.GB31779@e104818-lin.cambridge.arm.com>
Catalin,
> On 07 Dec 2016, at 17:32, Catalin Marinas <catalin.marinas@arm.com> wrote:
>
>>> In other words: Why not keep ILP32 simple an ask users that need a 16TB+ offset
>>> to use LP64? It seems much more consistent with the other choices takes so far.
>>
>> If user can switch to lp64, he doesn't need ilp32 at all, right? :)
>> Also, I don't understand how true 64-bit offset in mmap64() would
>> complicate this port.
>
> It's more like the user wanting a quick transition from code that was
> only ever compiled for AArch32 (or other 32-bit architecture) with a
> goal of full LP64 transition on the long run. I have yet to see
> convincing benchmarks showing ILP32 as an advantage over LP64 (of
> course, I hear the argument of reading a pointer a loop is twice as fast
> with a half-size pointer but I don't consider such benchmarks relevant).
Most of the performance advantage in benchmarks comes from a reduction
in the size of data-structures and/or tighter packing of arrays. In other words,
we can make slightly better use of the caches and push the memory subsystem
a little further when running multiple instances of benchmarks.
Most of these advantages should eventually go away, when struct-reorg makes
it way into the compiler. That said, it?s a marginal (but real) improvement for a
subset of SPEC.
In the real world, the importance of ILP32 as an aid to transition legacy code
that is not 64bit clean? and this should drive the ILP32 discussion. That we
get a boost in our SPEC scores is just a nice extra that we get from it ;-)
Regards,
Philipp.
^ permalink raw reply
* Tearing down DMA transfer setup after DMA client has finished
From: Vinod Koul @ 2016-12-07 16:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <yw1xwpfd2o9f.fsf@unicorn.mansr.com>
On Tue, Dec 06, 2016 at 01:14:20PM +0000, M?ns Rullg?rd wrote:
>
> That's not going to work very well. Device drivers typically request
> dma channels in their probe functions or when the device is opened.
> This means that reserving one of the few channels there will inevitably
> make some other device fail to operate.
No that doesnt make sense at all, you should get a channel only when you
want to use it and not in probe!
--
~Vinod
^ permalink raw reply
* [PATCH] drm: hdlcd: Work properly in big-endian mode
From: Ville Syrjälä @ 2016-12-07 16:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161207155714.ldmshptddwvhsdop@phenom.ffwll.local>
On Wed, Dec 07, 2016 at 04:57:14PM +0100, Daniel Vetter wrote:
> On Wed, Dec 07, 2016 at 03:31:40PM +0000, Robin Murphy wrote:
> > Under a big-endian kernel, colours on the framebuffer all come out a
> > delightful shade of wrong, since we fail to take the reversed byte
> > order into account. Fortunately, the HDLCD has a control bit to make it
> > automatically byteswap big-endian data; let's use it as appropriate.
> >
> > Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>
> fourcc codes (and the drm fourcc codes) are supposed to be little-endian.
> All of them. So either we fix up the drivers and userspace to set that
> flag correctly (which would mean hdlcd should expose twice as many
> formats, each one with the little and big endian mode).
>
> Or we nuke the big endian flag from drm fourcc. Adding AMD folks who afaik
> are the only other ones who ever cared about big endian in drm.
I don't like the idea of nuking the flag. If the fb endianness is
defined by the CPU, how would userspace even know that it would have
to byteswap the data when feeding it to the device if the device
and CPU don't agree on the endianness?
> -Daniel
>
> > ---
> > drivers/gpu/drm/arm/hdlcd_crtc.c | 7 ++++++-
> > 1 file changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
> > index 28341b32067f..eceb7bed5dd0 100644
> > --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
> > +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
> > @@ -63,6 +63,7 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
> > uint32_t pixel_format;
> > struct simplefb_format *format = NULL;
> > int i;
> > + u32 reg;
> >
> > pixel_format = crtc->primary->state->fb->pixel_format;
> >
> > @@ -76,7 +77,11 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
> >
> > /* HDLCD uses 'bytes per pixel', zero means 1 byte */
> > btpp = (format->bits_per_pixel + 7) / 8;
> > - hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, (btpp - 1) << 3);
> > + reg = (btpp - 1) << 3;
> > +#ifdef __BIG_ENDIAN
> > + reg |= HDLCD_PIXEL_FMT_BIG_ENDIAN;
> > +#endif
> > + hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, reg);
> >
> > /*
> > * The format of the HDLCD_REG_<color>_SELECT register is:
> > --
> > 2.10.2.dirty
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Ville Syrj?l?
Intel OTC
^ permalink raw reply
* Tearing down DMA transfer setup after DMA client has finished
From: Måns Rullgård @ 2016-12-07 16:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161207164156.GW6408@localhost>
Vinod Koul <vinod.koul@intel.com> writes:
> On Tue, Dec 06, 2016 at 01:42:31PM +0100, Mason wrote:
>> On 06/12/2016 06:12, Vinod Koul wrote:
>>
>> > On Tue, Nov 29, 2016 at 07:25:02PM +0100, Mason wrote:
>> >
>> >> Is there a way to write a driver within the existing framework?
>> >
>> > I think so, looking back at comments from Russell, I do tend to agree with
>> > that. Is there a specific reason why sbox can't be tied to alloc and free
>> > channels?
>>
>> Here's a recap of the situation.
>>
>> The "SBOX+MBUS" HW is used in several iterations of the tango SoC:
>
> btw is SBOX setup dependent upon the peripheral connected to?
The sbox is basically a crossbar that connects each of a number of input
ports to any of a number of output ports. A few of the inputs and
outputs are dma channels reading or writing to memory while the rest are
peripheral devices. To perform a mem-to-device transfer, you pick a dma
read channel, program the sbox to connect it to the chosen device, and
finally program the dma channel with address and size to transfer.
>> tango3
>> 2 memory channels available
>> 6 devices ("clients"?) may request an MBUS channel
>
> But only 2 can get a channel at any time..
>
>> tango4 (one more channel)
>> 3 memory channels available
>> 7 devices may request an MBUS channel :
>> NFC0, NFC1, SATA0, SATA1, memcpy, (IDE0, IDE1)
>
> Same here
>
> Only thing is users shouldn't hold on to channel and freeup when not in use.
>
>> Notes:
>> The current NFC driver supports only one controller.
>> IDE is mostly obsolete at this point.
>>
>> tango5 (SATA gets own dedicated MBUS channel pair)
>> 3 memory channels available
>> 5 devices may request an MBUS channel :
>> NFC0, NFC1, memcpy, (IDE0, IDE1)
>>
>>
>> If I understand the current DMA driver (written by Mans), client
>> drivers are instructed to use a specific channel in the DT, and
>> the DMA driver muxes access to that channel. The DMA driver
>> manages a per-channel queue of outstanding DMA transfer requests,
>> and a new transfer is started friom within the DMA ISR
>> (modulo the fact that the interrupt does not signal completion
>> of the transfer, as explained else-thread).
>>
>> What you're proposing, Vinod, is to make a channel exclusive
>> to a driver, as long as the driver has not explicitly released
>> the channel, via dma_release_channel(), right?
>
> Precisely, but yes the downside of that is concurrent access are
> limited, but am not sure if driver implements virtual channels and
> allows that..
My driver implements virtual channels. The problem is that the physical
dma channels signal completion slightly too soon, at least with
mem-to-device transfers. Apparently we need to keep the sbox routing
until the peripheral indicates that it has actually received all the
data.
--
M?ns Rullg?rd
^ permalink raw reply
* Tearing down DMA transfer setup after DMA client has finished
From: Måns Rullgård @ 2016-12-07 16:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161207164341.GX6408@localhost>
Vinod Koul <vinod.koul@intel.com> writes:
> On Tue, Dec 06, 2016 at 01:14:20PM +0000, M?ns Rullg?rd wrote:
>>
>> That's not going to work very well. Device drivers typically request
>> dma channels in their probe functions or when the device is opened.
>> This means that reserving one of the few channels there will inevitably
>> make some other device fail to operate.
>
> No that doesnt make sense at all, you should get a channel only when you
> want to use it and not in probe!
Tell that to just about every single driver ever written.
--
M?ns Rullg?rd
^ permalink raw reply
* [PATCH 8/9] arm64: dts: rockchip: partially describe PWM regulators for Gru
From: Heiko Stuebner @ 2016-12-07 16:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480645653-36943-9-git-send-email-briannorris@chromium.org>
Hi Brian,
Am Donnerstag, 1. Dezember 2016, 18:27:32 CET schrieb Brian Norris:
> We need to add regulators to the CPU nodes, so cpufreq doesn't think it
> can crank up the clock speed without changing the voltage. However, we
> don't yet have the DT bindings to fully describe the Over Voltage
> Protection (OVP) circuits on these boards. Without that description, we
> might end up changing the voltage too much, too fast.
>
> Add the pwm-regulator descriptions and associate the CPU OPPs, but leave
> them disabled.
>
> Signed-off-by: Brian Norris <briannorris@chromium.org>
is there a specific reason for keeping this change separate?
While it is nice for documentation reasons, as it stands now the previous
patch introduces a regression (cpufreq trying to scale without regulators) and
immediately fixes it here.
So if you're ok with it, I'd like to merge this one back into the previous
patch when applying.
Heiko
^ permalink raw reply
* [PATCH] drm: hdlcd: Work properly in big-endian mode
From: Robin Murphy @ 2016-12-07 16:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <548dc9d9-4d21-7f93-cc92-5bc3234f1b8f@arm.com>
On 07/12/16 16:42, Robin Murphy wrote:
> On 07/12/16 15:57, Daniel Vetter wrote:
>> On Wed, Dec 07, 2016 at 03:31:40PM +0000, Robin Murphy wrote:
>>> Under a big-endian kernel, colours on the framebuffer all come out a
>>> delightful shade of wrong, since we fail to take the reversed byte
>>> order into account. Fortunately, the HDLCD has a control bit to make it
>>> automatically byteswap big-endian data; let's use it as appropriate.
>>>
>>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>>
>> fourcc codes (and the drm fourcc codes) are supposed to be little-endian.
>> All of them. So either we fix up the drivers and userspace to set that
>> flag correctly (which would mean hdlcd should expose twice as many
>> formats, each one with the little and big endian mode).
>
> AFAICS, SIMPLEFB_FORMATS *is* supposed to be explicitly little-endian
> modes. I see that DRM_FORMAT_BIG_ENDIAN exists, but nothing in-tree ever
> sets it :/
>
> My vague (and probably wrong) assumption was that the HDLCD is still
> expecting little-endian data, but the the CPU is writing framebuffer
> data as host-endian words, hence what the HDLCD thinks is xRGB is
> actually RGBx under a big-endian kernel - It's certainly consistent
> between kernel (fbcon) and userspace (fb-test[1]): white is yellow, blue
> is black, green is red and red is green. I don't know how to test
> "proper" DRM (I've failed to get X to work with the Arch Linux ARM
> distro I have on there at the moment).
>
> Once again I'm somewhat out of my depth here - I just found a thing that
> seemed appropriate and visibly resolved the immediate problem :)
> By comparison, the same use-cases (fbcon and fb-test) under the same
> big-endian kernel do *not* show the same problem with nouveau driving a
> PCIe 7600GT card, which led me to believe it was HDLCD-specific.
Off the back of that, upon closer inspection, nv_crtc_commit() would
appear to already be doing very much the equivalent thing to what I'm
doing in this patch, so now I have no idea whether this is right or
everything's wrong.
Robin.
> [1]:https://github.com/prpplague/fb-test-app
>
>> Or we nuke the big endian flag from drm fourcc. Adding AMD folks who afaik
>> are the only other ones who ever cared about big endian in drm.
>> -Daniel
>>
>>> ---
>>> drivers/gpu/drm/arm/hdlcd_crtc.c | 7 ++++++-
>>> 1 file changed, 6 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
>>> index 28341b32067f..eceb7bed5dd0 100644
>>> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
>>> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
>>> @@ -63,6 +63,7 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
>>> uint32_t pixel_format;
>>> struct simplefb_format *format = NULL;
>>> int i;
>>> + u32 reg;
>>>
>>> pixel_format = crtc->primary->state->fb->pixel_format;
>>>
>>> @@ -76,7 +77,11 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
>>>
>>> /* HDLCD uses 'bytes per pixel', zero means 1 byte */
>>> btpp = (format->bits_per_pixel + 7) / 8;
>>> - hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, (btpp - 1) << 3);
>>> + reg = (btpp - 1) << 3;
>>> +#ifdef __BIG_ENDIAN
>>> + reg |= HDLCD_PIXEL_FMT_BIG_ENDIAN;
>>> +#endif
>>> + hdlcd_write(hdlcd, HDLCD_REG_PIXEL_FORMAT, reg);
>>>
>>> /*
>>> * The format of the HDLCD_REG_<color>_SELECT register is:
>>> --
>>> 2.10.2.dirty
>>>
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel at lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply
* [PATCH v2 00/10] perf: arm64: Support for Hisilicon SoC Hardware event counters
From: Anurup M @ 2016-12-07 16:50 UTC (permalink / raw)
To: linux-arm-kernel
From: John Garry <john.garry@huawei.com>
Provide Support for Hisilicon SoC(HiP05/06/07) Hardware event counters.
The Hisilicon SoC HiP0x series has many uncore or non-CPU performance
events and counters units.
This patch series is implemented refering to arm-cci, Intel/AMD uncore and
also the cavium thunderX and xgene uncore pmu patches.
This v2 version has addressed the review comments of v1 version.
Support for Hisilicon L3 cache(L3C) and Misclennaneous nodes(MN) hardware
events and counters are added in this implementation.
The Hisilicon uncore PMUs can be found under /sys/bus/event_source/devices.
The counters are exported via sysfs in the corresponding events files
under the PMU directory so the perf tool can list the event names.
ToDo:
1) The counter overflow handling is currently unsupported in this
patch series.
2) ACPI support.
Version history
---------------
v2
--
- Fix review comments of v2 version.
- Move djtag driver to drivers/perf/hisilicon.
- Have separate PMU instance for each L3 cache banks.
- Modify device properties in DTS as per review comments.
- Handle hardware version difference.
- Change compatible names of djtag so use prefix hisi-
and remove chip version as driver only depend on djtag
hw version.
- use devm_kzalloc.
- Remove DDRC changes in this series. As the DDRC PMU doesnot
depend on djtag it will be send separately.
v1
--
-Initial version with support for L3C, MN and DDRC event counters
-Djtag driver is used to access registers of L3 cache and MN.
Anurup M (7):
arm64: MAINTAINERS: hisi: Add hisilicon SoC PMU support
dt-bindings: perf: hisi: Add Devicetree bindings for Hisilicon SoC PMU
Documentation: perf: hisi: Documentation for HIP05/06/07 PMU event
counting.
perf: hisi: Update Kconfig for Hisilicon PMU support
perf: hisi: Add support for Hisilicon SoC event counters
perf: hisi: Add sysfs attributes for L3 cache(L3C) PMU
dts: arm64: hip06: Add Hisilicon SoC PMU support
Shaokun Zhang (1):
perf: hisi: Miscellanous node(MN) event counting in perf
Tan Xiaojun (2):
dt-bindings: hisi: Add Hisilicon HiP05/06/07 Djtag dts bindings
drivers: perf: hisi: Add support for Hisilicon Djtag driver
.../devicetree/bindings/arm/hisilicon/djtag.txt | 66 ++
.../devicetree/bindings/arm/hisilicon/pmu.txt | 98 +++
Documentation/perf/hisi-pmu.txt | 75 +++
MAINTAINERS | 9 +
arch/arm64/boot/dts/hisilicon/hip06.dtsi | 78 +++
drivers/perf/Kconfig | 8 +
drivers/perf/Makefile | 1 +
drivers/perf/hisilicon/Makefile | 1 +
drivers/perf/hisilicon/djtag.c | 729 +++++++++++++++++++++
drivers/perf/hisilicon/djtag.h | 39 ++
drivers/perf/hisilicon/hisi_uncore_l3c.c | 629 ++++++++++++++++++
drivers/perf/hisilicon/hisi_uncore_mn.c | 516 +++++++++++++++
drivers/perf/hisilicon/hisi_uncore_pmu.c | 365 +++++++++++
drivers/perf/hisilicon/hisi_uncore_pmu.h | 128 ++++
14 files changed, 2742 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/djtag.txt
create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/pmu.txt
create mode 100644 Documentation/perf/hisi-pmu.txt
create mode 100644 drivers/perf/hisilicon/Makefile
create mode 100644 drivers/perf/hisilicon/djtag.c
create mode 100644 drivers/perf/hisilicon/djtag.h
create mode 100644 drivers/perf/hisilicon/hisi_uncore_l3c.c
create mode 100644 drivers/perf/hisilicon/hisi_uncore_mn.c
create mode 100644 drivers/perf/hisilicon/hisi_uncore_pmu.c
create mode 100644 drivers/perf/hisilicon/hisi_uncore_pmu.h
--
2.1.4
^ permalink raw reply
* [PATCH v4 0/5] Add support for the STM32F4 I2C
From: M'boumba Cedric Madianga @ 2016-12-07 16:51 UTC (permalink / raw)
To: linux-arm-kernel
This patchset adds support for the I2C controller embedded in STM32F4xx SoC.
It enables I2C transfer in interrupt mode with Standard-mode and Fast-mode bus
speed.
Changes since v3 after Wolfram's review:
- Add COMPILE_TEST flag in Kconfig
- Use correct driver name in Kconfig i.e i2c-stm32f4 instead of i2c-st
- Use more comprehensible name stm32f4_i2c_msg for client specific data
- Don't store reset control node as just needed in probe
- Use clamp() function to test value between 2 ranges
- Use new "i2c_8bit_addr_from_msg() function to build I2C address
- Don't write error messages for timeout
- Remove error message when i2c_add_adapter() fails as it is already handled by
the i2c core driver
M'boumba Cedric Madianga (5):
dt-bindings: Document the STM32 I2C bindings
i2c: Add STM32F4 I2C driver
ARM: dts: Add I2C1 support for STM32F429 SoC
ARM: dts: Add I2C1 support for STM32429 eval board
ARM: configs: Add I2C support for STM32 defconfig
.../devicetree/bindings/i2c/i2c-stm32.txt | 33 +
arch/arm/boot/dts/stm32429i-eval.dts | 6 +
arch/arm/boot/dts/stm32f429.dtsi | 23 +
arch/arm/configs/stm32_defconfig | 3 +
drivers/i2c/busses/Kconfig | 10 +
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-stm32f4.c | 857 +++++++++++++++++++++
7 files changed, 933 insertions(+)
create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt
create mode 100644 drivers/i2c/busses/i2c-stm32f4.c
--
1.9.1
^ permalink raw reply
* [PATCH v4 1/5] dt-bindings: Document the STM32 I2C bindings
From: M'boumba Cedric Madianga @ 2016-12-07 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481129492-26600-1-git-send-email-cedric.madianga@gmail.com>
This patch adds documentation of device tree bindings for the STM32 I2C
controller.
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/i2c/i2c-stm32.txt | 33 ++++++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt
diff --git a/Documentation/devicetree/bindings/i2c/i2c-stm32.txt b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
new file mode 100644
index 0000000..78eaf7b
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
@@ -0,0 +1,33 @@
+* I2C controller embedded in STMicroelectronics STM32 I2C platform
+
+Required properties :
+- compatible : Must be "st,stm32f4-i2c"
+- reg : Offset and length of the register set for the device
+- interrupts : Must contain the interrupt id for I2C event and then the
+ interrupt id for I2C error.
+- resets: Must contain the phandle to the reset controller.
+- clocks: Must contain the input clock of the I2C instance.
+- A pinctrl state named "default" must be defined to set pins in mode of
+ operation for I2C transfer
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties :
+- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified,
+ the default 100 kHz frequency will be used. As only Normal and Fast modes
+ are supported, possible values are 100000 and 400000.
+
+Example :
+
+ i2c at 40005400 {
+ compatible = "st,stm32f4-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x40005400 0x400>;
+ interrupts = <31>,
+ <32>;
+ resets = <&rcc 277>;
+ clocks = <&rcc 0 149>;
+ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
+ pinctrl-names = "default";
+ };
--
1.9.1
^ permalink raw reply related
* [PATCH v4 2/5] i2c: Add STM32F4 I2C driver
From: M'boumba Cedric Madianga @ 2016-12-07 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481129492-26600-1-git-send-email-cedric.madianga@gmail.com>
This patch adds support for the STM32F4 I2C controller.
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
drivers/i2c/busses/Kconfig | 10 +
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-stm32f4.c | 857 +++++++++++++++++++++++++++++++++++++++
3 files changed, 868 insertions(+)
create mode 100644 drivers/i2c/busses/i2c-stm32f4.c
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 8e43914..584e0d7 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -886,6 +886,16 @@ config I2C_ST
This driver can also be built as module. If so, the module
will be called i2c-st.
+config I2C_STM32F4
+ tristate "STMicroelectronics STM32F4 I2C support"
+ depends on ARCH_STM32 || COMPILE_TEST
+ help
+ Enable this option to add support for STM32 I2C controller embedded
+ in STM32F4 SoCs.
+
+ This driver can also be built as module. If so, the module
+ will be called i2c-stm32f4.
+
config I2C_STU300
tristate "ST Microelectronics DDC I2C interface"
depends on MACH_U300
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 1c1bac8..a2c6ff5 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
obj-$(CONFIG_I2C_ST) += i2c-st.o
+obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c
new file mode 100644
index 0000000..faf12fd
--- /dev/null
+++ b/drivers/i2c/busses/i2c-stm32f4.c
@@ -0,0 +1,857 @@
+/*
+ * Driver for STMicroelectronics STM32 I2C controller
+ *
+ * Copyright (C) M'boumba Cedric Madianga 2015
+ * Author: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
+ *
+ * This driver is based on i2c-st.c
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+/* STM32F4 I2C offset registers */
+#define STM32F4_I2C_CR1 0x00
+#define STM32F4_I2C_CR2 0x04
+#define STM32F4_I2C_DR 0x10
+#define STM32F4_I2C_SR1 0x14
+#define STM32F4_I2C_SR2 0x18
+#define STM32F4_I2C_CCR 0x1C
+#define STM32F4_I2C_TRISE 0x20
+#define STM32F4_I2C_FLTR 0x24
+
+/* STM32F4 I2C control 1*/
+#define STM32F4_I2C_CR1_SWRST BIT(15)
+#define STM32F4_I2C_CR1_POS BIT(11)
+#define STM32F4_I2C_CR1_ACK BIT(10)
+#define STM32F4_I2C_CR1_STOP BIT(9)
+#define STM32F4_I2C_CR1_START BIT(8)
+#define STM32F4_I2C_CR1_PE BIT(0)
+
+/* STM32F4 I2C control 2 */
+#define STM32F4_I2C_CR2_FREQ_MASK GENMASK(5, 0)
+#define STM32F4_I2C_CR2_FREQ(n) ((n & STM32F4_I2C_CR2_FREQ_MASK))
+#define STM32F4_I2C_CR2_ITBUFEN BIT(10)
+#define STM32F4_I2C_CR2_ITEVTEN BIT(9)
+#define STM32F4_I2C_CR2_ITERREN BIT(8)
+#define STM32F4_I2C_CR2_IRQ_MASK (STM32F4_I2C_CR2_ITBUFEN \
+ | STM32F4_I2C_CR2_ITEVTEN \
+ | STM32F4_I2C_CR2_ITERREN)
+
+/* STM32F4 I2C Status 1 */
+#define STM32F4_I2C_SR1_AF BIT(10)
+#define STM32F4_I2C_SR1_ARLO BIT(9)
+#define STM32F4_I2C_SR1_BERR BIT(8)
+#define STM32F4_I2C_SR1_TXE BIT(7)
+#define STM32F4_I2C_SR1_RXNE BIT(6)
+#define STM32F4_I2C_SR1_BTF BIT(2)
+#define STM32F4_I2C_SR1_ADDR BIT(1)
+#define STM32F4_I2C_SR1_SB BIT(0)
+#define STM32F4_I2C_SR1_ITEVTEN_MASK (STM32F4_I2C_SR1_BTF \
+ | STM32F4_I2C_SR1_ADDR \
+ | STM32F4_I2C_SR1_SB)
+#define STM32F4_I2C_SR1_ITBUFEN_MASK (STM32F4_I2C_SR1_TXE \
+ | STM32F4_I2C_SR1_RXNE)
+#define STM32F4_I2C_SR1_ITERREN_MASK (STM32F4_I2C_SR1_AF \
+ | STM32F4_I2C_SR1_ARLO \
+ | STM32F4_I2C_SR1_BERR)
+
+/* STM32F4 I2C Status 2 */
+#define STM32F4_I2C_SR2_BUSY BIT(1)
+
+/* STM32F4 I2C Control Clock */
+#define STM32F4_I2C_CCR_CCR_MASK GENMASK(11, 0)
+#define STM32F4_I2C_CCR_CCR(n) ((n & STM32F4_I2C_CCR_CCR_MASK))
+#define STM32F4_I2C_CCR_FS BIT(15)
+#define STM32F4_I2C_CCR_DUTY BIT(14)
+
+/* STM32F4 I2C Trise */
+#define STM32F4_I2C_TRISE_VALUE_MASK GENMASK(5, 0)
+#define STM32F4_I2C_TRISE_VALUE(n) ((n & STM32F4_I2C_TRISE_VALUE_MASK))
+
+/* STM32F4 I2C Filter */
+#define STM32F4_I2C_FLTR_DNF_MASK GENMASK(3, 0)
+#define STM32F4_I2C_FLTR_DNF(n) ((n & STM32F4_I2C_FLTR_DNF_MASK))
+#define STM32F4_I2C_FLTR_ANOFF BIT(4)
+
+#define STM32F4_I2C_MIN_FREQ 2
+#define STM32F4_I2C_MAX_FREQ 42
+#define FAST_MODE_MAX_RISE_TIME 1000
+#define STD_MODE_MAX_RISE_TIME 300
+#define MHZ_TO_HZ 1000000
+
+enum stm32f4_i2c_speed {
+ STM32F4_I2C_SPEED_STANDARD, /* 100 kHz */
+ STM32F4_I2C_SPEED_FAST, /* 400 kHz */
+ STM32F4_I2C_SPEED_END,
+};
+
+/**
+ * struct stm32f4_i2c_timings - per-Mode tuning parameters
+ * @duty: Fast mode duty cycle
+ * @mul_ccr: Value to be multiplied to CCR to reach 100Khz/400Khz SCL frequency
+ * @min_ccr: Minimum clock ctrl reg value to reach 100Khz/400Khz SCL frequency
+ */
+struct stm32f4_i2c_timings {
+ u32 rate;
+ u32 duty;
+ u32 mul_ccr;
+ u32 min_ccr;
+};
+
+/**
+ * struct stm32f4_i2c_msg - client specific data
+ * @addr: 8-bit slave addr, including r/w bit
+ * @count: number of bytes to be transferred
+ * @buf: data buffer
+ * @result: result of the transfer
+ * @stop: last I2C msg to be sent, i.e. STOP to be generated
+ */
+struct stm32f4_i2c_msg {
+ u8 addr;
+ u32 count;
+ u8 *buf;
+ int result;
+ bool stop;
+};
+
+/**
+ * struct stm32f4_i2c_dev - private data of the controller
+ * @adap: I2C adapter for this controller
+ * @dev: device for this controller
+ * @base: virtual memory area
+ * @complete: completion of I2C message
+ * @irq_event: interrupt event line for the controller
+ * @irq_error: interrupt error line for the controller
+ * @clk: hw i2c clock
+ * speed: I2C clock frequency of the controller. Standard or Fast only supported
+ * @msg: I2C transfer information
+ */
+struct stm32f4_i2c_dev {
+ struct i2c_adapter adap;
+ struct device *dev;
+ void __iomem *base;
+ struct completion complete;
+ int irq_event;
+ int irq_error;
+ struct clk *clk;
+ int speed;
+ struct stm32f4_i2c_msg msg;
+};
+
+static struct stm32f4_i2c_timings i2c_timings[] = {
+ [STM32F4_I2C_SPEED_STANDARD] = {
+ .mul_ccr = 1,
+ .min_ccr = 4,
+ .duty = 0,
+ },
+ [STM32F4_I2C_SPEED_FAST] = {
+ .mul_ccr = 16,
+ .min_ccr = 1,
+ .duty = 1,
+ },
+};
+
+static inline void stm32f4_i2c_set_bits(void __iomem *reg, u32 mask)
+{
+ writel_relaxed(readl_relaxed(reg) | mask, reg);
+}
+
+static inline void stm32f4_i2c_clr_bits(void __iomem *reg, u32 mask)
+{
+ writel_relaxed(readl_relaxed(reg) & ~mask, reg);
+}
+
+static void stm32f4_i2c_soft_reset(struct stm32f4_i2c_dev *i2c_dev)
+{
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_SWRST);
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_SWRST);
+}
+
+static void stm32f4_i2c_disable_it(struct stm32f4_i2c_dev *i2c_dev)
+{
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_IRQ_MASK);
+}
+
+static void stm32f4_i2c_set_periph_clk_freq(struct stm32f4_i2c_dev *i2c_dev)
+{
+ u32 clk_rate, cr2, freq;
+
+ cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ cr2 &= ~STM32F4_I2C_CR2_FREQ_MASK;
+
+ clk_rate = clk_get_rate(i2c_dev->clk);
+ freq = clk_rate / MHZ_TO_HZ;
+
+ if (freq > STM32F4_I2C_MAX_FREQ)
+ freq = STM32F4_I2C_MAX_FREQ;
+ else if (freq < STM32F4_I2C_MIN_FREQ)
+ freq = STM32F4_I2C_MIN_FREQ;
+
+ cr2 |= STM32F4_I2C_CR2_FREQ(freq);
+ writel_relaxed(cr2, i2c_dev->base + STM32F4_I2C_CR2);
+}
+
+static void stm32f4_i2c_set_rise_time(struct stm32f4_i2c_dev *i2c_dev)
+{
+ u32 trise, freq, cr2, val;
+
+ cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ freq = cr2 & STM32F4_I2C_CR2_FREQ_MASK;
+
+ trise = readl_relaxed(i2c_dev->base + STM32F4_I2C_TRISE);
+ trise &= ~STM32F4_I2C_TRISE_VALUE_MASK;
+
+ /* Maximum rise time computation */
+ if (i2c_dev->speed == STM32F4_I2C_SPEED_STANDARD) {
+ trise |= STM32F4_I2C_TRISE_VALUE((freq + 1));
+ } else {
+ val = freq * FAST_MODE_MAX_RISE_TIME / STD_MODE_MAX_RISE_TIME;
+ trise |= STM32F4_I2C_TRISE_VALUE((val + 1));
+ }
+
+ writel_relaxed(trise, i2c_dev->base + STM32F4_I2C_TRISE);
+}
+
+static void stm32f4_i2c_set_speed_mode(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_timings *t = &i2c_timings[i2c_dev->speed];
+ u32 ccr, clk_rate;
+ int val;
+
+ ccr = readl_relaxed(i2c_dev->base + STM32F4_I2C_CCR);
+ ccr &= ~(STM32F4_I2C_CCR_FS | STM32F4_I2C_CCR_DUTY |
+ STM32F4_I2C_CCR_CCR_MASK);
+
+ clk_rate = clk_get_rate(i2c_dev->clk);
+ val = clk_rate / MHZ_TO_HZ * t->mul_ccr;
+ if (val < t->min_ccr)
+ val = t->min_ccr;
+ ccr |= STM32F4_I2C_CCR_CCR(val);
+
+ if (t->duty)
+ ccr |= STM32F4_I2C_CCR_FS | STM32F4_I2C_CCR_DUTY;
+
+ writel_relaxed(ccr, i2c_dev->base + STM32F4_I2C_CCR);
+}
+
+static void stm32f4_i2c_set_filter(struct stm32f4_i2c_dev *i2c_dev)
+{
+ u32 filter;
+
+ /* Enable analog noise filter and disable digital noise filter */
+ filter = readl_relaxed(i2c_dev->base + STM32F4_I2C_FLTR);
+ filter &= ~(STM32F4_I2C_FLTR_ANOFF | STM32F4_I2C_FLTR_DNF_MASK);
+ writel_relaxed(filter, i2c_dev->base + STM32F4_I2C_FLTR);
+}
+
+/**
+ * stm32f4_i2c_hw_config() - Prepare I2C block
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_hw_config(struct stm32f4_i2c_dev *i2c_dev)
+{
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+
+ /* Disable I2C */
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_PE);
+
+ stm32f4_i2c_set_periph_clk_freq(i2c_dev);
+
+ stm32f4_i2c_set_rise_time(i2c_dev);
+
+ stm32f4_i2c_set_speed_mode(i2c_dev);
+
+ stm32f4_i2c_set_filter(i2c_dev);
+
+ /* Enable I2C */
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_PE);
+}
+
+static int stm32f4_i2c_wait_free_bus(struct stm32f4_i2c_dev *i2c_dev)
+{
+ u32 status;
+ int ret;
+
+ ret = readl_relaxed_poll_timeout(i2c_dev->base + STM32F4_I2C_SR2,
+ status,
+ !(status & STM32F4_I2C_SR2_BUSY),
+ 10, 1000);
+ if (ret) {
+ dev_err(i2c_dev->dev, "bus not free\n");
+ ret = -EBUSY;
+ }
+
+ return ret;
+}
+
+/**
+ * stm32f4_i2c_write_ byte() - Write a byte in the data register
+ * @i2c_dev: Controller's private data
+ * @byte: Data to write in the register
+ */
+static void stm32f4_i2c_write_byte(struct stm32f4_i2c_dev *i2c_dev, u8 byte)
+{
+ writel_relaxed(byte, i2c_dev->base + STM32F4_I2C_DR);
+}
+
+/**
+ * stm32f4_i2c_write_msg() - Fill the data register in write mode
+ * @i2c_dev: Controller's private data
+ *
+ * This function fills the data register with I2C transfer buffer
+ */
+static void stm32f4_i2c_write_msg(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+
+ stm32f4_i2c_write_byte(i2c_dev, *msg->buf++);
+ msg->count--;
+}
+
+static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ u32 rbuf;
+
+ rbuf = readl_relaxed(i2c_dev->base + STM32F4_I2C_DR);
+ *msg->buf++ = (u8)rbuf & 0xff;
+ msg->count--;
+}
+
+static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+ stm32f4_i2c_disable_it(i2c_dev);
+
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ if (msg->stop)
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+ else
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+
+ complete(&i2c_dev->complete);
+}
+
+/**
+ * stm32f4_i2c_handle_write() - Handle FIFO empty interrupt in case of write
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_write(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+ if (msg->count) {
+ stm32f4_i2c_write_msg(i2c_dev);
+ if (!msg->count) {
+ /* Disable BUF interrupt */
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+ }
+ } else {
+ stm32f4_i2c_terminate_xfer(i2c_dev);
+ }
+}
+
+/**
+ * stm32f4_i2c_handle_read() - Handle FIFO empty interrupt in case of read
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_read(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+ switch (msg->count) {
+ case 1:
+ stm32f4_i2c_disable_it(i2c_dev);
+ stm32f4_i2c_read_msg(i2c_dev);
+ complete(&i2c_dev->complete);
+ break;
+ case 2:
+ case 3:
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+ break;
+ default:
+ stm32f4_i2c_read_msg(i2c_dev);
+ }
+}
+
+/**
+ * stm32f4_i2c_handle_rx_btf() - Handle byte transfer finished interrupt
+ * in case of read
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_rx_btf(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg;
+ u32 mask;
+ int i;
+
+ switch (msg->count) {
+ case 2:
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ /* Generate STOP or REPSTART */
+ if (msg->stop)
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+ else
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+
+ /* Read two last data bytes */
+ for (i = 2; i > 0; i--)
+ stm32f4_i2c_read_msg(i2c_dev);
+
+ /* Disable EVT and ERR interrupt */
+ reg = i2c_dev->base + STM32F4_I2C_CR2;
+ mask = STM32F4_I2C_CR2_ITEVTEN | STM32F4_I2C_CR2_ITERREN;
+ stm32f4_i2c_clr_bits(reg, mask);
+
+ complete(&i2c_dev->complete);
+ break;
+ case 3:
+ /* Enable ACK and read data */
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+ stm32f4_i2c_read_msg(i2c_dev);
+ break;
+ default:
+ stm32f4_i2c_read_msg(i2c_dev);
+ }
+}
+
+/**
+ * stm32f4_i2c_handle_rx_addr() - Handle address matched interrupt in case of
+ * master receiver
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_rx_addr(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg;
+ u32 sr2;
+
+ switch (msg->count) {
+ case 0:
+ stm32f4_i2c_terminate_xfer(i2c_dev);
+ /* Clear ADDR flag */
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+ break;
+ case 1:
+ /*
+ * Single byte reception:
+ * Enable NACK, clear ADDR flag and generate STOP or RepSTART
+ */
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+ if (msg->stop)
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+ else
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+ break;
+ case 2:
+ /*
+ * 2-byte reception:
+ * Enable NACK and PEC Position Ack and clear ADDR flag
+ */
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_POS);
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+ break;
+
+ default:
+ /* N-byte reception: Enable ACK and clear ADDR flag */
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_ACK);
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+ break;
+ }
+}
+
+/**
+ * stm32f4_i2c_isr_event() - Interrupt routine for I2C bus event
+ * @irq: interrupt number
+ * @data: Controller's private data
+ */
+static irqreturn_t stm32f4_i2c_isr_event(int irq, void *data)
+{
+ struct stm32f4_i2c_dev *i2c_dev = data;
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg;
+ u32 real_status, possible_status, ien, sr2;
+ int flag;
+
+ ien = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ ien &= STM32F4_I2C_CR2_IRQ_MASK;
+ possible_status = 0;
+
+ /* Check possible status combinations */
+ if (ien & STM32F4_I2C_CR2_ITEVTEN) {
+ possible_status = STM32F4_I2C_SR1_ITEVTEN_MASK;
+ if (ien & STM32F4_I2C_CR2_ITBUFEN)
+ possible_status |= STM32F4_I2C_SR1_ITBUFEN_MASK;
+ }
+
+ real_status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+
+ if (!(real_status & possible_status)) {
+ dev_dbg(i2c_dev->dev,
+ "spurious evt it (status=0x%08x, ien=0x%08x)\n",
+ real_status, ien);
+ return IRQ_NONE;
+ }
+
+ /* Use __fls() to check error bits first */
+ flag = __fls(real_status & possible_status);
+
+ switch (1 << flag) {
+ case STM32F4_I2C_SR1_SB:
+ stm32f4_i2c_write_byte(i2c_dev, msg->addr);
+ break;
+
+ case STM32F4_I2C_SR1_ADDR:
+ if (msg->addr & I2C_M_RD)
+ stm32f4_i2c_handle_rx_addr(i2c_dev);
+ else
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+
+ /* Enable ITBUF interrupts */
+ reg = i2c_dev->base + STM32F4_I2C_CR2;
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+ break;
+
+ case STM32F4_I2C_SR1_BTF:
+ if (msg->addr & I2C_M_RD)
+ stm32f4_i2c_handle_rx_btf(i2c_dev);
+ else
+ stm32f4_i2c_handle_write(i2c_dev);
+ break;
+
+ case STM32F4_I2C_SR1_TXE:
+ stm32f4_i2c_handle_write(i2c_dev);
+ break;
+
+ case STM32F4_I2C_SR1_RXNE:
+ stm32f4_i2c_handle_read(i2c_dev);
+ break;
+
+ default:
+ dev_err(i2c_dev->dev,
+ "evt it unhandled: status=0x%08x)\n", real_status);
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * stm32f4_i2c_isr_error() - Interrupt routine for I2C bus error
+ * @irq: interrupt number
+ * @data: Controller's private data
+ */
+static irqreturn_t stm32f4_i2c_isr_error(int irq, void *data)
+{
+ struct stm32f4_i2c_dev *i2c_dev = data;
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg;
+ u32 real_status, possible_status, ien;
+ int flag;
+
+ ien = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ ien &= STM32F4_I2C_CR2_IRQ_MASK;
+ possible_status = 0;
+
+ /* Check possible status combinations */
+ if (ien & STM32F4_I2C_CR2_ITERREN)
+ possible_status = STM32F4_I2C_SR1_ITERREN_MASK;
+
+ real_status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+
+ if (!(real_status & possible_status)) {
+ dev_dbg(i2c_dev->dev,
+ "spurious err it (status=0x%08x, ien=0x%08x)\n",
+ real_status, ien);
+ return IRQ_NONE;
+ }
+
+ /* Use __fls() to check error bits first */
+ flag = __fls(real_status & possible_status);
+
+ switch (1 << flag) {
+ case STM32F4_I2C_SR1_BERR:
+ reg = i2c_dev->base + STM32F4_I2C_SR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_SR1_BERR);
+ msg->result = -EIO;
+ break;
+
+ case STM32F4_I2C_SR1_ARLO:
+ reg = i2c_dev->base + STM32F4_I2C_SR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_SR1_ARLO);
+ msg->result = -EAGAIN;
+ break;
+
+ case STM32F4_I2C_SR1_AF:
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+ msg->result = -EIO;
+ break;
+
+ default:
+ dev_err(i2c_dev->dev,
+ "err it unhandled: status=0x%08x)\n", real_status);
+ return IRQ_NONE;
+ }
+
+ stm32f4_i2c_soft_reset(i2c_dev);
+ stm32f4_i2c_disable_it(i2c_dev);
+ complete(&i2c_dev->complete);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * stm32f4_i2c_xfer_msg() - Transfer a single I2C message
+ * @i2c_dev: Controller's private data
+ * @msg: I2C message to transfer
+ * @is_first: first message of the sequence
+ * @is_last: last message of the sequence
+ */
+static int stm32f4_i2c_xfer_msg(struct stm32f4_i2c_dev *i2c_dev,
+ struct i2c_msg *msg, bool is_first,
+ bool is_last)
+{
+ struct stm32f4_i2c_msg *f4_msg = &i2c_dev->msg;
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+ unsigned long timeout;
+ u32 mask;
+ int ret;
+
+ f4_msg->addr = i2c_8bit_addr_from_msg(msg);
+ f4_msg->buf = msg->buf;
+ f4_msg->count = msg->len;
+ f4_msg->result = 0;
+ f4_msg->stop = is_last;
+
+ reinit_completion(&i2c_dev->complete);
+
+ /* Enable ITEVT and ITERR interrupts */
+ mask = STM32F4_I2C_CR2_ITEVTEN | STM32F4_I2C_CR2_ITERREN;
+ stm32f4_i2c_set_bits(i2c_dev->base + STM32F4_I2C_CR2, mask);
+
+ if (is_first) {
+ ret = stm32f4_i2c_wait_free_bus(i2c_dev);
+ if (ret)
+ return ret;
+
+ /* START generation */
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+ }
+
+ timeout = wait_for_completion_timeout(&i2c_dev->complete,
+ i2c_dev->adap.timeout);
+ ret = f4_msg->result;
+
+ /* Disable PEC position Ack */
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_POS);
+
+ if (!timeout)
+ ret = -ETIMEDOUT;
+
+ return ret;
+}
+
+/**
+ * stm32f4_i2c_xfer() - Transfer combined I2C message
+ * @i2c_adap: Adapter pointer to the controller
+ * @msgs: Pointer to data to be written.
+ * @num: Number of messages to be executed
+ */
+static int stm32f4_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+ int num)
+{
+ struct stm32f4_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
+ int ret, i;
+
+ ret = clk_enable(i2c_dev->clk);
+ if (ret) {
+ dev_err(i2c_dev->dev, "Failed to enable clock\n");
+ return ret;
+ }
+
+ stm32f4_i2c_hw_config(i2c_dev);
+
+ for (i = 0; i < num && !ret; i++)
+ ret = stm32f4_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0,
+ i == num - 1);
+
+ clk_disable(i2c_dev->clk);
+
+ return (ret < 0) ? ret : i;
+}
+
+static u32 stm32f4_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm stm32f4_i2c_algo = {
+ .master_xfer = stm32f4_i2c_xfer,
+ .functionality = stm32f4_i2c_func,
+};
+
+static int stm32f4_i2c_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct stm32f4_i2c_dev *i2c_dev;
+ struct resource *res;
+ u32 clk_rate;
+ struct i2c_adapter *adap;
+ struct reset_control *rst;
+ int ret;
+
+ i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+ if (!i2c_dev)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(i2c_dev->base))
+ return PTR_ERR(i2c_dev->base);
+
+ i2c_dev->irq_event = irq_of_parse_and_map(np, 0);
+ if (!i2c_dev->irq_event) {
+ dev_err(&pdev->dev, "IRQ missing or invalid\n");
+ return -EINVAL;
+ }
+
+ i2c_dev->irq_error = irq_of_parse_and_map(np, 1);
+ if (!i2c_dev->irq_error) {
+ dev_err(&pdev->dev, "IRQ missing or invalid\n");
+ return -EINVAL;
+ }
+
+ i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(i2c_dev->clk)) {
+ dev_err(&pdev->dev, "Error: Missing controller clock\n");
+ return PTR_ERR(i2c_dev->clk);
+ }
+ ret = clk_prepare(i2c_dev->clk);
+ if (ret) {
+ dev_err(i2c_dev->dev, "Failed to prepare clock\n");
+ return ret;
+ }
+
+ rst = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(rst)) {
+ dev_err(&pdev->dev, "Error: Missing controller reset\n");
+ ret = PTR_ERR(rst);
+ goto clk_free;
+ }
+ reset_control_assert(rst);
+ udelay(2);
+ reset_control_deassert(rst);
+
+ i2c_dev->speed = STM32F4_I2C_SPEED_STANDARD;
+ ret = of_property_read_u32(np, "clock-frequency", &clk_rate);
+ if ((!ret) && (clk_rate == 400000))
+ i2c_dev->speed = STM32F4_I2C_SPEED_FAST;
+
+ i2c_dev->dev = &pdev->dev;
+
+ ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq_event,
+ NULL, stm32f4_i2c_isr_event,
+ IRQF_ONESHOT, pdev->name, i2c_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq %i\n",
+ i2c_dev->irq_error);
+ goto clk_free;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq_error,
+ NULL, stm32f4_i2c_isr_error,
+ IRQF_ONESHOT, pdev->name, i2c_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq %i\n",
+ i2c_dev->irq_error);
+ goto clk_free;
+ }
+
+ adap = &i2c_dev->adap;
+ i2c_set_adapdata(adap, i2c_dev);
+ snprintf(adap->name, sizeof(adap->name), "STM32 I2C(%pa)", &res->start);
+ adap->owner = THIS_MODULE;
+ adap->timeout = 2 * HZ;
+ adap->retries = 0;
+ adap->algo = &stm32f4_i2c_algo;
+ adap->dev.parent = &pdev->dev;
+ adap->dev.of_node = pdev->dev.of_node;
+
+ init_completion(&i2c_dev->complete);
+
+ ret = i2c_add_adapter(adap);
+ if (ret)
+ goto clk_free;
+
+ platform_set_drvdata(pdev, i2c_dev);
+
+ dev_info(i2c_dev->dev, "STM32F4 I2C driver initialized\n");
+
+ return 0;
+
+clk_free:
+ clk_unprepare(i2c_dev->clk);
+ return ret;
+}
+
+static int stm32f4_i2c_remove(struct platform_device *pdev)
+{
+ struct stm32f4_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&i2c_dev->adap);
+
+ clk_unprepare(i2c_dev->clk);
+
+ return 0;
+}
+
+static const struct of_device_id stm32f4_i2c_match[] = {
+ { .compatible = "st,stm32f4-i2c", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, stm32f4_i2c_match);
+
+static struct platform_driver stm32f4_i2c_driver = {
+ .driver = {
+ .name = "stm32f4-i2c",
+ .of_match_table = stm32f4_i2c_match,
+ },
+ .probe = stm32f4_i2c_probe,
+ .remove = stm32f4_i2c_remove,
+};
+
+module_platform_driver(stm32f4_i2c_driver);
+
+MODULE_AUTHOR("M'boumba Cedric Madianga <cedric.madianga@gmail.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32F4 I2C driver");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related
* [PATCH v4 3/5] ARM: dts: Add I2C1 support for STM32F429 SoC
From: M'boumba Cedric Madianga @ 2016-12-07 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481129492-26600-1-git-send-email-cedric.madianga@gmail.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
arch/arm/boot/dts/stm32f429.dtsi | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 7de52ee..cbdece7 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -48,6 +48,7 @@
#include "skeleton.dtsi"
#include "armv7-m.dtsi"
#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
+#include <dt-bindings/mfd/stm32f4-rcc.h>
/ {
clocks {
@@ -337,6 +338,16 @@
slew-rate = <2>;
};
};
+
+ i2c1_pins_b: i2c1 at 0 {
+ pins1 {
+ pinmux = <STM32F429_PB9_FUNC_I2C1_SDA>;
+ drive-open-drain;
+ };
+ pins2 {
+ pinmux = <STM32F429_PB6_FUNC_I2C1_SCL>;
+ };
+ };
};
rcc: rcc at 40023810 {
@@ -409,6 +420,18 @@
interrupts = <80>;
clocks = <&rcc 0 38>;
};
+
+ i2c1: i2c at 40005400 {
+ compatible = "st,stm32f4-i2c";
+ reg = <0x40005400 0x400>;
+ interrupts = <31>,
+ <32>;
+ resets = <&rcc STM32F4_APB1_RESET(I2C1)>;
+ clocks = <&rcc 0 STM32F4_APB1_CLOCK(I2C1)>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
};
--
1.9.1
^ permalink raw reply related
* [PATCH v4 4/5] ARM: dts: Add I2C1 support for STM32429 eval board
From: M'boumba Cedric Madianga @ 2016-12-07 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481129492-26600-1-git-send-email-cedric.madianga@gmail.com>
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
arch/arm/boot/dts/stm32429i-eval.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts
index afb90bc..74e0045 100644
--- a/arch/arm/boot/dts/stm32429i-eval.dts
+++ b/arch/arm/boot/dts/stm32429i-eval.dts
@@ -141,3 +141,9 @@
pinctrl-names = "default";
status = "okay";
};
+
+&i2c1 {
+ pinctrl-0 = <&i2c1_pins_b>;
+ pinctrl-names = "default";
+ status = "okay";
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v4 5/5] ARM: configs: Add I2C support for STM32 defconfig
From: M'boumba Cedric Madianga @ 2016-12-07 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481129492-26600-1-git-send-email-cedric.madianga@gmail.com>
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
arch/arm/configs/stm32_defconfig | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig
index e7b56d4..9494eaf 100644
--- a/arch/arm/configs/stm32_defconfig
+++ b/arch/arm/configs/stm32_defconfig
@@ -52,6 +52,9 @@ CONFIG_SERIAL_NONSTANDARD=y
CONFIG_SERIAL_STM32=y
CONFIG_SERIAL_STM32_CONSOLE=y
# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_STM32F4=y
# CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_NEW_LEDS=y
--
1.9.1
^ permalink raw reply related
* [PATCH v2 00/10] perf: arm64: Support for Hisilicon SoC Hardware event counters
From: Anurup M @ 2016-12-07 16:53 UTC (permalink / raw)
To: linux-arm-kernel
Provide Support for Hisilicon SoC(HiP05/06/07) Hardware event counters.
The Hisilicon SoC HiP0x series has many uncore or non-CPU performance
events and counters units.
This patch series is implemented refering to arm-cci, Intel/AMD uncore and
also the cavium thunderX and xgene uncore pmu patches.
This v2 version has addressed the review comments of v1 version.
Support for Hisilicon L3 cache(L3C) and Misclennaneous nodes(MN) hardware
events and counters are added in this implementation.
The Hisilicon uncore PMUs can be found under /sys/bus/event_source/devices.
The counters are exported via sysfs in the corresponding events files
under the PMU directory so the perf tool can list the event names.
ToDo:
1) The counter overflow handling is currently unsupported in this
patch series.
2) ACPI support.
Version history
---------------
v2
--
- Fix review comments of v2 version.
- Move djtag driver to drivers/perf/hisilicon.
- Have separate PMU instance for each L3 cache banks.
- Modify device properties in DTS as per review comments.
- Handle hardware version difference.
- Change compatible names of djtag so use prefix hisi-
and remove chip version as driver only depend on djtag
hw version.
- use devm_kzalloc.
- Remove DDRC changes in this series. As the DDRC PMU doesnot
depend on djtag it will be send separately.
v1
--
-Initial version with support for L3C, MN and DDRC event counters
-Djtag driver is used to access registers of L3 cache and MN.
Anurup M (7):
arm64: MAINTAINERS: hisi: Add hisilicon SoC PMU support
dt-bindings: perf: hisi: Add Devicetree bindings for Hisilicon SoC PMU
Documentation: perf: hisi: Documentation for HIP05/06/07 PMU event
counting.
perf: hisi: Update Kconfig for Hisilicon PMU support
perf: hisi: Add support for Hisilicon SoC event counters
perf: hisi: Add sysfs attributes for L3 cache(L3C) PMU
dts: arm64: hip06: Add Hisilicon SoC PMU support
Shaokun Zhang (1):
perf: hisi: Miscellanous node(MN) event counting in perf
Tan Xiaojun (2):
dt-bindings: hisi: Add Hisilicon HiP05/06/07 Djtag dts bindings
drivers: perf: hisi: Add support for Hisilicon Djtag driver
.../devicetree/bindings/arm/hisilicon/djtag.txt | 66 ++
.../devicetree/bindings/arm/hisilicon/pmu.txt | 98 +++
Documentation/perf/hisi-pmu.txt | 75 +++
MAINTAINERS | 9 +
arch/arm64/boot/dts/hisilicon/hip06.dtsi | 78 +++
drivers/perf/Kconfig | 8 +
drivers/perf/Makefile | 1 +
drivers/perf/hisilicon/Makefile | 1 +
drivers/perf/hisilicon/djtag.c | 729 +++++++++++++++++++++
drivers/perf/hisilicon/djtag.h | 39 ++
drivers/perf/hisilicon/hisi_uncore_l3c.c | 629 ++++++++++++++++++
drivers/perf/hisilicon/hisi_uncore_mn.c | 516 +++++++++++++++
drivers/perf/hisilicon/hisi_uncore_pmu.c | 365 +++++++++++
drivers/perf/hisilicon/hisi_uncore_pmu.h | 128 ++++
14 files changed, 2742 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/djtag.txt
create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/pmu.txt
create mode 100644 Documentation/perf/hisi-pmu.txt
create mode 100644 drivers/perf/hisilicon/Makefile
create mode 100644 drivers/perf/hisilicon/djtag.c
create mode 100644 drivers/perf/hisilicon/djtag.h
create mode 100644 drivers/perf/hisilicon/hisi_uncore_l3c.c
create mode 100644 drivers/perf/hisilicon/hisi_uncore_mn.c
create mode 100644 drivers/perf/hisilicon/hisi_uncore_pmu.c
create mode 100644 drivers/perf/hisilicon/hisi_uncore_pmu.h
--
2.1.4
^ 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