Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/3] interconnect: Add generic on-chip interconnect API
From: Georgi Djakov @ 2017-12-12 15:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAHLCerOgm+T6S1pxjo5hFajyU+vqUgBFcwfuBCsphgECRMf3Yw@mail.gmail.com>

Hi Amit,

On 12/08/2017 08:38 PM, Amit Kucheria wrote:
> On Fri, Sep 8, 2017 at 10:48 PM, Georgi Djakov <georgi.djakov@linaro.org> wrote:
>> This patch introduce a new API to get requirements and configure the
>> interconnect buses across the entire chipset to fit with the current demand.
>>
>> The API is using a consumer/provider-based model, where the providers are
>> the interconnect buses and the consumers could be various drivers.
>> The consumers request interconnect resources (path) between endpoints and
>> set the desired constraints on this data flow path. The providers receive
>> requests from consumers and aggregate these requests for all master-slave
>> pairs on that path. Then the providers configure each participating in the
>> topology node according to the requested data flow path, physical links and
>> constraints. The topology could be complicated and multi-tiered and is SoC
>> specific.
>>
>> Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>

[..]

>> +inline int interconnect_set(struct interconnect_path *path,
>> +                           struct interconnect_creq *creq);
> 
> Remove the semi colon

Thanks! Fixed.

> 
>> +{
>> +       return -ENOTSUPP
> 
> return ERR_PTR(-ENOTSUPP);

I do not agree here. It should be left as is, because the function
returns int.

> 
>> +}
>> +
> 
> This breaks the build with INTERCONNECT disabled in Kconfig.

Ok, i have fixed this as well.

Thanks,
Georgi

^ permalink raw reply

* [PATCH v2 22/36] KVM: arm64: Prepare to handle traps on deferred VM sysregs
From: Christoffer Dall @ 2017-12-12 15:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <622521ec-013c-cf89-3222-5f40237d0ada@arm.com>

On Tue, Dec 12, 2017 at 01:08:30PM +0000, Marc Zyngier wrote:
> On 11/12/17 11:24, Christoffer Dall wrote:
> > On Mon, Dec 11, 2017 at 11:10:36AM +0000, Marc Zyngier wrote:
> >> On 07/12/17 17:06, Christoffer Dall wrote:
> >>> When we defer the save/restore of system registers to vcpu_load and
> >>> vcpu_put, we need to take care of the emulation code that handles traps
> >>> to these registers, since simply reading the memory array will return
> >>> stale data.
> >>>
> >>> Therefore, introduce two functions to directly read/write the registers
> >>> from the physical CPU when we're on a VHE system that has loaded the
> >>> system registers onto the physical CPU.
> >>>
> >>> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> >>> ---
> >>>
> >>> Notes:
> >>>     Changes since v1:
> >>>      - Removed spurious white space
> >>>
> >>>  arch/arm64/include/asm/kvm_host.h |  4 +++
> >>>  arch/arm64/kvm/sys_regs.c         | 53 +++++++++++++++++++++++++++++++++++++--
> >>>  2 files changed, 55 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> >>> index de0d55b30b61..f6afe685a280 100644
> >>> --- a/arch/arm64/include/asm/kvm_host.h
> >>> +++ b/arch/arm64/include/asm/kvm_host.h
> >>> @@ -279,6 +279,10 @@ struct kvm_vcpu_arch {
> >>>  
> >>>  	/* Detect first run of a vcpu */
> >>>  	bool has_run_once;
> >>> +
> >>> +	/* True when deferrable sysregs are loaded on the physical CPU,
> >>> +	 * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */
> >>> +	bool sysregs_loaded_on_cpu;
> >>>  };
> >>>  
> >>>  #define vcpu_gp_regs(v)		(&(v)->arch.ctxt.gp_regs)
> >>> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> >>> index 62c12ab9e6c4..80adbec933de 100644
> >>> --- a/arch/arm64/kvm/sys_regs.c
> >>> +++ b/arch/arm64/kvm/sys_regs.c
> >>> @@ -35,6 +35,7 @@
> >>>  #include <asm/kvm_coproc.h>
> >>>  #include <asm/kvm_emulate.h>
> >>>  #include <asm/kvm_host.h>
> >>> +#include <asm/kvm_hyp.h>
> >>>  #include <asm/kvm_mmu.h>
> >>>  #include <asm/perf_event.h>
> >>>  #include <asm/sysreg.h>
> >>> @@ -111,6 +112,54 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
> >>>  	return true;
> >>>  }
> >>>  
> >>> +static u64 read_deferrable_vm_reg(struct kvm_vcpu *vcpu, int reg)
> >>> +{
> >>> +	if (vcpu->arch.sysregs_loaded_on_cpu) {
> >>> +		switch (reg) {
> >>> +		case SCTLR_EL1:		return read_sysreg_el1(sctlr);
> >>> +		case TTBR0_EL1:		return read_sysreg_el1(ttbr0);
> >>> +		case TTBR1_EL1:		return read_sysreg_el1(ttbr1);
> >>> +		case TCR_EL1:		return read_sysreg_el1(tcr);
> >>> +		case ESR_EL1:		return read_sysreg_el1(esr);
> >>> +		case FAR_EL1:		return read_sysreg_el1(far);
> >>> +		case AFSR0_EL1:		return read_sysreg_el1(afsr0);
> >>> +		case AFSR1_EL1:		return read_sysreg_el1(afsr1);
> >>> +		case MAIR_EL1:		return read_sysreg_el1(mair);
> >>> +		case AMAIR_EL1:		return read_sysreg_el1(amair);
> >>> +		case CONTEXTIDR_EL1:	return read_sysreg_el1(contextidr);
> >>> +		case DACR32_EL2:	return read_sysreg(dacr32_el2);
> >>> +		case IFSR32_EL2:	return read_sysreg(ifsr32_el2);
> >>> +		default:		BUG();
> >>> +		}
> >>> +	}
> >>> +
> >>> +	return vcpu_sys_reg(vcpu, reg);
> >>> +}
> >>> +
> >>> +static void write_deferrable_vm_reg(struct kvm_vcpu *vcpu, int reg, u64 val)
> >>> +{
> >>> +	if (vcpu->arch.sysregs_loaded_on_cpu) {
> >>> +		switch (reg) {
> >>> +		case SCTLR_EL1:		write_sysreg_el1(val, sctlr);	return;
> >>> +		case TTBR0_EL1:		write_sysreg_el1(val, ttbr0);	return;
> >>> +		case TTBR1_EL1:		write_sysreg_el1(val, ttbr1);	return;
> >>> +		case TCR_EL1:		write_sysreg_el1(val, tcr);	return;
> >>> +		case ESR_EL1:		write_sysreg_el1(val, esr);	return;
> >>> +		case FAR_EL1:		write_sysreg_el1(val, far);	return;
> >>> +		case AFSR0_EL1:		write_sysreg_el1(val, afsr0);	return;
> >>> +		case AFSR1_EL1:		write_sysreg_el1(val, afsr1);	return;
> >>> +		case MAIR_EL1:		write_sysreg_el1(val, mair);	return;
> >>> +		case AMAIR_EL1:		write_sysreg_el1(val, amair);	return;
> >>> +		case CONTEXTIDR_EL1:	write_sysreg_el1(val, contextidr); return;
> >>> +		case DACR32_EL2:	write_sysreg(val, dacr32_el2); return;
> >>> +		case IFSR32_EL2:	write_sysreg(val, ifsr32_el2); return;
> >>> +		default:		BUG();
> >>> +		}
> >>> +	}
> >>> +
> >>> +	vcpu_sys_reg(vcpu, reg) = val;
> >>> +}
> >>> +
> >>>  /*
> >>>   * Generic accessor for VM registers. Only called as long as HCR_TVM
> >>>   * is set. If the guest enables the MMU, we stop trapping the VM
> >>> @@ -133,14 +182,14 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
> >>>  	if (!p->is_aarch32 || !p->is_32bit) {
> >>>  		val = p->regval;
> >>>  	} else {
> >>> -		val = vcpu_sys_reg(vcpu, reg);
> >>> +		val = read_deferrable_vm_reg(vcpu, reg);
> >>>  		if (r->reg % 2)
> >>>  			val = (p->regval << 32) | (u64)lower_32_bits(val);
> >>>  		else
> >>>  			val = ((u64)upper_32_bits(val) << 32) |
> >>>  				(u64)lower_32_bits(p->regval);
> >>>  	}
> >>> -	vcpu_sys_reg(vcpu, reg) = val;
> >>> +	write_deferrable_vm_reg(vcpu, reg, val);
> >>>  
> >>>  	kvm_toggle_cache(vcpu, was_enabled);
> >>>  	return true;
> >>>
> >>
> >> I'm slightly uneasy with this. It means that the rest of the KVM code
> >> has to know whether a given register is deferrable or not (or face the
> >> wrath of the BUG). I'd be more inclined to hide the "loaded on cpu"
> >> magic in the vcpu_sys_reg() accessors.
> >>
> >> Thoughts?
> >>
> > 
> > Yes, this is the main reservation I also have with the series.
> > 
> > I did start out with a giant "rewrite everything to vcpu_get_sys_reg and
> > vcpu_get_sys_reg" which hides this logic, and we may want to go back to
> > that.
> > 
> > That does mean that we need a giant switch statement which knows how to
> > read any deferrable EL1 (and EL0) system register from hardware, and
> > still BUG/WARN if someone adds a system register but forgets to add that
> > handler and test on VHE.  Unless there's some fantastic auto-gen
> > mechanism that can take a hash define and figure out which sysreg
> > instruction to use - I couldn't think of that.
> 
> Coming back to this, as I'm currently prototyping something.
> 
> What is the rational for the BUG()? It is not like we can add a random
> sysreg and expect it to be deferred. It is a conscious decision to do
> so, and I feel that the default should be that the sysreg should be
> save/restored. What am I missing?
> 

The rationale is simply that as we're developing code, if we start
accessing registers while the sysregs are still loaded on the CPU, which
we haven't accessed before, and don't have an accessor for (new sysregs,
rework other parts of the flow etc.,), I wanted to have a clear point
where we realize that we forgot something.  Especially if we mostly test
on non-VHE systems.

But, actually, BUG() may be too hard, as it would only ever affect the
VM, and not the host, so reads could be WARN+RAZ, and writes could be
WARN+WI.

Thanks,
-Christoffer

^ permalink raw reply

* [PATCH 05/12] arm64: mm: Remove VMALLOC checks from update_mapping_prot(.)
From: Steve Capper @ 2017-12-12 15:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu80J1vGn6V6Z3eXajDos=sjY_fLhUQP=-n0A8MyunTfgQ@mail.gmail.com>

Hi Ard,

On Mon, Dec 04, 2017 at 04:01:09PM +0000, Ard Biesheuvel wrote:
> On 4 December 2017 at 14:13, Steve Capper <steve.capper@arm.com> wrote:
> > update_mapping_prot assumes that it will be used on the VA for the
> > kernel .text section. (Via the check virt >= VMALLOC_START)
> >
> > Recent kdump patches employ this function to modify the protection of
> > the direct linear mapping (which is strictly speaking outside of this
> > area), via mark_linear_text_alias_ro(.).
> >
> 
> Isn't that a bug? Is it guaranteed that those protection attributes
> can be modified without splitting live page tables, and the resulting
> risk of TLB conflicts?

IIUC there is a bug in my earlier patch to flip the kernel VA space round,
it should allow addresses from the linear mapping to be processed by
update_mapping_prot. I'll update the logic in VA flip patch, so this
patch can be removed from the series.

It is not apparent to me how mark_linear_text_alias_ro(.) guarantees
that no page table entries for the linear map are split, though.

Cheers,
-- 
Steve

^ permalink raw reply

* [PATCH v2] spi: atmel: Implements transfers with bounce buffer
From: Radu Pirea @ 2017-12-12 15:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch enables DMA transfers for Atmel SAM9 SoCs and implements a bounce
buffer for transfers which have vmalloc allocated buffers. Those buffers are
not cache coherent even if they have been transformed into sg lists. UBIFS
is affected by this cache coherency issue.

In this patch I also reverted "spi: atmel: fix corrupted data issue on SAM9
family SoCs"(7094576ccdc3acfe1e06a1e2ab547add375baf7f).


Signed-off-by: Radu Pirea <radu.pirea@microchip.com>
---
 Please ignore the previous version. I messed up with file names.
 drivers/spi/spi-atmel.c | 113 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 84 insertions(+), 29 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index f95da36..198b4cd 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -291,6 +291,10 @@ struct atmel_spi {
 	struct spi_transfer	*current_transfer;
 	int			current_remaining_bytes;
 	int			done_status;
+	dma_addr_t		dma_addr_rx_bbuf;
+	dma_addr_t		dma_addr_tx_bbuf;
+	void			*addr_rx_bbuf;
+	void			*addr_tx_bbuf;
 
 	struct completion	xfer_completion;
 
@@ -436,6 +440,11 @@ static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock)
 	spin_unlock_irqrestore(&as->lock, as->flags);
 }
 
+static inline bool atmel_spi_is_vmalloc_xfer(struct spi_transfer *xfer)
+{
+	return is_vmalloc_addr(xfer->tx_buf) || is_vmalloc_addr(xfer->rx_buf);
+}
+
 static inline bool atmel_spi_use_dma(struct atmel_spi *as,
 				struct spi_transfer *xfer)
 {
@@ -448,7 +457,12 @@ static bool atmel_spi_can_dma(struct spi_master *master,
 {
 	struct atmel_spi *as = spi_master_get_devdata(master);
 
-	return atmel_spi_use_dma(as, xfer);
+	if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5))
+		return atmel_spi_use_dma(as, xfer) &&
+			!atmel_spi_is_vmalloc_xfer(xfer);
+	else
+		return atmel_spi_use_dma(as, xfer);
+
 }
 
 static int atmel_spi_dma_slave_config(struct atmel_spi *as,
@@ -594,6 +608,11 @@ static void dma_callback(void *data)
 	struct spi_master	*master = data;
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 
+	if (is_vmalloc_addr(as->current_transfer->rx_buf) &&
+	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+		memcpy(as->current_transfer->rx_buf, as->addr_rx_bbuf,
+		       as->current_transfer->len);
+	}
 	complete(&as->xfer_completion);
 }
 
@@ -744,17 +763,41 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
 		goto err_exit;
 
 	/* Send both scatterlists */
