Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] arm64: traps: fix userspace cache maintenance emulation on a tagged pointer
From: Andre Przywara @ 2017-04-21 10:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492712234-4950-2-git-send-email-kristina.martsenko@arm.com>

Hi Kristina,

On 20/04/17 19:17, Kristina Martsenko wrote:
> When we emulate userspace cache maintenance in the kernel, we can
> currently send the task a SIGSEGV even though the maintenance was done
> on a valid address. This happens if the address has a non-zero address
> tag, and happens to not be mapped in.
> 
> When we get the address from a user register, we don't currently remove
> the address tag before performing cache maintenance on it. If the
> maintenance faults, we end up in either __do_page_fault, where find_vma
> can't find the VMA if the address has a tag, or in do_translation_fault,
> where the tagged address will appear to be above TASK_SIZE. In both
> cases, the address is not mapped in, and the task is sent a SIGSEGV.

Right, well spotted!
So thanks for the patch, which I think is correct. But ...

> This patch removes the tag from the address before using it. With this
> patch, the fault is handled correctly, the address gets mapped in, and
> the cache maintenance succeeds.

Looking more closely at this code, I see that we actually don't use the
address parameter in the force_signal_inject() function. Instead we
always put the PC address into the siginfo structure, which is wrong in
case this SEGV is triggered by an invalid address of a cache maintenance
operation.

I made a simple patch to fix this (using the address argument and
explicitly passing the PC in when we fault on an invalid instruction).

But now we would pass the untagged address back into userland. I am not
sure this is a real problem, since we don't promise anything in case of
tagged pointers, if I got this correctly.

But also our untagged_addr() macro seems to not cover all cases
correctly, for instance passing in 0x00ffffffffff5678 (which is an
invalid, but untagged address) would extend to some probably valid
kernel pointer. And although this would fail our user space address
check, we would return a wrong address (with all the upper bits being 1)
in siginfo.

Do we care about this?
What would be the best fix for the untagged_addr macro? Is that macro
actually the proper place to fix this issue?

Cheers,
Andre.