-	rxdesc = dmaengine_prep_slave_sg(rxchan,
-					 xfer->rx_sg.sgl, xfer->rx_sg.nents,
-					 DMA_FROM_DEVICE,
-					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (atmel_spi_is_vmalloc_xfer(xfer) &&
+	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+		rxdesc = dmaengine_prep_slave_single(rxchan,
+						     as->dma_addr_rx_bbuf,
+						     xfer->len,
+						     DMA_FROM_DEVICE,
+						     DMA_PREP_INTERRUPT |
+						     DMA_CTRL_ACK);
+	} else {
+		rxdesc = dmaengine_prep_slave_sg(rxchan,
+						 xfer->rx_sg.sgl,
+						 xfer->rx_sg.nents,
+						 DMA_FROM_DEVICE,
+						 DMA_PREP_INTERRUPT |
+						 DMA_CTRL_ACK);
+	}
 	if (!rxdesc)
 		goto err_dma;
 
-	txdesc = dmaengine_prep_slave_sg(txchan,
-					 xfer->tx_sg.sgl, xfer->tx_sg.nents,
-					 DMA_TO_DEVICE,
-					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (atmel_spi_is_vmalloc_xfer(xfer) &&
+	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+		memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len);
+		txdesc = dmaengine_prep_slave_single(txchan,
+						     as->dma_addr_tx_bbuf,
+						     xfer->len, DMA_TO_DEVICE,
+						     DMA_PREP_INTERRUPT |
+						     DMA_CTRL_ACK);
+	} else {
+		txdesc = dmaengine_prep_slave_sg(txchan,
+						 xfer->tx_sg.sgl,
+						 xfer->tx_sg.nents,
+						 DMA_TO_DEVICE,
+						 DMA_PREP_INTERRUPT |
+						 DMA_CTRL_ACK);
+	}
 	if (!txdesc)
 		goto err_dma;
 
@@ -1426,27 +1469,7 @@ static void atmel_get_caps(struct atmel_spi *as)
 
 	as->caps.is_spi2 = version > 0x121;
 	as->caps.has_wdrbt = version >= 0x210;
-#ifdef CONFIG_SOC_SAM_V4_V5
-	/*
-	 * Atmel SoCs based on ARM9 (SAM9x) cores should not use spi_map_buf()
-	 * since this later function tries to map buffers with dma_map_sg()
-	 * even if they have not been allocated inside DMA-safe areas.
-	 * On SoCs based on Cortex A5 (SAMA5Dx), it works anyway because for
-	 * those ARM cores, the data cache follows the PIPT model.
-	 * Also the L2 cache controller of SAMA5D2 uses the PIPT model too.
-	 * In case of PIPT caches, there cannot be cache aliases.
-	 * However on ARM9 cores, the data cache follows the VIVT model, hence
-	 * the cache aliases issue can occur when buffers are allocated from
-	 * DMA-unsafe areas, by vmalloc() for instance, where cache coherency is
-	 * not taken into account or at least not handled completely (cache
-	 * lines of aliases are not invalidated).
-	 * This is not a theorical issue: it was reproduced when trying to mount
-	 * a UBI file-system on a at91sam9g35ek board.
-	 */
-	as->caps.has_dma_support = false;
-#else
 	as->caps.has_dma_support = version >= 0x212;
-#endif
 	as->caps.has_pdc_support = version < 0x212;
 }
 
@@ -1592,6 +1615,30 @@ static int atmel_spi_probe(struct platform_device *pdev)
 		as->use_pdc = true;
 	}
 
+	if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+		as->addr_rx_bbuf = dma_alloc_coherent(&pdev->dev,
+						      SPI_MAX_DMA_XFER,
+						      &as->dma_addr_rx_bbuf,
+						      GFP_KERNEL | GFP_DMA);
+		if (!as->addr_rx_bbuf) {
+			as->use_dma = false;
+		} else {
+			as->addr_tx_bbuf = dma_alloc_coherent(&pdev->dev,
+					SPI_MAX_DMA_XFER,
+					&as->dma_addr_tx_bbuf,
+					GFP_KERNEL | GFP_DMA);
+			if (!as->addr_tx_bbuf) {
+				as->use_dma = false;
+				dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
+						  as->addr_rx_bbuf,
+						  as->dma_addr_rx_bbuf);
+			}
+		}
+		if(!as->use_dma)
+			dev_info(master->dev.parent,
+				"  can not allocate dma coherent memory\n");
+	}
+
 	if (as->caps.has_dma_support && !as->use_dma)
 		dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
 
@@ -1665,6 +1712,14 @@ static int atmel_spi_remove(struct platform_device *pdev)
 	if (as->use_dma) {
 		atmel_spi_stop_dma(master);
 		atmel_spi_release_dma(master);
+		if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+			dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
+					  as->addr_tx_bbuf,
+					  as->dma_addr_tx_bbuf);
+			dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
+					  as->addr_rx_bbuf,
+					  as->dma_addr_rx_bbuf);
+		}
 	}
 
 	spi_writel(as, CR, SPI_BIT(SWRST));
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2] firmware: qcom: scm: Fix incorrect of_node_put call in scm_init
From: Loys Ollivier @ 2017-12-12 15:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171208170449.GD4283@codeaurora.org>



On 08/12/2017 18:04, Stephen Boyd wrote:
> On 12/07, Loys Ollivier wrote:
>>
>>
>> On 07/12/2017 09:42, Jerome Forissier wrote:
>>>
>>>
>>> On 12/06/2017 09:06 PM, Stephen Boyd wrote:
>>>> On 12/06, Loys Ollivier wrote:
>>>>> When using other platform architectures, in the init of the qcom_scm
>>>>> driver, of_node_put is called on /firmware if no qcom dt is found.
>>>>> This results in a kernel error: Bad of_node_put() on /firmware.
>>>>>
>>>>> The call to of_node_put from the qcom_scm init is unnecessary as
>>>>> of_find_matching_node is calling it automatically.
>>>>>
>>>>> Remove this of_node_put().
>>>>>
>>>>> Fixes: d0f6fa7ba2d6 ("firmware: qcom: scm: Convert SCM to platform driver")
>>>>> Signed-off-by: Loys Ollivier <lollivier@baylibre.com>
>>>>> ---
>>>>
>>>> This still looks wrong. Especially if of_find_matching_node() is
>>>> going to look for siblings of the /firmware node for the
>>>> compatible string for scm device. Why do we check at all? Can't
>>>> we just delete this and let of_platform_populate() take care of
>>>> it? BTW, OP-TEE driver seems to have a similar problem.
>>>
>>> https://lkml.org/lkml/2017/11/29/230
>>>
>> Well, the patch I sent is a fix for a specific bug I am encountering.
>> I tested the patch and it solves my problem. Stephen, your changes looks
>> good but it's a change in the driver's behavior. Maybe it could be
>> another patch ?
> 
> Sure. But there's another of_node_put(fw_np) in this function, so
> why isn't that also removed? Assuming of_find_matching_node() is
> calling of_node_put() on what's passed in, then the node is going
> to get put twice in the "working" case.
> 
> Andy?
>
Agreed, I had a look and this second call to of_node_put(fw_np) seem to
be unnecessary as well. Unfortunately I can't test your suggestion as I
am using another platform arch. I am just testing that this driver does
not break my arch.
I can submit a v3 removing this of_node_put as well if you want.

^ permalink raw reply

* [PATCH v2] spi: atmel: bounce buffer spi
From: Alexandre Belloni @ 2017-12-12 15:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513092150-11129-1-git-send-email-radu.pirea@microchip.com>

Hi,

This definitively needs a proper commit message.

On 12/12/2017 at 17:22:30 +0200, Radu Pirea wrote:
> Signed-off-by: Radu Pirea <radu.pirea@microchip.com>
> ---
>  drivers/spi/spi-atmel.c | 112 +++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 82 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
> index f95da36..59b59ae 100644
> --- a/drivers/spi/spi-atmel.c
> +++ b/drivers/spi/spi-atmel.c
> @@ -291,6 +291,10 @@ struct atmel_spi {
>  	struct spi_transfer	*current_transfer;
>  	int			current_remaining_bytes;
>  	int			done_status;
> +	dma_addr_t		dma_addr_rx_bbuf;
> +	dma_addr_t		dma_addr_tx_bbuf;
> +	void			*addr_rx_bbuf;
> +	void			*addr_tx_bbuf;
>  
>  	struct completion	xfer_completion;
>  
> @@ -436,10 +440,15 @@ static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock)
>  	spin_unlock_irqrestore(&as->lock, as->flags);
>  }
>  
> +static inline bool atmel_spi_is_vmalloc_xfer(struct spi_transfer *xfer)
> +{
> +	return is_vmalloc_addr(xfer->tx_buf) || is_vmalloc_addr(xfer->rx_buf);
> +}
> +
>  static inline bool atmel_spi_use_dma(struct atmel_spi *as,
>  				struct spi_transfer *xfer)
>  {
> -	return as->use_dma && xfer->len >= DMA_MIN_BYTES;
> +		return as->use_dma && xfer->len >= DMA_MIN_BYTES;
>  }
>  
>  static bool atmel_spi_can_dma(struct spi_master *master,
> @@ -448,7 +457,12 @@ static bool atmel_spi_can_dma(struct spi_master *master,
>  {
>  	struct atmel_spi *as = spi_master_get_devdata(master);
>  
> -	return atmel_spi_use_dma(as, xfer);
> +	if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5))
> +		return atmel_spi_use_dma(as, xfer) &&
> +			!atmel_spi_is_vmalloc_xfer(xfer);
> +	else
> +		return atmel_spi_use_dma(as, xfer);
> +
>  }
>  
>  static int atmel_spi_dma_slave_config(struct atmel_spi *as,
> @@ -594,6 +608,11 @@ static void dma_callback(void *data)
>  	struct spi_master	*master = data;
>  	struct atmel_spi	*as = spi_master_get_devdata(master);
>  
> +	if (is_vmalloc_addr(as->current_transfer->rx_buf) &&
> +	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
> +		memcpy(as->current_transfer->rx_buf, as->addr_rx_bbuf,
> +		       as->current_transfer->len);
> +	}
>  	complete(&as->xfer_completion);
>  }
>  
> @@ -744,17 +763,41 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
>  		goto err_exit;
>  
>  	/* Send both scatterlists */
> -	rxdesc = dmaengine_prep_slave_sg(rxchan,
> -					 xfer->rx_sg.sgl, xfer->rx_sg.nents,
> -					 DMA_FROM_DEVICE,
> -					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> +	if (atmel_spi_is_vmalloc_xfer(xfer) &&
> +	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
> +		rxdesc = dmaengine_prep_slave_single(rxchan,
> +						     as->dma_addr_rx_bbuf,
> +						     xfer->len,
> +						     DMA_FROM_DEVICE,
> +						     DMA_PREP_INTERRUPT |
> +						     DMA_CTRL_ACK);
> +	} else {
> +		rxdesc = dmaengine_prep_slave_sg(rxchan,
> +						 xfer->rx_sg.sgl,
> +						 xfer->rx_sg.nents,
> +						 DMA_FROM_DEVICE,
> +						 DMA_PREP_INTERRUPT |
> +						 DMA_CTRL_ACK);
> +	}
>  	if (!rxdesc)
>  		goto err_dma;
>  
> -	txdesc = dmaengine_prep_slave_sg(txchan,
> -					 xfer->tx_sg.sgl, xfer->tx_sg.nents,
> -					 DMA_TO_DEVICE,
> -					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> +	if (atmel_spi_is_vmalloc_xfer(xfer) &&
> +	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
> +		memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len);
> +		txdesc = dmaengine_prep_slave_single(txchan,
> +						     as->dma_addr_tx_bbuf,
> +						     xfer->len, DMA_TO_DEVICE,
> +						     DMA_PREP_INTERRUPT |
> +						     DMA_CTRL_ACK);
> +	} else {
> +		txdesc = dmaengine_prep_slave_sg(txchan,
> +						 xfer->tx_sg.sgl,
> +						 xfer->tx_sg.nents,
> +						 DMA_TO_DEVICE,
> +						 DMA_PREP_INTERRUPT |
> +						 DMA_CTRL_ACK);
> +	}
>  	if (!txdesc)
>  		goto err_dma;
>  
> @@ -1426,27 +1469,7 @@ static void atmel_get_caps(struct atmel_spi *as)
>  
>  	as->caps.is_spi2 = version > 0x121;
>  	as->caps.has_wdrbt = version >= 0x210;
> -#ifdef CONFIG_SOC_SAM_V4_V5
> -	/*
> -	 * Atmel SoCs based on ARM9 (SAM9x) cores should not use spi_map_buf()
> -	 * since this later function tries to map buffers with dma_map_sg()
> -	 * even if they have not been allocated inside DMA-safe areas.
> -	 * On SoCs based on Cortex A5 (SAMA5Dx), it works anyway because for
> -	 * those ARM cores, the data cache follows the PIPT model.
> -	 * Also the L2 cache controller of SAMA5D2 uses the PIPT model too.
> -	 * In case of PIPT caches, there cannot be cache aliases.
> -	 * However on ARM9 cores, the data cache follows the VIVT model, hence
> -	 * the cache aliases issue can occur when buffers are allocated from
> -	 * DMA-unsafe areas, by vmalloc() for instance, where cache coherency is
> -	 * not taken into account or at least not handled completely (cache
> -	 * lines of aliases are not invalidated).
> -	 * This is not a theorical issue: it was reproduced when trying to mount
> -	 * a UBI file-system on a at91sam9g35ek board.
> -	 */
> -	as->caps.has_dma_support = false;
> -#else
>  	as->caps.has_dma_support = version >= 0x212;
> -#endif
>  	as->caps.has_pdc_support = version < 0x212;
>  }
>  
> @@ -1592,6 +1615,27 @@ static int atmel_spi_probe(struct platform_device *pdev)
>  		as->use_pdc = true;
>  	}
>  
> +	if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
> +		as->addr_rx_bbuf = dma_alloc_coherent(&pdev->dev,
> +						      SPI_MAX_DMA_XFER,
> +						      &as->dma_addr_rx_bbuf,
> +						      GFP_KERNEL | GFP_DMA);
> +		if (!as->addr_rx_bbuf) {
> +			as->use_dma = false;
> +		} else {
> +			as->addr_tx_bbuf = dma_alloc_coherent(&pdev->dev,
> +					SPI_MAX_DMA_XFER,
> +					&as->dma_addr_tx_bbuf,
> +					GFP_KERNEL | GFP_DMA);
> +			if (!as->addr_tx_bbuf) {
> +				as->use_dma = false;
> +				dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
> +						  as->addr_rx_bbuf,
> +						  as->dma_addr_rx_bbuf);
> +			}
> +		}
> +	}
> +
>  	if (as->caps.has_dma_support && !as->use_dma)
>  		dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
>  
> @@ -1665,6 +1709,14 @@ static int atmel_spi_remove(struct platform_device *pdev)
>  	if (as->use_dma) {
>  		atmel_spi_stop_dma(master);
>  		atmel_spi_release_dma(master);
> +		if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
> +			dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
> +					  as->addr_tx_bbuf,
> +					  as->dma_addr_tx_bbuf);
> +			dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
> +					  as->addr_rx_bbuf,
> +					  as->dma_addr_rx_bbuf);
> +		}
>  	}
>  
>  	spi_writel(as, CR, SPI_BIT(SWRST));
> -- 
> 2.7.4
> 

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH v2] spi: atmel: bounce buffer spi
From: Radu Pirea @ 2017-12-12 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Radu Pirea <radu.pirea@microchip.com>
---
 drivers/spi/spi-atmel.c | 112 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 82 insertions(+), 30 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index f95da36..59b59ae 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -291,6 +291,10 @@ struct atmel_spi {
 	struct spi_transfer	*current_transfer;
 	int			current_remaining_bytes;
 	int			done_status;
+	dma_addr_t		dma_addr_rx_bbuf;
+	dma_addr_t		dma_addr_tx_bbuf;
+	void			*addr_rx_bbuf;
+	void			*addr_tx_bbuf;
 
 	struct completion	xfer_completion;
 
@@ -436,10 +440,15 @@ static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock)
 	spin_unlock_irqrestore(&as->lock, as->flags);
 }
 
+static inline bool atmel_spi_is_vmalloc_xfer(struct spi_transfer *xfer)
+{
+	return is_vmalloc_addr(xfer->tx_buf) || is_vmalloc_addr(xfer->rx_buf);
+}
+
 static inline bool atmel_spi_use_dma(struct atmel_spi *as,
 				struct spi_transfer *xfer)
 {
-	return as->use_dma && xfer->len >= DMA_MIN_BYTES;
+		return as->use_dma && xfer->len >= DMA_MIN_BYTES;
 }
 
 static bool atmel_spi_can_dma(struct spi_master *master,
@@ -448,7 +457,12 @@ static bool atmel_spi_can_dma(struct spi_master *master,
 {
 	struct atmel_spi *as = spi_master_get_devdata(master);
 
-	return atmel_spi_use_dma(as, xfer);
+	if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5))
+		return atmel_spi_use_dma(as, xfer) &&
+			!atmel_spi_is_vmalloc_xfer(xfer);
+	else
+		return atmel_spi_use_dma(as, xfer);
+
 }
 
 static int atmel_spi_dma_slave_config(struct atmel_spi *as,
@@ -594,6 +608,11 @@ static void dma_callback(void *data)
 	struct spi_master	*master = data;
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 
+	if (is_vmalloc_addr(as->current_transfer->rx_buf) &&
+	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+		memcpy(as->current_transfer->rx_buf, as->addr_rx_bbuf,
+		       as->current_transfer->len);
+	}
 	complete(&as->xfer_completion);
 }
 
@@ -744,17 +763,41 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
 		goto err_exit;
 
 	/* Send both scatterlists */
-	rxdesc = dmaengine_prep_slave_sg(rxchan,
-					 xfer->rx_sg.sgl, xfer->rx_sg.nents,
-					 DMA_FROM_DEVICE,
-					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (atmel_spi_is_vmalloc_xfer(xfer) &&
+	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+		rxdesc = dmaengine_prep_slave_single(rxchan,
+						     as->dma_addr_rx_bbuf,
+						     xfer->len,
+						     DMA_FROM_DEVICE,
+						     DMA_PREP_INTERRUPT |
+						     DMA_CTRL_ACK);
+	} else {
+		rxdesc = dmaengine_prep_slave_sg(rxchan,
+						 xfer->rx_sg.sgl,
+						 xfer->rx_sg.nents,
+						 DMA_FROM_DEVICE,
+						 DMA_PREP_INTERRUPT |
+						 DMA_CTRL_ACK);
+	}
 	if (!rxdesc)
 		goto err_dma;
 
-	txdesc = dmaengine_prep_slave_sg(txchan,
-					 xfer->tx_sg.sgl, xfer->tx_sg.nents,
-					 DMA_TO_DEVICE,
-					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (atmel_spi_is_vmalloc_xfer(xfer) &&
+	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+		memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len);
+		txdesc = dmaengine_prep_slave_single(txchan,
+						     as->dma_addr_tx_bbuf,
+						     xfer->len, DMA_TO_DEVICE,
+						     DMA_PREP_INTERRUPT |
+						     DMA_CTRL_ACK);
+	} else {
+		txdesc = dmaengine_prep_slave_sg(txchan,
+						 xfer->tx_sg.sgl,
+						 xfer->tx_sg.nents,
+						 DMA_TO_DEVICE,
+						 DMA_PREP_INTERRUPT |
+						 DMA_CTRL_ACK);
+	}
 	if (!txdesc)
 		goto err_dma;
 
@@ -1426,27 +1469,7 @@ static void atmel_get_caps(struct atmel_spi *as)
 
 	as->caps.is_spi2 = version > 0x121;
 	as->caps.has_wdrbt = version >= 0x210;
-#ifdef CONFIG_SOC_SAM_V4_V5
-	/*
-	 * Atmel SoCs based on ARM9 (SAM9x) cores should not use spi_map_buf()
-	 * since this later function tries to map buffers with dma_map_sg()
-	 * even if they have not been allocated inside DMA-safe areas.
-	 * On SoCs based on Cortex A5 (SAMA5Dx), it works anyway because for
-	 * those ARM cores, the data cache follows the PIPT model.
-	 * Also the L2 cache controller of SAMA5D2 uses the PIPT model too.
-	 * In case of PIPT caches, there cannot be cache aliases.
-	 * However on ARM9 cores, the data cache follows the VIVT model, hence
-	 * the cache aliases issue can occur when buffers are allocated from
-	 * DMA-unsafe areas, by vmalloc() for instance, where cache coherency is
-	 * not taken into account or at least not handled completely (cache
-	 * lines of aliases are not invalidated).
-	 * This is not a theorical issue: it was reproduced when trying to mount
-	 * a UBI file-system on a at91sam9g35ek board.
-	 */
-	as->caps.has_dma_support = false;
-#else
 	as->caps.has_dma_support = version >= 0x212;
-#endif
 	as->caps.has_pdc_support = version < 0x212;
 }
 
@@ -1592,6 +1615,27 @@ static int atmel_spi_probe(struct platform_device *pdev)
 		as->use_pdc = true;
 	}
 
+	if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+		as->addr_rx_bbuf = dma_alloc_coherent(&pdev->dev,
+						      SPI_MAX_DMA_XFER,
+						      &as->dma_addr_rx_bbuf,
+						      GFP_KERNEL | GFP_DMA);
+		if (!as->addr_rx_bbuf) {
+			as->use_dma = false;
+		} else {
+			as->addr_tx_bbuf = dma_alloc_coherent(&pdev->dev,
+					SPI_MAX_DMA_XFER,
+					&as->dma_addr_tx_bbuf,
+					GFP_KERNEL | GFP_DMA);
+			if (!as->addr_tx_bbuf) {
+				as->use_dma = false;
+				dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
+						  as->addr_rx_bbuf,
+						  as->dma_addr_rx_bbuf);
+			}
+		}
+	}
+
 	if (as->caps.has_dma_support && !as->use_dma)
 		dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
 
@@ -1665,6 +1709,14 @@ static int atmel_spi_remove(struct platform_device *pdev)
 	if (as->use_dma) {
 		atmel_spi_stop_dma(master);
 		atmel_spi_release_dma(master);
+		if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+			dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
+					  as->addr_tx_bbuf,
+					  as->dma_addr_tx_bbuf);
+			dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
+					  as->addr_rx_bbuf,
+					  as->dma_addr_rx_bbuf);
+		}
 	}
 
 	spi_writel(as, CR, SPI_BIT(SWRST));
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/8] iio: adc: axp20x_adc: add support for AXP813 ADC
From: Jonathan Cameron @ 2017-12-12 15:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <b2cdd796-5c22-c114-bc74-41b900a05464@free-electrons.com>

On Mon, 11 Dec 2017 09:18:55 +0100
Quentin Schulz <quentin.schulz@free-electrons.com> wrote:

> Hi Jonathan,
> 
> On 10/12/2017 17:36, Jonathan Cameron wrote:
> > On Mon,  4 Dec 2017 15:12:48 +0100
> > Quentin Schulz <quentin.schulz@free-electrons.com> wrote:
> >   
> >> The X-Powers AXP813 PMIC is really close to what is already done for
> >> AXP20X/AXP22X.
> >>
> >> There are two pairs of bits to set the rate (one for Voltage and Current
> >> measurements and one for TS/GPIO0 voltage measurements) instead of one.  
> > 
> > This would normally imply we need to split the device into two logical
> > IIO devices.  However, that only becomes relevant if we are using
> > buffered output which this driver doesn't support.  
> > > It'll be nasty to deal with this if we add that support down the line  
> > though.  Up to you though as it's more likely to be your problem than
> > anyone else's :)
> >   
> 
> I have no plans for supporting buffered output for the AXPs at the
> moment. But that's an interesting (and important) limitation to raise.
> Wouldn't be more of a hack to have two IIO devices representing the
> actual same IP?

We have thought about allowing multiple buffers from a single IIO device
but that makes for some horrible changes to the ABI - so as things stand
the only option is two devices for one IP.  Ultimately they aren't really
two devices - in the same way we have triggers separating registered on
the IIO bus (often many of them).  Just two different elements of the same IP.

> 
> > For now you could elect to support the different sampling frequencies
> > if you wanted to but just providing controls for each channel.
> >   
> 
> I guess that you're offering to use IIO_CHAN_INFO_SAMP_FREQ in
> info_mask_separate for each channel?
Yes
> 
> > Given the driver doesn't currently expose these at all (I think)
> > this is all rather immaterial ;)  
> 
> I'm not giving the user the option to chose the sampling frequency for
> now. I have no plans to do it either, but I think it would be rather
> simple to later add support for setting frequency sampling since we only
> need to add a sysfs entry (with IIO_CHAN_INFO_SAMP_FREQ) that does not
> exist yet. Don't you think? Am I missing something?
No should be straight forward as long as we keep clear of the buffered
interfaces with their limitations.