> As a second bug, if cache maintenance (correctly) fails on an invalid
> tagged address, the address gets passed into arm64_notify_segfault,
> where find_vma fails to find the VMA due to the tag, and the wrong
> si_code may be sent as part of the siginfo_t of the segfault. With this
> patch, the correct si_code is sent.
> 
> Fixes: 7dd01aef0557 ("arm64: trap userspace "dc cvau" cache operation on errata-affected core")
> Signed-off-by: Kristina Martsenko <kristina.martsenko@arm.com>
> ---
> 
> Note that patch #3 would also fix the first bug (incorrect segfault),
> but not the second (wrong si_code), hence this patch.
> 
>  arch/arm64/kernel/traps.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index e52be6aa44ee..45c8eca951bc 100644
> --- a/arch/arm64/kernel/traps.c
> +++ b/arch/arm64/kernel/traps.c
> @@ -443,7 +443,7 @@ int cpu_enable_cache_maint_trap(void *__unused)
>  }
>  
>  #define __user_cache_maint(insn, address, res)			\
> -	if (untagged_addr(address) >= user_addr_max()) {	\
> +	if (address >= user_addr_max()) {			\
>  		res = -EFAULT;					\
>  	} else {						\
>  		uaccess_ttbr0_enable();				\
> @@ -469,7 +469,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
>  	int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
>  	int ret = 0;
>  
> -	address = pt_regs_read_reg(regs, rt);
> +	address = untagged_addr(pt_regs_read_reg(regs, rt));
>  
>  	switch (crm) {
>  	case ESR_ELx_SYS64_ISS_CRM_DC_CVAU:	/* DC CVAU, gets promoted */
> 

^ permalink raw reply

* linux-next: build failure after merge of the arm tree
From: Mason @ 2017-04-21 11:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <9858a4ed-bdd9-bd6c-d8a4-e9e6bd539904@free.fr>

On 21/04/2017 09:58, Mason wrote:

> Weird that I didn't catch this when I ran make allyesconfig.

Doh! make allyesconfig builds for BE systems.

CONFIG_CPU_BIG_ENDIAN=y
CONFIG_CPU_ENDIAN_BE8=y

But the patch I originally tested with only updated the LE bitops.

With the complete patch, I didn't see any build issues, other than
drivers/dma/sun4i-dma.c

Regards.

^ permalink raw reply

* [PATCH v3 7/8] arm64: exception: handle asynchronous SError interrupt
From: Xiongfeng Wang @ 2017-04-21 11:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <58F876EB.2020805@arm.com>

Hi James,

Thanks for your reply.

On 2017/4/20 16:52, James Morse wrote:
> Hi Wang Xiongfeng,
> 
> On 19/04/17 03:37, Xiongfeng Wang wrote:
>> On 2017/4/18 18:51, James Morse wrote:
>>> The host expects to receive physical SError Interrupts. The ARM-ARM doesn't
>>> describe a way to inject these as they are generated by the CPU.
>>>
>>> Am I right in thinking you want this to use SError Interrupts as an APEI
>>> notification? (This isn't a CPU thing so the RAS spec doesn't cover this use)
>>
>> Yes, using sei as an APEI notification is one part of my consideration. Another use is for ESB.
>> RAS spec 6.5.3 'Example software sequences: Variant: asynchronous External Abort with ESB'
>> describes the SEI recovery process when ESB is implemented.
>>
>> In this situation, SEI is routed to EL3 (SCR_EL3.EA = 1). When an SEI occurs in EL0 and not been taken immediately,
>> and then an ESB instruction at SVC entry is executed, SEI is taken to EL3. The ESB at SVC entry is
>> used for preventing the error propagating from user space to kernel space. The EL3 SEI handler collects
> 
>> the errors and fills in the APEI table, and then jump to EL2 SEI handler. EL2 SEI handler inject
>> an vSEI into EL1 by setting HCR_EL2.VSE = 1, so that when returned to OS, an SEI is pending.
> 
> This step has confused me. How would this work with VHE where the host runs at
> EL2 and there is nothing at Host:EL1?

RAS spec 6.5.3 'Example software sequences: Variant: asynchronous External Abort with ESB'
I don't know whether the step described in the section is designed for guest os or host os or both.
Yes, it doesn't work with VHE where the host runs at EL2.

>>From your description I assume you have some firmware resident at EL2.

Our actual SEI step is planned as follows:
Host OS:  EL0/EL1 -> EL3 -> EL0/EL1
Guest OS:  EL0/EL1 -> EL3 -> EL2 -> EL0/EL1

Our problem is that, when returning to EL0/EL1, whether we should jump to EL1 SEI vector or just return to where the SEI is taken from?
In guest os situation, we can inject an vSEI and return to where the SEI is taken from.
But in host os situation, we can't inject an vSEI (if we don't set HCR_EL2.AMO), so we have to jump to EL1 SEI vector.
Then the process following ESB won't be executed becuase SEI is taken to EL3 from the ESB instruction in EL1, and when control
is returned to OS, we are in EL1 SEI vector rather than the ESB instruction.

It is ok to just ignore the process following the ESB instruction in el0_sync, because the process will be sent SIGBUS signal.
But for el0_irq, the irq process following the ESB may should be executed because the irq is not related to the user process.

If we set HCR_EL2.AMO when SCR_EL3.EA is set. We can still inject an vSEI into host OS in EL3.
Physical SError won't be taken to EL2 because SCR_EL3.EA is set. But this may be too racy is
not consistent with ARM rules.
> 
> 
>> Then ESB is executed again, and DISR_EL1.A is set by hardware (2.4.4 ESB and virtual errors), so that
>> the following process can be executed.
> 
> 
>> So we want to inject a vSEI into OS, when control is returned from EL3/2 to OS, no matter whether
>> it is on host OS or guest OS.
> 
> I disagree. With Linux/KVM you can't use Virtual SError to notify the host OS.
> The host OS expects to receive Physical SError, these shouldn't be taken to EL2
> unless a guest is running. Notifications from firmware that use SEA or SEI
> should follow the routing rules in the ARM-ARM, which means they should never
> reach a guest OS.

Yes, I agree. When running the host os, exception should not be taken to EL2, because
EL2 SEI vector always suppose that exception is taken from guest os and save
guest context in the first place.
> 
> For VHE the host runs at EL2 and sets HCR_EL2.AMO. Any firmware notification
> should come from EL3 to the host at EL2. The host may choose to notify the
> guest, but this should always go via Qemu.
> 
> For non-VHE systems the host runs at EL1 and KVM lives at EL2 to do the world
> switch. When KVM is running a guest it sets HCR_EL2.AMO, when it has switched
> back to the host it clears it.
> 
> Notifications from EL3 that pretend to be SError should route SError to EL2 or
> EL1 depending on HCR_EL2.AMO.
> When KVM gets a Synchronous External Abort or an SError while a guest is running
> it will switch back to the host and tell the handle_exit() code.  Again the host
> may choose to notify the guest, but this should always go via Qemu.
> 
> The ARM-ARM pseudo code for the routing rules is in
> AArch64.TakePhysicalSErrorException(). Firmware injecting fake SError should
> behave exactly like this.
> 
> 
> Newly appeared in the ARM-ARM is HCR_EL2.TEA, which takes Synchronous External
> Aborts to EL2 (if SCR_EL3 hasn't claimed them). We should set/clear this bit
> like we do HCR_EL2.AMO if the CPU has the RAS extensions.
> 
> 
>>> You cant use SError to cover all the possible RAS exceptions. We already have
>>> this problem using SEI if PSTATE.A was set and the exception was an imprecise
>>> abort from EL2. We can't return to the interrupted context and we can't deliver
>>> an SError to EL2 either.
>>
>> SEI came from EL2 and PSTATE.A is set. Is it the situation where VHE is enabled and CPU is running
>> in kernel space. If SEI occurs in kernel space, can we just panic or shutdown.
> 
> firmware-panic? We can do a little better than that:
> If the IESB bit is set in the ESR we can behave as if this were an ESB and have
> firmware write an appropriate ESR to DISR_EL1 if PSTATE.A is set and the
> exception came from EL2.

This method may solve the problem I said above.
Is IESB a new bit added int ESR in the newest RAS spec?
> 
> Linux should have an ESB in its __switch_to(), I've re-worked the daif masking
> in entry.S so that PSTATE.A will always be unmasked here.
> 
> Other than these two cases, yes, this CPU really is wrecked. Firmware can power
> it off via PSCI, and could notify another CPU about what happened. UEFI's table
> 250 'Processor Generic Error Section' has a 'Processor ID' field, with a note
> that on ARM this is the MPIDR_EL1. Table 260 'ARM Processor Error Section' has
> something similar.
> 
> 
> Thanks,
> 
> James
> 
> .
> 
Thanks,

Wang Xiongfeng

^ permalink raw reply

* [PATCH 1/1] PCI: Add MCFG quirk for 2nd node of Cavium ThunderX pass2.x host controller
From: Robert Richter @ 2017-04-21 11:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1490789773-21506-1-git-send-email-tn@semihalf.com>

On 29.03.17 14:16:13, Tomasz Nowicki wrote:
> Currently SoCs pass2.x do not emulate EA headers for ACPI boot method at all.
> However, for pass2.x some devices (like EDAC) advertise incorrect base addresses
> in their BARs which results in driver probe failure during resource request.
> Since all problematic blocks are on 2nd NUMA node under domain 10 add necessary
> quirk entry to obtain BAR addresses correction using EA header emulation.
> 
> Fixes: 44f22bd91e88 ("PCI: Add MCFG quirks for Cavium ThunderX pass2.x host controller")
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> CC: stable at vger.kernel.org	# v4.10+

Acked-by: Robert Richter <rrichter@cavium.com>

Bjorn, please apply.

Thanks,

-Robert

^ permalink raw reply

* [PATCH v2 2/3] crypto: inside-secure: add SafeXcel EIP197 crypto engine driver
From: Corentin Labbe @ 2017-04-21 11:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170421092935.fszux3qg5hbwwobj@kwain>

> > > +	memset(ipad + keylen, 0, blocksize - keylen);
> > > +	memcpy(opad, ipad, blocksize);
> > > +
> > > +	for (i = 0; i < blocksize; i++) {
> > > +		ipad[i] ^= 0x36;
> > > +		opad[i] ^= 0x5c;
> > 
> > What are these constant ?
> 
> They are defined in the HMAC RFC, as ipad and opad values. See
> https://www.ietf.org/rfc/rfc2104.txt.
> 

Since many driver use them, I think defining them in include/ should be done (HMAC_IPAD/HMAC_OPAD)
I will send a patch for it.

> > [...]
> > > +struct safexcel_alg_template safexcel_alg_sha256 = {
> > > +	.type = SAFEXCEL_ALG_TYPE_AHASH,
> > > +	.alg.ahash = {
> > > +		.init = safexcel_sha256_init,
> > > +		.update = safexcel_ahash_update,
> > > +		.final = safexcel_ahash_final,
> > > +		.finup = safexcel_ahash_finup,
> > > +		.digest = safexcel_sha256_digest,
> > > +		.export = safexcel_ahash_export,
> > > +		.import = safexcel_ahash_import,
> > > +		.halg = {
> > > +			.digestsize = SHA256_DIGEST_SIZE,
> > > +			.statesize = sizeof(struct safexcel_ahash_export_state),
> > > +			.base = {
> > > +				.cra_name = "sha256",
> > > +				.cra_driver_name = "safexcel-sha256",
> > > +				.cra_priority = 300,
> > > +				.cra_flags = CRYPTO_ALG_ASYNC |
> > > +					     CRYPTO_ALG_KERN_DRIVER_ONLY,
> > 
> > Why do use CRYPTO_ALG_KERN_DRIVER_ONLY ?
> 
> See http://lxr.free-electrons.com/source/include/linux/crypto.h#L97.
> 

Sorry, I had understood that flag as "do not let userspace use me".
Anyway, this flag is totally ignored by the cryptoAPI.

^ permalink raw reply

* [PATCH v2 2/3] crypto: inside-secure: add SafeXcel EIP197 crypto engine driver
From: Antoine Tenart @ 2017-04-21 12:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170421113645.GA18422@Red>

On Fri, Apr 21, 2017 at 01:36:45PM +0200, Corentin Labbe wrote:
> > > > +	memset(ipad + keylen, 0, blocksize - keylen);
> > > > +	memcpy(opad, ipad, blocksize);
> > > > +
> > > > +	for (i = 0; i < blocksize; i++) {
> > > > +		ipad[i] ^= 0x36;
> > > > +		opad[i] ^= 0x5c;
> > > 
> > > What are these constant ?
> > 
> > They are defined in the HMAC RFC, as ipad and opad values. See
> > https://www.ietf.org/rfc/rfc2104.txt.
> > 
> 
> Since many driver use them, I think defining them in include/ should be done (HMAC_IPAD/HMAC_OPAD)
> I will send a patch for it.

OK, I'll send a following up patch on this driver when your series is
merged.

Antoine

-- 
Antoine T?nart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170421/76266910/attachment.sig>

^ permalink raw reply

* [PATCH v5 1/4] printk/nmi: generic solution for safe printk in NMI
From: Petr Mladek @ 2017-04-21 12:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170421015724.GA586@jagdpanzerIV.localdomain>

On Fri 2017-04-21 10:57:25, Sergey Senozhatsky wrote:
> On (04/20/17 15:11), Petr Mladek wrote:
> [..]
> >  void printk_nmi_enter(void)
> >  {
> > -	this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK);
> > +	/*
> > +	 * The size of the extra per-CPU buffer is limited. Use it
> > +	 * only when really needed.
> > +	 */
> > +	if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK ||
> > +	    raw_spin_is_locked(&logbuf_lock)) {
> > +		this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK);
> > +	} else {
> > +		this_cpu_or(printk_context, PRINTK_NMI_DEFERRED_CONTEXT_MASK);
> > +	}
> >  }
> 
> well... the logbuf_lock can temporarily be locked from another CPU. I'd say
> that spin_is_locked() has better chances for false positive than
> this_cpu_read(printk_context). because this_cpu_read(printk_context) depends
> only on this CPU state, while spin_is_locked() depends on all CPUs. and the
> idea with this_cpu_read(printk_context) was that we check if the logbuf_lock
> was locked from this particular CPU.

I finally see the point. I confess that I did not think much about
this way yesterday because it looked too tricky (indirect) and possibly
error prone.

> I agree that this_cpu_read(printk_context) covers slightly more than
> logbuf_lock scope, so we may get positive this_cpu_read(printk_context)
> with unlocked logbuf_lock, but I don't tend to think that it's a big
> problem.

PRINTK_SAFE_CONTEXT is set also in call_console_drivers().
It might take rather long and logbuf_lock is availe. So, it is
noticeable source of false positives.

Hmm, my version actually checks both the lock and the context.
It is very deffensive to be always on the safe side.

We could get the best restults with both checks and by using "&&":

void printk_nmi_enter(void)
{
	/*
	 * The size of the extra per-CPU buffer is limited. Use it
	 * only when the lock for the main log buffer is not
	 * available.
	 *
	 * logbuf_lock might be taken on another CPU. But it must be
	 * in PRINTK_SAFE context. Reduce false positives by a check
	 * of the context.
	 */
	if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK ||
	    raw_spin_is_locked(&logbuf_lock)) {
		this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK);
	} else {
		this_cpu_or(printk_context, PRINTK_NMI_DEFERRED_CONTEXT_MASK);
	}
}


But after all, I would prefer to keep it simple, strightforward,
and check only the logbuf_lock:

	if (raw_spin_is_locked(&logbuf_lock))
		this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK);
	else
		this_cpu_or(printk_context, PRINTK_NMI_DEFERRED_CONTEXT_MASK);


> wouldn't something as simple as below do the trick?
> // absolutely and completely untested //
> 
> 
> diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c
> index 033e50a7d706..c7477654c5b1 100644
> --- a/kernel/printk/printk_safe.c
> +++ b/kernel/printk/printk_safe.c
> @@ -303,7 +303,10 @@ static int vprintk_nmi(const char *fmt, va_list args)
>  {
>         struct printk_safe_seq_buf *s = this_cpu_ptr(&nmi_print_seq);
>  
> -       return printk_safe_log_store(s, fmt, args);
> +       if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK)
> +               return printk_safe_log_store(s, fmt, args);
> +
> +       return vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args);
>  }

It looks simple but some things are missing. It will be used also
outside panic/oops, so it should queue the irq_work to flush the console.
Also the serialization of nmi_cpu_backtrace() backtrace calls is
needed.

All in all, we could get rid only of the extra
PRINTK_NMI_DEFERRED_CONTEXT_MASK with this approach. Other than
that it looks more tricky to me.

Sigh, I hate problems without the single best solution.

Best Regards,
Petr

^ permalink raw reply

* [PATCH V15 03/11] cper: add timestamp print to CPER status printing
From: Borislav Petkov @ 2017-04-21 12:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492556723-9189-4-git-send-email-tbaicar@codeaurora.org>

On Tue, Apr 18, 2017 at 05:05:15PM -0600, Tyler Baicar wrote:
> The ACPI 6.1 spec added a timestamp to the HEST generic data

HEST?

I see the timestamp in

Table 18-343 Generic Error Data Entry

where those things are "One or more Generic Error Data Entry structures
may be recorded in the Generic Error Data Entries field of the Generic
Error Status Block structure."

And those are part of the "18.3.2.7 Generic Hardware Error Source",
i.e., GHES. So why do you say "HEST" above?

> structure. Print the timestamp out when printing out the error
> status information.
> 
> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
> CC: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
> Reviewed-by: James Morse <james.morse@arm.com>
> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Remove those Reviewed-by:s

> ---
>  drivers/firmware/efi/cper.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
> index 8328a6f..46585f9 100644
> --- a/drivers/firmware/efi/cper.c
> +++ b/drivers/firmware/efi/cper.c
> @@ -32,6 +32,8 @@
>  #include <linux/acpi.h>
>  #include <linux/pci.h>
>  #include <linux/aer.h>
> +#include <linux/printk.h>
> +#include <linux/bcd.h>
>  #include <acpi/ghes.h>
>  
>  #define INDENT_SP	" "
> @@ -387,6 +389,29 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
>  	pfx, pcie->bridge.secondary_status, pcie->bridge.control);
>  }
>  
> +static void cper_estatus_timestamp(const char *pfx,

cper_print_tstamp()

> +				   struct acpi_hest_generic_data_v300 *gdata)
> +{
> +	__u8 hour, min, sec, day, mon, year, century, *timestamp;
> +
> +	if (gdata->validation_bits & ACPI_HEST_GEN_VALID_TIMESTAMP) {
> +		timestamp = (__u8 *)&(gdata->time_stamp);
> +		sec       = bcd2bin(timestamp[0]);
> +		min       = bcd2bin(timestamp[1]);
> +		hour      = bcd2bin(timestamp[2]);
> +		day       = bcd2bin(timestamp[4]);
> +		mon       = bcd2bin(timestamp[5]);
> +		year      = bcd2bin(timestamp[6]);
> +		century   = bcd2bin(timestamp[7]);
> +
> +		if (*(timestamp + 3) & 0x1)
> +			printk("%stimestamp is precise\n", pfx);
> +
> +		printk("%stime: %02d%02d-%02d-%02d %02d:%02d:%02d\n", pfx,
> +			century, year, mon, day, hour, min, sec);

Yeah, about the precise tstamp, you can do something like this:

---
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 46585f92b741..a649884e2264 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -404,10 +404,8 @@ static void cper_estatus_timestamp(const char *pfx,
 		year      = bcd2bin(timestamp[6]);
 		century   = bcd2bin(timestamp[7]);
 
-		if (*(timestamp + 3) & 0x1)
-			printk("%stimestamp is precise\n", pfx);
-
-		printk("%stime: %02d%02d-%02d-%02d %02d:%02d:%02d\n", pfx,
+		printk("%s%ststamp: %02d%02d-%02d-%02d %02d:%02d:%02d\n", pfx,
+			(timestamp[3] & 0x1 ? "precise " : ""), 
 			century, year, mon, day, hour, min, sec);
 	}
 }

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply related

* [PATCH/RFC 0/5] arm64: dts: renesas: Break out common board support
From: Geert Uytterhoeven @ 2017-04-21 12:55 UTC (permalink / raw)
  To: linux-arm-kernel

	Hi all,

The Renesas Salvator-X and ULCB development board can be equipped with
either an R-Car H3 or M3-W SiP, which are pin-compatible.  All boards
use separate DTBs, but currently there's no sharing of board-specific
devices in DTS.

This series reduces duplication by extracting common board support into
their own .dtsi files.  As the level of support varies across boards and
SoCs, this requires the addition of a few external clocks and
placeholder devices on R-Car M3-W, so the common board support DTS can
refer to them.

  - Patches 1 and 2 add the external audio and PCIe bus clocks on R-Car
    M3-W, which are present in r8a7795.dtsi, and used in
    r8a7795-salvator-x.dts,
  - RFC patch 3 adds placeholders for devices that are not yet supported
    and/or tested on R-Car M3-W, but used on R-Car H3,
  - RFC patch 4 extracts common Salvator-X board support,
  - RFC patch 5 extracts common ULCB board support.

For R-Car H3 based boards, there are no functional changes.
For R-Car M3-W based boards, some new devices are now described in DT.

Dependencies:
  - renesas-devel-20170420-v4.11-rc7,
  - Patches 1 and 2 can be applied as-is,
  - Patches 4 and 5 depend on "[PATCH 0/8] arm64: dts: renesas: Break
    out R-Car H3 and M3-W SiP"
    (http://www.spinics.net/lists/devicetree/msg173820.html).

DTB changes have been inspected using scripts/dtc/dtx_diff.
This has been tested on Salvator-X (both H3 and M3-W).
This has not been tested on H3ULCB and M3ULCB due to lack of hardware.

Thanks for your comments!

Geert Uytterhoeven (5):
  arm64: renesas: r8a7796: Add external audio clocks
  arm64: renesas: r8a7796: Add external PCIe bus clock
  [RFC] arm64: dts: r8a7796: Add placeholders for various devices
  [RFC] arm64: dts: renesas: Extract common Salvator-X board support
  [RFC] arm64: dts: renesas: Extract common ULCB board support

 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts     | 341 +-------------
 arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 522 +--------------------
 arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts     | 201 +-------
 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts | 259 +---------
 arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 112 +++++
 .../{r8a7795-salvator-x.dts => salvator-x.dtsi}    | 372 +++++++--------
 .../dts/renesas/{r8a7795-h3ulcb.dts => ulcb.dtsi}  | 243 +++++-----
 7 files changed, 421 insertions(+), 1629 deletions(-)
 copy arch/arm64/boot/dts/renesas/{r8a7795-salvator-x.dts => salvator-x.dtsi} (95%)
 copy arch/arm64/boot/dts/renesas/{r8a7795-h3ulcb.dts => ulcb.dtsi} (96%)

-- 
2.7.4

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply

* [PATCH 2/5] arm64: renesas: r8a7796: Add external PCIe bus clock
From: Geert Uytterhoeven @ 2017-04-21 12:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492779321-23939-1-git-send-email-geert+renesas@glider.be>

Add the external PCIe bus clock as a zero Hz fixed-frequency clock.
Boards that provide this clock should override it.

Based on r8a7795.dtsi.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 arch/arm64/boot/dts/renesas/r8a7796.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
index 101cd41d693a7ab5..8e2aab8b6b103cc9 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
@@ -157,6 +157,13 @@
 		clock-frequency = <0>;
 	};
 
+	/* External PCIe clock - can be overridden by the board */
+	pcie_bus_clk: pcie_bus {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
 	soc {
 		compatible = "simple-bus";
 		interrupt-parent = <&gic>;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/5] mtd: nand: gpmi: add i.MX 7 SoC support
From: Marek Vasut @ 2017-04-21 13:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5cf26d2b020392c875464c7504a9fb5b@agner.ch>

On 04/21/2017 05:15 AM, Stefan Agner wrote:
> On 2017-04-20 19:03, Marek Vasut wrote:
>> On 04/21/2017 03:07 AM, Stefan Agner wrote:
>>> Add support for i.MX 7 SoC. The i.MX 7 has a slightly different
>>> clock architecture requiring only two clocks to be referenced.
>>> The IP is slightly different compared to i.MX 6SoloX, but currently
>>> none of this differences are in use so there is no detection needed
>>> and the driver can reuse IS_MX6SX.
>>>
>>> Signed-off-by: Stefan Agner <stefan@agner.ch>
>>> ---
>>>  drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 15 +++++++++++++++
>>>  1 file changed, 15 insertions(+)
>>>
>>> diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
>>> index c8bbf5da2ab8..4a45d37ddc80 100644
>>> --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
>>> +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
>>> @@ -127,6 +127,18 @@ static const struct gpmi_devdata gpmi_devdata_imx6sx = {
>>>  	.clks_count = ARRAY_SIZE(gpmi_clks_for_mx6),
>>>  };
>>>
>>> +static const char * const gpmi_clks_for_mx7d[] = {
>>> +	"gpmi_io", "gpmi_bch_apb",
>>> +};
>>> +
>>> +static const struct gpmi_devdata gpmi_devdata_imx7d = {
>>> +	.type = IS_MX6SX,
>>
>> Would it make sense to use IS_MX7 here already to prevent future surprises ?
>>
> 
> Yeah I was thinking we can do it once we have an actual reason to
> distinguish.

So what are the differences anyway ?

> But then, adding the type would only require 2-3 lines of change if I
> add it to the GPMI_IS_MX6 macro...

Then at least add a comment because using type = IMX6SX right under
gpmi_data_mx7d can trigger some head-scratching. And put my R-B on V2.

-- 
Best regards,
Marek Vasut

^ permalink raw reply

* [PATCH v5 0/2] crypto: hw_random - Add new Exynos RNG driver
From: Herbert Xu @ 2017-04-21 13:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170411180835.8928-1-krzk@kernel.org>

On Tue, Apr 11, 2017 at 08:08:33PM +0200, Krzysztof Kozlowski wrote:
> Hi,
> 
> This is a follow up of my questions around exynos-rng [1].
> 
> Changes since v4:
> =================
> 1. Patch 2/2: Use "stdrng" name, as suggested by Herbert.
> 2. Patch 2/2: Add Bartlomiej's reviewed-by.

All applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH v2 0/2] hwrng: mtk: add support for hardware random generator on MT7623 SoC
From: Herbert Xu @ 2017-04-21 13:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492705466-27287-1-git-send-email-sean.wang@mediatek.com>

On Fri, Apr 21, 2017 at 12:24:24AM +0800, sean.wang at mediatek.com wrote:
> From: Sean Wang <sean.wang@mediatek.com>
> 
> This patchset introduces support for Mediatek hardware random generator (RNG)
> Currently, the driver is already tested successfully with rng-tools on MT7623
> SoC. And it should also be workable on other similar Mediatek SoCs.
> 
> Changes since v1:

All applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH] kvm: pass the virtual SEI syndrome to guest OS
From: gengdongjiu @ 2017-04-21 13:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <6ac1597a-2ed5-36b2-848d-5fd048b16d66@redhat.com>

Hi all/Laszlo,

  sorry, I have a question to consult with you.


On 2017/4/7 2:55, Laszlo Ersek wrote:
> On 04/06/17 14:35, gengdongjiu wrote:
>> Dear, Laszlo
>>    Thanks for your detailed explanation.
>>
>> On 2017/3/29 19:58, Laszlo Ersek wrote:
>>> (This ought to be one of the longest address lists I've ever seen :)
>>> Thanks for the CC. I'm glad Shannon is already on the CC list. For good
>>> measure, I'm adding MST and Igor.)
>>>
>>> On 03/29/17 12:36, Achin Gupta wrote:
>>>> Hi gengdongjiu,
>>>>
>>>> On Wed, Mar 29, 2017 at 05:36:37PM +0800, gengdongjiu wrote:
>>>>>
>>>>> Hi Laszlo/Biesheuvel/Qemu developer,
>>>>>
>>>>>    Now I encounter a issue and want to consult with you in ARM64 platform? as described below:
>>>>>
>>>>> when guest OS happen synchronous or asynchronous abort, kvm needs
>>>>> to send the error address to Qemu or UEFI through sigbus to
>>>>> dynamically generate APEI table. from my investigation, there are
>>>>> two ways:
>>>>>
>>>>> (1) Qemu get the error address, and generate the APEI table, then
>>>>> notify UEFI to know this generation, then inject abort error to
>>>>> guest OS, guest OS read the APEI table.
>>>>> (2) Qemu get the error address, and let UEFI to generate the APEI
>>>>> table, then inject abort error to guest OS, guest OS read the APEI
>>>>> table.
>>>>
>>>> Just being pedantic! I don't think we are talking about creating the APEI table
>>>> dynamically here. The issue is: Once KVM has received an error that is destined
>>>> for a guest it will raise a SIGBUS to Qemu. Now before Qemu can inject the error
>>>> into the guest OS, a CPER (Common Platform Error Record) has to be generated
>>>> corresponding to the error source (GHES corresponding to memory subsystem,
>>>> processor etc) to allow the guest OS to do anything meaningful with the
>>>> error. So who should create the CPER is the question.
>>>>
>>>> At the EL3/EL2 interface (Secure Firmware and OS/Hypervisor), an error arrives
>>>> at EL3 and secure firmware (at EL3 or a lower secure exception level) is
>>>> responsible for creating the CPER. ARM is experimenting with using a Standalone
>>>> MM EDK2 image in the secure world to do the CPER creation. This will avoid
>>>> adding the same code in ARM TF in EL3 (better for security). The error will then
>>>> be injected into the OS/Hypervisor (through SEA/SEI/SDEI) through ARM Trusted
>>>> Firmware.
>>>>
>>>> Qemu is essentially fulfilling the role of secure firmware at the EL2/EL1
>>>> interface (as discussed with Christoffer below). So it should generate the CPER
>>>> before injecting the error.
>>>>
>>>> This is corresponds to (1) above apart from notifying UEFI (I am assuming you
>>>> mean guest UEFI). At this time, the guest OS already knows where to pick up the
>>>> CPER from through the HEST. Qemu has to create the CPER and populate its address
>>>> at the address exported in the HEST. Guest UEFI should not be involved in this
>>>> flow. Its job was to create the HEST at boot and that has been done by this
>>>> stage.
>>>>
>>>> Qemu folk will be able to add but it looks like support for CPER generation will
>>>> need to be added to Qemu. We need to resolve this.
>>>>
>>>> Do shout if I am missing anything above.
>>>
>>> After reading this email, the use case looks *very* similar to what
>>> we've just done with VMGENID for QEMU 2.9.
>>>
>>> We have a facility between QEMU and the guest firmware, called "ACPI
>>> linker/loader", with which QEMU instructs the firmware to
>>>
>>> - allocate and download blobs into guest RAM (AcpiNVS type memory) --
>>> ALLOCATE command,
>>>
>>> - relocate pointers in those blobs, to fields in other (or the same)
>>> blobs -- ADD_POINTER command,
>>>
>>> - set ACPI table checksums -- ADD_CHECKSUM command,
>>>
>>> - and send GPAs of fields within such blobs back to QEMU --
>>> WRITE_POINTER command.
>>>
>>> This is how I imagine we can map the facility to the current use case
>>> (note that this is the first time I read about HEST / GHES / CPER):

Laszlo lists a Qemu GHES table generation solution, Mainly use the four commands: "ALLOCATE/ADD_POINTER/ADD_CHECKSUM/WRITE_POINTER" to communicate with BIOS
so whether the four commands needs to be supported by the guest firware/UEFI.  I found the  "WRITE_POINTER" always failed. so I suspect guest UEFI/firmware not support the "WRITE_POINTER" command. please help me confirm it, thanks so much.

^ permalink raw reply

* [PATCH V2] scsi: mpt3sas: remove redundant wmb
From: Sinan Kaya @ 2017-04-21 13:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK=zhgpmcmq-CnWuU9=WRJpAaEduw63LSPLE9yZzF_sUHkM4AA@mail.gmail.com>

On 4/21/2017 3:56 AM, Sreekanth Reddy wrote:
> [Sreekanth] Whether same thing applicable for SPARC & POWER
> architectures. If yes then we are fine with this patch changes.

This behavior is common for all architectures according to this document.

Who would be the best person to comment on SPARC and POWER architectures
in specific? James and I exchanged some comments on the first version. 

James? can you comment on POWER behavior.

https://www.kernel.org/doc/Documentation/memory-barriers.txt

Inside of the Linux kernel, I/O should be done through the appropriate accessor
routines - such as inb() or writel() - which know how to make such accesses
appropriately sequential.  

"Whilst this, for the most part, renders the explicit
use of memory barriers unnecessary", 

there are a couple of situations where they might be needed:

 (1) On some systems, I/O stores are not strongly ordered across all CPUs, and
     so for _all_ general drivers locks should be used and mmiowb() must be
     issued prior to unlocking the critical section.

 (2) If the accessor functions are used to refer to an I/O memory window with
     relaxed memory access properties, then _mandatory_ memory barriers are
     required to enforce ordering.

-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH V8 4/5] PCI/ASPM: save power on values during bridge init
From: Sinan Kaya @ 2017-04-21 13:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <92EBB4272BF81E4089A7126EC1E7B2846676C7EF@IRSMSX101.ger.corp.intel.com>

On 4/21/2017 3:46 AM, Patel, Mayurkumar wrote:
> If we want to follow above approach then shall we consider having something similar as following?

Do you see this problem if you boot with pcie_aspm.policy=powersave option?


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH, 3.18-stable regression] ARM: psci: fix header file
From: Arnd Bergmann @ 2017-04-21 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

Commit be95485a0b828 was incorrectly backported to 3.18 and
now causes a different build error when CONFIG_SMP is disabled:

 arch/arm/kernel/psci.c:287:12: error: redefinition of 'psci_init'

This version is how it should be on 3.18, with the main psci
code built for both SMP and UP, but the psci_smp_available()
function only being available for SMP builds.

Fixes: dbcfee724255 ("ARM: 8457/1: psci-smp is built only for SMP")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/include/asm/psci.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
index e3789fb02c9c..8ca5308a05d7 100644
--- a/arch/arm/include/asm/psci.h
+++ b/arch/arm/include/asm/psci.h
@@ -37,11 +37,15 @@ struct psci_operations {
 extern struct psci_operations psci_ops;
 extern struct smp_operations psci_smp_ops;
 
-#if defined(CONFIG_SMP) && defined(CONFIG_ARM_PSCI)
+#ifdef CONFIG_ARM_PSCI
 int psci_init(void);
-bool psci_smp_available(void);
 #else
 static inline int psci_init(void) { return 0; }
+#endif
+
+#if defined(CONFIG_SMP) && defined(CONFIG_ARM_PSCI)
+bool psci_smp_available(void);
+#else
 static inline bool psci_smp_available(void) { return false; }
 #endif
 
-- 
2.9.0

^ permalink raw reply related

* [PATCH V8 4/5] PCI/ASPM: save power on values during bridge init
From: Patel, Mayurkumar @ 2017-04-21 14:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <16c80ef9-8928-b7c9-dc6e-f1c96efb6da3@codeaurora.org>

>
>On 4/21/2017 3:46 AM, Patel, Mayurkumar wrote:
>> If we want to follow above approach then shall we consider having something similar as following?
>
>Do you see this problem if you boot with pcie_aspm.policy=powersave option?
>

No problems. with pcie_aspm.policy=powersave(L1SS are not enabled in this case
but L1 stays ok all the time after many Power(hotplug) cycles but I think that is expected with this policy)
and pcie_aspm.policy=powersupersave (L1/L1SS both stays ok all the time).

>
>--
>Sinan Kaya
>Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
>Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Christian Lamprechter
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply

* stable/linux-3.18.y build: 204 builds: 5 failed, 199 passed, 35 errors, 212 warnings (v3.18.49)
From: Arnd Bergmann @ 2017-04-21 14:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <58f8ea00.84621c0a.da7d6.1c19@mx.google.com>

On Thu, Apr 20, 2017 at 7:04 PM, kernelci.org bot <bot@kernelci.org> wrote:
> stable/linux-3.18.y build: 204 builds: 5 failed, 199 passed, 35 errors, 212 warnings (v3.18.49)

I've gone through all these now and found a fix. In three cases, there is no
fix yet since the respective drivers got removed before the warning was
noticed. Do we have a policy for how to deal with those? Should I just
send patches to address the warnings for 3.18?

> Errors summary:
> 7 arch/mips/jz4740/irq.h:21:38: error: 'struct irq_data' declared inside
> parameter list will not be visible outside of this definition or declaration
> [-Werror]
> 7 arch/mips/jz4740/irq.h:20:39: error: 'struct irq_data' declared inside
> parameter list will not be visible outside of this definition or declaration
> [-Werror]


5b235dc2647e4 MIPS: Fix the build on jz4740 after removing the custom gpio.h

> 2 arch/mips/mm/fault.c:321:1: error: the frame size of 1104 bytes is larger
> than 1024 bytes [-Werror=frame-larger-than=]

This is a result of a newer compiler version, combined with the -Werror
flag that is applied to arch/mips/, and two of the mips defconfigs overriding
CONFIG_FRAME_WARN to 1024 on a 64-bit architecture (probably by
accident).

I saw this also when I looked at the 3.16 warnings, but only now actually
bisected it. The fix is

86038c5ea81b ("perf: Avoid horrible stack usage")

> Detailed per-defconfig build reports:
>
> allmodconfig+CONFIG_OF=n (x86) ? PASS, 0 errors, 8 warnings, 0 section
> mismatches
>
> Warnings:
> fs/nfs/nfs4proc.c:3062:10: warning: switch condition has boolean value
> [-Wswitch-bool]

c7757074839f ("fs/nfs: fix new compiler warning about boolean in switch")

> drivers/iommu/intel-iommu.c:1762:25: warning: unused variable 'drhd'
> [-Wunused-variable]

509fca899d56 ("iommu/vt-d: Remove unused variable")

> drivers/message/i2o/i2o_config.c:893:19: warning: cast to pointer from
> integer of different size [-Wint-to-pointer-cast]
> drivers/message/i2o/i2o_config.c:953:10: warning: cast to pointer from
> integer of different size [-Wint-to-pointer-cast]

The driver is obsolete and was removed in v4.2. It looks like the warning
should still be there in v4.1.y, but I don't remember having seen it. It
would be trivial to fix this with an obvious patch adding a cast.


> drivers/staging/bcm/CmHost.c:1503:3: warning: cast to pointer from integer
> of different size [-Wint-to-pointer-cast]
> drivers/staging/bcm/CmHost.c:1546:3: warning: cast to pointer from integer
> of different size [-Wint-to-pointer-cast]
> drivers/staging/bcm/CmHost.c:1564:3: warning: cast to pointer from integer
> of different size [-Wint-to-pointer-cast]

Similarly, the driver was removed in v3.19, but I could create a patch for
the warning.

> drivers/scsi/advansys.c:71:2: warning: #warning this driver is still not
> properly converted to the DMA API [-Wcpp]

The driver was properly converted in v4.2 and the warning removed, but the
conversion would be outside of stable-kernel-rules.

> Section mismatches:
> WARNING: arch/x86/kernel/built-in.o(.text.unlikely+0x157f): Section mismatch
> in reference from the function cpumask_empty.constprop.3() to the variable
> .init.data:nmi_ipi_mask
> WARNING: arch/x86/built-in.o(.text.unlikely+0x189b): Section mismatch in
> reference from the function cpumask_empty.constprop.3() to the variable
> .init.data:nmi_ipi_mask
> WARNING: vmlinux.o(.text.unlikely+0x1962): Section mismatch in reference
> from the function cpumask_empty.constprop.3() to the variable
> .init.data:nmi_ipi_mask

f0ba662a6e06f2 x86: Properly _init-annotate NMI selftest code

> allnoconfig (mips) ? PASS, 0 errors, 1 warning, 0 section mismatches
>
> Warnings:
> mm/page_alloc.c:5346:34: warning: array subscript is below array bounds
> [-Warray-bounds]

Also bisected this one now, this is also missing on 3.16:

90cae1fe1c35 ("mm/init: fix zone boundary creation")

> ar7_defconfig (mips) ? PASS, 0 errors, 2 warnings, 0 section mismatches
>
> Warnings:
> include/linux/kernel.h:713:17: warning: comparison of distinct pointer types
> lacks a cast

2f5281ba2a8f ("net: ti: cpmac: Fix compiler warning due to type confusion")

> at91_dt_defconfig (arm) ? PASS, 0 errors, 2 warnings, 0 section mismatches
>
> Warnings:
> drivers/clk/at91/clk-usb.c:155:20: warning: initialization from incompatible
> pointer type [-Wincompatible-pointer-types]
> drivers/clk/at91/clk-usb.c:193:20: warning: initialization from incompatible
> pointer type [-Wincompatible-pointer-types]

I've send this fix:

8<------
clk: at91: usb: fix determine_rate prototype again

We had an incorrect backport of
4591243102fa ("clk: at91: usb: propagate rate modification to the parent clk")
that was fixed incorrectly in linux-3.18.y by
76723e7ed589 ("clk: at91: usb: fix determine_rate prototype")

This should fix it properly.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
index 0283a5713d6c..930a424cc4a0 100644
--- a/drivers/clk/at91/clk-usb.c
+++ b/drivers/clk/at91/clk-usb.c
@@ -59,7 +59,7 @@ static unsigned long
at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
 static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
       unsigned long rate,
       unsigned long *best_parent_rate,
-      struct clk_hw **best_parent_hw)
+      struct clk **best_parent_hw)
 {
  struct clk *parent = NULL;
  long best_rate = -EINVAL;
@@ -91,7 +91,7 @@ static long at91sam9x5_clk_usb_determine_rate(struct
clk_hw *hw,
  best_rate = tmp_rate;
  best_diff = tmp_diff;
  *best_parent_rate = tmp_parent_rate;
- *best_parent_hw = __clk_get_hw(parent);
+ *best_parent_hw = parent;
  }

  if (!best_diff || tmp_rate < rate)
---------->8

> ath79_defconfig (mips) ? PASS, 0 errors, 2 warnings, 0 section mismatches
>
> Warnings:
> arch/mips/kernel/entry.S:170: Warning: tried to set unrecognized symbol:
> MIPS_ISA_LEVEL_RAW

aebac99384f7 ("MIPS: kernel: entry.S: Set correct ISA level for mips_ihb")

> cerfcube_defconfig (arm) ? PASS, 0 errors, 2 warnings, 0 section mismatches
>
> Warnings:
> fs/nfsd/nfs4state.c:3781:3: warning: 'old_deny_bmap' may be used
> uninitialized in this function [-Wmaybe-uninitialized]

5368e1a6 ("nfsd: work around a gcc-5.1 warning")

> corgi_defconfig (arm) ? PASS, 0 errors, 2 warnings, 0 section mismatches
>
> Warnings:
> drivers/usb/gadget/legacy/inode.c:648:10: warning: 'value' may be used
> uninitialized in this function [-Wmaybe-uninitialized]

This is caused by the backport of f01d35a15fa0416 from 4.0 to 3.18:
c81fc59be42c6e0 gadgetfs: use-after-free in ->aio_read()

The backported patch was buggy, but the mainline code was
rewritten in a larger patch directly following this one in a way that
fixed the bug.

For stable, we should need only a one-line change, which I sent now:

diff --git a/drivers/usb/gadget/legacy/inode.c
b/drivers/usb/gadget/legacy/inode.c
index 54f964bbc79a..fe45311f243e 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -654,6 +654,7 @@ fail:
    GFP_KERNEL);
  if (!priv->iv) {
  kfree(priv);
+ value = -ENOMEM;
  goto fail;
  }
  }

> defconfig+CONFIG_LKDTM=y (mips) ? PASS, 0 errors, 3 warnings, 0 section
> mismatches
>
> Warnings:
> include/asm-generic/div64.h:43:28: warning: comparison of distinct pointer
> types lacks a cast
> include/asm-generic/div64.h:43:28: warning: comparison of distinct pointer
> types lacks a cast

2ae83bf93882 ("[CIFS] Fix setting time before epoch (negative time values)")

> efm32_defconfig (arm) ? PASS, 0 errors, 1 warning, 0 section mismatches
>
> Warnings:
> arch/arm/kernel/head-nommu.S:167: Warning: Use of r13 as a source register
> is deprecated when r15 is the destination register.

970d96f9a81b ("ARM: 8383/1: nommu: avoid deprecated source register on mov")

> imx_v6_v7_defconfig (arm) ? PASS, 0 errors, 2 warnings, 0 section mismatches
>
> Warnings:
> drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c:1478:8: warning: 'skb'
> may be used uninitialized in this function [-Wmaybe-uninitialized]

22f44150aad7 ("brcmfmac: avoid gcc-5.1 warning")

> ip27_defconfig (mips) ? PASS, 0 errors, 6 warnings, 0 section mismatches
>
> Warnings:
> lib/cpumask.c:194:25: warning: the address of 'cpu_all_bits' will always
> evaluate as 'true' [-Waddress]