> 
> Thanks,
> Quentin

^ permalink raw reply

* arm64: unhandled level 0 translation fault
From: Geert Uytterhoeven @ 2017-12-12 15:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171212103635.GD28301@arm.com>

Hi Will,

On Tue, Dec 12, 2017 at 11:36 AM, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, Dec 12, 2017 at 11:20:09AM +0100, Geert Uytterhoeven wrote:
>> During userspace (Debian jessie NFS root) boot on arm64:
>>
>> rpcbind[1083]: unhandled level 0 translation fault (11) at 0x00000008,
>> esr 0x92000004, in dash[aaaaadf77000+1a000]
>> CPU: 0 PID: 1083 Comm: rpcbind Not tainted
>> 4.15.0-rc3-arm64-renesas-02176-g14f9a1826e48e355 #51
>> Hardware name: Renesas Salvator-X 2nd version board based on r8a7795 ES2.0+ (DT)
>> pstate: 80000000 (Nzcv daif -PAN -UAO)
>> pc : 0xaaaaadf8a51c
>> lr : 0xaaaaadf8ac08
>> sp : 0000ffffcffeac00
>> x29: 0000ffffcffeac00 x28: 0000aaaaadfa1000
>> x27: 0000ffffcffebf7c x26: 0000ffffcffead20
>> x25: 0000aaaacea1c5f0 x24: 0000000000000000
>> x23: 0000aaaaadfa1000 x22: 0000aaaaadfa1000
>> x21: 0000000000000000 x20: 0000000000000008
>> x19: 0000000000000000 x18: 0000ffffcffeb500
>> x17: 0000ffffa22babfc x16: 0000aaaaadfa1ae8
>> x15: 0000ffffa2363588 x14: ffffffffffffffff
>> x13: 0000000000000020 x12: 0000000000000010
>> x11: 0101010101010101 x10: 0000aaaaadfa1000
>> x9 : 00000000ffffff81 x8 : 0000aaaaadfa2000
>> x7 : 0000000000000000 x6 : 0000000000000000
>> x5 : 0000aaaaadfa2338 x4 : 0000aaaaadfa2000
>> x3 : 0000aaaaadfa2338 x2 : 0000000000000000
>> x1 : 0000aaaaadfa28b0 x0 : 0000aaaaadfa4c30
>>
>> Sometimes it happens with other processes, but the main address, esr, and
>> pstate values are always the same.
>>
>> I regularly run arm64/for-next/core (through bi-weekly renesas-drivers
>> releases, so the last time was two weeks ago), but never saw the issue
>> before until today, so probably v4.15-rc1 is OK.
>> Unfortunately it doesn't happen during every boot, which makes it
>> cumbersome to bisect.
>>
>> My first guess was UNMAP_KERNEL_AT_EL0, but even after disabling that,
>> and even without today's arm64/for-next/core merged in, I still managed to
>> reproduce the issue, so I believe it was introduced in v4.15-rc2 or
>> v4.15-rc3.
>
> Urgh, this looks nasty. Thanks for the report! A few questions:
>
>  - Can you share your .config somewhere please?

I managed to reproduce it on plain v4.15-rc3 using both arm64_defconfig, and
renesas_defconfig (from Simon's repo).

>  - What was your last known-good kernel?

v4.15-rc1.

>  - Have you seen it on any other Soc?

I haven't seen it on any Renesas arm32 SoC, only on arm64.

>  - What's the CPU in your SoC?

Quad Cortex A57.

> If I can reproduce the failure here, then I should be able to debug ASAP.

Thanks!

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 02/10] clk: qcom: Fix .set_rate to handle alpha PLLs w/wo dynamic update
From: Julien Thierry @ 2017-12-12 15:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513081897-31612-3-git-send-email-ilialin@codeaurora.org>

Hi,

On 12/12/17 12:31, Ilia Lin wrote:
> From: Taniya Das <tdas@codeaurora.org>
> 
> From: Taniya Das <tdas@codeaurora.org>
> 
> Alpha PLLs which do not support dynamic update feature
> need to be explicitly disabled before a rate change.
> The ones which do support dynamic update do so within a
> single vco range, so add a min/max freq check for such
> PLLs so they fall in the vco range.
> 
> Signed-off-by: Taniya Das <tdas@codeaurora.org>
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>   drivers/clk/qcom/clk-alpha-pll.c | 71 +++++++++++++++++++++++++++++++++-------
>   drivers/clk/qcom/clk-alpha-pll.h |  5 +++
>   2 files changed, 65 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
> index 47a1da3..ecb9e7f 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.c
> +++ b/drivers/clk/qcom/clk-alpha-pll.c
> @@ -376,19 +376,46 @@ static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
>   	return alpha_pll_calc_rate(prate, l, a);
>   }
>   
> -static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> -				  unsigned long prate)
> +static int alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> +			      unsigned long prate,
> +			      int (*enable)(struct clk_hw *hw),
> +			      void (*disable)(struct clk_hw *hw))
>   {
> +	bool enabled;

Some remarks about this.

>   	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
>   	const struct pll_vco *vco;
>   	u32 l, off = pll->offset;
>   	u64 a;
>   
>   	rate = alpha_pll_round_rate(rate, prate, &l, &a);
> -	vco = alpha_pll_find_vco(pll, rate);
> -	if (!vco) {
> -		pr_err("alpha pll not in a valid vco range\n");
> -		return -EINVAL;
> +	enabled = clk_hw_is_enabled(hw);

This is not needed unless we go through the 'else' branch.

> +
> +	if (pll->flags & SUPPORTS_DYNAMIC_UPDATE) {
> +		/*
> +		 * PLLs which support dynamic updates support one single
> +		 * vco range, between min_rate and max_rate supported
> +		 */
> +		if (rate < pll->min_rate || rate > pll->max_rate) {
> +			pr_err("alpha pll rate outside supported min/max range\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		/*
> +		 * All alpha PLLs which do not support dynamic update,
> +		 * should be disabled before a vco update.
> +		 */
> +		if (enabled)
> +			disable(hw);
> +
> +		vco = alpha_pll_find_vco(pll, rate);
> +		if (!vco) {
> +			pr_err("alpha pll not in a valid vco range\n");
> +			return -EINVAL;
> +		}
> +
> +		regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
> +				   PLL_VCO_MASK << PLL_VCO_SHIFT,
> +				   vco->val << PLL_VCO_SHIFT);
>   	}
>   
>   	regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
> @@ -401,16 +428,29 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>   		regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
>   	}
>   
> -	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
> -			   PLL_VCO_MASK << PLL_VCO_SHIFT,
> -			   vco->val << PLL_VCO_SHIFT);
> -
>   	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN,
>   			   PLL_ALPHA_EN);
>   
> +	if (!(pll->flags & SUPPORTS_DYNAMIC_UPDATE) && enabled)
> +		enable(hw);
> +

This condition is only "did we disable the clock and need to reenable it?".

To make it clearer, I'd suggest renaming 'enabled' to something like 
'need_reenabling' and the code look like this:

static int alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
			      unsigned long prate,
			      int (*enable)(struct clk_hw *hw),
			      void (*disable)(struct clk_hw *hw))
{
	bool need_reenabling = false;

	[...]

	if(pll->flags & SUPPORTS_DYNAMIC_UPDATE) {
		[...]
	} else {
		if (clk_hw_is_enabled(hw)) {
			disable(hw);
			need_reenabling = true;
		}
		[...]
	}

	[...]

	if (need_reenabling)
		enable(hw);

}


Cheers,

-- 
Julien Thierry

^ permalink raw reply

* [PATCH v2] arm64: v8.4: Support for new floating point multiplication instructions
From: Dave Martin @ 2017-12-12 14:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513089419-13295-1-git-send-email-gengdongjiu@huawei.com>

On Tue, Dec 12, 2017 at 10:36:59PM +0800, Dongjiu Geng wrote:
> ARM v8.4 extensions add new neon instructions for performing a
> multiplication of each FP16 element of one vector with the corresponding
> FP16 element of a second vector, and to add or subtract this without an
> intermediate rounding to the corresponding FP32 element in a third vector.
> 
> This patch detects this feature and let the userspace know about it via a
> HWCAP bit and MRS emulation.
> 
> Cc: Dave Martin <Dave.Martin@arm.com>
> Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Change since v1:
> 1. Address Dave and Suzuki's comments to update the commit message.
> 2. Address Dave's comments to update Documentation/arm64/elf_hwcaps.txt.
> ---
>  Documentation/arm64/cpu-feature-registers.txt | 4 +++-
>  Documentation/arm64/elf_hwcaps.txt            | 4 ++++
>  arch/arm64/include/asm/sysreg.h               | 1 +
>  arch/arm64/include/uapi/asm/hwcap.h           | 1 +
>  arch/arm64/kernel/cpufeature.c                | 2 ++
>  arch/arm64/kernel/cpuinfo.c                   | 1 +
>  6 files changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/arm64/cpu-feature-registers.txt b/Documentation/arm64/cpu-feature-registers.txt
> index bd9b3fa..a70090b 100644
> --- a/Documentation/arm64/cpu-feature-registers.txt
> +++ b/Documentation/arm64/cpu-feature-registers.txt
> @@ -110,7 +110,9 @@ infrastructure:
>       x--------------------------------------------------x
>       | Name                         |  bits   | visible |
>       |--------------------------------------------------|
> -     | RES0                         | [63-48] |    n    |
> +     | RES0                         | [63-52] |    n    |
> +     |--------------------------------------------------|
> +     | FHM                          | [51-48] |    y    |
>       |--------------------------------------------------|
>       | DP                           | [47-44] |    y    |
>       |--------------------------------------------------|
> diff --git a/Documentation/arm64/elf_hwcaps.txt b/Documentation/arm64/elf_hwcaps.txt
> index 89edba1..987c40e 100644
> --- a/Documentation/arm64/elf_hwcaps.txt
> +++ b/Documentation/arm64/elf_hwcaps.txt
> @@ -158,3 +158,7 @@ HWCAP_SHA512
>  HWCAP_SVE
>  
>      Functionality implied by ID_AA64PFR0_EL1.SVE == 0b0001.
> +
> +HWCAP_FHM

This needs to match the name of the #define in hwcap.h.

With that change, Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Cheers
---Dave


> +
> +   Functionality implied by ID_AA64ISAR0_EL1.FHM == 0b0001.
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 08cc885..1818077 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -419,6 +419,7 @@
>  #define SCTLR_EL1_CP15BEN	(1 << 5)
>  
>  /* id_aa64isar0 */
> +#define ID_AA64ISAR0_FHM_SHIFT		48
>  #define ID_AA64ISAR0_DP_SHIFT		44
>  #define ID_AA64ISAR0_SM4_SHIFT		40
>  #define ID_AA64ISAR0_SM3_SHIFT		36
> diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
> index cda76fa..f018c3d 100644
> --- a/arch/arm64/include/uapi/asm/hwcap.h
> +++ b/arch/arm64/include/uapi/asm/hwcap.h
> @@ -43,5 +43,6 @@
>  #define HWCAP_ASIMDDP		(1 << 20)
>  #define HWCAP_SHA512		(1 << 21)
>  #define HWCAP_SVE		(1 << 22)
> +#define HWCAP_ASIMDFHM		(1 << 23)
>  
>  #endif /* _UAPI__ASM_HWCAP_H */
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index c5ba009..bc7e707 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -123,6 +123,7 @@ static int __init register_cpu_hwcaps_dumper(void)
>   * sync with the documentation of the CPU feature register ABI.
>   */
>  static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
> +	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_FHM_SHIFT, 4, 0),
>  	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_DP_SHIFT, 4, 0),
>  	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM4_SHIFT, 4, 0),
>  	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM3_SHIFT, 4, 0),
> @@ -991,6 +992,7 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus
>  	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM3_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SM3),
>  	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM4_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SM4),
>  	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_DP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_ASIMDDP),
> +	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_FHM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_ASIMDFHM),
>  	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_FP),
>  	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_FPHP),
>  	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_ASIMD),
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index 1e25545..7f94623 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -76,6 +76,7 @@
>  	"asimddp",
>  	"sha512",
>  	"sve",
> +	"asimdfhm",
>  	NULL
>  };
>  
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* mainline/master boot bisection: v4.15-rc3 on peach-pi #3228-staging
From: Shuah Khan @ 2017-12-12 14:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <88bebc9d-a889-403b-a742-c11ad6617638@samsung.com>