f36963c9d3f6f4 cpumask_set_cpu_local_first => cpumask_local_spread, lament

> include/linux/sched.h:1975:56: warning: 'noio_flag' may be used
> uninitialized in this function [-Wmaybe-uninitialized]

I've bisected this to
be0c37c985ed ("MIPS: Rearrange PTE bits into fixed positions.")
which accidentally shuts up the warning, but does not apply to
3.18, and is not appropriate for a stable backport.

The code is correct, so we can probably just add an initialization
for the variable. Patch sent.

> drivers/tty/nozomi.c:857:9: warning: 'size' may be used uninitialized in
> this function [-Wmaybe-uninitialized]

a4f642a8a3c2 ("tty: nozomi: avoid a harmless gcc warning")

> drivers/net/ethernet/neterion/vxge/vxge-main.c:2149:13: warning:
> 'adaptive_coalesce_rx_interrupts' defined but not used [-Wunused-function]
> drivers/net/ethernet/neterion/vxge/vxge-main.c:2121:13: warning:
> 'adaptive_coalesce_tx_interrupts' defined but not used [-Wunused-function]

57e7c8cef224 ("net: vxge: avoid unused function warnings")

> ip32_defconfig (mips) ? PASS, 0 errors, 2 warnings, 0 section mismatches
>
> Warnings:
> drivers/misc/ioc4.c:194:16: warning: 'start' may be used uninitialized in
> this function [-Wmaybe-uninitialized]

769105aa740d ("misc: ioc4: simplify wave period measurement in clock_calibrate")

> malta_defconfig (mips) ? PASS, 0 errors, 3 warnings, 0 section mismatches
>
> Warnings:
> drivers/net/wireless/hostap/hostap_hw.c:842:5: warning: 'rec' may be used
> uninitialized in this function [-Wmaybe-uninitialized]

48dc5fb3ba53b2 hostap: avoid uninitialized variable use in hfa384x_get_rid

> msp71xx_defconfig (mips) ? PASS, 0 errors, 3 warnings, 0 section mismatches
>
> Warnings:
> arch/mips/pci/ops-pmcmsp.c:196:24: warning: 'bpci_lock' defined but not used
> [-Wunused-variable]

c4a305374bbf ("MIPS: MSP71xx: remove odd locking in PCI config space
access code")
> mtx1_defconfig (mips) ? PASS, 0 errors, 4 warnings, 0 section mismatches
>
> Warnings:
> drivers/net/ethernet/dec/tulip/winbond-840.c:910:2: warning: #warning
> Processor architecture undefined [-Wcpp]

de92718883dd ("net: tulip: turn compile-time warning into dev_warn()")

> multi_v7_defconfig+CONFIG_ARM_LPAE=y (arm) ? PASS, 0 errors, 3 warnings, 0
> section mismatches
>
> Warnings:
> drivers/mmc/host/sunxi-mmc.c:297:35: warning: cast to pointer from integer
> of different size [-Wint-to-pointer-cast]

d34712d2e3db ("mmc: sunxi: avoid invalid pointer calculation")

> multi_v7_defconfig+CONFIG_SMP=n (arm) ? FAIL, 1 error, 2 warnings, 0 section
> mismatches
>
> Errors:
> arch/arm/kernel/psci.c:287:12: error: redefinition of 'psci_init'
> Warnings:

patch sent:

commit 37290221124afbaa9a11f17d2b1fc6bf2e829872
Author: Arnd Bergmann <arnd@arndb.de>
Date:   Fri Apr 21 15:54:10 2017 +0200

    [3.18-stable regression] ARM: psci: fix header file

    Commit be95485a0b828 was incorrectly backported to 3.18 and
    now causes a different build error when CONFIG_SMP is disabled:

     arch/arm/kernel/psci.c:287:12: error: redefinition of 'psci_init'

    This version is how it should be on 3.18, with the main psci
    code built for both SMP and UP, but the psci_smp_available()
    function only being available for SMP builds.

    Fixes: dbcfee724255 ("ARM: 8457/1: psci-smp is built only for SMP")
    Signed-off-by: Arnd Bergmann <arnd@arndb.de>

diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
index e3789fb02c9c..8ca5308a05d7 100644
--- a/arch/arm/include/asm/psci.h
+++ b/arch/arm/include/asm/psci.h
@@ -37,11 +37,15 @@ struct psci_operations {
 extern struct psci_operations psci_ops;
 extern struct smp_operations psci_smp_ops;

-#if defined(CONFIG_SMP) && defined(CONFIG_ARM_PSCI)
+#ifdef CONFIG_ARM_PSCI
 int psci_init(void);
-bool psci_smp_available(void);
 #else
 static inline int psci_init(void) { return 0; }
+#endif
+
+#if defined(CONFIG_SMP) && defined(CONFIG_ARM_PSCI)
+bool psci_smp_available(void);
+#else
 static inline bool psci_smp_available(void) { return false; }
 #endif

> nlm_xlp_defconfig (mips) ? FAIL, 1 error, 3 warnings, 0 section mismatches
>
> Errors:
> fs/gfs2/dir.c:768:9: warning: 'leaf_no' may be used uninitialized in this
> function [-Wmaybe-uninitialized]
> fs/gfs2/dir.c:987:8: warning: 'leaf_no' may be used uninitialized in this
> function [-Wmaybe-uninitialized]

67893f12e537 ("gfs2: avoid uninitialized variable warning")

(also needed on v4.4.y)

> fs/btrfs/extent_io.c:2166:13: warning: cast to pointer from integer of
> different size [-Wint-to-pointer-cast]

6e1103a6e9b1 ("btrfs: fix state->private cast on 32 bit machines")

> realview-smp_defconfig
>
> Warnings:
> arch/arm/mm/cache-l2x0.c:168:13: warning: 'l2x0_cache_sync' defined but not
> used [-Wunused-function]
> arch/arm/mm/cache-l2x0.c:185:13: warning: 'l2x0_flush_all' defined but not
> used [-Wunused-function]
> arch/arm/mm/cache-l2x0.c:195:13: warning: 'l2x0_disable' defined but not
> used [-Wunused-function]

20e783e39e55 ARM: 8296/1: cache-l2x0: clean up aurora cache handling

> rm200_defconfig (mips) ? FAIL, 0 errors, 5 warnings, 0 section mismatches
>
> Warnings:
> drivers/scsi/aic94xx/aic94xx_sds.c:597:2: warning: 'offs' may be used
> uninitialized in this function [-Wmaybe-uninitialized]

36dd5acd196574d4 aic94xx: Skip reading user settings if flash is not found

> arch/mips/boot/elf2ecoff.c:270:8: warning: variable 'shstrtab' set but not
> used [-Wunused-but-set-variable]

> Warnings:
> arch/mips/ralink/prom.c:64:2: warning: 'argc' is used uninitialized in this
> function [-Wuninitialized]
> arch/mips/ralink/prom.c:64:2: warning: 'argv' is used uninitialized in this
> function [-Wuninitialized]

9c48568b3692 ("MIPS: ralink: Cosmetic change to prom_init().")

> tinyconfig (arm) ? PASS, 0 errors, 3 warnings, 0 section mismatches
>
> Warnings:
> .config:807:warning: override: KERNEL_XZ changes choice state
> .config:809:warning: override: SLOB changes choice state

236dec051078 ("kconfig: tinyconfig: provide whole choice blocks to
avoid warnings")

^ permalink raw reply related

* [PATCH 1/3] arm64: extend ioremap for cacheable non-shareable memory
From: Roy Pledge @ 2017-04-21 14:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170421091156.GA6406@leverpostej>

These transactions are done in HW via an ACP port which if I remember correctly only supports non coherent transactions.  I will need to go back and check through email conversations I had with Catalin last year when debugging an issue using this mechanism (cacheable/nonshareable mapping) but it was deemed to be valid ARM setup architecturally for this type of device.

Just for some background the page the QBMan device presented to a core is only accessed by a single core (i.e. SW portals are core affine). In this model each page is always mapped as non shareable and another core will never access it. The important factor is that it is not DDR memory being mapped non sharable, but a non-coherent master on the bus in our SoC.  I agree regular RAM shouldn?t be mapped this way but we cannot map this device as cacheable/shareable (coherent) on CCN-504 devices without getting exceptions from the CCN-504. Treating it as non cacheable is functionally OK but performance suffers in that case.

Your help will be appreciated as we want to get support for these devices with good performance in upstream kernels.

Roy

On 2017-04-21, 5:11 AM, "Mark Rutland" <mark.rutland@arm.com> wrote:

    Hi,
    
    I notice you missed Catalin and Will from Cc. In future, please ensure
    that you Cc them when altering arm64 arch code.
    
    On Thu, Apr 20, 2017 at 03:34:16PM -0400, Haiying Wang wrote:
    > NXP arm64 based SoC needs to allocate cacheable and
    > non-shareable memory for the software portals of
    > Queue manager, so we extend the arm64 ioremap support
    > for this memory attribute.
    
    NAK to this patch.
    
    It is not possible to safely use Non-Shareable attributes in Linux page
    tables, given that these page tables are shared by all PEs (i.e. CPUs).
    
    My understanding is that if several PEs map a region as Non-Shareable,
    the usual background behaviour of the PEs (e.g. speculation,
    prefetching, natural eviction) mean that uniprocessor semantics are not
    guaranteed (i.e. a read following a write may see stale data).
    
    For example, in a system like:
    
        +------+  +------+
        | PE-a |  | PE-b |
        +------+  +------+
        | L1-a |  | L1-b |
        +------+  +------+
           ||        ||
        +----------------+
        |  Shared cache  |
        +----------------+
                ||
        +----------------+
        |     Memory     |
        +----------------+
    
    ... you could have a sequence like:
    
    1) PE-a allocates a line into L1-a for address X in preparation for a
       store.
    
    2) PE-b allocates a line into L1-b for the same address X as a result of
       speculation.
    
    3) PE-a makes a store to the line in L1-a. Since address X is mapped as
       Non-shareable, no snoops are performed to keep other copies of the
       line in sync.
    
    4) As a result of explicit maintenance or as a natural eviction, L1-a
       evicts its line into shared cache. The shared cache subsequently
       evicts this to memory.
    
    5) L1-b evicts its line to shared cache as a natural eviction.
    
    6) L1-a fetches the line from shared cache in response to a load by
       PE-a, returning stale data (i.e. the store is lost).
    
    No amount of cache maintenance can avoid this. In general, Non-Shareable
    mappings are a bad idea.
    
    Thanks,
    Mark.
    
    > Signed-off-by: Haiying Wang <Haiying.Wang@nxp.com>
    > ---
    >  arch/arm64/include/asm/io.h           | 1 +
    >  arch/arm64/include/asm/pgtable-prot.h | 1 +
    >  2 files changed, 2 insertions(+)
    > 
    > diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
    > index 0c00c87..b6f03e7 100644
    > --- a/arch/arm64/include/asm/io.h
    > +++ b/arch/arm64/include/asm/io.h
    > @@ -170,6 +170,7 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
    >  #define ioremap_nocache(addr, size)	__ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
    >  #define ioremap_wc(addr, size)		__ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
    >  #define ioremap_wt(addr, size)		__ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
    > +#define ioremap_cache_ns(addr, size)	__ioremap((addr), (size), __pgprot(PROT_NORMAL_NS))
    >  #define iounmap				__iounmap
    >  
    >  /*
    > diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
    > index 2142c77..7fc7910 100644
    > --- a/arch/arm64/include/asm/pgtable-prot.h
    > +++ b/arch/arm64/include/asm/pgtable-prot.h
    > @@ -42,6 +42,7 @@
    >  #define PROT_NORMAL_NC		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
    >  #define PROT_NORMAL_WT		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT))
    >  #define PROT_NORMAL		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
    > +#define PROT_NORMAL_NS		(PTE_TYPE_PAGE | PTE_AF | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
    >  
    >  #define PROT_SECT_DEVICE_nGnRE	(PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
    >  #define PROT_SECT_NORMAL	(PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
    > -- 
    > 2.7.4
    > 
    > 
    > _______________________________________________
    > 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 2/3] bus: fsl-mc: dpio: enable qbman CENA portal memory access
From: Catalin Marinas @ 2017-04-21 14:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492716858-24509-3-git-send-email-Haiying.Wang@nxp.com>

On Thu, Apr 20, 2017 at 03:34:17PM -0400, Haiying Wang wrote:
> Once we enable the cacheable portal memory, we need to do
> cache flush for enqueue, vdq, buffer release, and management
> commands, as well as invalidate and prefetch for the valid bit
> of management command response and next index of dqrr.
> 
> Signed-off-by: Haiying Wang <Haiying.Wang@nxp.com>

For the record, NAK on the whole series. It may appear to improve the
performance a bit but this is not architecturally compliant and relies
heavily on specific CPU and SoC implementation details which may
fail in very subtle way.

> --- a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c
> +++ b/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c
> @@ -99,6 +99,14 @@ enum qbman_sdqcr_fc {
>  	qbman_sdqcr_fc_up_to_3 = 1
>  };
>  
> +#define dccvac(p) { asm volatile("dc cvac, %0;" : : "r" (p) : "memory"); }
> +#define dcivac(p) { asm volatile("dc ivac, %0" : : "r"(p) : "memory"); }
> +static inline void qbman_inval_prefetch(struct qbman_swp *p, uint32_t offset)
> +{
> +	dcivac(p->addr_cena + offset);
> +	prefetch(p->addr_cena + offset);
> +}
[...]
> @@ -435,6 +445,7 @@ int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
>  	/* Set the verb byte, have to substitute in the valid-bit */
>  	dma_wmb();
>  	p->verb = d->verb | EQAR_VB(eqar);
> +	dccvac(p);

The command buffer is on a device and currently mapped as write-combined
memory (that is Normal Non-cacheable on ARM). To enqueue a command, the
current code populates the struct qbman_eq_desc fields, followed by a
dma_wmb() (that is a DSB SY on ARM) and the subsequent update of the
"verb" byte to mark the descriptor as valid. These are all pretty much
*slave* (vs master) accesses since the device does not read such memory
through the system's point of serialisation. The DSB may happen ensure
the ordering of the verb update on your specific SoC, though
architecturally this is not guaranteed.

With your cacheable mapping patch, things get worse. The above dma_wmb()
does not have any effect at all with respect to the QBMan device since
all the code does is populate qbman_eq_desc *within* the CPU's L1 cache
which the device does *not* see. Once you call the dccvac() macro, you
would find that the "verb" is evicted first (since it's the beginning of
the qbman_eq_desc structure which is not what you want). The
interconnect may also split the cache eviction into multiple
transactions, so what the device would see is not guaranteed to be
atomic.

Similarly for the dequeue ring, the CPU is allowed to generate
transactions to fill its cache lines in any order (usually it can start
on any of the 4 quad words of the cache line), so it could as well
preload stale descriptors but with a valid verb.

-- 
Catalin

^ permalink raw reply

* [PATCH v2] dmaengine: sun4i: fix invalid argument
From: Maxime Ripard @ 2017-04-21 14:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3e98596a-0322-e4f1-7cc2-9b0eaceb4465@free.fr>

On Fri, Apr 21, 2017 at 10:43:20AM +0200, Mason wrote:
> From: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
> 
> The "pchans_used" field is an unsigned long array.
> 
> for_each_clear_bit_from() expects an unsigned long pointer,
> not an array address.
> 
> $ make C=2 drivers/dma/sun4i-dma.o
>   CHECK   drivers/dma/sun4i-dma.c
> drivers/dma/sun4i-dma.c:241:9: warning: incorrect type in argument 1 (different base types)
> drivers/dma/sun4i-dma.c:241:9:    expected unsigned long const *p
> drivers/dma/sun4i-dma.c:241:9:    got unsigned long ( *<noident> )[1]
> 
> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170421/75899912/attachment.sig>

^ permalink raw reply

* stable/linux-3.18.y build: 204 builds: 5 failed, 199 passed, 35 errors, 212 warnings (v3.18.49)
From: Mark Brown @ 2017-04-21 14:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK8P3a3QsSMtc7AWjVjtM+tW8ARt1Ygw53=CSjgbG6Pvpq0QvQ@mail.gmail.com>

On Fri, Apr 21, 2017 at 04:27:14PM +0200, Arnd Bergmann wrote:
> On Thu, Apr 20, 2017 at 7:04 PM, kernelci.org bot <bot@kernelci.org> wrote:
> > stable/linux-3.18.y build: 204 builds: 5 failed, 199 passed, 35 errors, 212 warnings (v3.18.49)

> > 2 arch/mips/mm/fault.c:321:1: error: the frame size of 1104 bytes is larger
> > than 1024 bytes [-Werror=frame-larger-than=]

> This is a result of a newer compiler version, combined with the -Werror
> flag that is applied to arch/mips/, and two of the mips defconfigs overriding
> CONFIG_FRAME_WARN to 1024 on a 64-bit architecture (probably by
> accident).

I'm wondering how good an idea it is to leave -Werror on in stable
kernels given that they're very likely to get used with newer compilers
at some point.  But then I've never been a fan of -Werror in the first
place.
-------------- 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/20170421/2fa696a6/attachment.sig>

^ permalink raw reply

* [PATCH V2] scsi: mpt3sas: remove redundant wmb
From: Brian King @ 2017-04-21 15:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK=zhgpmcmq-CnWuU9=WRJpAaEduw63LSPLE9yZzF_sUHkM4AA@mail.gmail.com>