On 12/12/2017 01:47 AM, Marek Szyprowski wrote:
> Hi Javier,
> 
> On 2017-12-12 09:00, Javier Martinez Canillas wrote:
>> On Tue, Dec 12, 2017 at 8:54 AM, Marek Szyprowski
>> <m.szyprowski@samsung.com> wrote:
>>> On 2017-12-12 00:25, Shuah Khan wrote:
>>>> On 12/11/2017 04:02 PM, Russell King - ARM Linux wrote:
>>>>> On Mon, Dec 11, 2017 at 10:58:29PM +0000, Russell King - ARM Linux wrote:
>>>>>> On Mon, Dec 11, 2017 at 11:54:48PM +0100, Javier Martinez Canillas
>>>>>> wrote:
>>>>>>> So I gave a quick look to this, and at the very least there's a bug in
>>>>>>> the Exynos5800 Peach Pi DTS caused by commit 1cb686c08d12 ("ARM: dts:
>>>>>>> exynos: Add status property to Exynos 542x Mixer nodes").
>>>>>>>
>>>>>>> I've posted a fix for that:
>>>>>>>
>>>>>>> https://patchwork.kernel.org/patch/10105921/
>>>>>>>
>>>>>>> I believe this could be also be the cause for the boot failure, since
>>>>>>> I see in the boot log that things start to go wrong after exynos-drm
>>>>>>> fails to bind the HDMI component:
>>>>>>>
>>>>>>> [ 2.916347] exynos-drm exynos-drm: failed to bind 14530000.hdmi (ops
>>>>>>> 0xc1398690): -1
>>>>>> Umm, -1 ?? Looking that error code up in
>>>>>> include/uapi/asm-generic/errno-base.h says it's -EPERM.
>>>>>>
>>>>>> I suspect that's someone just returning -1 because they're lazy...
>>>>>> which is real bad form and needs fixing.
>>>>> Oh, it really is -EPERM:
>>>>>
>>>>> struct exynos_drm_crtc *exynos_drm_crtc_get_by_type(struct drm_device
>>>>> *drm_dev,
>>>>> ???????????????????????????????????????? enum exynos_drm_output_type
>>>>> out_type)
>>>>> {
>>>>> ????????? struct drm_crtc *crtc;
>>>>>
>>>>> ????????? drm_for_each_crtc(crtc, drm_dev)
>>>>> ????????????????? if (to_exynos_crtc(crtc)->type == out_type)
>>>>> ????????????????????????? return to_exynos_crtc(crtc);
>>>>>
>>>>> ????????? return ERR_PTR(-EPERM);
>>>>> }
>>>>>
>>>>> Does "Operation not permitted" really convey the error here?? It doesn't
>>>>> look like a permission error to me.
>>>>>
>>>>> Can we please avoid abusing errno codes?
>>>> I tried 4.15-rc3 on odroid-xu4 after seeing drm issues reported. 4.15-rc2+
>>>> with top commit g968edbd worked just fine for me last Friday. I ran
>>>> several
>>>> tests and everything checked out except the exynos-gsc lockdep issue I
>>>> sent
>>>> a 4.14 patch for.
>>>>
>>>> However, with 4.15-rc3, dmesg is gets filled with
>>>>
>>>> [? 342.337181] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 342.337470] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 342.337851] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 402.382346] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 402.396682] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 402.399244] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 402.399496] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 402.399848] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 402.400163] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 402.400495] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 402.401294] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>> [? 402.401595] [drm] Non-contiguous allocation is not supported without
>>>> IOMMU, falling back to contiguous buffer
>>>>
>>>> Something broke in 4.15-rc3 on odroix-xu4 badly with exynos_defconfig.
>>>>
>>>> I will start bisect and try to isolate the problem. I suspect this is
>>>> related to dts
>>>> changes perhaps? I used to this problem a while back and it has been
>>>> fixed.
>>>
>>> This warning has been added intentionally, see following discussions:
>>> https://patchwork.kernel.org/patch/10034919/
>>> https://patchwork.kernel.org/patch/10070475/
>>>
>>> This means that your test apps should be updated or you should enable Exynos
>>> IOMMU support in your config. Maybe it is a good time to finally enable it
>>> in exynos_defconfig.
>>>
>> Has the issue that the boot-loader keeps the display controller
>> enabled and scanning pages on the Exynos Chromebooks resolved?
>>
>> I think that's that preventing to enable it by default in
>> exynos_defconfig since it caused boot failures when enabled on these
>> machines. I don't follow exynos development too closely nowadays so
>> maybe there's a fix in place now.
> 
> Not directly. I still didn't find time to properly add support for
> devices, which were left in-working state (with active DMA
> transactions) by bootloader, but due to some other changes in the
> order of operations during boot process, power domains are
> initialized very early and due to temporary lack of devices (which
> are not yet added to the system), are turned off. This practically
> stops FIMD for scanning framebuffer and "solves" this issue.
> 
> I've checked now and Exynos Snow Chromebook boots fine with IOMMU
> support enabled, both with v4.15-rc3 and linux-next.
> 

Good to know it doesn't break Exynos Snow. This is why I test without
IOMMU and then enable IOMMU on odroid-xu4 for test with IOMMU

thanks,
-- Shuah

^ permalink raw reply

* mainline/master boot bisection: v4.15-rc3 on peach-pi #3228-staging
From: Shuah Khan @ 2017-12-12 14:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <8e506908-153f-2782-e7ef-7f2cc2c48662@samsung.com>

Hi Marek,

On 12/12/2017 04:38 AM, Marek Szyprowski wrote:
> Hi All,
> 
> On 2017-12-11 23:28, Javier Martinez Canillas wrote:
>> [adding Marek and Shuah to cc list]
>>
>> On Mon, Dec 11, 2017 at 6:05 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>>> On Mon, Dec 11, 2017 at 11:30 AM, Guillaume Tucker
>>> <guillaume.tucker@collabora.com> wrote:
>>>> Hi Daniel,
>>>>
>>>> Please see below, I've had several bisection results pointing at
>>>> that commit over the week-end on mainline but also on linux-next
>>>> and net-next.? While the peach-pi is a bit flaky at the moment
>>>> and is likely to have more than one issue, it does seem like this
>>>> commit is causing some well reproducible kernel hang.
>>>>
>>>> Here's a re-run with v4.15-rc3 showing the issue:
>>>>
>>>> ?? https://lava.collabora.co.uk/scheduler/job/1018478
>>>>
>>>> and here's another one with the change mentioned below reverted:
>>>>
>>>> ?? https://lava.collabora.co.uk/scheduler/job/1018479
>>>>
>>>> They both show a warning about "unbalanced disables for lcd_vdd",
>>>> I don't know if this is related as I haven't investigated any
>>>> further.? It does appear to reliably hang with v4.15-rc3 and
>>>> boot most of the time with the commit reverted though.
>>>>
>>>> The automated kernelci.org bisection is still an experimental
>>>> tool and it may well be a false positive, so please take this
>>>> result with a pinch of salt...
>>> The patch just very minimal moves the connector cleanup around (so
>>> timing change), but except when you unload a driver (or maybe that
>>> funny EPROBE_DEFER stuff) it shouldn't matter. So if you don't have
>>> more info than "seems to hang a bit more" I have no idea what's wrong.
>>> The patch itself should work, at least it survived quite some serious
>>> testing we do on everything.
>>> -Daniel
>>>
>> Marek was pointing to a different culprit [0] in this [1] thread. I
>> see that both commits made it to v4.15-rc3, which is the first version
>> where boot fails. So maybe is a combination of both? Or rather
>> reverting one patch masks the error in the other.
>>
>> I've access to the machine but unfortunately not a lot of time to dig
>> on this, I could try to do it in the weekend though.
> 
> After a recent discussion on the Javier's patch:
> https://patchwork.kernel.org/patch/10106417/
> I've managed to reproduce this issue also on Exynos5250 based Samsung
> Snow Chromebook and investigate a bit.
> 
> It is caused by a deadlock in the main kernel workqueue. Here are details:
> 
> 1. Exynos DRM fails to initialize due to missing regulators and gets moved
> to deferred probe device list
> 
> 2. Deferred probe is triggered and kernel "events" workqueue calls
> deferred_probe_work_func()
> 
> 3. exynos_drm_bind() is called, component_bind_all() fails due to missing
> Exynos Mixer device
> 
> 4. error handling path is executed in exynos_drm_bind(), which calls
> drm_mode_config_cleanup()
> 
> 5. drm_mode_config_cleanup() calls flush_scheduled_work(), what causes
> deadlock.
> 
> Do You have idea how to fix this issue properly?
> 
> Taking a look at git blame, this indeed shows that the issue has been
> introduced by the commit a703c55004e1 ("drm: safely free connectors from
> connector_ite"), which added a call to flush_scheduled_work() in
> drm_mode_config_cleanup().

This commit is making its way into stable releases. It has been added to
4.14-6 stable. If this patch poses problems, maybe somebody should comment
on the stable release thread.

> 
> drm_mode_config_cleanup() should avoid calling flush_scheduled_work() if
> called from the workqueue, but I don't have idea how to check that. The
> other way of fixing it would be to resurrect separate workqueue for DRM
> related events.
> 

Especially since there is no solution :)

thanks,
-- Shuah

^ permalink raw reply

* [PATCH v2] arm64: v8.4: Support for new floating point multiplication instructions
From: Dongjiu Geng @ 2017-12-12 14:36 UTC (permalink / raw)
  To: linux-arm-kernel

ARM v8.4 extensions add new neon instructions for performing a
multiplication of each FP16 element of one vector with the corresponding
FP16 element of a second vector, and to add or subtract this without an
intermediate rounding to the corresponding FP32 element in a third vector.

This patch detects this feature and let the userspace know about it via a
HWCAP bit and MRS emulation.

Cc: Dave Martin <Dave.Martin@arm.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Change since v1:
1. Address Dave and Suzuki's comments to update the commit message.
2. Address Dave's comments to update Documentation/arm64/elf_hwcaps.txt.
---
 Documentation/arm64/cpu-feature-registers.txt | 4 +++-
 Documentation/arm64/elf_hwcaps.txt            | 4 ++++
 arch/arm64/include/asm/sysreg.h               | 1 +
 arch/arm64/include/uapi/asm/hwcap.h           | 1 +
 arch/arm64/kernel/cpufeature.c                | 2 ++
 arch/arm64/kernel/cpuinfo.c                   | 1 +
 6 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/Documentation/arm64/cpu-feature-registers.txt b/Documentation/arm64/cpu-feature-registers.txt
index bd9b3fa..a70090b 100644
--- a/Documentation/arm64/cpu-feature-registers.txt
+++ b/Documentation/arm64/cpu-feature-registers.txt
@@ -110,7 +110,9 @@ infrastructure:
      x--------------------------------------------------x
      | Name                         |  bits   | visible |
      |--------------------------------------------------|
-     | RES0                         | [63-48] |    n    |
+     | RES0                         | [63-52] |    n    |
+     |--------------------------------------------------|
+     | FHM                          | [51-48] |    y    |
      |--------------------------------------------------|
      | DP                           | [47-44] |    y    |
      |--------------------------------------------------|
diff --git a/Documentation/arm64/elf_hwcaps.txt b/Documentation/arm64/elf_hwcaps.txt
index 89edba1..987c40e 100644
--- a/Documentation/arm64/elf_hwcaps.txt
+++ b/Documentation/arm64/elf_hwcaps.txt
@@ -158,3 +158,7 @@ HWCAP_SHA512
 HWCAP_SVE
 
     Functionality implied by ID_AA64PFR0_EL1.SVE == 0b0001.
+
+HWCAP_FHM
+
+   Functionality implied by ID_AA64ISAR0_EL1.FHM == 0b0001.
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 08cc885..1818077 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -419,6 +419,7 @@
 #define SCTLR_EL1_CP15BEN	(1 << 5)
 
 /* id_aa64isar0 */
+#define ID_AA64ISAR0_FHM_SHIFT		48
 #define ID_AA64ISAR0_DP_SHIFT		44
 #define ID_AA64ISAR0_SM4_SHIFT		40
 #define ID_AA64ISAR0_SM3_SHIFT		36
diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
index cda76fa..f018c3d 100644
--- a/arch/arm64/include/uapi/asm/hwcap.h
+++ b/arch/arm64/include/uapi/asm/hwcap.h
@@ -43,5 +43,6 @@
 #define HWCAP_ASIMDDP		(1 << 20)
 #define HWCAP_SHA512		(1 << 21)
 #define HWCAP_SVE		(1 << 22)
+#define HWCAP_ASIMDFHM		(1 << 23)
 
 #endif /* _UAPI__ASM_HWCAP_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index c5ba009..bc7e707 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -123,6 +123,7 @@ static int __init register_cpu_hwcaps_dumper(void)
  * sync with the documentation of the CPU feature register ABI.
  */
 static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_FHM_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_DP_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM4_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM3_SHIFT, 4, 0),
@@ -991,6 +992,7 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus
 	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM3_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SM3),
 	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM4_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SM4),
 	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_DP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_ASIMDDP),
+	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_FHM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_ASIMDFHM),
 	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_FP),
 	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_FPHP),
 	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_ASIMD),
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 1e25545..7f94623 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -76,6 +76,7 @@
 	"asimddp",
 	"sha512",
 	"sve",
+	"asimdfhm",
 	NULL
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH][next] net: phy: meson-gxl: make function meson_gxl_read_status static
From: Jerome Brunet @ 2017-12-12 14:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171212130311.17185-1-colin.king@canonical.com>

On Tue, 2017-12-12 at 13:03 +0000, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
> 
> The function meson_gxl_read_status is local to the source and does
> not need to be in global scope, so make it static.
> 
> Cleans up sparse warning:
> symbol 'meson_gxl_read_status' was not declared. Should it be static?
> 
> Signed-off-by: Colin Ian King <colin.king@canonical.com>

Indeed, silly mistake, thx for spotting it.

Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>

^ permalink raw reply

* [PATCH V3 09/29] drm/i915: deprecate pci_get_bus_and_slot()
From: Joonas Lahtinen @ 2017-12-12 14:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bd6c6365-c265-30f4-029b-3e19af3078f2@codeaurora.org>

Hi,

I sent this individual i915 patch to our CI, and it is passing on all platforms:

https://patchwork.freedesktop.org/series/34822/

Is it ok if I merge this to drm-tip already?

Regards, Joonas

On Mon, 2017-11-27 at 13:50 -0500, Sinan Kaya wrote:
> +dri-devel at lists.freedesktop.org
> 
> On 11/27/2017 11:57 AM, Sinan Kaya wrote:
> > pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> > where a PCI device is present. This restricts the device drivers to be
> > reused for other domain numbers.
> > 
> > Getting ready to remove pci_get_bus_and_slot() function in favor of
> > pci_get_domain_bus_and_slot().
> > 
> > Extract the domain number from drm_device and pass it into
> > pci_get_domain_bus_and_slot() function.
> > 
> > Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 9f45cfe..5a8cb79 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -419,7 +419,10 @@ static int i915_getparam(struct drm_device *dev, void *data,
> >  
> >  static int i915_get_bridge_dev(struct drm_i915_private *dev_priv)
> >  {
> > -	dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
> > +	int domain = pci_domain_nr(dev_priv->drm.pdev->bus);
> > +
> > +	dev_priv->bridge_dev =
> > +		pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0));
> >  	if (!dev_priv->bridge_dev) {
> >  		DRM_ERROR("bridge device not found\n");
> >  		return -1;
> > 
> 
> 
-- 
Joonas Lahtinen
Open Source Technology Center
Intel Corporation

^ permalink raw reply

* [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
From: Mark Rutland @ 2017-12-12 14:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513081897-31612-2-git-send-email-ilialin@codeaurora.org>

Hi,

On Tue, Dec 12, 2017 at 02:31:28PM +0200, Ilia Lin wrote:
> The driver provides kernel level API for other drivers
> to access the MSM8996 L2 cache registers.
> Separating the L2 access code from the PMU driver and
> making it public to allow other drivers use it.
> The accesses must be separated with a single spinlock,
> maintained in this driver.

> -static void set_l2_indirect_reg(u64 reg, u64 val)
> -{
> -	unsigned long flags;
> -
> -	raw_spin_lock_irqsave(&l2_access_lock, flags);
> -	write_sysreg_s(reg, L2CPUSRSELR_EL1);
> -	isb();
> -	write_sysreg_s(val, L2CPUSRDR_EL1);
> -	isb();
> -	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> -}

> +/**
> + * set_l2_indirect_reg: write value to an L2 register
> + * @reg: Address of L2 register.
> + * @value: Value to be written to register.
> + *
> + * Use architecturally required barriers for ordering between system register
> + * accesses, and system registers with respect to device memory
> + */
> +void set_l2_indirect_reg(u64 reg, u64 val)
> +{
> +	unsigned long flags;
> +	mb();

We didn't need this for the PMU driver, so it's unfortuante that it now
has to pay the cost.

Can we please factor this mb() into the callers that need it?

> +	raw_spin_lock_irqsave(&l2_access_lock, flags);
> +	write_sysreg_s(reg, L2CPUSRSELR_EL1);
> +	isb();
> +	write_sysreg_s(val, L2CPUSRDR_EL1);
> +	isb();
> +	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> +}
> +EXPORT_SYMBOL(set_l2_indirect_reg);

[...]

> +#ifdef CONFIG_ARCH_QCOM
> +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> +u64 get_l2_indirect_reg(u64 reg_addr);
> +#else
> +static inline void set_l2_indirect_reg(u32 reg_addr, u32 val) {}
> +static inline u32 get_l2_indirect_reg(u32 reg_addr)
> +{
> +	return 0;
> +}
> +#endif
> +#endif

Are there any drivers that will bne built for !CONFIG_ARCH_QCOM that
reference this?

It might be better to not have the stub versions, so that we get a
build-error if they are erroneously used.

Thannks,
Mark.

^ permalink raw reply

* [PATCH 1/6] ARM: stm32: prepare stm32 family to welcome armv7 architecture
From: Ludovic BARRE @ 2017-12-12 13:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171212110315.GA4118@afzalpc>

Hi all

-This patch serie hasn't goal to create a platform with
asymmetric linux processor (like vf610).

-Today, STM32 family have several boards with mcu microcontroler
Cortex-M like stm32f429, stm32f746...
And this patch serie prepare new board with support of Cortex-A
instead-of Cortex-M. (that's all)

BR
Ludo

On 12/12/2017 12:03 PM, afzal mohammed wrote:
> Hi,
> 
> On Mon, Dec 11, 2017 at 02:40:43PM +0100, Arnd Bergmann wrote:
>> On Mon, Dec 11, 2017 at 11:25 AM, Linus Walleij
> 
>>>> This patch prepares the STM32 machine for the integration of Cortex-A
>>>> based microprocessor (MPU), on top of the existing Cortex-M
>>>> microcontroller family (MCU). Since both MCUs and MPUs are sharing
>>>> common hardware blocks we can keep using ARCH_STM32 flag for most of
>>>> them. If a hardware block is specific to one family we can use either
>>>> ARCH_STM32_MCU or ARCH_STM32_MPU flag.
> 
>> To what degree do we need to treat them as separate families
>> at all then? I wonder if the MCU/MPU distinction is always that
>> clear along the Cortex-M/Cortex-A separation,
> 
>> What
>> exactly would we miss if we do away with the ARCH_STM32_MCU
>> symbol here?
> 
> Based on this patch series, the only difference seems to be w.r.t ARM
> components, not peripherals outside ARM subystem. Vybrid VF610 is a
> similar case, though not identical (it can have both instead of
> either), deals w/o extra symbols,
> 
> 8064887e02fd6 (ARM: vf610: enable Cortex-M4 configuration on Vybrid SoC)
> 
>> especially if
>> we ever get to a chip that has both types of cores.
> 
> Your wish fulfilled, Vybrid VF610 has both A5 & M4F and mainline Linux
> boots on both (simultaneously as well), and the second Linux support,
> i.e. on M4 went thr' your keyboard, see above commit :)
> 
> There are quite a few others as well, TI's AM335x (A8 + M3), AM437x
> (A9 + M3), AM57x (A15 + M4), but of these Cortex M's, the one in AM57x
> only can be Linux'able. On others they are meant for PM with limited
> resources.
> 
>>> So yesterdays application processors are todays MCU processors.
>>>
>>> I said this on a lecture for control systems a while back and
>>> stated it as a reason I think RTOSes are not really seeing a bright
>>> future compared to Linux.
> 
>> I think there is still lots of room for smaller RTOS in the long run,
> 
> Me being an electrical engineer & worked to some extent in motor
> control on RTOS/no OS (the value of my opinion is questionable
> though), the thought of handling the same in Linux (even RT) sends
> shivers down my spine. Here, case being considered is the type of
> motor (like permanent magnet ones) where each phase of the motor has
> to be properly excited during every PWM period (say every 100us,
> depending on the feedback, algorithm, other synchronization) w/o which
> the motor that has been told to run might try to fly. This is
> different from stepper motor where if control misbehaves/stops nothing
> harmful normally happens.
> 
> But my opinion is a kind of knee-jerk reaction and based on prevalent
> atitude in that field, hmm.., probably i should attempt it first.
> 
> Regards
> afzal
> 

^ permalink raw reply

* [PATCH v2 22/36] KVM: arm64: Prepare to handle traps on deferred VM sysregs
From: Marc Zyngier @ 2017-12-12 13:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171211112436.GH910@cbox>

On 11/12/17 11:24, Christoffer Dall wrote:
> On Mon, Dec 11, 2017 at 11:10:36AM +0000, Marc Zyngier wrote:
>> On 07/12/17 17:06, Christoffer Dall wrote:
>>> When we defer the save/restore of system registers to vcpu_load and
>>> vcpu_put, we need to take care of the emulation code that handles traps
>>> to these registers, since simply reading the memory array will return
>>> stale data.
>>>
>>> Therefore, introduce two functions to directly read/write the registers
>>> from the physical CPU when we're on a VHE system that has loaded the
>>> system registers onto the physical CPU.
>>>
>>> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
>>> ---
>>>
>>> Notes:
>>>     Changes since v1:
>>>      - Removed spurious white space
>>>
>>>  arch/arm64/include/asm/kvm_host.h |  4 +++
>>>  arch/arm64/kvm/sys_regs.c         | 53 +++++++++++++++++++++++++++++++++++++--
>>>  2 files changed, 55 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>>> index de0d55b30b61..f6afe685a280 100644
>>> --- a/arch/arm64/include/asm/kvm_host.h
>>> +++ b/arch/arm64/include/asm/kvm_host.h
>>> @@ -279,6 +279,10 @@ struct kvm_vcpu_arch {
>>>  
>>>  	/* Detect first run of a vcpu */
>>>  	bool has_run_once;
>>> +
>>> +	/* True when deferrable sysregs are loaded on the physical CPU,
>>> +	 * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */
>>> +	bool sysregs_loaded_on_cpu;
>>>  };
>>>  
>>>  #define vcpu_gp_regs(v)		(&(v)->arch.ctxt.gp_regs)
>>> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
>>> index 62c12ab9e6c4..80adbec933de 100644
>>> --- a/arch/arm64/kvm/sys_regs.c
>>> +++ b/arch/arm64/kvm/sys_regs.c
>>> @@ -35,6 +35,7 @@
>>>  #include <asm/kvm_coproc.h>
>>>  #include <asm/kvm_emulate.h>
>>>  #include <asm/kvm_host.h>
>>> +#include <asm/kvm_hyp.h>
>>>  #include <asm/kvm_mmu.h>
>>>  #include <asm/perf_event.h>
>>>  #include <asm/sysreg.h>
>>> @@ -111,6 +112,54 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
>>>  	return true;
>>>  }
>>>  
>>> +static u64 read_deferrable_vm_reg(struct kvm_vcpu *vcpu, int reg)
>>> +{
>>> +	if (vcpu->arch.sysregs_loaded_on_cpu) {
>>> +		switch (reg) {
>>> +		case SCTLR_EL1:		return read_sysreg_el1(sctlr);
>>> +		case TTBR0_EL1:		return read_sysreg_el1(ttbr0);
>>> +		case TTBR1_EL1:		return read_sysreg_el1(ttbr1);
>>> +		case TCR_EL1:		return read_sysreg_el1(tcr);
>>> +		case ESR_EL1:		return read_sysreg_el1(esr);
>>> +		case FAR_EL1:		return read_sysreg_el1(far);
>>> +		case AFSR0_EL1:		return read_sysreg_el1(afsr0);
>>> +		case AFSR1_EL1:		return read_sysreg_el1(afsr1);
>>> +		case MAIR_EL1:		return read_sysreg_el1(mair);
>>> +		case AMAIR_EL1:		return read_sysreg_el1(amair);
>>> +		case CONTEXTIDR_EL1:	return read_sysreg_el1(contextidr);
>>> +		case DACR32_EL2:	return read_sysreg(dacr32_el2);
>>> +		case IFSR32_EL2:	return read_sysreg(ifsr32_el2);
>>> +		default:		BUG();
>>> +		}
>>> +	}
>>> +
>>> +	return vcpu_sys_reg(vcpu, reg);
>>> +}
>>> +
>>> +static void write_deferrable_vm_reg(struct kvm_vcpu *vcpu, int reg, u64 val)
>>> +{
>>> +	if (vcpu->arch.sysregs_loaded_on_cpu) {
>>> +		switch (reg) {
>>> +		case SCTLR_EL1:		write_sysreg_el1(val, sctlr);	return;
>>> +		case TTBR0_EL1:		write_sysreg_el1(val, ttbr0);	return;
>>> +		case TTBR1_EL1:		write_sysreg_el1(val, ttbr1);	return;
>>> +		case TCR_EL1:		write_sysreg_el1(val, tcr);	return;
>>> +		case ESR_EL1:		write_sysreg_el1(val, esr);	return;
>>> +		case FAR_EL1:		write_sysreg_el1(val, far);	return;
>>> +		case AFSR0_EL1:		write_sysreg_el1(val, afsr0);	return;
>>> +		case AFSR1_EL1:		write_sysreg_el1(val, afsr1);	return;
>>> +		case MAIR_EL1:		write_sysreg_el1(val, mair);	return;
>>> +		case AMAIR_EL1:		write_sysreg_el1(val, amair);	return;
>>> +		case CONTEXTIDR_EL1:	write_sysreg_el1(val, contextidr); return;
>>> +		case DACR32_EL2:	write_sysreg(val, dacr32_el2); return;
>>> +		case IFSR32_EL2:	write_sysreg(val, ifsr32_el2); return;
>>> +		default:		BUG();
>>> +		}
>>> +	}
>>> +
>>> +	vcpu_sys_reg(vcpu, reg) = val;
>>> +}
>>> +
>>>  /*
>>>   * Generic accessor for VM registers. Only called as long as HCR_TVM
>>>   * is set. If the guest enables the MMU, we stop trapping the VM
>>> @@ -133,14 +182,14 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
>>>  	if (!p->is_aarch32 || !p->is_32bit) {
>>>  		val = p->regval;
>>>  	} else {
>>> -		val = vcpu_sys_reg(vcpu, reg);
>>> +		val = read_deferrable_vm_reg(vcpu, reg);
>>>  		if (r->reg % 2)
>>>  			val = (p->regval << 32) | (u64)lower_32_bits(val);
>>>  		else
>>>  			val = ((u64)upper_32_bits(val) << 32) |
>>>  				(u64)lower_32_bits(p->regval);
>>>  	}
>>> -	vcpu_sys_reg(vcpu, reg) = val;
>>> +	write_deferrable_vm_reg(vcpu, reg, val);
>>>  
>>>  	kvm_toggle_cache(vcpu, was_enabled);
>>>  	return true;
>>>
>>
>> I'm slightly uneasy with this. It means that the rest of the KVM code
>> has to know whether a given register is deferrable or not (or face the
>> wrath of the BUG). I'd be more inclined to hide the "loaded on cpu"
>> magic in the vcpu_sys_reg() accessors.
>>
>> Thoughts?
>>
> 
> Yes, this is the main reservation I also have with the series.
> 
> I did start out with a giant "rewrite everything to vcpu_get_sys_reg and
> vcpu_get_sys_reg" which hides this logic, and we may want to go back to
> that.
> 
> That does mean that we need a giant switch statement which knows how to
> read any deferrable EL1 (and EL0) system register from hardware, and
> still BUG/WARN if someone adds a system register but forgets to add that
> handler and test on VHE.  Unless there's some fantastic auto-gen
> mechanism that can take a hash define and figure out which sysreg
> instruction to use - I couldn't think of that.

Coming back to this, as I'm currently prototyping something.

What is the rational for the BUG()? It is not like we can add a random
sysreg and expect it to be deferred. It is a conscious decision to do
so, and I feel that the default should be that the sysreg should be
save/restored. What am I missing?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCH][next] net: phy: meson-gxl: make function meson_gxl_read_status static
From: Colin King @ 2017-12-12 13:03 UTC (permalink / raw)
  To: linux-arm-kernel

From: Colin Ian King <colin.king@canonical.com>

The function meson_gxl_read_status is local to the source and does
not need to be in global scope, so make it static.

Cleans up sparse warning:
symbol 'meson_gxl_read_status' was not declared. Should it be static?

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 drivers/net/phy/meson-gxl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
index c64b81e50f60..4ee630afe43a 100644
--- a/drivers/net/phy/meson-gxl.c
+++ b/drivers/net/phy/meson-gxl.c
@@ -67,7 +67,7 @@ static int meson_gxl_config_init(struct phy_device *phydev)
  * When this failure happens, the first retry is usually successful but,
  * in some cases, it may take up to 6 retries to get a decent result
  */
-int meson_gxl_read_status(struct phy_device *phydev)
+static int meson_gxl_read_status(struct phy_device *phydev)
 {
 	int ret, wol, lpa, exp;
 
-- 
2.14.1

^ permalink raw reply related

* [PATCH V7 0/7] dmaengine: qcom_hidma: add support for bugfixed HW
From: Rafael J. Wysocki @ 2017-12-12 12:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171212053845.GB18649@localhost>

On Tue, Dec 12, 2017 at 6:38 AM, Vinod Koul <vinod.koul@intel.com> wrote:
> On Thu, Dec 07, 2017 at 04:10:24PM -0500, Sinan Kaya wrote:
>> Introduce new ACPI and OF device ids for thw HW along with the helper
>> functions.
>>
>> Changes from v6:
>> * add const to the device callback parameter in fwnode.
>> * reorganize the callbacks in the code
>> * rename get_match_data() as device_get_match_data()
>> * place pointer checks into acpi_get_match_data()
>
> This fails for me at 3rd patch. I am on -rc1 is there a dependency?

There shouldn't be any.

According to git, all changes to the files touched by the [3/7] are in
-rc1 already.

^ permalink raw reply

* [PATCH 03/41] drm/rockchip: support prime import sg table
From: Heiko Stuebner @ 2017-12-12 12:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170310043305.17216-4-seanpaul@chromium.org>

Am Donnerstag, 9. M?rz 2017, 23:32:18 CET schrieb Sean Paul:
> From: Haixia Shi <hshi@chromium.org>
> 
> The prime fd to handle ioctl was not used with rockchip before. Support
> was added in order to pass graphics_Gbm and to support potential uses
> within Chrome OS (e.g. zero-copy video decode, camera).
> 
> Signed-off-by: Haixia Shi <hshi@chromium.org>

missing a further Signed-off from Sean Paul as the sender.

I've tested this on the rk3328 together with the wip Lima driver and my wip
Mesa Rockchip Pipe and the kmscube improved from a failure about importing
the buffer to producing actual output, so

Tested-by: Heiko Stuebner <heiko@sntech.de>

^ permalink raw reply

* [PATCH 10/10] DT: QCOM: Add thermal mitigation to msm8996
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513081897-31612-1-git-send-email-ilialin@codeaurora.org>

Add thermal mitigation configuration to msm8996.
With the cpufreq-dt OPP table the CPU frequency may be
scaled and therefore throttled by the thermal config.

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 98 +++++++++++++++++++++++++++++++----
 1 file changed, 87 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 8beea7e..6fa061f 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -14,6 +14,7 @@
 #include <dt-bindings/clock/qcom,gcc-msm8996.h>
 #include <dt-bindings/clock/qcom,mmcc-msm8996.h>
 #include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM8996";
@@ -88,6 +89,10 @@
 			enable-method = "psci";
 			clocks = <&kryocc 0>;
 			operating-points-v2 = <&cluster0_opp>;
+			/* cooling options */
+			cooling-min-level = <0>;
+			cooling-max-level = <15>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_0>;
 			L2_0: l2-cache {
 			      compatible = "cache";
@@ -102,6 +107,10 @@
 			enable-method = "psci";
 			clocks = <&kryocc 0>;
 			operating-points-v2 = <&cluster0_opp>;
+			/* cooling options */
+			cooling-min-level = <0>;
+			cooling-max-level = <15>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_0>;
 		};
 
@@ -112,6 +121,10 @@
 			enable-method = "psci";
 			clocks = <&kryocc 1>;
 			operating-points-v2 = <&cluster1_opp>;
+			/* cooling options */
+			cooling-min-level = <0>;
+			cooling-max-level = <15>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_1>;
 			L2_1: l2-cache {
 			      compatible = "cache";
@@ -126,6 +139,10 @@
 			enable-method = "psci";
 			clocks = <&kryocc 1>;
 			operating-points-v2 = <&cluster1_opp>;
+			/* cooling options */
+			cooling-min-level = <0>;
+			cooling-max-level = <15>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_1>;
 		};
 
@@ -336,18 +353,33 @@
 			thermal-sensors = <&tsens0 3>;
 
 			trips {
-				cpu_alert0: trip0 {
+				cpu_alert0: cpu_alert0 {
 					temperature = <75000>;
 					hysteresis = <2000>;
+					type = "active";
+				};
+				cpu_warn0: cpu_warn0 {
+					temperature = <90000>;
+					hysteresis = <2000>;
 					type = "passive";
 				};
-
-				cpu_crit0: trip1 {
+				cpu_crit0: cpu_crit0 {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device = <&CPU0 THERMAL_NO_LIMIT 7>;
+				};
+				map1 {
+					trip = <&cpu_warn0>;
+					cooling-device = <&CPU0 8 THERMAL_NO_LIMIT>;
+				};
+			};
 		};
 
 		cpu-thermal1 {
@@ -357,18 +389,33 @@
 			thermal-sensors = <&tsens0 5>;
 
 			trips {
-				cpu_alert1: trip0 {
+				cpu_alert1: cpu_alert1 {
 					temperature = <75000>;
 					hysteresis = <2000>;
+					type = "active";
+				};
+				cpu_warn1: cpu_warn1 {
+					temperature = <90000>;
+					hysteresis = <2000>;
 					type = "passive";
 				};
-
-				cpu_crit1: trip1 {
+				cpu_crit1: cpu_crit1 {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert1>;
+					cooling-device = <&CPU0 THERMAL_NO_LIMIT 7>;
+				};
+				map1 {
+					trip = <&cpu_warn1>;
+					cooling-device = <&CPU0 8 THERMAL_NO_LIMIT>;
+				};
+			};
 		};
 
 		cpu-thermal2 {
@@ -378,18 +425,32 @@
 			thermal-sensors = <&tsens0 8>;
 
 			trips {
-				cpu_alert2: trip0 {
+				cpu_alert2: cpu_alert2 {
 					temperature = <75000>;
 					hysteresis = <2000>;
+					type = "active";
+				};
+				cpu_warn2: cpu_warn2 {
+					temperature = <90000>;
+					hysteresis = <2000>;
 					type = "passive";
 				};
-
-				cpu_crit2: trip1 {
+				cpu_crit2: cpu_crit2 {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert2>;
+					cooling-device = <&CPU2 THERMAL_NO_LIMIT 7>;
+				};
+				map1 {
+					trip = <&cpu_warn2>;
+					cooling-device = <&CPU2 8 THERMAL_NO_LIMIT>;
+				};
+			};
 		};
 
 		cpu-thermal3 {
@@ -399,18 +460,33 @@
 			thermal-sensors = <&tsens0 10>;
 
 			trips {
-				cpu_alert3: trip0 {
+				cpu_alert3: cpu_alert3 {
 					temperature = <75000>;
 					hysteresis = <2000>;
+					type = "active";
+				};
+				cpu_warn3: cpu_warn3 {
+					temperature = <90000>;
+					hysteresis = <2000>;
 					type = "passive";
 				};
-
 				cpu_crit3: trip1 {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert3>;
+					cooling-device = <&CPU2 THERMAL_NO_LIMIT 7>;
+				};
+				map1 {
+					trip = <&cpu_warn3>;
+					cooling-device = <&CPU2 8 THERMAL_NO_LIMIT>;
+				};
+			};
 		};
 	};
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 09/10] DT: QCOM: Add cpufreq-dt to msm8996
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513081897-31612-1-git-send-email-ilialin@codeaurora.org>

Add device tree frequency table for the MSM8996 to be
used by the upstream cpufreq-dt driver with the clk-cpu-8996
driver as infrastructure.

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi       | 184 ++++++++++++++++++++++++++++
 drivers/cpufreq/cpufreq-dt-platdev.c        |   3 +
 3 files changed, 188 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 230e9c8..da23bda 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -17,5 +17,5 @@
 
 / {
 	model = "Qualcomm Technologies, Inc. DB820c";
-	compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc";
+	compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc", "qcom,apq8096";
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 4b2afcc..8beea7e 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -86,6 +86,8 @@
 			compatible = "qcom,kryo";
 			reg = <0x0 0x0>;
 			enable-method = "psci";
+			clocks = <&kryocc 0>;
+			operating-points-v2 = <&cluster0_opp>;
 			next-level-cache = <&L2_0>;
 			L2_0: l2-cache {
 			      compatible = "cache";
@@ -98,6 +100,8 @@
 			compatible = "qcom,kryo";
 			reg = <0x0 0x1>;
 			enable-method = "psci";
+			clocks = <&kryocc 0>;
+			operating-points-v2 = <&cluster0_opp>;
 			next-level-cache = <&L2_0>;
 		};
 
@@ -106,6 +110,8 @@
 			compatible = "qcom,kryo";
 			reg = <0x0 0x100>;
 			enable-method = "psci";
+			clocks = <&kryocc 1>;
+			operating-points-v2 = <&cluster1_opp>;
 			next-level-cache = <&L2_1>;
 			L2_1: l2-cache {
 			      compatible = "cache";
@@ -118,6 +124,8 @@
 			compatible = "qcom,kryo";
 			reg = <0x0 0x101>;
 			enable-method = "psci";
+			clocks = <&kryocc 1>;
+			operating-points-v2 = <&cluster1_opp>;
 			next-level-cache = <&L2_1>;
 		};
 
@@ -144,6 +152,182 @@
 		};
 	};
 
+	cluster0_opp: opp_table0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp at 307200000 {
+			opp-hz = /bits/ 64 <  307200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 422400000 {
+			opp-hz = /bits/ 64 <  422400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 480000000 {
+			opp-hz = /bits/ 64 <  480000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 556800000 {
+			opp-hz = /bits/ 64 <  556800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 652800000 {
+			opp-hz = /bits/ 64 <  652800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 729600000 {
+			opp-hz = /bits/ 64 <  729600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 844800000 {
+			opp-hz = /bits/ 64 <  844800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 960000000 {
+			opp-hz = /bits/ 64 <  960000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1036800000 {
+			opp-hz = /bits/ 64 < 1036800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1113600000 {
+			opp-hz = /bits/ 64 < 1113600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1190400000 {
+			opp-hz = /bits/ 64 < 1190400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1228800000 {
+			opp-hz = /bits/ 64 < 1228800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1324800000 {
+			opp-hz = /bits/ 64 < 1324800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1401600000 {
+			opp-hz = /bits/ 64 < 1401600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1478400000 {
+			opp-hz = /bits/ 64 < 1478400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1593600000 {
+			opp-hz = /bits/ 64 < 1593600000 >;
+			clock-latency-ns = <200000>;
+		};
+	};
+
+	cluster1_opp: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp at 307200000 {
+			opp-hz = /bits/ 64 <  307200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 403200000 {
+			opp-hz = /bits/ 64 <  403200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 480000000 {
+			opp-hz = /bits/ 64 <  480000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 556800000 {
+			opp-hz = /bits/ 64 <  556800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 652800000 {
+			opp-hz = /bits/ 64 <  652800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 729600000 {
+			opp-hz = /bits/ 64 <  729600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 806400000 {
+			opp-hz = /bits/ 64 <  806400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 883200000 {
+			opp-hz = /bits/ 64 <  883200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 940800000 {
+			opp-hz = /bits/ 64 <  940800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1036800000 {
+			opp-hz = /bits/ 64 < 1036800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1113600000 {
+			opp-hz = /bits/ 64 < 1113600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1190400000 {
+			opp-hz = /bits/ 64 < 1190400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1248000000 {
+			opp-hz = /bits/ 64 < 1248000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1324800000 {
+			opp-hz = /bits/ 64 < 1324800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1401600000 {
+			opp-hz = /bits/ 64 < 1401600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1478400000 {
+			opp-hz = /bits/ 64 < 1478400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1552000000 {
+			opp-hz = /bits/ 64 < 1552000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1632000000 {
+			opp-hz = /bits/ 64 < 1632000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1708800000 {
+			opp-hz = /bits/ 64 < 1708800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1785600000 {
+			opp-hz = /bits/ 64 < 1785600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1824000000 {
+			opp-hz = /bits/ 64 < 1824000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1920000000 {
+			opp-hz = /bits/ 64 < 1920000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1996800000 {
+			opp-hz = /bits/ 64 < 1996800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 2073600000 {
+			opp-hz = /bits/ 64 < 2073600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 2150400000 {
+			opp-hz = /bits/ 64 < 2150400000 >;
+			clock-latency-ns = <200000>;
+		};
+
+	};
 	thermal-zones {
 		cpu-thermal0 {
 			polling-delay-passive = <250>;
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index ecc56e2..0feca0e 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -95,6 +95,9 @@
 	{ .compatible = "xlnx,zynq-7000", },
 	{ .compatible = "xlnx,zynqmp", },
 
+	{ .compatible = "qcom,msm8996", },
+	{ .compatible = "qcom,apq8096", },
+
 	{ }
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513081897-31612-1-git-send-email-ilialin@codeaurora.org>

The PMUX for each duplex allows for selection of ACD clock source.
The DVM (Dynamic Variation Monitor) will flag an error
when a voltage droop event is detected. This flagged error
enables ACD to provide a div-by-2 clock, sourced from the primary PLL.
The duplex will be provided the divided clock
until a pre-programmed delay has expired.

This change configures ACD during the probe and switches
the PMUXes to the ACD clock source.

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 122 ++++++++++++++++++++++++++++++++++------
 1 file changed, 106 insertions(+), 16 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 0d41fa9..6f89471 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -17,6 +17,7 @@
 #include <linux/regmap.h>
 #include <linux/clk-provider.h>
 #include "clk-alpha-pll.h"
+#include <soc/qcom/kryo-l2-accessors.h>
 
 #define VCO(a, b, c) { \
 	.val = a,\
@@ -29,6 +30,27 @@
 #define ACD_INDEX		2
 #define ALT_INDEX		3
 #define DIV_2_THRESHOLD		600000000
+#define PWRCL_REG_OFFSET 0x0
+#define PERFCL_REG_OFFSET 0x80000
+#define MUX_OFFSET	0x40
+#define ALT_PLL_OFFSET	0x100
+#define SSSCTL_OFFSET 0x160
+/*
+APCy_QLL_SSSCTL value:
+SACDRCLEN=1
+SSWEN=1
+SSTRTEN=1
+SSTPAPMSWEN=1
+*/
+#define SSSCTL_VAL 0xF
+
+enum {
+	APC_BASE,
+	EFUSE_BASE,
+	NUM_BASES
+};
+
+static void __iomem *vbases[NUM_BASES];
 
 /* PLLs */
 
@@ -43,7 +65,7 @@
 };
 
 static struct clk_alpha_pll perfcl_pll = {
-	.offset = 0x80000,
+	.offset = PERFCL_REG_OFFSET,
 	.min_rate = 600000000,
 	.max_rate = 3000000000,
 	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_16BIT_ALPHA
@@ -57,7 +79,7 @@
 };
 
 static struct clk_alpha_pll pwrcl_pll = {
-	.offset = 0x0,
+	.offset = PWRCL_REG_OFFSET,
 	.min_rate = 600000000,
 	.max_rate = 3000000000,
 	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_16BIT_ALPHA
@@ -89,7 +111,7 @@
 };
 
 static struct clk_alpha_pll perfcl_alt_pll = {
-	.offset = 0x80100,
+	.offset = PERFCL_REG_OFFSET + ALT_PLL_OFFSET,
 	.vco_table = alt_pll_vco_modes,
 	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
 	.flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
@@ -102,7 +124,7 @@
 };
 
 static struct clk_alpha_pll pwrcl_alt_pll = {
-	.offset = 0x100,
+	.offset = PWRCL_REG_OFFSET + ALT_PLL_OFFSET,
 	.vco_table = alt_pll_vco_modes,
 	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
 	.flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
@@ -113,6 +135,7 @@
 		.ops = &clk_alpha_pll_hwfsm_ops,
 	},
 };
+static void qcom_cpu_clk_msm8996_acd_init(void);
 
 /* Mux'es */
 
@@ -196,6 +219,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 	switch (event) {
 	case PRE_RATE_CHANGE:
 		ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, ALT_INDEX);
+		qcom_cpu_clk_msm8996_acd_init();
 		break;
 	case POST_RATE_CHANGE:
 		if (cnd->new_rate < DIV_2_THRESHOLD)
@@ -203,7 +227,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 							  DIV_2_INDEX);
 		else
 			ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw,
-							  PLL_INDEX);
+							  ACD_INDEX);
 		break;
 	default:
 		ret = 0;
@@ -220,7 +244,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 };
 
 static struct clk_cpu_8996_mux pwrcl_smux = {
-	.reg = 0x40,
+	.reg = PWRCL_REG_OFFSET + MUX_OFFSET,
 	.shift = 2,
 	.width = 2,
 	.clkr.hw.init = &(struct clk_init_data) {
@@ -236,7 +260,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 };
 
 static struct clk_cpu_8996_mux perfcl_smux = {
-	.reg = 0x80040,
+	.reg = PERFCL_REG_OFFSET + MUX_OFFSET,
 	.shift = 2,
 	.width = 2,
 	.clkr.hw.init = &(struct clk_init_data) {
@@ -252,7 +276,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 };
 
 static struct clk_cpu_8996_mux pwrcl_pmux = {
-	.reg = 0x40,
+	.reg = PWRCL_REG_OFFSET + MUX_OFFSET,
 	.shift = 0,
 	.width = 2,
 	.pll = &pwrcl_pll.clkr.hw,
@@ -273,7 +297,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 };
 
 static struct clk_cpu_8996_mux perfcl_pmux = {
-	.reg = 0x80040,
+	.reg = PERFCL_REG_OFFSET + MUX_OFFSET,
 	.shift = 0,
 	.width = 2,
 	.pll = &perfcl_pll.clkr.hw,
@@ -341,7 +365,17 @@ struct clk_hw_clks {
 						   CLK_SET_RATE_PARENT, 1, 2);
 	pwrcl_smux.pll = hws->hws[1];
 
-	hws->num = 2;
+	hws->hws[2] = clk_hw_register_fixed_factor(dev, "perfcl_pll_acd",
+						   "perfcl_pll",
+						   CLK_SET_RATE_PARENT, 1, 1);
+	perfcl_pmux.pll = hws->hws[2];
+
+	hws->hws[3] = clk_hw_register_fixed_factor(dev, "pwrcl_pll_acd",
+						   "pwrcl_pll",
+						   CLK_SET_RATE_PARENT, 1, 1);
+	pwrcl_pmux.pll = hws->hws[3];
+
+	hws->num = 4;
 
 	for (i = 0; i < ARRAY_SIZE(clks); i++) {
 		ret = devm_clk_register_regmap(dev, clks[i]);
@@ -377,10 +411,65 @@ struct clk_hw_clks {
 	return ret;
 }
 
+#define CPU_AFINITY_MASK 0xFFF
+#define PWRCL_CPU_REG_MASK 0x3
+#define PERFCL_CPU_REG_MASK 0x103
+
+/* ACD static settings (HMSS HPG 7.2.2) */
+#define L2ACDCR_REG 0x580ULL
+#define L2ACDTD_REG 0x581ULL
+#define L2ACDDVMRC_REG 0x584ULL
+#define L2ACDSSCR_REG 0x589ULL
+#define ACDTD_VAL 0x00006A11
+#define ACDCR_VAL 0x002C5FFD
+#define ACDSSCR_VAL 0x00000601
+#define ACDDVMRC_VAL 0x000E0F0F
+
+static DEFINE_SPINLOCK(acd_lock);
+
+static void qcom_cpu_clk_msm8996_acd_init(void)
+{
+	u64 hwid;
+	unsigned long flags;
+
+	spin_lock_irqsave(&acd_lock, flags);
+
+	hwid = read_cpuid_mpidr() & CPU_AFINITY_MASK;
+
+	/* Program ACD Tunable-Length Delay (TLD) */
+	set_l2_indirect_reg(L2ACDTD_REG, ACDTD_VAL);
+	/* Initial ACD for *this* cluster */
+	set_l2_indirect_reg(L2ACDDVMRC_REG, ACDDVMRC_VAL);
+	/* Program ACD soft start control bits. */
+	set_l2_indirect_reg(L2ACDSSCR_REG, ACDSSCR_VAL);
+
+	if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
+		/* Enable Soft Stop/Start */
+		if (vbases[APC_BASE])
+			writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
+					PWRCL_REG_OFFSET + SSSCTL_OFFSET);
+		/* Ensure SSSCTL config goes through before enabling ACD. */
+		mb();
+		/* Program ACD control bits */
+		set_l2_indirect_reg(L2ACDCR_REG, ACDCR_VAL);
+	}
+	if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) { //else {
+		/* Program ACD control bits */
+		set_l2_indirect_reg(L2ACDCR_REG, ACDCR_VAL);
+		/* Enable Soft Stop/Start */
+		if (vbases[APC_BASE])
+			writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
+					PERFCL_REG_OFFSET + SSSCTL_OFFSET);
+		/* Ensure SSSCTL config goes through before enabling ACD. */
+		mb();
+	}
+
+	spin_unlock_irqrestore(&acd_lock, flags);
+}
+
 static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
 {
 	int ret;
-	void __iomem *base;
 	struct resource *res;
 	struct regmap *regmap_cpu;
 	struct clk_hw_clks *hws;
@@ -393,17 +482,17 @@ static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
 	if (!data)
 		return -ENOMEM;
 
-	hws = devm_kzalloc(dev, sizeof(*hws) + 2 * sizeof(struct clk_hw *),
+	hws = devm_kzalloc(dev, sizeof(*hws) + 4 * sizeof(struct clk_hw *),
 			   GFP_KERNEL);
 	if (!hws)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
+	vbases[APC_BASE] = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vbases[APC_BASE]))
+		return PTR_ERR(vbases[APC_BASE]);
 
-	regmap_cpu = devm_regmap_init_mmio(dev, base,
+	regmap_cpu = devm_regmap_init_mmio(dev, vbases[APC_BASE],
 					   &cpu_msm8996_regmap_config);
 	if (IS_ERR(regmap_cpu))
 		return PTR_ERR(regmap_cpu);
@@ -411,6 +500,7 @@ static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
 	ret = qcom_cpu_clk_msm8996_register_clks(dev, hws, regmap_cpu);
 	if (ret)
 		return ret;
+	qcom_cpu_clk_msm8996_acd_init();
 
 	data->hws[0] = &pwrcl_pmux.clkr.hw;
 	data->hws[1] = &perfcl_pmux.clkr.hw;
-- 
1.9.1

^ permalink raw reply related


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