On 04/21/2017 02:56 AM, Sreekanth Reddy wrote:
> On Thu, Apr 20, 2017 at 7:58 AM, Martin K. Petersen
> <martin.petersen@oracle.com> wrote:
>> Sinan Kaya <okaya@codeaurora.org> writes:
>>
>>> Due to relaxed ordering requirements on multiple architectures,
>>> drivers are required to use wmb/rmb/mb combinations when they need to
>>> guarantee observability between the memory and the HW.
>>>
>>> The mpt3sas driver is already using wmb() for this purpose.  However,
>>> it issues a writel following wmb(). writel() function on arm/arm64
>>> arhictectures have an embedded wmb() call inside.
> 
> [Sreekanth] Whether same thing applicable for SPARC & POWER
> architectures. If yes then we are fine with this patch changes.

This is also true for Power. 

Reviewed-by: Brian King <brking@linux.vnet.ibm.com>

-Brian

-- 
Brian King
Power Linux I/O
IBM Linux Technology Center

^ permalink raw reply

* [linux-sunxi] [PATCH 13/15] drm/sun4i: Add HDMI support
From: Chen-Yu Tsai @ 2017-04-21 15:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <c63d01aedeccc58bf8d6f5bfd66d8595156e9491.1488876832.git-series.maxime.ripard@free-electrons.com>

Hi,

On Tue, Mar 7, 2017 at 4:56 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The earlier Allwinner SoCs (A10, A10s, A20, A31) have an embedded HDMI
> controller.
>
> That HDMI controller is able to do audio and CEC, but those have been left
> out for now.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/Makefile              |   5 +-
>  drivers/gpu/drm/sun4i/sun4i_hdmi.h          | 124 ++++++-
>  drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c  | 128 ++++++-
>  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c      | 449 +++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c | 236 +++++++++++-
>  5 files changed, 942 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi.h
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c

Applying patch #9608371 using 'git am'
Description: [13/15] drm/sun4i: Add HDMI support
Applying: drm/sun4i: Add HDMI support
.git/rebase-apply/patch:116: trailing whitespace.

.git/rebase-apply/patch:531: trailing whitespace.

.git/rebase-apply/patch:701: trailing whitespace.

warning: 3 lines add whitespace errors.

> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 59b757350a1f..68a0f6244a59 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -7,7 +7,12 @@ sun4i-tcon-y += sun4i_dotclock.o
>  sun4i-tcon-y += sun4i_crtc.o
>  sun4i-tcon-y += sun4i_layer.o
>
> +sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
> +sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
> +sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
> +
>  obj-$(CONFIG_DRM_SUN4I)                += sun4i-drm.o sun4i-tcon.o
>  obj-$(CONFIG_DRM_SUN4I)                += sun4i_backend.o
>  obj-$(CONFIG_DRM_SUN4I)                += sun6i_drc.o
> +obj-$(CONFIG_DRM_SUN4I)                += sun4i-drm-hdmi.o
>  obj-$(CONFIG_DRM_SUN4I)                += sun4i_tv.o
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi.h b/drivers/gpu/drm/sun4i/sun4i_hdmi.h
> new file mode 100644
> index 000000000000..2ad25b8fd3cd
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi.h
> @@ -0,0 +1,124 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUN4I_HDMI_H_
> +#define _SUN4I_HDMI_H_
> +
> +#include <drm/drm_connector.h>
> +#include <drm/drm_encoder.h>
> +
> +#define SUN4I_HDMI_CTRL_REG            0x004
> +#define SUN4I_HDMI_CTRL_ENABLE                 BIT(31)
> +
> +#define SUN4I_HDMI_IRQ_REG             0x008
> +#define SUN4I_HDMI_IRQ_STA_MASK                        0x73
> +#define SUN4I_HDMI_IRQ_STA_FIFO_OF             BIT(1)
> +#define SUN4I_HDMI_IRQ_STA_FIFO_UF             BIT(0)
> +
> +#define SUN4I_HDMI_HPD_REG             0x00c
> +#define SUN4I_HDMI_HPD_HIGH                    BIT(0)
> +
> +#define SUN4I_HDMI_VID_CTRL_REG                0x010
> +#define SUN4I_HDMI_VID_CTRL_ENABLE             BIT(31)
> +#define SUN4I_HDMI_VID_CTRL_HDMI_MODE          BIT(30)
> +
> +#define SUN4I_HDMI_VID_TIMING_ACT_REG  0x014
> +#define SUN4I_HDMI_VID_TIMING_BP_REG   0x018
> +#define SUN4I_HDMI_VID_TIMING_FP_REG   0x01c
> +#define SUN4I_HDMI_VID_TIMING_SPW_REG  0x020
> +
> +#define SUN4I_HDMI_VID_TIMING_X(x)             ((((x) - 1) & GENMASK(11, 0)))
> +#define SUN4I_HDMI_VID_TIMING_Y(y)             ((((y) - 1) & GENMASK(11, 0)) << 16)
> +
> +#define SUN4I_HDMI_VID_TIMING_POL_REG  0x024
> +#define SUN4I_HDMI_VID_TIMING_POL_TX_CLK        (0x3e0 << 16)
> +#define SUN4I_HDMI_VID_TIMING_POL_VSYNC                BIT(1)
> +#define SUN4I_HDMI_VID_TIMING_POL_HSYNC                BIT(0)
> +
> +#define SUN4I_HDMI_AVI_INFOFRAME_REG(n)        (0x080 + (n))
> +
> +#define SUN4I_HDMI_PAD_CTRL0_REG       0x200
> +
> +#define SUN4I_HDMI_PAD_CTRL1_REG       0x204
> +#define SUN4I_HDMI_PAD_CTRL1_HALVE_CLK         BIT(6)
> +
> +#define SUN4I_HDMI_PLL_CTRL_REG                0x208
> +#define SUN4I_HDMI_PLL_CTRL_DIV(n)             ((n) << 4)
> +#define SUN4I_HDMI_PLL_CTRL_DIV_MASK           GENMASK(7, 4)
> +
> +#define SUN4I_HDMI_PLL_DBG0_REG                0x20c
> +#define SUN4I_HDMI_PLL_DBG0_TMDS_PARENT(n)     (((n) & 1) << 21)
> +#define SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_MASK   BIT(21)
> +#define SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_SHIFT  21
> +
> +#define SUN4I_HDMI_PKT_CTRL_REG(n)     (0x2f0 + (4 * (n)))
> +#define SUN4I_HDMI_PKT_CTRL_TYPE(n, t)         ((t) << (((n) % 4) * 4))
> +
> +#define SUN4I_HDMI_UNKNOWN_REG         0x300
> +#define SUN4I_HDMI_UNKNOWN_INPUT_SYNC          BIT(27)
> +
> +#define SUN4I_HDMI_DDC_CTRL_REG                0x500
> +#define SUN4I_HDMI_DDC_CTRL_ENABLE             BIT(31)
> +#define SUN4I_HDMI_DDC_CTRL_START_CMD          BIT(30)
> +#define SUN4I_HDMI_DDC_CTRL_RESET              BIT(0)
> +
> +#define SUN4I_HDMI_DDC_ADDR_REG                0x504
> +#define SUN4I_HDMI_DDC_ADDR_SEGMENT(seg)       (((seg) & 0xff) << 24)
> +#define SUN4I_HDMI_DDC_ADDR_EDDC(addr)         (((addr) & 0xff) << 16)
> +#define SUN4I_HDMI_DDC_ADDR_OFFSET(off)                (((off) & 0xff) << 8)
> +#define SUN4I_HDMI_DDC_ADDR_SLAVE(addr)                ((addr) & 0xff)
> +
> +#define SUN4I_HDMI_DDC_FIFO_CTRL_REG   0x510
> +#define SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR         BIT(31)
> +
> +#define SUN4I_HDMI_DDC_FIFO_DATA_REG   0x518
> +#define SUN4I_HDMI_DDC_BYTE_COUNT_REG  0x51c
> +
> +#define SUN4I_HDMI_DDC_CMD_REG         0x520
> +#define SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ  6
> +
> +#define SUN4I_HDMI_DDC_CLK_REG         0x528
> +#define SUN4I_HDMI_DDC_CLK_M(m)                        (((m) & 0x7) << 3)
> +#define SUN4I_HDMI_DDC_CLK_N(n)                        ((n) & 0x7)
> +
> +#define SUN4I_HDMI_DDC_LINE_CTRL_REG   0x540
> +#define SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE    BIT(9)
> +#define SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE    BIT(8)
> +
> +#define SUN4I_HDMI_DDC_FIFO_SIZE       16
> +
> +enum sun4i_hdmi_pkt_type {
> +       SUN4I_HDMI_PKT_AVI = 2,
> +       SUN4I_HDMI_PKT_END = 15,
> +};
> +
> +struct sun4i_hdmi {
> +       struct drm_connector    connector;
> +       struct drm_encoder      encoder;
> +       struct device           *dev;
> +
> +       void __iomem            *base;
> +       struct clk              *bus_clk;
> +       struct clk              *ddc_clk;
> +       struct clk              *mod_clk;
> +       struct clk              *pll0_clk;
> +       struct clk              *pll1_clk;
> +       struct clk              *tmds_clk;
> +
> +       struct sun4i_drv        *drv;
> +
> +       bool                    hdmi_monitor;
> +};
> +
> +int sun4i_ddc_create(struct sun4i_hdmi *hdmi, struct clk *clk);
> +int sun4i_tmds_create(struct sun4i_hdmi *hdmi);
> +
> +#endif /* _SUN4I_HDMI_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> new file mode 100644
> index 000000000000..5125b14ea7a5
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> @@ -0,0 +1,128 @@
> +/*
> + * Copyright (C) 2016 Free Electrons
> + * Copyright (C) 2016 NextThing Co
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "sun4i_tcon.h"
> +#include "sun4i_hdmi.h"
> +
> +struct sun4i_ddc {
> +       struct clk_hw           hw;
> +       struct sun4i_hdmi       *hdmi;
> +};
> +
> +static inline struct sun4i_ddc *hw_to_ddc(struct clk_hw *hw)
> +{
> +       return container_of(hw, struct sun4i_ddc, hw);
> +}
> +
> +static unsigned long sun4i_ddc_calc_divider(unsigned long rate,
> +                                           unsigned long parent_rate,
> +                                           u8 *m, u8 *n)
> +{
> +       unsigned long best_rate = 0;
> +       u8 best_m = 0, best_n = 0, _m, _n;
> +
> +       for (_m = 0; _m < 8; _m++) {
> +               for (_n = 0; _n < 8; _n++) {
> +                       unsigned long tmp_rate;
> +
> +                       tmp_rate = (((parent_rate / 2) / 10) >> _n) / (_m + 1);
> +
> +                       if (tmp_rate > rate)
> +                               continue;
> +
> +                       if (abs(rate - tmp_rate) < abs(rate - best_rate)) {
> +                               best_rate = tmp_rate;
> +                               best_m = _m;
> +                               best_n = _n;
> +                       }
> +               }
> +       }
> +
> +       if (m && n) {
> +               *m = best_m;
> +               *n = best_n;
> +       }
> +
> +       return best_rate;
> +}
> +
> +static long sun4i_ddc_round_rate(struct clk_hw *hw, unsigned long rate,
> +                                unsigned long *prate)
> +{
> +       return sun4i_ddc_calc_divider(rate, *prate, NULL, NULL);
> +}
> +
> +static unsigned long sun4i_ddc_recalc_rate(struct clk_hw *hw,
> +                                           unsigned long parent_rate)
> +{
> +       struct sun4i_ddc *ddc = hw_to_ddc(hw);
> +       u32 reg;
> +       u8 m, n;
> +
> +       reg = readl(ddc->hdmi->base + SUN4I_HDMI_DDC_CLK_REG);
> +       m = (reg >> 3) & 0x7;
> +       n = reg & 0x7;
> +
> +       return (((parent_rate / 2) / 10) >> n) / (m + 1);
> +}
> +
> +static int sun4i_ddc_set_rate(struct clk_hw *hw, unsigned long rate,
> +                             unsigned long parent_rate)
> +{
> +       struct sun4i_ddc *ddc = hw_to_ddc(hw);
> +       u8 div_m, div_n;
> +
> +       sun4i_ddc_calc_divider(rate, parent_rate, &div_m, &div_n);
> +
> +       writel(SUN4I_HDMI_DDC_CLK_M(div_m) | SUN4I_HDMI_DDC_CLK_N(div_n),
> +              ddc->hdmi->base + SUN4I_HDMI_DDC_CLK_REG);
> +
> +       return 0;
> +}
> +
> +static const struct clk_ops sun4i_ddc_ops = {
> +       .recalc_rate    = sun4i_ddc_recalc_rate,
> +       .round_rate     = sun4i_ddc_round_rate,
> +       .set_rate       = sun4i_ddc_set_rate,
> +};
> +
> +int sun4i_ddc_create(struct sun4i_hdmi *hdmi, struct clk *parent)
> +{
> +       struct clk_init_data init;
> +       struct sun4i_ddc *ddc;
> +       const char *parent_name;
> +
> +       parent_name = __clk_get_name(parent);
> +       if (!parent_name)
> +               return -ENODEV;
> +
> +       ddc = devm_kzalloc(hdmi->dev, sizeof(*ddc), GFP_KERNEL);
> +       if (!ddc)
> +               return -ENOMEM;
> +
> +       init.name = "hdmi-ddc";
> +       init.ops = &sun4i_ddc_ops;
> +       init.parent_names = &parent_name;
> +       init.num_parents = 1;
> +       init.flags = CLK_SET_RATE_PARENT;

I don't think this is really needed. It probably doesn't hurt though,
since DDC is used when HDMI is not used for displaying, but it might
affect any upstream PLLs, which theoretically may affect other users
of said PLLs. The DDC clock is slow enough that we should be able to
generate a usable clock rate anyway.

> +
> +       ddc->hdmi = hdmi;
> +       ddc->hw.init = &init;
> +
> +       hdmi->ddc_clk = devm_clk_register(hdmi->dev, &ddc->hw);
> +       if (IS_ERR(hdmi->ddc_clk))
> +               return PTR_ERR(hdmi->ddc_clk);
> +
> +       return 0;
> +}
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> new file mode 100644
> index 000000000000..33175308c2ed
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -0,0 +1,449 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
> +#include <drm/drm_panel.h>
> +
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/iopoll.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +
> +#include "sun4i_backend.h"
> +#include "sun4i_drv.h"
> +#include "sun4i_hdmi.h"
> +#include "sun4i_tcon.h"
> +
> +static inline struct sun4i_hdmi *
> +drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
> +{
> +       return container_of(encoder, struct sun4i_hdmi,
> +                           encoder);
> +}
> +
> +static inline struct sun4i_hdmi *
> +drm_connector_to_sun4i_hdmi(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct sun4i_hdmi,
> +                           connector);
> +}
> +
> +static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
> +                                          struct drm_display_mode *mode)
> +{
> +       struct hdmi_avi_infoframe frame;
> +       u8 buffer[17];
> +       int i, ret;
> +
> +       ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +       if (ret < 0) {
> +               DRM_ERROR("Failed to get infoframes from mode\n");
> +               return ret;
> +       }
> +
> +       ret = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
> +       if (ret < 0) {
> +               DRM_ERROR("Failed to pack infoframes\n");
> +               return ret;
> +       }
> +
> +       for (i = 0; i < sizeof(buffer); i++)
> +               writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i));
> +
> +       return 0;
> +}
> +
> +static void sun4i_hdmi_disable(struct drm_encoder *encoder)
> +{
> +       struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> +       struct sun4i_drv *drv = hdmi->drv;
> +       struct sun4i_tcon *tcon = drv->tcon;
> +       u32 val;
> +
> +       DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
> +
> +       val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
> +       val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
> +       writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
> +
> +       sun4i_tcon_channel_disable(tcon, 1);
> +}
> +
> +static void sun4i_hdmi_enable(struct drm_encoder *encoder)
> +{
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> +       struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> +       struct sun4i_drv *drv = hdmi->drv;
> +       struct sun4i_tcon *tcon = drv->tcon;
> +       u32 val = 0;
> +
> +       DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
> +
> +       sun4i_tcon_channel_enable(tcon, 1);
> +
> +       sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
> +       val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
> +       val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
> +       writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
> +
> +       val = SUN4I_HDMI_VID_CTRL_ENABLE;
> +       if (hdmi->hdmi_monitor)
> +               val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
> +
> +       writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
> +}
> +
> +static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
> +                               struct drm_display_mode *mode,
> +                               struct drm_display_mode *adjusted_mode)
> +{
> +       struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> +       struct sun4i_drv *drv = hdmi->drv;
> +       struct sun4i_tcon *tcon = drv->tcon;
> +       unsigned int x, y;
> +       u32 val;
> +
> +       sun4i_tcon1_mode_set(tcon, encoder, mode);
> +       clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
> +       clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
> +
> +       /* Set input sync enable */
> +       writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC,
> +              hdmi->base + SUN4I_HDMI_UNKNOWN_REG);
> +
> +       /* Setup timing registers */
> +       writel(SUN4I_HDMI_VID_TIMING_X(mode->hdisplay) |
> +              SUN4I_HDMI_VID_TIMING_Y(mode->vdisplay),
> +              hdmi->base + SUN4I_HDMI_VID_TIMING_ACT_REG);
> +
> +       x = mode->htotal - mode->hsync_start;
> +       y = mode->vtotal - mode->vsync_start;

I'm a bit skeptical about this one. All the other parameters are not
inclusive of other, why would this one be different? Shouldn't it
be "Xtotal - Xsync_end" instead?

> +       writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
> +              hdmi->base + SUN4I_HDMI_VID_TIMING_BP_REG);
> +
> +       x = mode->hsync_start - mode->hdisplay;
> +       y = mode->vsync_start - mode->vdisplay;
> +       writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
> +              hdmi->base + SUN4I_HDMI_VID_TIMING_FP_REG);
> +
> +       x = mode->hsync_end - mode->hsync_start;
> +       y = mode->vsync_end - mode->vsync_start;
> +       writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
> +              hdmi->base + SUN4I_HDMI_VID_TIMING_SPW_REG);
> +
> +       val = SUN4I_HDMI_VID_TIMING_POL_TX_CLK;
> +       if (mode->flags & DRM_MODE_FLAG_PHSYNC)
> +               val |= SUN4I_HDMI_VID_TIMING_POL_HSYNC;
> +
> +       if (mode->flags & DRM_MODE_FLAG_PVSYNC)
> +               val |= SUN4I_HDMI_VID_TIMING_POL_VSYNC;
> +
> +       writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);

You don't handle the interlaced video here, even though you set

    hdmi->connector.interlace_allowed = true

later.

The double clock and double scan flags aren't handled either, though
I don't understand which one is supposed to represent the need for the
HDMI pixel repeater. AFAIK this is required for resolutions with pixel
clocks lower than 25 MHz, the lower limit of HDMI's TMDS link.

> +}
> +
> +static struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
> +       .disable        = sun4i_hdmi_disable,
> +       .enable         = sun4i_hdmi_enable,
> +       .mode_set       = sun4i_hdmi_mode_set,
> +};
> +
> +static struct drm_encoder_funcs sun4i_hdmi_funcs = {
> +       .destroy        = drm_encoder_cleanup,
> +};
> +
> +static int sun4i_hdmi_read_sub_block(struct sun4i_hdmi *hdmi,
> +                                    unsigned int blk, unsigned int offset,
> +                                    u8 *buf, unsigned int count)
> +{
> +       unsigned long reg;
> +       int i;
> +
> +       reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG);
> +       writel(reg | SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR,
> +              hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG);
> +       writel(SUN4I_HDMI_DDC_ADDR_SEGMENT(offset >> 8) |
> +              SUN4I_HDMI_DDC_ADDR_EDDC(0x60) |
> +              SUN4I_HDMI_DDC_ADDR_OFFSET(offset) |
> +              SUN4I_HDMI_DDC_ADDR_SLAVE(0x50),

You can use DDC_ADDR from drm_edid.h.

> +              hdmi->base + SUN4I_HDMI_DDC_ADDR_REG);
> +
> +       writel(count, hdmi->base + SUN4I_HDMI_DDC_BYTE_COUNT_REG);
> +       writel(SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ,
> +              hdmi->base + SUN4I_HDMI_DDC_CMD_REG);
> +
> +       reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
> +       writel(reg | SUN4I_HDMI_DDC_CTRL_START_CMD,
> +              hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
> +
> +       if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg,
> +                              !(reg & SUN4I_HDMI_DDC_CTRL_START_CMD),
> +                              100, 2000))
> +               return -EIO;
> +
> +       for (i = 0; i < count; i++)
> +               buf[i] = readb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG);
> +
> +       return 0;
> +}
> +
> +static int sun4i_hdmi_read_edid_block(void *data, u8 *buf, unsigned int blk,
> +                                     size_t length)
> +{
> +       struct sun4i_hdmi *hdmi = data;
> +       int retry = 2, i;
> +
> +       do {
> +               for (i = 0; i < length; i += SUN4I_HDMI_DDC_FIFO_SIZE) {
> +                       unsigned char offset = blk * EDID_LENGTH + i;
> +                       unsigned int count = min((unsigned int)SUN4I_HDMI_DDC_FIFO_SIZE,
> +                                                length - i);
> +                       int ret;
> +
> +                       ret = sun4i_hdmi_read_sub_block(hdmi, blk, offset,
> +                                                       buf + i, count);
> +                       if (ret)
> +                               return ret;
> +               }
> +       } while (!drm_edid_block_valid(buf, blk, true, NULL) && (retry--));
> +
> +       return 0;
> +}
> +
> +static int sun4i_hdmi_get_modes(struct drm_connector *connector)
> +{
> +       struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
> +       unsigned long reg;
> +       struct edid *edid;
> +       int ret;
> +
> +       /* Reset i2c controller */
> +       writel(SUN4I_HDMI_DDC_CTRL_ENABLE | SUN4I_HDMI_DDC_CTRL_RESET,
> +              hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
> +       if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg,
> +                              !(reg & SUN4I_HDMI_DDC_CTRL_RESET),
> +                              100, 2000))
> +               return -EIO;
> +
> +       writel(SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE |
> +              SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE,
> +              hdmi->base + SUN4I_HDMI_DDC_LINE_CTRL_REG);
> +
> +       clk_set_rate(hdmi->ddc_clk, 100000);
> +
> +       edid = drm_do_get_edid(connector, sun4i_hdmi_read_edid_block, hdmi);
> +       if (!edid)
> +               return 0;
> +
> +       hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid);
> +       DRM_DEBUG_DRIVER("Monitor is %s monitor\n",
> +                        hdmi->hdmi_monitor ? "an HDMI" : "a DVI");
> +
> +       drm_mode_connector_update_edid_property(connector, edid);
> +       ret = drm_add_edid_modes(connector, edid);
> +       kfree(edid);
> +
> +       return ret;
> +}
> +
> +static struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = {
> +       .get_modes      = sun4i_hdmi_get_modes,
> +};
> +
> +static enum drm_connector_status
> +sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force)
> +{
> +       struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
> +       unsigned long reg;
> +
> +       if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_HPD_REG, reg,
> +                              reg & SUN4I_HDMI_HPD_HIGH,
> +                              0, 500000))

We shouldn't need to do polling here. It should just return the status
at the instance it's called. Instead we should have a worker that does
polling to check if something is plugged or unplugged. I don't see any
interrupt bits for this though. :(

> +               return connector_status_disconnected;
> +
> +       return connector_status_connected;
> +}
> +
> +static struct drm_connector_funcs sun4i_hdmi_connector_funcs = {
> +       .dpms                   = drm_atomic_helper_connector_dpms,
> +       .detect                 = sun4i_hdmi_connector_detect,
> +       .fill_modes             = drm_helper_probe_single_connector_modes,
> +       .destroy                = drm_connector_cleanup,
> +       .reset                  = drm_atomic_helper_connector_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int sun4i_hdmi_bind(struct device *dev, struct device *master,
> +                        void *data)
> +{
> +       struct drm_device *drm = data;
> +       struct sun4i_drv *drv = drm->dev_private;
> +       struct sun4i_hdmi *hdmi = dev_get_drvdata(dev);
> +       int ret;
> +
> +       hdmi->drv = drv;
> +       drm_encoder_helper_add(&hdmi->encoder,
> +                              &sun4i_hdmi_helper_funcs);
> +       ret = drm_encoder_init(drm,
> +                              &hdmi->encoder,
> +                              &sun4i_hdmi_funcs,
> +                              DRM_MODE_ENCODER_TMDS,
> +                              NULL);
> +       if (ret) {
> +               dev_err(dev, "Couldn't initialise the HDMI encoder\n");
> +               return ret;
> +       }
> +
> +       hdmi->encoder.possible_crtcs = BIT(0);

You can use drm_of_find_possible_crtcs() now. See the TV encoder driver.

> +
> +       drm_connector_helper_add(&hdmi->connector,
> +                                &sun4i_hdmi_connector_helper_funcs);
> +       ret = drm_connector_init(drm, &hdmi->connector,
> +                                &sun4i_hdmi_connector_funcs,
> +                                DRM_MODE_CONNECTOR_HDMIA);
> +       if (ret) {
> +               dev_err(dev,
> +                       "Couldn't initialise the Composite connector\n");

Wrong connector.

> +               goto err_cleanup_connector;
> +       }
> +       hdmi->connector.interlace_allowed = true;
> +
> +       drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder);
> +
> +       return 0;
> +
> +err_cleanup_connector:
> +       drm_encoder_cleanup(&hdmi->encoder);
> +       return ret;
> +}
> +
> +static void sun4i_hdmi_unbind(struct device *dev, struct device *master,
> +                           void *data)
> +{
> +       struct sun4i_hdmi *hdmi = dev_get_drvdata(dev);
> +
> +       drm_connector_cleanup(&hdmi->connector);
> +       drm_encoder_cleanup(&hdmi->encoder);
> +}
> +
> +static struct component_ops sun4i_hdmi_ops = {
> +       .bind   = sun4i_hdmi_bind,
> +       .unbind = sun4i_hdmi_unbind,
> +};
> +
> +static int sun4i_hdmi_probe(struct platform_device *pdev)
> +{
> +       struct sun4i_hdmi *hdmi;
> +       struct resource *res;
> +       int ret;
> +
> +       hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
> +       if (!hdmi)
> +               return -ENOMEM;
> +       dev_set_drvdata(&pdev->dev, hdmi);
> +       hdmi->dev = &pdev->dev;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       hdmi->base = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(hdmi->base)) {
> +               dev_err(&pdev->dev, "Couldn't map the HDMI encoder registers\n");
> +               return PTR_ERR(hdmi->base);
> +       }
> +
> +       hdmi->bus_clk = devm_clk_get(&pdev->dev, "ahb");
> +       if (IS_ERR(hdmi->bus_clk)) {
> +               dev_err(&pdev->dev, "Couldn't get the HDMI bus clock\n");
> +               return PTR_ERR(hdmi->bus_clk);
> +       }
> +       clk_prepare_enable(hdmi->bus_clk);
> +
> +       hdmi->mod_clk = devm_clk_get(&pdev->dev, "mod");
> +       if (IS_ERR(hdmi->mod_clk)) {
> +               dev_err(&pdev->dev, "Couldn't get the HDMI mod clock\n");
> +               return PTR_ERR(hdmi->mod_clk);
> +       }
> +       clk_prepare_enable(hdmi->mod_clk);
> +
> +       hdmi->pll0_clk = devm_clk_get(&pdev->dev, "pll-0");
> +       if (IS_ERR(hdmi->pll0_clk)) {
> +               dev_err(&pdev->dev, "Couldn't get the HDMI PLL 0 clock\n");
> +               return PTR_ERR(hdmi->pll0_clk);
> +       }
> +
> +       hdmi->pll1_clk = devm_clk_get(&pdev->dev, "pll-1");
> +       if (IS_ERR(hdmi->pll1_clk)) {
> +               dev_err(&pdev->dev, "Couldn't get the HDMI PLL 1 clock\n");
> +               return PTR_ERR(hdmi->pll1_clk);
> +       }
> +
> +       ret = sun4i_tmds_create(hdmi);
> +       if (ret) {
> +               dev_err(&pdev->dev, "Couldn't create the TMDS clock\n");
> +               return ret;
> +       }
> +
> +       writel(SUN4I_HDMI_CTRL_ENABLE, hdmi->base + SUN4I_HDMI_CTRL_REG);
> +
> +#define SUN4I_HDMI_PAD_CTRL0 0xfe800000
> +
> +       writel(SUN4I_HDMI_PAD_CTRL0, hdmi->base + SUN4I_HDMI_PAD_CTRL0_REG);
> +
> +       /* TODO: defines */
> +       writel((6 << 3) | (2 << 10) | BIT(14) | BIT(15) |
> +              BIT(19) | BIT(20) | BIT(22) | BIT(23),
> +              hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
> +
> +       /* TODO: defines */
> +       writel((8 << 0) | (7 << 8) | (239 << 12) | (7 << 17) | (4 << 20) |
> +              BIT(25) | BIT(27) | BIT(28) | BIT(29) | BIT(30) | BIT(31),
> +              hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);

FYI some bits in this register look a lot like the MIPI PLL on the A33.
Bit 31 looks like the enable bit.

> +
> +       ret = sun4i_ddc_create(hdmi, hdmi->tmds_clk);
> +       if (ret) {
> +               dev_err(&pdev->dev, "Couldn't create the DDC clock\n");
> +               return ret;
> +       }

We do all this in the bind function for all the other components.
Any particular reason to do it differently here?

> +
> +       return component_add(&pdev->dev, &sun4i_hdmi_ops);
> +}
> +
> +static int sun4i_hdmi_remove(struct platform_device *pdev)
> +{
> +       component_del(&pdev->dev, &sun4i_hdmi_ops);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id sun4i_hdmi_of_table[] = {
> +       { .compatible = "allwinner,sun5i-a10s-hdmi" },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, sun4i_hdmi_of_table);
> +
> +static struct platform_driver sun4i_hdmi_driver = {
> +       .probe          = sun4i_hdmi_probe,
> +       .remove         = sun4i_hdmi_remove,
> +       .driver         = {
> +               .name           = "sun4i-hdmi",
> +               .of_match_table = sun4i_hdmi_of_table,
> +       },
> +};
> +module_platform_driver(sun4i_hdmi_driver);
> +
> +MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
> +MODULE_DESCRIPTION("Allwinner A10 HDMI Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> new file mode 100644
> index 000000000000..40f48f1d4685
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> @@ -0,0 +1,236 @@
> +/*
> + * Copyright (C) 2016 Free Electrons
> + * Copyright (C) 2016 NextThing Co
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "sun4i_tcon.h"
> +#include "sun4i_hdmi.h"
> +
> +struct sun4i_tmds {
> +       struct clk_hw           hw;
> +       struct sun4i_hdmi       *hdmi;
> +};
> +
> +static inline struct sun4i_tmds *hw_to_tmds(struct clk_hw *hw)
> +{
> +       return container_of(hw, struct sun4i_tmds, hw);
> +}
> +
> +
> +static unsigned long sun4i_tmds_calc_divider(unsigned long rate,
> +                                            unsigned long parent_rate,
> +                                            u8 *div,
> +                                            bool *half)
> +{
> +       unsigned long best_rate = 0;
> +       u8 best_m = 0, m;
> +       bool is_double;
> +
> +       for (m = 1; m < 16; m++) {
> +               u8 d;
> +
> +               for (d = 1; d < 3; d++) {
> +                       unsigned long tmp_rate;
> +
> +                       tmp_rate = parent_rate / m / d;
> +
> +                       if (tmp_rate > rate)
> +                               continue;
> +
> +                       if (!best_rate ||
> +                           (rate - tmp_rate) < (rate - best_rate)) {
> +                               best_rate = tmp_rate;
> +                               best_m = m;
> +                               is_double = d;
> +                       }
> +               }
> +       }
> +
> +       if (div && half) {
> +               *div = best_m;
> +               *half = is_double;
> +       }
> +
> +       return best_rate;
> +}
> +
> +
> +static int sun4i_tmds_determine_rate(struct clk_hw *hw,
> +                                    struct clk_rate_request *req)
> +{
> +       struct clk_hw *parent;
> +       unsigned long best_parent = 0;
> +       unsigned long rate = req->rate;
> +       int best_div = 1, best_half = 1;
> +       int i, j;
> +
> +       printk("%s %d rate %lu\n", __func__, __LINE__, rate);

Stray printk?

> +
> +       /*
> +        * We only consider PLL3, since the TCON is very likely to be
> +        * clocked from it, and to have the same rate than our HDMI
> +        * clock, so we should not need to do anything.
> +        */
> +
> +       parent = clk_hw_get_parent_by_index(hw, 0);
> +       if (!parent)
> +               return -EINVAL;
> +
> +       for (i = 1; i < 3; i++) {
> +               for (j = 1; j < 16; j++) {
> +                       unsigned long ideal = rate * i * j;
> +                       unsigned long rounded;
> +
> +                       rounded = clk_hw_round_rate(parent, ideal);
> +
> +                       if (rounded == ideal) {
> +                               best_parent = rounded;
> +                               best_half = i;
> +                               best_div = j;
> +                               goto out;
> +                       }
> +
> +                       if (abs(rate - rounded / i) <
> +                           abs(rate - best_parent / best_div)) {
> +                               best_parent = rounded;
> +                               best_div = i;
> +                       }
> +               }
> +       }
> +
> +out:
> +       req->rate = best_parent / best_half / best_div;
> +       req->best_parent_rate = best_parent;
> +       req->best_parent_hw = parent;
> +
> +       printk("%s %d rate %lu parent rate %lu (%s) div %d half %d\n",
> +              __func__, __LINE__, req->rate, req->best_parent_rate,
> +              clk_hw_get_name(req->best_parent_hw),
> +              best_div, best_half);

Stray printk?

> +
> +       return 0;
> +}
> +
> +static unsigned long sun4i_tmds_recalc_rate(struct clk_hw *hw,
> +                                           unsigned long parent_rate)
> +{
> +       struct sun4i_tmds *tmds = hw_to_tmds(hw);
> +       u32 reg;
> +
> +       reg = readl(tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
> +       if (reg & SUN4I_HDMI_PAD_CTRL1_HALVE_CLK)
> +               parent_rate /= 2;
> +
> +       reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
> +       reg = (reg >> 4) & 0xf;
> +       if (!reg)
> +               reg = 1;
> +
> +       return parent_rate / reg;
> +}
> +
> +static int sun4i_tmds_set_rate(struct clk_hw *hw, unsigned long rate,
> +                              unsigned long parent_rate)
> +{
> +       struct sun4i_tmds *tmds = hw_to_tmds(hw);
> +       bool half;
> +       u32 reg;
> +       u8 div;
> +
> +       sun4i_tmds_calc_divider(rate, parent_rate, &div, &half);
> +
> +       printk("%s %d rate %lu parent rate %lu div %d half %s\n",
> +              __func__, __LINE__, rate, parent_rate, div,
> +              half ? "yes" : "no");

Stray printk?

> +
> +       reg = readl(tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
> +       reg &= ~SUN4I_HDMI_PAD_CTRL1_HALVE_CLK;
> +       if (half)
> +               reg |= SUN4I_HDMI_PAD_CTRL1_HALVE_CLK;
> +       writel(reg, tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
> +
> +       reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
> +       reg &= ~SUN4I_HDMI_PLL_CTRL_DIV_MASK;
> +       writel(reg | SUN4I_HDMI_PLL_CTRL_DIV(div),
> +              tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
> +
> +       return 0;
> +}
> +
> +static u8 sun4i_tmds_get_parent(struct clk_hw *hw)
> +{
> +       struct sun4i_tmds *tmds = hw_to_tmds(hw);
> +       u32 reg;
> +
> +       reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_DBG0_REG);
> +       return ((reg & SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_MASK) >>
> +               SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_SHIFT);
> +}
> +
> +static int sun4i_tmds_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct sun4i_tmds *tmds = hw_to_tmds(hw);
> +       u32 reg;
> +
> +       if (index > 1)
> +               return -EINVAL;
> +
> +       reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_DBG0_REG);
> +       reg &= ~SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_MASK;
> +       writel(reg | SUN4I_HDMI_PLL_DBG0_TMDS_PARENT(index),
> +              tmds->hdmi->base + SUN4I_HDMI_PLL_DBG0_REG);
> +
> +       return 0;
> +}
> +
> +static const struct clk_ops sun4i_tmds_ops = {
> +       .determine_rate = sun4i_tmds_determine_rate,
> +       .recalc_rate    = sun4i_tmds_recalc_rate,
> +       .set_rate       = sun4i_tmds_set_rate,
> +
> +       .get_parent     = sun4i_tmds_get_parent,
> +       .set_parent     = sun4i_tmds_set_parent,
> +};
> +
> +int sun4i_tmds_create(struct sun4i_hdmi *hdmi)
> +{
> +       struct clk_init_data init;
> +       struct sun4i_tmds *tmds;
> +       const char *parents[2];
> +
> +       parents[0] = __clk_get_name(hdmi->pll0_clk);
> +       if (!parents[0])
> +               return -ENODEV;
> +
> +       parents[1] = __clk_get_name(hdmi->pll1_clk);
> +       if (!parents[1])
> +               return -ENODEV;
> +
> +       tmds = devm_kzalloc(hdmi->dev, sizeof(*tmds), GFP_KERNEL);
> +       if (!tmds)
> +               return -ENOMEM;
> +
> +       init.name = "hdmi-tmds";
> +       init.ops = &sun4i_tmds_ops;
> +       init.parent_names = parents;
> +       init.num_parents = 2;
> +       init.flags = CLK_SET_RATE_PARENT;
> +
> +       tmds->hdmi = hdmi;
> +       tmds->hw.init = &init;
> +
> +       hdmi->tmds_clk = devm_clk_register(hdmi->dev, &tmds->hw);
> +       if (IS_ERR(hdmi->tmds_clk))
> +               return PTR_ERR(hdmi->tmds_clk);
> +
> +       return 0;
> +}
> --

I also compared the manuals of A20 and A31, and the existing U-boot driver.

So far it looks like the DDC bits are quite different. We could probably
use regfields to work around it, but the DDC clock formula is completely
different. The TMDS clock pre-divider is also different, your usual sun4i
vs sun6i factor offset. Last, the initial values for the 3 PLL related
registers are different.

I'm currently working on an A31 variant for this, basically just copying
the DDC and TMDS bits.

Regards
ChenYu

> git-series 0.8.11
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe at googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox