Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Tegra baseline test results for v4.8
From: Jon Hunter @ 2016-10-03 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

Here are some basic Tegra test results for Linux v4.8.
Logs and other details at:

    https://nvtb.github.io//linux/test_v4.8/20161002170103/


Test summary
------------

Build: zImage:
    Pass: ( 2/ 2): multi_v7_defconfig, tegra_defconfig

Build: Image:
    Pass: ( 1/ 1): defconfig

Boot to userspace: defconfig:
    Pass: ( 4/ 4): qemu-vexpress64, tegra132-norrin,
		   tegra210-p2371-0000, tegra210-smaug

Boot to userspace: multi_v7_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

Boot to userspace: tegra_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

PM: System suspend: multi_v7_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

PM: System suspend: tegra_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver


vmlinux object size
(delta in bytes from test_v4.8-rc8 (08895a8b6b06ed2323cd97a36ee40a116b3db8ed)):
   text     data      bss    total  kernel
     +4        0        0       +4  defconfig
   +156        0        0     +156  multi_v7_defconfig
   +220        0        0     +220  tegra_defconfig


Boot-time memory difference
(delta in bytes from test_v4.8-rc8 (08895a8b6b06ed2323cd97a36ee40a116b3db8ed))
    avail    rsrvd     high    freed                board              kconfig                  dtb
        .        .        .        .      qemu-vexpress64            defconfig           __internal
        .        .        .        . tegra114-dalmore-a04   multi_v7_defconfig     tegra114-dalmore
        .        .        .        . tegra114-dalmore-a04      tegra_defconfig     tegra114-dalmore
        .        .        .        .  tegra124-jetson-tk1   multi_v7_defconfig  tegra124-jetson-tk1
        .        .        .        .  tegra124-jetson-tk1      tegra_defconfig  tegra124-jetson-tk1
        .        .        .        .    tegra124-nyan-big   multi_v7_defconfig    tegra124-nyan-big
        .        .        .        .    tegra124-nyan-big      tegra_defconfig    tegra124-nyan-big
        .        .        .        .      tegra132-norrin            defconfig      tegra132-norrin
        .        .        .        .    tegra20-trimslice   multi_v7_defconfig    tegra20-trimslice
        .        .        .        .    tegra20-trimslice      tegra_defconfig    tegra20-trimslice
        .        .        .        .  tegra210-p2371-0000            defconfig  tegra210-p2371-0000
        .        .        .        .       tegra210-smaug            defconfig       tegra210-smaug
        .        .        .        .       tegra30-beaver   multi_v7_defconfig       tegra30-beaver
        .        .        .        .       tegra30-beaver      tegra_defconfig       tegra30-beaver

--
nvpublic

^ permalink raw reply

* Tegra baseline test results for v4.8-rc8
From: Jon Hunter @ 2016-10-03 14:57 UTC (permalink / raw)
  To: linux-arm-kernel

Here are some basic Tegra test results for Linux v4.8-rc8.
Logs and other details at:

    https://nvtb.github.io//linux/test_v4.8-rc8/20160925190103/


Test summary
------------

Build: zImage:
    Pass: ( 2/ 2): multi_v7_defconfig, tegra_defconfig

Build: Image:
    Pass: ( 1/ 1): defconfig

Boot to userspace: defconfig:
    Pass: ( 4/ 4): qemu-vexpress64, tegra132-norrin,
		   tegra210-p2371-0000, tegra210-smaug

Boot to userspace: multi_v7_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

Boot to userspace: tegra_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

PM: System suspend: multi_v7_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

PM: System suspend: tegra_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver


vmlinux object size
(delta in bytes from test_v4.8-rc7 (3be7988674ab33565700a37b210f502563d932e6)):
   text     data      bss    total  kernel
     -4        0        0       -4  defconfig
   +850        0        0     +850  multi_v7_defconfig
   +534        0        0     +534  tegra_defconfig


Boot-time memory difference
(delta in bytes from test_v4.8-rc7 (3be7988674ab33565700a37b210f502563d932e6))
    avail    rsrvd     high    freed                board              kconfig                  dtb
        .        .        .        .      qemu-vexpress64            defconfig           __internal
        .        .        .        . tegra114-dalmore-a04   multi_v7_defconfig     tegra114-dalmore
        .        .        .        . tegra114-dalmore-a04      tegra_defconfig     tegra114-dalmore
        .        .        .        .  tegra124-jetson-tk1   multi_v7_defconfig  tegra124-jetson-tk1
        .        .        .        .  tegra124-jetson-tk1      tegra_defconfig  tegra124-jetson-tk1
        .        .        .        .    tegra124-nyan-big   multi_v7_defconfig    tegra124-nyan-big
        .        .        .        .    tegra124-nyan-big      tegra_defconfig    tegra124-nyan-big
        .        .        .        .      tegra132-norrin            defconfig      tegra132-norrin
        .        .        .        .    tegra20-trimslice   multi_v7_defconfig    tegra20-trimslice
        .        .        .        .    tegra20-trimslice      tegra_defconfig    tegra20-trimslice
        .        .        .        .  tegra210-p2371-0000            defconfig  tegra210-p2371-0000
        .        .        .        .       tegra210-smaug            defconfig       tegra210-smaug
        .        .        .        .       tegra30-beaver   multi_v7_defconfig       tegra30-beaver
        .        .        .        .       tegra30-beaver      tegra_defconfig       tegra30-beaver

--
nvpublic

^ permalink raw reply

* [PATCH] coresight: tmc: implementing TMC-ETR AUX space API
From: Suzuki K Poulose @ 2016-10-03 14:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474319674-18172-1-git-send-email-mathieu.poirier@linaro.org>

On 19/09/16 22:14, Mathieu Poirier wrote:
> This patch implements the AUX area interfaces required to
> use the TMC-ETR (configured to work in scatter-gather mode)
> from the Perf sub-system.
>
> Some of this work was inspired from the original implementation
> done by Pratik Patel at CodeAurora.
>

Hi Mathieu,

Thanks for nailing the monster. I have a few comments below on the implementation.

> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> ---
>  drivers/hwtracing/coresight/coresight-tmc-etr.c | 629 +++++++++++++++++++++++-
>  drivers/hwtracing/coresight/coresight-tmc.h     |   1 +
>  2 files changed, 621 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 6d7de0309e94..581d6393bb5d 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -17,10 +17,60 @@
>
>  #include <linux/coresight.h>
>  #include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +
>  #include "coresight-priv.h"
>  #include "coresight-tmc.h"
>
> -void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
> +/**
> + * struct etr_page - DMA'able and virtual address representation for a page
> + * @daddr:		DMA'able page address returned by dma_map_page()
> + * @vaddr:		Virtual address returned by page_address()
> + */
> +struct etr_page {
> +	dma_addr_t	daddr;
> +	u64		vaddr;
> +};
> +
> +/**
> + * struct cs_etr_buffer - keep track of a recording session' specifics
> + * @dev:		device reference to be used with the DMA API
> + * @tmc:		generic portion of the TMC buffers
> + * @etr_nr_pages:	number of memory pages for the ETR-SG trace storage
> + * @pt_vaddr:		the virtual address of the first page table entry
> + * @page_addr:		quick access to all the pages held in the page table
> + */
> +struct cs_etr_buffers {
> +	struct device		*dev;
> +	struct cs_buffers	tmc;
> +	unsigned int		etr_nr_pages;
> +	void __iomem		*pt_vaddr;
> +	struct etr_page		page_addr[0];
> +};
> +
> +#define TMC_ETR_ENTRIES_PER_PT (PAGE_SIZE / sizeof(u32))
> +
> +/*
> + * Helpers for scatter-gather descriptors.  Descriptors are defined as follow:
> + *
> + * ---Bit31------------Bit4-------Bit1-----Bit0--
> + * |     Address[39:12]    | SBZ |  Entry Type  |
> + * ----------------------------------------------
> + *
> + * Address: Bits [39:12] of a physical page address. Bits [11:0] are
> + *	    always zero.
> + *
> + * Entry type:	b10 - Normal entry
> + *		b11 - Last entry in a page table
> + *		b01 - Last entry
> + */
> +#define TMC_ETR_SG_LST_ENT(phys_pte)	(((phys_pte >> PAGE_SHIFT) << 4) | 0x1)
> +#define TMC_ETR_SG_ENT(phys_pte)	(((phys_pte >> PAGE_SHIFT) << 4) | 0x2)
> +#define TMC_ETR_SG_NXT_TBL(phys_pte)	(((phys_pte >> PAGE_SHIFT) << 4) | 0x3)
> +

Please be aware that on arm64, the PAGE_SIZE can be 16K or 64K. So hard coding
PAGE_SHIFT here might be problematic on those configurations as the ETR page size
is always 4K.

> +#define TMC_ETR_SG_ENT_TO_PG(entry)	((entry >> 4) << PAGE_SHIFT)
> +
> +void tmc_etr_enable_hw_cnt_mem(struct tmc_drvdata *drvdata)
>  {
>  	u32 axictl;
>
> @@ -57,7 +107,47 @@ void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
>  	CS_LOCK(drvdata->base);
>  }
>
> -static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
> +void tmc_etr_enable_hw_sg_mem(struct tmc_drvdata *drvdata)


> +	 * DBAHI Holds the upper eight bits of the 40-bit address used to
> +	 * locate the trace buffer in system memory.
> +	 */
> +	writel_relaxed((drvdata->paddr >> 32) & 0xFF,
> +			drvdata->base + TMC_DBAHI);

I think we should do the same for tmc_etr_enable_hw_cnt_mem().

> @@ -199,7 +290,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
>  		goto out;
>  	}
>
> -	tmc_etr_enable_hw(drvdata);
> +	tmc_etr_enable_hw_sg_mem(drvdata);
>  out:
>  	spin_unlock_irqrestore(&drvdata->spinlock, flags);
>
> @@ -241,9 +332,528 @@ static void tmc_disable_etr_sink(struct coresight_device *csdev)
>  	dev_info(drvdata->dev, "TMC-ETR disabled\n");
>  }
>
> +/*
> + * The default perf ring buffer size is 32 and 1024 pages for user and kernel
> + * space respectively.  The size of the intermediate SG list is allowed
> + * to match the size of the perf ring buffer but cap it to the default
> + * kernel size.
> + */
> +#define DEFAULT_NR_KERNEL_PAGES	1024
> +static int tmc_get_etr_pages(int nr_pages)

The name could be confusing, as it kind of implies it allocates nr_pages.
It might be worth renaming it to tmc_get_etr_pages_nr ?

> +{
> +	if (nr_pages <= DEFAULT_NR_KERNEL_PAGES)
> +		return nr_pages;
> +
> +	return DEFAULT_NR_KERNEL_PAGES;
> +}
> +
> +/*
> + * Go through all the pages in the SG list and check if @phys_addr
> + * falls within one of those.  If so record the information in
> + * @page and @offset.
> + */
> +static int
> +tmc_get_sg_page_index(struct cs_etr_buffers *etr_buffer,
> +		      u64 phys_addr, u32 *page, u32 *offset)
> +{
> +	int i = 0, pte = 0, nr_pages = etr_buffer->etr_nr_pages;
> +	u32 *page_table_itr = etr_buffer->pt_vaddr;
> +	phys_addr_t phys_page_addr;
> +
> +	/* Circle through all the pages in the SG list */
> +	while (pte < nr_pages) {
> +		phys_page_addr = TMC_ETR_SG_ENT_TO_PG((u64)*page_table_itr);

Could we not find the phys_addr by scanning the etr_pages[].daddr and use the
index to hope through the PageTable links to reach the entry which could have it
and return the offset within that page ?

> +
> +		/* Does @phys_addr falls within this page? */
> +		if (phys_addr >= phys_page_addr &&
> +		    phys_addr < (phys_page_addr + PAGE_SIZE)) {
> +			*page = pte;
> +			*offset = phys_addr - phys_page_addr;
> +			return 0;
> +		}
> +
> +		if (pte == nr_pages - 1) {
> +			/* The last page in the SG list */
> +			pte++;
> +		} else if (i == TMC_ETR_ENTRIES_PER_PT - 1) {
> +			/*
> +			 * The last entry in this page table - get a reference
> +			 * on the next page table and do _not_ increment @pte
> +			 */
> +			page_table_itr = phys_to_virt(phys_page_addr);
> +			i = 0;
> +		} else {
> +			/* A normal page in the SG list */
> +			page_table_itr++;
> +			pte++;
> +			i++;
> +		}
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static void tmc_sg_page_sync(struct cs_etr_buffers *etr_buffer,
> +			     int start_page, u64 to_sync)

nit: to_sync doesn't give a clue on what the unit is ? pages ? bytes ?
could it be u64 size ?

> +{
> +	int i, index;
> +	int pages_to_sync = DIV_ROUND_UP_ULL(to_sync, PAGE_SIZE);
> +	dma_addr_t daddr;
> +	struct device *dev = etr_buffer->dev;
> +
> +	for (i = start_page; i < (start_page + pages_to_sync); i++) {
> +		/* Wrap around the etr page list if need be */
> +		index = i % etr_buffer->etr_nr_pages;
> +		daddr = etr_buffer->page_addr[index].daddr;
> +		dma_sync_single_for_cpu(dev, daddr, PAGE_SIZE, DMA_FROM_DEVICE);
> +	}
> +}
> +

> +static void tmc_free_sg_buffer(struct cs_etr_buffers *etr_buffer, int nr_pages)
> +{
> +	int i = 0, pte = 0;
> +	u32 *page_addr, *page_table_itr;
> +	u32 *page_table_addr = etr_buffer->pt_vaddr;
> +	phys_addr_t phys_page_addr;
> +	dma_addr_t daddr;
> +	struct device *dev = etr_buffer->dev;
> +
> +	if (!page_table_addr)
> +		return;
> +

Please check comments on tmc_alloc_sg_buffer().

> +
> +static int
> +tmc_alloc_sg_buffer(struct cs_etr_buffers *etr_buffer, int cpu, int nr_pages)
> +{
> +	int i = 0, node, pte = 0, ret = 0;
> +	dma_addr_t dma_page_addr;
> +	u32 *page_table_addr, *page_addr;
> +	struct page *page;
> +	struct device *dev = etr_buffer->dev;
> +
> +	if (cpu == -1)
> +		cpu = smp_processor_id();
> +	node = cpu_to_node(cpu);
> +
> +	/* Allocate the first page table */
> +	page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
> +	if (!page)
> +		return -ENOMEM;
> +
> +	page_table_addr = page_address(page);

Would it be simpler to allocate the pages required for the PageTables and track them
separately ? i.e for a given nr_pages, we could easily calculate the number of Table
entries required.

nr_table_pages = (nr_pages << (PAGE_SHIFT - 12)) / (TMC_ETR_ENTRIES_PER_PT - 1);
table_pages = alloc_pages_exact_nid(node, GFP_KERNEL|__GFP_ZERO, nr_table_pages * PAGE_SIZE);

where, PAGE_SHIFT - 12 ( = PAGE_SHIFT_4K) gives the log2 number 4K pages in a system
page.

That way, we can link the pages easily and also free them easily in tmc_free_sg_buffer() without
traversing the page table once again, since we track the ETR pages and the pages for the tables now.
Also the page table initialisation below could be much simpler as we could link the table entries
at one shot.
	
> +	/*
> +	 * Keep track of the first page table, the rest will be chained
> +	 * in the last page table entry.
> +	 */
> +	etr_buffer->pt_vaddr = page_table_addr;
> +
> +	while (pte < nr_pages) {
> +		page = alloc_pages_node(node,
> +					GFP_KERNEL | __GFP_ZERO, 0);
> +		if (!page) {
> +			ret = -ENOMEM;
> +			goto err;
> +		}
> +
> +		page_addr = page_address(page);
> +
> +		if (pte == nr_pages - 1) {
> +			/* The last page in the list */
> +			dma_page_addr = tmc_setup_dma_page(dev, page);
> +			if (dma_page_addr == -EINVAL) {
> +				ret = -EINVAL;
> +				goto err;
> +			}
> +
> +			*page_table_addr = TMC_ETR_SG_LST_ENT(dma_page_addr);
> +
> +			etr_buffer->page_addr[pte].vaddr = (u64)page_addr;
> +			etr_buffer->page_addr[pte].daddr = dma_page_addr;
> +
> +			pte++;
> +		} else if (i == TMC_ETR_ENTRIES_PER_PT - 1) {
> +			/* The last entry in this page table */
> +			*page_table_addr =
> +				TMC_ETR_SG_NXT_TBL(virt_to_phys(page_addr));

Shouldn't this also be a dma_addr_t of the page ? The TMC ETR would use the
address in the table to "read" the page table in this case, while the other
pte entries are used to "write" data to the addresses (for which you correctly
set up the dma address). I don't see why the "read" address should be any different.
The TMC TRM uses PTn_BaseAddr for the page table base, which can be confusing.
But if you see the DBALO which points to the PT0_BaseAddr, it should be clear.

> +			/* Move on to the next page table */
> +			page_table_addr = page_addr;
> +
> +			i = 0;
> +		} else {
> +			/* A normal page in the SG list */
> +			dma_page_addr = tmc_setup_dma_page(dev, page);
> +			if (dma_page_addr == -EINVAL) {
> +				ret = -EINVAL;
> +				goto err;
> +			}
> +
> +			*page_table_addr = TMC_ETR_SG_ENT(dma_page_addr);
> +
> +			etr_buffer->page_addr[pte].vaddr = (u64)page_addr;
> +			etr_buffer->page_addr[pte].daddr = dma_page_addr;
> +
> +			page_table_addr++;

As mentioned above, with a page size other than 4K, we are wasting space here.

> +			pte++;
> +			i++;
> +		}
> +	}
> +
> +	return 0;
> +
> +err:
> +	tmc_free_sg_buffer(etr_buffer, pte);
> +	etr_buffer->pt_vaddr = NULL;
> +	return ret;
> +}
> +
> +static void *tmc_alloc_etr_buffer(struct coresight_device *csdev, int cpu,
> +				  void **pages, int nr_pages, bool overwrite)
> +{
> +	int etr_pages, node;
> +	struct device *dev = csdev->dev.parent;
> +	struct cs_etr_buffers *buf;
> +
> +	if (cpu == -1)
> +		cpu = smp_processor_id();
> +	node = cpu_to_node(cpu);
> +
> +	/* Register DBALO and DBAHI form a 40-bit address range */
> +	if (dma_set_mask(dev, DMA_BIT_MASK(40)))
> +		return NULL;
> +
> +	/*
> +	 * The HW can't start collecting data in the middle of the SG list,
> +	 * it must start at the beginning.  As such we can't use the ring
> +	 * buffer provided by perf as entries into the page tables since
> +	 * it is not guaranteed that user space will have the chance to
> +	 * consume the data before the next trace run begins.
> +	 *
> +	 * To work around this reserve a set of pages that will be used as
> +	 * and intermediate (SG) buffer.  This isn't optimal but the best we
> +	 * can do with the current HW revision.

Just for my understanding, is this because we don't get a notification from
the hardware when the buffers are (getting) full ?

> +	 */
> +	etr_pages = tmc_get_etr_pages(nr_pages);

nit: As mentioned above the function name and the variable name etr_pages could be
confusing. How about renaming the variable to nr_etr_pages ?

> +static int tmc_set_etr_buffer(struct coresight_device *csdev,
> +			      struct perf_output_handle *handle,
> +			      void *sink_config)
> +{
> +	unsigned long head;
> +	struct cs_etr_buffers *buf = sink_config;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +	/* wrap head around to the amount of space we have */
> +	head = handle->head & ((buf->tmc.nr_pages << PAGE_SHIFT) - 1);
> +
> +	/* find the page to write to */
> +	buf->tmc.cur = head / PAGE_SIZE;
> +
> +	/* and offset within that page */
> +	buf->tmc.offset = head % PAGE_SIZE;
> +
> +	local_set(&buf->tmc.data_size, 0);
> +
> +	/* Keep track of how big the internal SG list is */
> +	drvdata->size = buf->etr_nr_pages << PAGE_SHIFT;
> +
> +	/* Tell the HW where to put the trace data */
> +	drvdata->paddr = virt_to_phys(buf->pt_vaddr);

Shouldn't this be a dma_addr as we used to program in the normal mode ?

> +
> +	return 0;
> +}
> +
> +static unsigned long tmc_reset_etr_buffer(struct coresight_device *csdev,
> +					  struct perf_output_handle *handle,
> +					  void *sink_config, bool *lost)
> +{
> +	long size = 0;
> +	struct cs_etr_buffers *buf = sink_config;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +	if (buf) {
> +		/*
> +		 * In snapshot mode ->data_size holds the new address of the
> +		 * ring buffer's head.  The size itself is the whole address
> +		 * range since we want the latest information.
> +		 */
> +		if (buf->tmc.snapshot) {
> +			size = buf->tmc.nr_pages << PAGE_SHIFT;
> +			handle->head = local_xchg(&buf->tmc.data_size, size);
> +		}
> +
> +		/*
> +		 * Tell the tracer PMU how much we got in this run and if
> +		 * something went wrong along the way.  Nobody else can use
> +		 * this cs_etr_buffers instance until we are done.  As such
> +		 * resetting parameters here and squaring off with the ring
> +		 * buffer API in the tracer PMU is fine.
> +		 */
> +		*lost = !!local_xchg(&buf->tmc.lost, 0);
> +		size = local_xchg(&buf->tmc.data_size, 0);

I don't fully understand the cs_buffer API, but we set the data_size to 0, unconditionally here.
Whats the point of setting the data_size above for snapshot mode ?

> +	}
> +
> +	/* Get ready for another run */
> +	drvdata->vaddr = NULL;
> +	drvdata->paddr = 0;
> +
> +	return size;
> +}
> +
> +static void tmc_update_etr_buffer(struct coresight_device *csdev,
> +				  struct perf_output_handle *handle,
> +				  void *sink_config)
> +{
> +	bool full;
> +	int i, rb_index, sg_index = 0;
> +	u32 rwplo, rwphi, rb_offset, sg_offset = 0;
> +	u32 stop_index, stop_offset, to_copy, sg_size;
> +	u32 *rb_ptr, *sg_ptr;
> +	u64 rwp, to_read;
> +	struct cs_etr_buffers *etr_buf = sink_config;
> +	struct cs_buffers *cs_buf = &etr_buf->tmc;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +	if (!etr_buf)
> +		return;
> +
> +	/* This shouldn't happen */
> +	if (WARN_ON_ONCE(local_read(&drvdata->mode) != CS_MODE_PERF))
> +		return;
> +
> +	CS_UNLOCK(drvdata->base);
> +
> +	tmc_flush_and_stop(drvdata);
> +
> +	rwplo = readl_relaxed(drvdata->base + TMC_RWP);
> +	rwphi = readl_relaxed(drvdata->base + TMC_RWPHI);
> +	full = (readl_relaxed(drvdata->base + TMC_STS) & TMC_STS_FULL);

nitpick: you don't need the brackets above.

> +
> +	/* Combine the high and low part of the rwp to make a full address */
> +	rwp = (u64)rwphi << 32;
> +	rwp |= rwplo;
> +
> +	/* Convert the stop address in RAM to a page and an offset */
> +	if (tmc_get_sg_page_index(etr_buf, rwp, &stop_index, &stop_offset))
> +		goto out;
> +
> +	if (full) {
> +		/*
> +		 * The buffer head has wrapped around.  As such the size
> +		 * is the entire buffer length and the index and offset in
> +		 * the scatter-gather list are moved forward.
> +		 */
> +		local_inc(&cs_buf->lost);
> +		to_read = drvdata->size;
> +		sg_index = stop_index;
> +		sg_offset = stop_offset;
> +	} else {
> +		to_read = (stop_index * PAGE_SIZE) + stop_offset;
> +	}
> +
> +	/*
> +	 * The TMC RAM buffer may be bigger than the space available in the
> +	 * perf ring buffer (handle->size).  If so advance the RRP so that we
> +	 * get the latest trace data.
> +	 */

A stupid question: Is this something we can tune in the tmc to match the handle->size so that we
don't have to worry about it ?

> +	if (to_read > handle->size) {
> +		u64 rrp;
> +
> +		/*
> +		 * Compute where we should start reading from
> +		 * relative to rwp.
> +		 */
> +		rrp = rwp + drvdata->size;
> +		/* Go back just enough */
> +		rrp -= handle->size;


This looks wrong to me. We cannot simply move the rrp pointer back and forth, as the buffer
is not guaranteed to be contiguous.

> +		/* Make sure we are still within our limits */
> +		rrp %= drvdata->size;

And the above step definitely makes it not an address. We may have to find the address by looking
at the page table.

> +
> +		/* Get a new index and offset based on rrp */
> +		if (tmc_get_sg_page_index(etr_buf, rrp,
> +					  &stop_index, &stop_offset))
> +			goto out;
> +
> +		/* Tell user space we lost data */
> +		local_inc(&cs_buf->lost);
> +		to_read = handle->size;
> +		/* Adjust start index and offset */
> +		sg_index = stop_index;
> +		sg_offset = stop_offset;
> +	}
> +
> +	/* Get a handle on where the Perf ring buffer is */
> +	rb_index = cs_buf->cur;
> +	rb_offset = cs_buf->offset;
> +
> +	/* Refresh the SG list */
> +	tmc_sg_page_sync(etr_buf, sg_index, to_read);
> +
> +	for (i = to_read; i > 0; ) {
> +		/* Get current location of the perf ring buffer */
> +		rb_ptr = cs_buf->data_pages[rb_index] + rb_offset;
> +		/* Get current location in the ETR SG list */
> +		sg_ptr = (u32 *)(etr_buf->page_addr[sg_index].vaddr +
> +				 sg_offset);
> +
> +		/*
> +		 * First figure out the maximum amount of data we can get out
> +		 * of the ETR SG list.
> +		 */
> +		if (i < PAGE_SIZE)
> +			sg_size = i;
> +		else
> +			sg_size = PAGE_SIZE - sg_offset;

If i < PAGE_SIZE and (PAGE_SIZE - sg_offset) < i, we could crash below trying to
copy from beyond the page.
I think it should be :

		sg_size = min(PAGE_SIZE - sg_offset, i);


Thanks
Suzuki

^ permalink raw reply

* [PATCH] Adding Support for Coresight Components on Zynq 7000.
From: Muhammad Abdul WAHAB @ 2016-10-03 14:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003133019.GF7630@xsjsorenbubuntu>

Hi again S?ren,

 > Sounds good. AFAICT, the change below should be OK. Probably some
 > stylistic changes to make it blend in with the rest of the DT (e.g.
 > use lower case characters in the address parts of the node name).

The change to low characters has been made for address part. I also
deleted some empty lines to respect the style of the rest of the DT.

 > I'd say that depends on what it is about. If it is about DT and the TPIU
 > Linux driver, I'd say, keep it on list and probably even include the
 > authors of that driver (the folks the get_maintainers script is
 > identifying for that driver).
 >
 > If it's specific to Zynq, the Xilinx forums can be quite helpful as
 > there are a lot of people familiar with the device
 > (https://forums.xilinx.com/t5/Embedded-Linux/bd-p/ELINUX).
 >
 > But when in doubt, feel free to reach out to me directly.

OK. Thank you !

M.Abdul WAHAB
---
--- linux-4.7/arch/arm/boot/dts/zynq-7000.dtsi.orig    2016-07-24 
21:23:50.000000000 +0200
+++ linux-4.7/arch/arm/boot/dts/zynq-7000.dtsi    2016-10-03 
15:54:35.228460164 +0200
@@ -96,6 +96,51 @@
              rx-fifo-depth = <0x40>;
          };

+        etb at f8801000 {
+            compatible = "arm,coresight-etb10", "arm,primecell";
+            reg = <0xf8801000 0x1000>;
+            coresight-default-sink;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            port {
+                etb_in_port: endpoint at 0 {
+                    slave-mode;
+                    remote-endpoint = <&replicator_out_port0>;
+                };
+            };
+        };
+
+        funnel at f8804000 {
+            compatible = "arm,coresight-funnel", "arm,primecell";
+            reg = <0xf8804000 0x1000>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            ports {
+                #address-cells = <0x1>;
+                #size-cells = <0x0>;
+                port at 0 {
+                    reg = <0x0>;
+                    funnel_out_port0: endpoint {
+                        remote-endpoint = <&replicator_in_port0>;
+                    };
+                };
+                port at 1 {
+                    reg = <0x0>;
+                    funnel_in_port0: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&ptm0_out_port>;
+                    };
+                };
+                port at 2 {
+                    reg = <0x1>;
+                    funnel_in_port1: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&ptm1_out_port>;
+                    };
+                };
+            };
+        };
+
          gpio0: gpio at e000a000 {
              compatible = "xlnx,zynq-gpio-1.0";
              #gpio-cells = <2>;
@@ -311,6 +356,59 @@
              clocks = <&clkc 4>;
          };

+        ptm0 at f889c000 {
+            compatible = "arm,coresight-etm3x", "arm,primecell";
+            reg = <0xf889c000 0x1000>;
+            cpu = <&cpu0>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            port {
+                ptm0_out_port: endpoint {
+                    remote-endpoint = <&funnel_in_port0>;
+                };
+            };
+        };
+
+        ptm1 at f889d000 {
+            compatible = "arm,coresight-etm3x", "arm,primecell";
+            reg = <0xf889d000 0x1000>;
+            cpu = <&cpu1>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            port {
+                ptm1_out_port: endpoint {
+                    remote-endpoint = <&funnel_in_port1>;
+                };
+            };
+        };
+
+        replicator {
+            compatible = "arm,coresight-replicator";
+            ports {
+                #address-cells = <0x1>;
+                #size-cells = <0x0>;
+                port at 0 {
+                    reg = <0x0>;
+                    replicator_out_port0: endpoint {
+                        remote-endpoint = <&etb_in_port>;
+                    };
+                };
+                port at 1 {
+                    reg = <0x1>;
+                    replicator_out_port1: endpoint {
+                        remote-endpoint = <&tpiu_in_port>;
+                    };
+                };
+                port at 2 {
+                    reg = <0x0>;
+                    replicator_in_port0: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&funnel_out_port0>;
+                    };
+                };
+            };
+        };
+
          ttc0: timer at f8001000 {
              interrupt-parent = <&intc>;
              interrupts = <0 10 4>, <0 11 4>, <0 12 4>;

^ permalink raw reply

* [PATCH v2 2/2] drm: zte: add initial vou drm driver
From: Daniel Vetter @ 2016-10-03 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACvgo53A7BpVWHgkFrZsjWnw_uW6xDmKRsrxF=46HOEWQ43BxA@mail.gmail.com>

On Mon, Oct 3, 2016 at 12:36 PM, Emil Velikov <emil.l.velikov@gmail.com> wrote:
>>> > +static int zx_gl_get_fmt(uint32_t format)
>>> > +{
>>> > +       switch (format) {
>>> > +       case DRM_FORMAT_ARGB8888:
>>> > +       case DRM_FORMAT_XRGB8888:
>>> > +               return GL_FMT_ARGB8888;
>>> > +       case DRM_FORMAT_RGB888:
>>> > +               return GL_FMT_RGB888;
>>> > +       case DRM_FORMAT_RGB565:
>>> > +               return GL_FMT_RGB565;
>>> > +       case DRM_FORMAT_ARGB1555:
>>> > +               return GL_FMT_ARGB1555;
>>> > +       case DRM_FORMAT_ARGB4444:
>>> > +               return GL_FMT_ARGB4444;
>>> > +       default:
>>> > +               WARN_ONCE(1, "invalid pixel format %d\n", format);
>>> > +               return -EINVAL;
>>> Afaics the only user of this is atomic_update() and that function
>>> cannot fail. You might want to move this to the _check() function.
>>> Same logic goes for the rest of the driver, in case I've missed any.
>>
>> The function does the conversion from DRM format values to the ones that
>> hardware accepts.  And I need to set up hardware register with the
>> converted value.
>>
>> I suppose that the error case in 'default' should never be hit, since
>> all valid format have been reported to DRM core by gl_formats?  In that
>> case, I can simply drop the WARN and return a sane default format
>> instead?
>>
> I'd just do the error checking in check() function and keep the
> mapping in update(). As devs add new formats to DRM core it's not
> possible for them to test every driver so getting a failure early is
> better (imho) than getting subtle visual and/or other issues. Either
> way it's up-to you really.

I think a WARN_ON here is perfectly fine. Like Shawn said, any invalid
formats should already be filtered out by the drm core (by checking
against the list of valid formats for this plane), so no need to move
this to ->check(). In i915.ko we have a MISSING_CASE macro to catch
these cases when someone adds a new format, but forgets to update all
the switch statements.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply

* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
From: Sinan Kaya @ 2016-10-03 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003033851.GP2467@localhost>

On 10/2/2016 11:38 PM, Vinod Koul wrote:
>> I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
>> > nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
>> > side effects on my testing either.
> yeah later on I did look up the of_msi_configure() and I suspected this. I
> think it would be worthwhile to document this assumption here.

Sure, let me do that.

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

^ permalink raw reply

* [PATCH] Adding Support for Coresight Components on Zynq 7000.
From: Sören Brinkmann @ 2016-10-03 13:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5b56a00a-ac69-b15d-1155-bab53ed766f3@supelec.fr>

Hi Muhammad,

On Mon, 2016-10-03 at 14:56:16 +0200, Muhammad Abdul WAHAB wrote:
> Hi S?ren,
> 
> > I tried to refresh my Zynq knowledge a bit. The clkc provides the
> > dbg_trc clock, and that is the clock you need (not fclk). I couldn't
> > find it in the binding (I guess I messed that up), but apparently,
> > you can provide a 'trace_emio_clk' as input to the clkc node in the
> > Zynq DT. Then, with the muxes correctly configured (FSBL should do
> > that if you select the EMIO trace clock in Vivado), the dbg_trc
> > output of the clkc should be that EMIO clock. And the dbg_trc output
> > of the clkc is what should be consumed by the tpiu node. Though, as
> > I see it the binding/driver for the TPIU do not support that.
> >
> > I.e.
> > In the clkc description you'd have to add 'trace_emio_clk' to the
> > clock-names property together with a matching reference in the 'clocks'
> > property. As this change would be specific to local setups, this is not
> > really appropriate for upstream.
> >
> > Then, for the trace clock, ideally the TPIU would consume and enable it
> > as needed.
> 
> Thank you very much for this. I will have a look into it.
> Below is the patch without TPIU, is it possible to submit it ? I will submit
> the TPIU part very soon once I manage to get it working.

Sounds good. AFAICT, the change below should be OK. Probably some
stylistic changes to make it blend in with the rest of the DT (e.g.
use lower case characters in the address parts of the node name).

> 
> > Unfortunately, this is not how it works. The DT bindings are not a
> > recommendation. The DT description must follow the binding, otherwise
> > drivers will not work correctly, or best case, just ignore what you put
> > there.
> 
> Thanks. The idea of including TPIU part was to get feedback as I am far from
> being an expert on DT.
> 
> > As I don't see this in the coresight binding, I doubt that it has any
> > effect or should be here.
> 
> That's what I was thinking also. I will re-look into TPIU part and send it
> soon. Besides, if I want to ask you a question regarding TPIU or DT, can I
> contact you alone or should I keep sending it to all the CS/DT maintainers ?

I'd say that depends on what it is about. If it is about DT and the TPIU
Linux driver, I'd say, keep it on list and probably even include the
authors of that driver (the folks the get_maintainers script is
identifying for that driver).

If it's specific to Zynq, the Xilinx forums can be quite helpful as
there are a lot of people familiar with the device
(https://forums.xilinx.com/t5/Embedded-Linux/bd-p/ELINUX).

But when in doubt, feel free to reach out to me directly.

	S?ren

^ permalink raw reply

* Coresight ETF trace dump failed in Juno r1 with 4.8-rc8
From: Sudeep Holla @ 2016-10-03 13:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGhh56F-VWCCy82msQ8CimZ4a0a2h=tqR2qv1KcfeyuQXo=R1w@mail.gmail.com>

Hi Venkatesh,

On 03/10/16 12:36, Venkatesh Vivekanandan wrote:
> Hi All,
>
> I am trying to collect ETF trace from Juno R1 and could see "cpu
> stall" while dumping the trace. Attached is the log of sequence
> followed. Was trying to collect the trace data from hardware and see
> if it is any valid data. Am I missing anything here?.
>

There are few fixes from me and Suzuki queued for v4.9.
Can you check if this issue persists even on linux-next ?

-- 
Regards,
Sudeep

^ permalink raw reply

* PROBLEM: DWC3 USB 3.0 not working on Odroid-XU4 with Exynos 5422
From: Michael Niewöhner @ 2016-10-03 13:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CANAwSgQMsK8YPxR==UXtR49kiJzYhkzvSCNwn8mDJfj-3wpa2w@mail.gmail.com>

Hi,

On Di, 2016-09-20 at 23:12 +0200, Michael Niew?hner wrote:
> 
> 
> Hi guys,
> > 
> > 
> > > 
> > > 
> > > Hi All
> > > ?
> > > Adding Vivek Gautam.
> > > ?
> > > On 29 August 2016 at 16:35, Michael Niew?hner
> > <linux@mniewoehner.de>
> > > 
> > > 
> > > wrote:
> > > > 
> > > > 
> > > > > 
> > > > > 
> > > > > ?
> > > > > Hi Mathias,
> > > > > On Mo, 2016-08-29 at 13:59 +0300, Mathias Nyman wrote:
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > ?
> > > > > > > On 29.08.2016 10:28, Felipe Balbi wrote:
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > ?
> > > > > > > > > ?
> > > > > > > > > ?
> > > > > > > > > Hi,
> > > > > > > > > ?
> > > > > > > > > Michael Niew?hner <linux@mniewoehner.de> writes:
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > ?
> > > > > > > > > > > ?
> > > > > > > > > > > [1.] One line summary of the problem:
> > > > > > > > > > > DWC3 USB 3.0 not working on Odroid-XU4 with
> > > > > > Exynos 5422
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > ?
> > > > > > > > > > > [2.] Full description of the problem/report:
> > > > > > > > > > > No usb 3.0 devices are being detected when
> > > > > > attached while USB
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 2.0
> > > > > > > > > > > devices work on the same port.
> > > > > > > > > > > USB 3.0 works after applying patches [9.1] and
> > > > > > [9.2], but
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > seems
> > > > > > > > > > > to be
> > > > > > > > > > > buggy. The usb hub is redetected every time an
> > > > > > usb device is
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > attached.
> > > > > > > > > ?
> > > > > > > > > dwc3 is host, which means it's actually XHCI :-)
> > > > > > > > > ?
> > > > > > > > > Adding Mathias
> > > > > > > > > ?
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > ?
> > > > > > > > > > > ?
> > > > > > > > > > > dmesg:
> > > > > > > > > > > [??192.287080] usb 3-1.2: USB disconnect, device
> > > > > > number 7
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > [??210.370699] hub 3-1:1.0: hub_ext_port_status
> > > > > > failed (err =
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > -71)
> > > > > > > ?
> > > > > > > Looks like the hub GetPortStatus request fails with
> > > > protocol
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > error.
> > > > > > > ?
> > > > > > > Reading xhci root hub port status is mostly just register
> > > > reads
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > and
> > > > > > > writes. It
> > > > > > > shouldn't include any actual transfers that could return
> > > > -EPROTO
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > ?
> > > > > > > So this is not the root hub? but a external or integrated
> > > > on your
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > board, right?
> > > > > > > ?
> > > > > > > The protocol error -71 is returned at transfer errors or
> > > > if
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > device
> > > > > > > stalled.
> > > > > > > ?
> > > > > > > Adding more xhci debugging options could show something:
> > > > > > > echo -n 'module xhci_hcd =p' >
> > > > > > > /sys/kernel/debug/dynamic_debug/control
> > > > > > > ?
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > ?
> > > > > > > > > ?
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > ?
> > > > > > > > > > > ?
> > > > > > > > > > > [9.] Other notes, patches, fixes, workarounds:
> > > > > > > > > > > [9.1] https://lkml.org/lkml/2014/4/28/234
> > > > > > > > > > > [9.2] https://lkml.org/lkml/2015/2/2/259
> > > > > > > ?
> > > > > > > The additional patches that makes things somehow work
> > > > involve
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > tuning
> > > > > > > the PHY,
> > > > > > > this is an area I'm not familiar with
> > > > > > > ?
> > > > > > > -Mathias
> > > > > > > ?
> > > > > ?
> > > > > ?
> > > > > I'm sorry, I should have said that this is the dmesg output
> > > with
> > > > 
> > > > 
> > > > > 
> > > > > 
> > > > > the
> > > > > patches applied. Without them there is no output at all when
> > > I
> > > > 
> > > > 
> > > > > 
> > > > > 
> > > > > attach
> > > > > an usb 3.0 device.
> > > > > ?
> > > > > Michael
> > > ?
> > > There are two dwc3 ports in the SoC : one for Gbit Ethernet
> > another
> > > 
> > > 
> > > one for on-board GL3521 USB 3.0 hub controller.
> > > ?
> > > 3.10.x kernel
> > > odroid at odroid:~$ lsusb -t
> > > /:??Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 5000M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Vendor Specific Class,
> > > Driver=r8152, 5000M
> > > /:??Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 480M
> > > 
> > > 
> > > /:??Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 5000M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 5000M
> > > /:??Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 480M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 480M
> > > /:??Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p,
> > 12M
> > > 
> > > 
> > > /:??Bus 01.Port 1: Dev 1, Class=root_hub, Driver=s5p-ehci/3p,
> > 480M
> > > 
> > > 
> > > ?
> > > 4.x kernel
> > > odroid at odroid:~$ lsusb -t
> > > /:??Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 5000M
> > > 
> > > 
> > > /:??Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 480M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Vendor Specific Class,
> > > Driver=r8152, 480M
> > > /:??Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 5000M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 5000M
> > > ?????????|__ Port 1: Dev 3, If 0, Class=Mass Storage, Driver=usb-
> > > storage, 5000M
> > > ?????????|__ Port 2: Dev 4, If 0, Class=Mass Storage, Driver=usb-
> > > storage, 5000M
> > > /:??Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 480M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 480M
> > > /:??Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p,
> > 12M
> > > 
> > > 
> > > /:??Bus 01.Port 1: Dev 1, Class=root_hub, Driver=exynos-ehci/3p,
> > 480M
> > > 
> > > 
> > > ?
> > > I fell that Ethernet driver r8152 is not getting registered to
> > > xhci-hcd to bus port 06
> > > which lead to other ports to miss configure, some time the
> > Ethernet
> > > 
> > > 
> > > port get register to bus port 04
> > > ?
> > > Their is also a possibility that all the port are not getting
> > proper
> > > 
> > > 
> > > power from the S2MPS11 PMIC
> > > and possible some reset of the phy is needed to reconfigure the
> > > exynos
> > > USB HSIC controller.
> > > ?
> > > Best Regards
> > > -Anand Moon
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-
> > > samsung-soc" in
> > > the body of a message to majordomo at vger.kernel.org
> > > More majordomo info at??http://vger.kernel.org/majordomo-
> > info.html
> ?
> ?
> today I've tested v4.8-rc7 (without the patches above). The USB 3.0
> ports have stopped working completely for me. Neither USB 2.0 nor USB
> 3.0 are being detected. The Ethernet port does not work, too. The
> USB-2.0-only Port works.
> ?
> There are some failures in the dmesg log:
> ...
> [???15.096251] 12100000.phy supply vbus not found, using dummy
> regulator
> ...
> [???19.642578] usb usb5-port1: connect-debounce failed
> ?
> ?
> dmesg:


looks like I forgot to append the dmesg in my last mail. Sorry about
that.
The problem is also present in v4.8. Let me know if you need more
information.

Michael


dmesg v4.8 without any additional patches:

[????0.000000] Booting Linux on physical CPU 0x100
[????0.000000] Linux version 4.8.0 (c0d3 at z3r0) (gcc version 5.3.1
20160412 (Linaro GCC 5.3-2016.05) ) #3 SMP Mon Oct 3 14:11:40 CEST 2016
[????0.000000] CPU: ARMv7 Processor [410fc073] revision 3 (ARMv7),
cr=10c5387d
[????0.000000] CPU: div instructions available: patching division code
[????0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing
instruction cache
[????0.000000] OF: fdt:Machine model: Hardkernel Odroid XU4
[????0.000000] Reserved memory: created DMA memory pool at 0xbe200000,
size 8 MiB
[????0.000000] OF: reserved mem: initialized node region_mfc_right,
compatible id shared-dma-pool
[????0.000000] Reserved memory: created DMA memory pool at 0xbd200000,
size 16 MiB
[????0.000000] OF: reserved mem: initialized node region_mfc_left,
compatible id shared-dma-pool
[????0.000000] Memory policy: Data cache writealloc
[????0.000000] Samsung CPU ID: 0xe5422001
[????0.000000] On node 0 totalpages: 512512
[????0.000000] free_area_init_node: node 0, pgdat c0c81840,
node_mem_map eee52000
[????0.000000]???Normal zone: 1728 pages used for memmap
[????0.000000]???Normal zone: 0 pages reserved
[????0.000000]???Normal zone: 196608 pages, LIFO batch:31
[????0.000000]???HighMem zone: 315904 pages, LIFO batch:31
[????0.000000] Running under secure firmware.
[????0.000000] percpu: Embedded 15 pages/cpu @eeda1000 s30272 r8192
d22976 u61440
[????0.000000] pcpu-alloc: s30272 r8192 d22976 u61440 alloc=15*4096
[????0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0] 4 [0] 5 [0] 6
[0] 7?
[????0.000000] Built 1 zonelists in Zone order, mobility grouping
on.??Total pages: 510784
[????0.000000] Kernel command line: console=ttySAC2,115200n8
root=/dev/mmcblk1p2 rootfstype=ext4 rootwait earlyprintk debug
[????0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[????0.000000] Dentry cache hash table entries: 131072 (order: 7,
524288 bytes)
[????0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144
bytes)
[????0.000000] Memory: 2018124K/2050048K available (7168K kernel code,
618K rwdata, 2064K rodata, 1024K init, 375K bss, 31924K reserved, 0K
cma-reserved, 1263616K highmem)
[????0.000000] Virtual kernel memory layout:
????vector??: 0xffff0000 - 0xffff1000???(???4 kB)
????fixmap??: 0xffc00000 - 0xfff00000???(3072 kB)
????vmalloc : 0xf0800000 - 0xff800000???( 240 MB)
????lowmem??: 0xc0000000 - 0xf0000000???( 768 MB)
????pkmap???: 0xbfe00000 - 0xc0000000???(???2 MB)
????modules : 0xbf000000 - 0xbfe00000???(??14 MB)
??????.text : 0xc0008000 - 0xc0800000???(8160 kB)
??????.init : 0xc0b00000 - 0xc0c00000???(1024 kB)
??????.data : 0xc0c00000 - 0xc0c9aafc???( 619 kB)
???????.bss : 0xc0c9c000 - 0xc0cf9d04???( 376 kB)
[????0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8,
Nodes=1
[????0.000000] Hierarchical RCU implementation.
[????0.000000]??Build-time adjustment of leaf fanout to 32.
[????0.000000]??RCU restricting CPUs from NR_CPUS=16 to nr_cpu_ids=8.
[????0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=32,
nr_cpu_ids=8
[????0.000000] NR_IRQS:16 nr_irqs:16 16
[????0.000000] Switching to timer-based delay loop, resolution 41ns
[????0.000000] clocksource: mct-frc: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 79635851949 ns
[????0.000007] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps
every 89478484971ns
[????0.001695] Console: colour dummy device 80x30
[????0.001738] Calibrating delay loop (skipped), value calculated using
timer frequency.. 48.00 BogoMIPS (lpj=240000)
[????0.001758] pid_max: default: 32768 minimum: 301
[????0.001911] Security Framework initialized
[????0.001928] Yama: becoming mindful.
[????0.001960] AppArmor: AppArmor disabled by boot time parameter
[????0.002017] Mount-cache hash table entries: 2048 (order: 1, 8192
bytes)
[????0.002033] Mountpoint-cache hash table entries: 2048 (order: 1,
8192 bytes)
[????0.003077] CPU: Testing write buffer coherency: ok
[????0.003125] ftrace: allocating 25558 entries in 75 pages
[????0.058307] CPU0: update cpu_capacity 448
[????0.058329] CPU0: thread -1, cpu 0, socket 1, mpidr 80000100
[????0.058499] Setting up static identity map for 0x40100000 -
0x40100058
[????0.059140] ARM CCI driver probed
[????0.059353] Exynos MCPM support installed
[????0.063820] CPU1: update cpu_capacity 448
[????0.063828] CPU1: thread -1, cpu 1, socket 1, mpidr 80000101
[????0.064893] CPU2: update cpu_capacity 448
[????0.064901] CPU2: thread -1, cpu 2, socket 1, mpidr 80000102
[????0.065969] CPU3: update cpu_capacity 448
[????0.065977] CPU3: thread -1, cpu 3, socket 1, mpidr 80000103
[????0.066934] CPU4: update cpu_capacity 1535
[????0.066942] CPU4: thread -1, cpu 0, socket 0, mpidr 80000000
[????0.067971] CPU5: update cpu_capacity 1535
[????0.067978] CPU5: thread -1, cpu 1, socket 0, mpidr 80000001
[????0.068967] CPU6: update cpu_capacity 1535
[????0.068974] CPU6: thread -1, cpu 2, socket 0, mpidr 80000002
[????0.069977] CPU7: update cpu_capacity 1535
[????0.069984] CPU7: thread -1, cpu 3, socket 0, mpidr 80000003
[????0.070124] Brought up 8 CPUs
[????0.070187] SMP: Total of 8 processors activated (384.00 BogoMIPS).
[????0.070198] CPU: WARNING: CPU(s) started in wrong/inconsistent modes
(primary CPU mode 0x1a)
[????0.070207] CPU: This may indicate a broken bootloader or firmware.
[????0.072308] devtmpfs: initialized
[????0.097643] VFP support v0.3: implementor 41 architecture 2 part 30
variant 7 rev 3
[????0.098142] clocksource: jiffies: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 19112604462750000 ns
[????0.098457] pinctrl core: initialized pinctrl subsystem
[????0.101390] NET: Registered protocol family 16
[????0.102209] DMA: preallocated 256 KiB pool for atomic coherent
allocations
[????0.149996] cpuidle: using governor ladder
[????0.189985] cpuidle: using governor menu
[????0.198708] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4
watchpoint registers.
[????0.198724] hw-breakpoint: maximum watchpoint size is 8 bytes.
[????0.199088] Serial: AMBA PL011 UART driver
[????0.208742] iommu: Adding device 11000000.codec to group 0
[????0.244099] iommu: Adding device 14450000.mixer to group 1
[????0.244643] iommu: Adding device 11c00000.rotator to group 2
[????0.254076] iommu: Adding device 13e00000.video-scaler to group 3
[????0.254594] iommu: Adding device 13e10000.video-scaler to group 4
[????0.255107] iommu: Adding device 11f50000.jpeg to group 5
[????0.255613] iommu: Adding device 11f60000.jpeg to group 6
[????0.256003] EXYNOS5420 PMU initialized
[????0.312565] SCSI subsystem initialized
[????0.312938] usbcore: registered new interface driver usbfs
[????0.313031] usbcore: registered new interface driver hub
[????0.313226] usbcore: registered new device driver usb
[????0.314692] s3c-i2c 12c80000.i2c: slave address 0x00
[????0.314712] s3c-i2c 12c80000.i2c: bus frequency set to 65 KHz
[????0.315240] s3c-i2c 12c80000.i2c: i2c-2: S3C I2C adapter
[????0.315709] media: Linux media interface: v0.10
[????0.315777] Linux video capture interface: v2.00
[????0.315874] pps_core: LinuxPPS API ver. 1 registered
[????0.315885] pps_core: Software ver. 5.3.6 - Copyright 2005-2007
Rodolfo Giometti <giometti@linux.it>
[????0.315914] PTP clock support registered
[????0.317980] clocksource: Switched to clocksource mct-frc
[????0.385905] VFS: Disk quotas dquot_6.6.0
[????0.385987] VFS: Dquot-cache hash table entries: 1024 (order 0, 4096
bytes)
[????0.405341] NET: Registered protocol family 2
[????0.406054] TCP established hash table entries: 8192 (order: 3,
32768 bytes)
[????0.406137] TCP bind hash table entries: 8192 (order: 4, 65536
bytes)
[????0.406295] TCP: Hash tables configured (established 8192 bind 8192)
[????0.406360] UDP hash table entries: 512 (order: 2, 16384 bytes)
[????0.406402] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[????0.406639] NET: Registered protocol family 1
[????0.410133] futex hash table entries: 2048 (order: 5, 131072 bytes)
[????0.410271] audit: initializing netlink subsys (disabled)
[????0.410335] audit: type=2000 audit(0.380:1): initialized
[????0.411455] workingset: timestamp_bits=14 max_order=19
bucket_order=5
[????0.422219] zbud: loaded
[????0.428206] Key type asymmetric registered
[????0.428281] bounce: pool size: 64 pages
[????0.428544] Block layer SCSI generic (bsg) driver version 0.4 loaded
(major 247)
[????0.428787] io scheduler noop registered
[????0.428801] io scheduler deadline registered (default)
[????0.429058] io scheduler cfq registered
[????0.439042] dma-pl330 121a0000.pdma: Loaded driver for PL330 DMAC-
241330
[????0.439060] dma-pl330 121a0000.pdma:?????????DBUFF-32x4bytes
Num_Chans-8 Num_Peri-32 Num_Events-32
[????0.443549] dma-pl330 121b0000.pdma: Loaded driver for PL330 DMAC-
241330
[????0.443568] dma-pl330 121b0000.pdma:?????????DBUFF-32x4bytes
Num_Chans-8 Num_Peri-32 Num_Events-32
[????0.444825] dma-pl330 10800000.mdma: Loaded driver for PL330 DMAC-
241330
[????0.444842] dma-pl330 10800000.mdma:?????????DBUFF-64x8bytes
Num_Chans-8 Num_Peri-1 Num_Events-32
[????0.446009] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[????0.448993] Serial: AMBA driver
[????0.449384] 12c00000.serial: ttySAC0 at MMIO 0x12c00000 (irq = 76,
base_baud = 0) is a S3C6400/10
[????0.449890] 12c10000.serial: ttySAC1 at MMIO 0x12c10000 (irq = 77,
base_baud = 0) is a S3C6400/10
[????0.450386] 12c20000.serial: ttySAC2 at MMIO 0x12c20000 (irq = 78,
base_baud = 0) is a S3C6400/10
[????1.007347] random: fast init done
[????1.291220] console [ttySAC2] enabled
[????1.295362] 12c30000.serial: ttySAC3 at MMIO 0x12c30000 (irq = 79,
base_baud = 0) is a S3C6400/10
[????1.304951] [drm] Initialized drm 1.1.0 20060810
[????1.311440] exynos-hdmi 14530000.hdmi: Failed to get supply 'vdd':
-517
[????1.318159] exynos-rot 11c00000.rotator: The exynos rotator is
probed successfully
[????1.324687] exynos-drm-gsc 13e00000.video-scaler: failed to get
system register.
[????1.331876] exynos-drm-gsc 13e00000.video-scaler: drm gsc registered
successfully.
[????1.339273] exynos-drm-gsc 13e10000.video-scaler: failed to get
system register.
[????1.346771] exynos-drm-gsc 13e10000.video-scaler: drm gsc registered
successfully.
[????1.354919] exynos-drm-ipp exynos-drm-ipp: drm ipp registered
successfully.
[????1.367209] libphy: Fixed MDIO Bus: probed
[????1.370337] usbcore: registered new interface driver usb-storage
[????1.376279] mousedev: PS/2 mouse device common for all mice
[????1.400256] vdd_ldo9: Bringing 3300000uV into 3000000-3000000uV
[????1.413855] vddq_mmc2: Bringing 3300000uV into 2800000-2800000uV
[????1.423183] vdd_ldo15: Bringing 3300000uV into 3100000-3100000uV
[????1.436801] vdd_sd: Bringing 3300000uV into 2800000-2800000uV
[????1.499343] s5m-rtc s2mps14-rtc: rtc core: registered s5m-rtc as
rtc0
[????1.512014] exynos-tmu 10060000.tmu: More trip points than supported
by this TMU.
[????1.518056] exynos-tmu 10060000.tmu: 2 trip points should be
configured in polling mode.
[????1.543169] sdhci: Secure Digital Host Controller Interface driver
[????1.547861] sdhci: Copyright(c) Pierre Ossman
[????1.552447] Synopsys Designware Multimedia Card Interface Driver
[????1.558827] dwmmc_exynos 12200000.mmc: IDMAC supports 32-bit address
mode.
[????1.565036] dwmmc_exynos 12200000.mmc: Using internal DMA
controller.
[????1.571462] dwmmc_exynos 12200000.mmc: Version ID is 250a
[????1.576835] dwmmc_exynos 12200000.mmc: DW MMC controller at irq
91,64 bit host data width,64 deep fifo
[????1.586254] dwmmc_exynos 12200000.mmc: Got CD GPIO
[????1.590920] dwmmc_exynos 12200000.mmc: allocated mmc-pwrseq
[????1.628648] mmc_host mmc0: Bus speed (slot 0) = 50000000Hz (slot req
400000Hz, actual 396825HZ div = 63)
[????1.658185] dwmmc_exynos 12200000.mmc: 1 slots initialized
[????1.662422] dwmmc_exynos 12220000.mmc: IDMAC supports 32-bit address
mode.
[????1.669071] dwmmc_exynos 12220000.mmc: Using internal DMA
controller.
[????1.675448] dwmmc_exynos 12220000.mmc: Version ID is 250a
[????1.680869] dwmmc_exynos 12220000.mmc: DW MMC controller at irq
92,64 bit host data width,64 deep fifo
[????1.718450] mmc_host mmc1: Bus speed (slot 0) = 50000000Hz (slot req
400000Hz, actual 396825HZ div = 63)
[????1.748015] dwmmc_exynos 12220000.mmc: 1 slots initialized
[????1.752198] sdhci-pltfm: SDHCI platform and OF driver helper
[????1.758808] ledtrig-cpu: registered to indicate activity on CPUs
[????1.763667] hidraw: raw HID events driver (C) Jiri Kosina
[????1.769408] usbcore: registered new interface driver usbhid
[????1.774539] usbhid: USB HID core driver
[????1.779758] exynos-audss-clk 3810000.audss-clock-controller: setup
completed
[????1.797575] exynos-nocp: new NoC Probe device registered:
10ca1000.nocp
[????1.802874] exynos-nocp: new NoC Probe device registered:
10ca1400.nocp
[????1.807126] mmc_host mmc1: Bus speed (slot 0) = 50000000Hz (slot req
50000000Hz, actual 50000000HZ div = 0)
[????1.807273] mmc1: new high speed SDHC card at address 59b4
[????1.807917] mmcblk1: mmc1:59b4 USDU1 14.7 GiB?
[????1.808982]??mmcblk1: p1 p2
[????1.831801] exynos-nocp: new NoC Probe device registered:
10ca1800.nocp
[????1.838398] exynos-nocp: new NoC Probe device registered:
10ca1c00.nocp
[????1.846409] NET: Registered protocol family 10
[????1.850110] mip6: Mobile IPv6
[????1.852315] NET: Registered protocol family 17
[????1.856737] mpls_gso: MPLS GSO support
[????1.860858] ThumbEE CPU extension supported.
[????1.864710] Registering SWP/SWPB emulation handler
[????1.870156] registered taskstats version 1
[????1.873593] zswap: loaded using pool lzo/zbud
[????1.882872] [drm] Exynos DRM: using 14450000.mixer device for DMA
mapping operations
[????1.889454] exynos-drm exynos-drm: bound 14450000.mixer (ops
0xc086e904)
[????1.896004] exynos-drm exynos-drm: bound 14530000.hdmi (ops
0xc086ead4)
[????1.902413] [drm] Supports vblank timestamp caching Rev 2
(21.10.2013).
[????1.908997] [drm] No driver support for vblank timestamp query.
[????1.914979] [drm] Initialized exynos 1.0.0 20110530 on minor 0
[????1.921516] s3c-rtc 101e0000.rtc: rtc disabled, re-enabling
[????1.926279] s3c-rtc 101e0000.rtc: warning: invalid RTC value so
initializing it
[????1.933578] rtc rtc1: invalid alarm value: 1900-1-2 0:0:0
[????1.939095] s3c-rtc 101e0000.rtc: rtc core: registered s3c as rtc1
[????1.946585] exynos-bus: new bus device registered: soc:bus_wcore (
84000 KHz ~ 400000 KHz)
[????1.954159] exynos-bus: new bus device registered: soc:bus_noc (
67000 KHz ~ 100000 KHz)
[????1.962043] exynos-bus: new bus device registered: soc:bus_fsys_apb
(100000 KHz ~ 200000 KHz)
[????1.970370] exynos-bus: new bus device registered: soc:bus_fsys
(100000 KHz ~ 200000 KHz)
[????1.978708] exynos-bus: new bus device registered: soc:bus_fsys2 (
75000 KHz ~ 150000 KHz)
[????1.987052] exynos-bus: new bus device registered: soc:bus_mfc (
96000 KHz ~ 333000 KHz)
[????1.995093] exynos-bus: new bus device registered: soc:bus_gen (
89000 KHz ~ 267000 KHz)
[????2.003458] exynos-bus: new bus device registered: soc:bus_peri (
67000 KHz ~??67000 KHz)
[????2.011853] devfreq soc:bus_wcore: Couldn't update frequency
transition information.
[????2.012120] exynos-bus: new bus device registered: soc:bus_g2d (
84000 KHz ~ 333000 KHz)
[????2.012845] exynos-bus: new bus device registered: soc:bus_g2d_acp (
67000 KHz ~ 267000 KHz)
[????2.013561] exynos-bus: new bus device registered: soc:bus_jpeg (
75000 KHz ~ 300000 KHz)
[????2.014273] exynos-bus: new bus device registered: soc:bus_jpeg_apb
( 84000 KHz ~ 167000 KHz)
[????2.014866] exynos-bus: new bus device registered:
soc:bus_disp1_fimd (120000 KHz ~ 200000 KHz)
[????2.015523] exynos-bus: new bus device registered: soc:bus_disp1
(120000 KHz ~ 300000 KHz)
[????2.016166] exynos-bus: new bus device registered:
soc:bus_gscl_scaler (150000 KHz ~ 300000 KHz)
[????2.016941] exynos-bus: new bus device registered: soc:bus_mscl (
84000 KHz ~ 400000 KHz)
[????2.019383] Power domain power-domain at 10044120 disable failed
[????2.026352] s5m-rtc s2mps14-rtc: setting system clock to 2000-01-01
00:00:04 UTC (946684804)
[????2.044135] PM: Hibernation image not present or could not be
loaded.
[????2.113332] EXT4-fs (mmcblk1p2): mounted filesystem with ordered
data mode. Opts: (null)
[????2.120019] VFS: Mounted root (ext4 filesystem) readonly on device
179:2.
[????2.127364] Freeing unused kernel memory: 1024K (c0b00000 -
c0c00000)
[????2.359928] systemd[1]: Mounting cgroup to /sys/fs/cgroup/cpuset of
type cgroup with options cpuset.
[????2.419442] systemd[1]: Mounting cgroup to
/sys/fs/cgroup/cpu,cpuacct of type cgroup with options cpu,cpuacct.
[????2.428599] systemd[1]: Mounting cgroup to /sys/fs/cgroup/blkio of
type cgroup with options blkio.
[????2.438504] systemd[1]: Mounting cgroup to /sys/fs/cgroup/memory of
type cgroup with options memory.
[????2.452714] systemd[1]: Mounting cgroup to /sys/fs/cgroup/devices of
type cgroup with options devices.
[????2.461081] systemd[1]: Mounting cgroup to /sys/fs/cgroup/freezer of
type cgroup with options freezer.
[????2.470341] systemd[1]: Mounting cgroup to
/sys/fs/cgroup/net_cls,net_prio of type cgroup with options
net_cls,net_prio.
[????2.481222] systemd[1]: Mounting cgroup to /sys/fs/cgroup/perf_event
of type cgroup with options perf_event.
[????2.491343] systemd[1]: systemd 215 running in system mode. (+PAM
+AUDIT +SELINUX +IMA +SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ -SECCOMP
-APPARMOR)
[????2.503894] systemd[1]: Detected architecture 'arm'.
[????2.733937] systemd-getty-generator[111]: Automatically adding
serial getty for /dev/ttySAC2.
[????2.738699] systemd-fstab-generator[112]: Parsing /etc/fstab
[????2.744149] systemd-rc-local-generator[120]: Automatically adding
rc-local.service.
[????2.745372] systemd-default-display-manager-generator[114]: No
/etc/X11/default-display-manager file, nothing to generate
[????2.746322] systemd-fstab-generator[112]: Found entry
what=/dev/mmcblk1p2 where=/ type=ext4
[????2.813116] systemd-gpt-auto-generator[117]: Root device
/dev/mmcblk1.
[????2.813603] systemd-sysv-generator[116]: Looking for unit files in
(higher priority first):
[????2.813612] systemd-sysv-generator[116]:?????/etc/systemd/system
[????2.813620] systemd-sysv-generator[116]:?????/run/systemd/system
[????2.813628] systemd-sysv-
generator[116]:?????/usr/local/lib/systemd/system
[????2.813635] systemd-sysv-generator[116]:?????/lib/systemd/system
[????2.813642] systemd-sysv-generator[116]:?????/usr/lib/systemd/system
[????2.813681] systemd-sysv-generator[116]: Looking for SysV init
scripts in:
[????2.813689] systemd-sysv-generator[116]:?????/etc/init.d
[????2.813699] systemd-sysv-generator[116]: Looking for SysV rcN.d
links in:
[????2.813706] systemd-sysv-generator[116]:?????/etc
[????2.815816] systemd-fstab-generator[112]: Found entry
what=/dev/mmcblk1p1 where=/boot type=vfat
[????2.819599] systemd-fstab-generator[112]: Checking was requested for
/dev/mmcblk1p1, but fsck.vfat does not exist: No such file or directory
[????2.874868] systemd-sysv-ge: 77 output lines suppressed due to
ratelimiting
[????2.959658] systemd-gpt-auto-generator[117]: Not a GPT partition
table, ignoring.
[????3.832303] systemd-journald[135]: Fixed max_use=98.5M
max_size=12.3M min_size=4.0M keep_free=147.8M
[????3.845615] systemd-journald[135]: Reserving 22435 entries in hash
table.
[????3.852075] systemd-journald[135]: Vacuuming...
[????3.855454] systemd-journald[135]: Vacuuming done, freed 0 bytes
[????3.861956] systemd-journald[135]: Flushing /dev/kmsg...
[????3.871445] systemd-journald[135]: Compressed data object 537 -> 288
[????3.899706] systemd-journald[135]: systemd-journald running as pid
135
[????4.454812] systemd-udevd[147]: starting version 215
[????4.611192] s5p-secss 10830000.sss: s5p-sss driver registered
[????4.626630] 12100000.phy supply vbus not found, using dummy
regulator
[????4.631925] 12100000.phy supply vbus-boost not found, using dummy
regulator
[????4.633739] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI)
Driver
[????4.638239] ehci-exynos: EHCI EXYNOS driver
[????4.642228] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[????4.646782] ohci-exynos: OHCI EXYNOS driver
[????4.660779] 12130000.phy supply vbus not found, using dummy
regulator
[????4.669297] exynos-ohci 12120000.usb: USB Host Controller
[????4.669734] exynos-ehci 12110000.usb: EHCI Host Controller
[????4.670063] exynos-ehci 12110000.usb: new USB bus registered,
assigned bus number 1
[????4.670250] exynos-ehci 12110000.usb: irq 89, io mem 0x12110000
[????4.693595] exynos-ohci 12120000.usb: new USB bus registered,
assigned bus number 2
[????4.698079] exynos-ehci 12110000.usb: USB 2.0 started, EHCI 1.00
[????4.698464] usb usb1: New USB device found, idVendor=1d6b,
idProduct=0002
[????4.698472] usb usb1: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.698481] usb usb1: Product: EHCI Host Controller
[????4.698489] usb usb1: Manufacturer: Linux 4.8.0 ehci_hcd
[????4.698496] usb usb1: SerialNumber: 12110000.usb
[????4.699299] hub 1-0:1.0: USB hub found
[????4.699350] hub 1-0:1.0: 3 ports detected
[????4.742843] exynos-ohci 12120000.usb: irq 89, io mem 0x12120000
[????4.822232] usb usb2: New USB device found, idVendor=1d6b,
idProduct=0001
[????4.827543] usb usb2: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.834815] usb usb2: Product: USB Host Controller
[????4.839569] usb usb2: Manufacturer: Linux 4.8.0 ohci_hcd
[????4.839580] usb usb2: SerialNumber: 12120000.usb
[????4.840406] hub 2-0:1.0: USB hub found
[????4.840468] hub 2-0:1.0: 3 ports detected
[????4.841589] 12500000.phy supply vbus not found, using dummy
regulator
[????4.841673] 12500000.phy supply vbus-boost not found, using dummy
regulator
[????4.842135] exynos-dwc3 soc:usb3-0: no suspend clk specified
[????4.843822] usb_phy_generic.0.auto supply vcc not found, using dummy
regulator
[????4.844425] usb_phy_generic.1.auto supply vcc not found, using dummy
regulator
[????4.845346] exynos-dwc3 soc:usb3-1: no suspend clk specified
[????4.848262] usb_phy_generic.2.auto supply vcc not found, using dummy
regulator
[????4.848573] usb_phy_generic.3.auto supply vcc not found, using dummy
regulator
[????4.873852] xhci-hcd xhci-hcd.4.auto: xHCI Host Controller
[????4.874040] xhci-hcd xhci-hcd.4.auto: new USB bus registered,
assigned bus number 3
[????4.874254] xhci-hcd xhci-hcd.4.auto: hcc params 0x0220f04c hci
version 0x100 quirks 0x00010010
[????4.874296] xhci-hcd xhci-hcd.4.auto: irq 135, io mem 0x12000000
[????4.874566] usb usb3: New USB device found, idVendor=1d6b,
idProduct=0002
[????4.874571] usb usb3: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.874575] usb usb3: Product: xHCI Host Controller
[????4.874579] usb usb3: Manufacturer: Linux 4.8.0 xhci-hcd
[????4.874583] usb usb3: SerialNumber: xhci-hcd.4.auto
[????4.875065] hub 3-0:1.0: USB hub found
[????4.875105] hub 3-0:1.0: 1 port detected
[????4.875475] xhci-hcd xhci-hcd.4.auto: xHCI Host Controller
[????4.875623] xhci-hcd xhci-hcd.4.auto: new USB bus registered,
assigned bus number 4
[????4.875743] usb usb4: We don't know the algorithms for LPM for this
host, disabling LPM.
[????4.875926] usb usb4: New USB device found, idVendor=1d6b,
idProduct=0003
[????4.875930] usb usb4: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.875934] usb usb4: Product: xHCI Host Controller
[????4.875938] usb usb4: Manufacturer: Linux 4.8.0 xhci-hcd
[????4.875942] usb usb4: SerialNumber: xhci-hcd.4.auto
[????4.876431] hub 4-0:1.0: USB hub found
[????4.876471] hub 4-0:1.0: 1 port detected
[????4.876897] xhci-hcd xhci-hcd.5.auto: xHCI Host Controller
[????4.877063] xhci-hcd xhci-hcd.5.auto: new USB bus registered,
assigned bus number 5
[????4.877266] xhci-hcd xhci-hcd.5.auto: hcc params 0x0220f04c hci
version 0x100 quirks 0x00010010
[????4.877299] xhci-hcd xhci-hcd.5.auto: irq 136, io mem 0x12400000
[????4.877525] usb usb5: New USB device found, idVendor=1d6b,
idProduct=0002
[????4.877530] usb usb5: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.877534] usb usb5: Product: xHCI Host Controller
[????4.877538] usb usb5: Manufacturer: Linux 4.8.0 xhci-hcd
[????4.877541] usb usb5: SerialNumber: xhci-hcd.5.auto
[????4.878099] hub 5-0:1.0: USB hub found
[????4.878138] hub 5-0:1.0: 1 port detected
[????4.878494] xhci-hcd xhci-hcd.5.auto: xHCI Host Controller
[????4.878654] xhci-hcd xhci-hcd.5.auto: new USB bus registered,
assigned bus number 6
[????4.878769] usb usb6: We don't know the algorithms for LPM for this
host, disabling LPM.
[????4.878947] usb usb6: New USB device found, idVendor=1d6b,
idProduct=0003
[????4.878952] usb usb6: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.878955] usb usb6: Product: xHCI Host Controller
[????4.878959] usb usb6: Manufacturer: Linux 4.8.0 xhci-hcd
[????4.878963] usb usb6: SerialNumber: xhci-hcd.5.auto
[????4.879480] hub 6-0:1.0: USB hub found
[????4.879520] hub 6-0:1.0: 1 port detected
[????5.304287] dma-pl330 3880000.adma: Loaded driver for PL330 DMAC-
241330
[????5.309497] dma-pl330 3880000.adma:??DBUFF-4x8bytes Num_Chans-6
Num_Peri-16 Num_Events-6
[????5.459652] EXT4-fs (mmcblk1p2): re-mounted. Opts: (null)
[????5.673544] FAT-fs (mmcblk1p1): utf8 is not a recommended IO charset
for FAT filesystems, filesystem will be case sensitive!
[????5.701124] FAT-fs (mmcblk1p1): Volume was not properly unmounted.
Some data may be corrupt. Please run fsck.
[????6.087658] systemd-journald[135]: Received request to flush runtime
journal from PID 1
[????6.095519] systemd-journald[135]: Vacuuming...
[????6.100071] systemd-journald[135]: Vacuuming done, freed 0 bytes
[????7.335312] RPC: Registered named UNIX socket transport module.
[????7.339802] RPC: Registered udp transport module.
[????7.344429] RPC: Registered tcp transport module.
[????7.349165] RPC: Registered tcp NFSv4.1 backchannel transport
module.
[????7.370961] FS-Cache: Loaded
[????7.406152] FS-Cache: Netfs 'nfs' registered for caching
[????7.453960] Installing knfsd (copyright (C) 1996 okir at monad.swb.de).
[????8.160157] random: crng init done
[????9.170682] usb usb5-port1: connect-debounce failed
[????9.170698] usb usb3-port1: connect-debounce failed

^ permalink raw reply

* [PATCH v2 4/4] ARM: dts: am4372: add DMA properties for tscadc
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003130318.12591-1-mugunthanvnm@ti.com>

Add DMA properties for tscadc

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 arch/arm/boot/dts/am4372.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 0fadae5..6094d17 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -867,6 +867,8 @@
 			clocks = <&adc_tsc_fck>;
 			clock-names = "fck";
 			status = "disabled";
+			dmas = <&edma 53 0>, <&edma 57 0>;
+			dma-names = "fifo0", "fifo1";
 
 			tsc {
 				compatible = "ti,am3359-tsc";
-- 
2.10.0.372.g6fe1b14

^ permalink raw reply related

* [PATCH v2 3/4] ARM: dts: am33xx: add DMA properties for tscadc
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003130318.12591-1-mugunthanvnm@ti.com>

Add DMA properties for tscadc

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 arch/arm/boot/dts/am33xx.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 98748c6..6d607b8 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -917,6 +917,8 @@
 			interrupts = <16>;
 			ti,hwmods = "adc_tsc";
 			status = "disabled";
+			dmas = <&edma 53 0>, <&edma 57 0>;
+			dma-names = "fifo0", "fifo1";
 
 			tsc {
 				compatible = "ti,am3359-tsc";
-- 
2.10.0.372.g6fe1b14

^ permalink raw reply related

* [PATCH v2 2/4] drivers: iio: ti_am335x_adc: add dma support
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003130318.12591-1-mugunthanvnm@ti.com>

This patch adds the required pieces to ti_am335x_adc driver for
DMA support

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/iio/adc/ti_am335x_adc.c      | 145 ++++++++++++++++++++++++++++++++++-
 include/linux/mfd/ti_am335x_tscadc.h |   7 ++
 2 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index c3cfacca..7e250be 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -30,10 +30,28 @@
 #include <linux/iio/buffer.h>
 #include <linux/iio/kfifo_buf.h>
 
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+
+#define DMA_BUFFER_SIZE		SZ_2K
+
+struct tiadc_dma {
+	struct dma_slave_config	conf;
+	struct dma_chan		*chan;
+	dma_addr_t		addr;
+	dma_cookie_t		cookie;
+	u8			*buf;
+	int			current_period;
+	int			period_size;
+	u8			fifo_thresh;
+};
+
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
+	struct tiadc_dma dma;
 	struct mutex fifo1_lock; /* to protect fifo access */
 	int channels;
+	int total_ch_enabled;
 	u8 channel_line[8];
 	u8 channel_step[8];
 	int buffer_en_ch_steps;
@@ -198,6 +216,67 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
 	return IRQ_HANDLED;
 }
 
+static void tiadc_dma_rx_complete(void *param)
+{
+	struct iio_dev *indio_dev = param;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
+	u8 *data;
+	int i;
+
+	data = dma->buf + dma->current_period * dma->period_size;
+	dma->current_period = 1 - dma->current_period; /* swap the buffer ID */
+
+	for (i = 0; i < dma->period_size; i += indio_dev->scan_bytes) {
+		iio_push_to_buffers(indio_dev, data);
+		data += indio_dev->scan_bytes;
+	}
+}
+
+static int tiadc_start_dma(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
+	struct dma_async_tx_descriptor *desc;
+
+	dma->current_period = 0; /* We start to fill period 0 */
+	/*
+	 * Make the fifo thresh as the multiple of total number of
+	 * channels enabled, so make sure that cyclic DMA period
+	 * length is also a multiple of total number of channels
+	 * enabled. This ensures that no invalid data is reported
+	 * to the stack via iio_push_to_buffers().
+	 */
+	dma->fifo_thresh = rounddown(FIFO1_THRESHOLD + 1,
+				     adc_dev->total_ch_enabled) - 1;
+	/* Make sure that period length is multiple of fifo thresh level */
+	dma->period_size = rounddown(DMA_BUFFER_SIZE / 2,
+				    (dma->fifo_thresh + 1) * sizeof(u16));
+
+	dma->conf.src_maxburst = dma->fifo_thresh + 1;
+	dmaengine_slave_config(dma->chan, &dma->conf);
+
+	desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
+					 dma->period_size * 2,
+					 dma->period_size, DMA_DEV_TO_MEM,
+					 DMA_PREP_INTERRUPT);
+	if (!desc)
+		return -EBUSY;
+
+	desc->callback = tiadc_dma_rx_complete;
+	desc->callback_param = indio_dev;
+
+	dma->cookie = dmaengine_submit(desc);
+
+	dma_async_issue_pending(dma->chan);
+
+	tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
+	tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
+	tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
+
+	return 0;
+}
+
 static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
@@ -218,20 +297,30 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
 static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
+	unsigned int irq_enable;
 	unsigned int enb = 0;
 	u8 bit;
 
 	tiadc_step_config(indio_dev);
-	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels)
+	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) {
 		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
+		adc_dev->total_ch_enabled++;
+	}
 	adc_dev->buffer_en_ch_steps = enb;
 
+	if (dma->chan)
+		tiadc_start_dma(indio_dev);
+
 	am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
 
 	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
 				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
-	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
-				| IRQENB_FIFO1OVRRUN);
+
+	irq_enable = IRQENB_FIFO1OVRRUN;
+	if (!dma->chan)
+		irq_enable |= IRQENB_FIFO1THRES;
+	tiadc_writel(adc_dev,  REG_IRQENABLE, irq_enable);
 
 	return 0;
 }
@@ -239,12 +328,18 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
 static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
 	int fifo1count, i, read;
 
 	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
 				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
 	adc_dev->buffer_en_ch_steps = 0;
+	adc_dev->total_ch_enabled = 0;
+	if (dma->chan) {
+		tiadc_writel(adc_dev, REG_DMAENABLE_CLEAR, 0x2);
+		dmaengine_terminate_async(dma->chan);
+	}
 
 	/* Flush FIFO of leftover data in the time it takes to disable adc */
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
@@ -430,6 +525,38 @@ static const struct iio_info tiadc_info = {
 	.driver_module = THIS_MODULE,
 };
 
+static int tiadc_request_dma(struct platform_device *pdev,
+			     struct tiadc_device *adc_dev)
+{
+	struct tiadc_dma	*dma = &adc_dev->dma;
+	dma_cap_mask_t		mask;
+
+	/* Default slave configuration parameters */
+	dma->conf.direction = DMA_DEV_TO_MEM;
+	dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_CYCLIC, mask);
+
+	/* Get a channel for RX */
+	dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
+	if (!dma->chan)
+		return -ENODEV;
+
+	/* RX buffer */
+	dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
+				      &dma->addr, GFP_KERNEL);
+	if (!dma->buf)
+		goto err;
+
+	return 0;
+err:
+	dma_release_channel(dma->chan);
+
+	return -ENOMEM;
+}
+
 static int tiadc_parse_dt(struct platform_device *pdev,
 			  struct tiadc_device *adc_dev)
 {
@@ -512,8 +639,14 @@ static int tiadc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, indio_dev);
 
+	err = tiadc_request_dma(pdev, adc_dev);
+	if (err && err != -ENODEV)
+		goto err_dma;
+
 	return 0;
 
+err_dma:
+	iio_device_unregister(indio_dev);
 err_buffer_unregister:
 	tiadc_iio_buffered_hardware_remove(indio_dev);
 err_free_channels:
@@ -525,8 +658,14 @@ static int tiadc_remove(struct platform_device *pdev)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
 	u32 step_en;
 
+	if (dma->chan) {
+		dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
+				  dma->buf, dma->addr);
+		dma_release_channel(dma->chan);
+	}
 	iio_device_unregister(indio_dev);
 	tiadc_iio_buffered_hardware_remove(indio_dev);
 	tiadc_channels_remove(indio_dev);
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index e45a208..b9a53e0 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -23,6 +23,8 @@
 #define REG_IRQENABLE		0x02C
 #define REG_IRQCLR		0x030
 #define REG_IRQWAKEUP		0x034
+#define REG_DMAENABLE_SET	0x038
+#define REG_DMAENABLE_CLEAR	0x03c
 #define REG_CTRL		0x040
 #define REG_ADCFSM		0x044
 #define REG_CLKDIV		0x04C
@@ -36,6 +38,7 @@
 #define REG_FIFO0THR		0xE8
 #define REG_FIFO1CNT		0xF0
 #define REG_FIFO1THR		0xF4
+#define REG_DMA1REQ		0xF8
 #define REG_FIFO0		0x100
 #define REG_FIFO1		0x200
 
@@ -126,6 +129,10 @@
 #define FIFOREAD_DATA_MASK (0xfff << 0)
 #define FIFOREAD_CHNLID_MASK (0xf << 16)
 
+/* DMA ENABLE/CLEAR Register */
+#define DMA_FIFO0		BIT(0)
+#define DMA_FIFO1		BIT(1)
+
 /* Sequencer Status */
 #define SEQ_STATUS BIT(5)
 #define CHARGE_STEP		0x11
-- 
2.10.0.372.g6fe1b14

^ permalink raw reply related

* [PATCH v2 1/4] mfd: ti_am335x_tscadc: store physical address
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003130318.12591-1-mugunthanvnm@ti.com>

store the physical address of the device in its priv to use it
for DMA addressing in the client drivers.

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/mfd/ti_am335x_tscadc.c       | 1 +
 include/linux/mfd/ti_am335x_tscadc.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index c8f027b..0f3fab4 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -183,6 +183,7 @@ static	int ti_tscadc_probe(struct platform_device *pdev)
 		tscadc->irq = err;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tscadc->tscadc_phys_base = res->start;
 	tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(tscadc->tscadc_base))
 		return PTR_ERR(tscadc->tscadc_base);
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 7f55b8b..e45a208 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -155,6 +155,7 @@ struct ti_tscadc_dev {
 	struct device *dev;
 	struct regmap *regmap;
 	void __iomem *tscadc_base;
+	phys_addr_t tscadc_phys_base;
 	int irq;
 	int used_cells;	/* 1-2 */
 	int tsc_wires;
-- 
2.10.0.372.g6fe1b14

^ permalink raw reply related

* [PATCH v2 0/4] Add DMA support for ti_am335x_adc driver
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel

The ADC has a 64 work depth fifo length which holds the ADC data
till the CPU reads. So when a user program needs a large ADC data
to operate on, then it has to do multiple reads to get its
buffer. Currently if the application asks for 4 samples per
channel with all 8 channels are enabled, kernel can provide only
3 samples per channel when all 8 channels are enabled (logs at
[1]). So with DMA support user can request for large number of
samples at a time (logs at [2]).

Tested the patch on AM437x-gp-evm and AM335x Boneblack with the
patch [3] to enable ADC and pushed a branch for testing [4]

Changes from Initial version:
* Changed DMA api from dma_request_slave_channel_compat() to
  dma_request_chan()
* Changed variable names to have more clear information as per
  comments from Peter.

[1] - http://pastebin.ubuntu.com/23211490/
[2] - http://pastebin.ubuntu.com/23269792/
[3] - http://pastebin.ubuntu.com/23211494/
[4] - git://git.ti.com/~mugunthanvnm/ti-linux-kernel/linux.git iio-dma-v2

Mugunthan V N (4):
  mfd: ti_am335x_tscadc: store physical address
  drivers: iio: ti_am335x_adc: add dma support
  ARM: dts: am33xx: add DMA properties for tscadc
  ARM: dts: am4372: add DMA properties for tscadc

 arch/arm/boot/dts/am33xx.dtsi        |   2 +
 arch/arm/boot/dts/am4372.dtsi        |   2 +
 drivers/iio/adc/ti_am335x_adc.c      | 145 ++++++++++++++++++++++++++++++++++-
 drivers/mfd/ti_am335x_tscadc.c       |   1 +
 include/linux/mfd/ti_am335x_tscadc.h |   8 ++
 5 files changed, 155 insertions(+), 3 deletions(-)

-- 
2.10.0.372.g6fe1b14

^ permalink raw reply

* [PATCH] drm/sun4i: Check that the plane coordinates are not negative
From: Maxime Ripard @ 2016-10-03 12:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160930180826.169e3daf@bbrezillon>

Hi Boris,

On Fri, Sep 30, 2016 at 06:08:26PM +0200, Boris Brezillon wrote:
> On Fri, 30 Sep 2016 16:33:20 +0200
> Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> 
> > Our planes cannot be set at negative coordinates. Make sure we reject such
> > configuration.
> > 
> > Reported-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_layer.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
> > index f0035bf5efea..f5463c4c2cde 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
> > @@ -29,6 +29,9 @@ struct sun4i_plane_desc {
> >  static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
> >  					    struct drm_plane_state *state)
> >  {
> > +	if ((state->crtc_x < 0) || (state->crtc_y < 0))
> > +		return -EINVAL;
> > +
> 
> Hm, I think it's a perfectly valid use case from the DRM framework and
> DRM user PoV: you may want to place your plane at a negative CRTC
> offset (which means part of the plane will be hidden).
> 
> Maybe I'm wrong, but it seems you can support that by adapting the
> start address of your framebuffer pointer and the layer size.

Indeed, that would probably work. This is even somewhat what we've
been using to implement the VGA hack we use on the CHIP.

Can you send that patch?

Thanks,
Maxime

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

^ permalink raw reply

* [PATCH] Adding Support for Coresight Components on Zynq 7000.
From: Muhammad Abdul WAHAB @ 2016-10-03 12:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160930165325.GA7630@xsjsorenbubuntu>

Hi S?ren,

 > I tried to refresh my Zynq knowledge a bit. The clkc provides the
 > dbg_trc clock, and that is the clock you need (not fclk). I couldn't
 > find it in the binding (I guess I messed that up), but apparently,
 > you can provide a 'trace_emio_clk' as input to the clkc node in the
 > Zynq DT. Then, with the muxes correctly configured (FSBL should do
 > that if you select the EMIO trace clock in Vivado), the dbg_trc
 > output of the clkc should be that EMIO clock. And the dbg_trc output
 > of the clkc is what should be consumed by the tpiu node. Though, as
 > I see it the binding/driver for the TPIU do not support that.
 >
 > I.e.
 > In the clkc description you'd have to add 'trace_emio_clk' to the
 > clock-names property together with a matching reference in the 'clocks'
 > property. As this change would be specific to local setups, this is not
 > really appropriate for upstream.
 >
 > Then, for the trace clock, ideally the TPIU would consume and enable it
 > as needed.

Thank you very much for this. I will have a look into it.
Below is the patch without TPIU, is it possible to submit it ? I will 
submit the TPIU part very soon once I manage to get it working.

 > Unfortunately, this is not how it works. The DT bindings are not a
 > recommendation. The DT description must follow the binding, otherwise
 > drivers will not work correctly, or best case, just ignore what you put
 > there.

Thanks. The idea of including TPIU part was to get feedback as I am far 
from being an expert on DT.

 > As I don't see this in the coresight binding, I doubt that it has any
 > effect or should be here.

That's what I was thinking also. I will re-look into TPIU part and send 
it soon. Besides, if I want to ask you a question regarding TPIU or DT, 
can I contact you alone or should I keep sending it to all the CS/DT 
maintainers ?

Thanks,
M.Abdul WAHAB
---
--- linux-4.7/arch/arm/boot/dts/zynq-7000.dtsi.orig    2016-07-24 
21:23:50.000000000 +0200
+++ linux-4.7/arch/arm/boot/dts/zynq-7000.dtsi    2016-10-03 
14:38:00.164515838 +0200
@@ -96,6 +96,57 @@
              rx-fifo-depth = <0x40>;
          };

+        etb at F8801000 {
+            compatible = "arm,coresight-etb10", "arm,primecell";
+            reg = <0xf8801000 0x1000>;
+
+            coresight-default-sink;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+
+            port {
+                etb_in_port: endpoint at 0 {
+                    slave-mode;
+                    remote-endpoint = <&replicator_out_port0>;
+                };
+            };
+        };
+
+        funnel at F8804000 {
+            compatible = "arm,coresight-funnel", "arm,primecell";
+            reg = <0xf8804000 0x1000>;
+
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            ports {
+                #address-cells = <0x1>;
+                #size-cells = <0x0>;
+
+                port at 0 {
+                    reg = <0x0>;
+                    funnel_out_port0: endpoint {
+                        remote-endpoint = <&replicator_in_port0>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <0x0>;
+                    funnel_in_port0: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&ptm0_out_port>;
+                    };
+                };
+
+                port at 2 {
+                    reg = <0x1>;
+                    funnel_in_port1: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&ptm1_out_port>;
+                    };
+                };
+            };
+        };
+
          gpio0: gpio at e000a000 {
              compatible = "xlnx,zynq-gpio-1.0";
              #gpio-cells = <2>;
@@ -311,6 +362,67 @@
              clocks = <&clkc 4>;
          };

+        ptm0 at F889C000 {
+            compatible = "arm,coresight-etm3x", "arm,primecell";
+            reg = <0xf889c000 0x1000>;
+
+            cpu = <&cpu0>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+
+            port {
+                ptm0_out_port: endpoint {
+                    remote-endpoint = <&funnel_in_port0>;
+                };
+            };
+        };
+
+        ptm1 at F889D000 {
+            compatible = "arm,coresight-etm3x", "arm,primecell";
+            reg = <0xf889d000 0x1000>;
+
+            cpu = <&cpu1>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+
+            port {
+                ptm1_out_port: endpoint {
+                    remote-endpoint = <&funnel_in_port1>;
+                };
+            };
+        };
+
+        replicator {
+            compatible = "arm,coresight-replicator";
+
+            ports {
+                #address-cells = <0x1>;
+                #size-cells = <0x0>;
+
+                port at 0 {
+                    reg = <0x0>;
+                    replicator_out_port0: endpoint {
+                        remote-endpoint = <&etb_in_port>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <0x1>;
+                    replicator_out_port1: endpoint {
+                        remote-endpoint = <&tpiu_in_port>;
+                    };
+                };
+
+                port at 2 {
+                    reg = <0x0>;
+                    replicator_in_port0: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&funnel_out_port0>;
+                    };
+                };
+            };
+        };
+
          ttc0: timer at f8001000 {
              interrupt-parent = <&intc>;
              interrupts = <0 10 4>,

^ permalink raw reply

* [PATCH v1 2/2] spi: spi-fsl-dspi: Add DMA support for Vybrid
From: Sanchayan Maity @ 2016-10-03 12:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <63fc108e2df00d2297a9b7014955f203bc802f34.1475498805.git.maitysanchayan@gmail.com>

Add DMA support for Vybrid.

Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
---
 drivers/spi/spi-fsl-dspi.c | 293 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 293 insertions(+)

diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 9e9dadb..ada50ee 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -15,6 +15,8 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
@@ -40,6 +42,7 @@
 #define TRAN_STATE_WORD_ODD_NUM	0x04
 
 #define DSPI_FIFO_SIZE			4
+#define DSPI_DMA_BUFSIZE		(DSPI_FIFO_SIZE * 1024)
 
 #define SPI_MCR		0x00
 #define SPI_MCR_MASTER		(1 << 31)
@@ -71,6 +74,11 @@
 #define SPI_SR_EOQF		0x10000000
 #define SPI_SR_TCFQF		0x80000000
 
+#define SPI_RSER_TFFFE		BIT(25)
+#define SPI_RSER_TFFFD		BIT(24)
+#define SPI_RSER_RFDFE		BIT(17)
+#define SPI_RSER_RFDFD		BIT(16)
+
 #define SPI_RSER		0x30
 #define SPI_RSER_EOQFE		0x10000000
 #define SPI_RSER_TCFQE		0x80000000
@@ -108,6 +116,8 @@
 
 #define SPI_TCR_TCNT_MAX	0x10000
 
+#define DMA_COMPLETION_TIMEOUT	msecs_to_jiffies(3000)
+
 struct chip_data {
 	u32 mcr_val;
 	u32 ctar_val;
@@ -117,6 +127,7 @@ struct chip_data {
 enum dspi_trans_mode {
 	DSPI_EOQ_MODE = 0,
 	DSPI_TCFQ_MODE,
+	DSPI_DMA_MODE,
 };
 
 struct fsl_dspi_devtype_data {
@@ -139,6 +150,22 @@ static const struct fsl_dspi_devtype_data ls2085a_data = {
 	.max_clock_factor = 8,
 };
 
+struct fsl_dspi_dma {
+	u32 curr_xfer_len;
+
+	u32 *tx_dma_buf;
+	struct dma_chan *chan_tx;
+	dma_addr_t tx_dma_phys;
+	struct completion cmd_tx_complete;
+	struct dma_async_tx_descriptor *tx_desc;
+
+	u32 *rx_dma_buf;
+	struct dma_chan *chan_rx;
+	dma_addr_t rx_dma_phys;
+	struct completion cmd_rx_complete;
+	struct dma_async_tx_descriptor *rx_desc;
+};
+
 struct fsl_dspi {
 	struct spi_master	*master;
 	struct platform_device	*pdev;
@@ -165,6 +192,7 @@ struct fsl_dspi {
 	u32			waitflags;
 
 	u32			spi_tcnt;
+	struct fsl_dspi_dma	*dma;
 };
 
 static inline int is_double_byte_mode(struct fsl_dspi *dspi)
@@ -368,6 +396,264 @@ static void dspi_tcfq_read(struct fsl_dspi *dspi)
 	dspi_data_from_popr(dspi, rx_word);
 }
 
+static void dspi_tx_dma_callback(void *arg)
+{
+	struct fsl_dspi *dspi = arg;
+	struct fsl_dspi_dma *dma = dspi->dma;
+
+	complete(&dma->cmd_tx_complete);
+}
+
+static void dspi_rx_dma_callback(void *arg)
+{
+	struct fsl_dspi *dspi = arg;
+	struct fsl_dspi_dma *dma = dspi->dma;
+	int rx_word;
+	int i, len;
+	u16 d;
+
+	rx_word = is_double_byte_mode(dspi);
+
+	len = rx_word ? (dma->curr_xfer_len / 2) : dma->curr_xfer_len;
+
+	if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) {
+		for (i = 0; i < len; i++) {
+			d = dspi->dma->rx_dma_buf[i];
+			rx_word ? (*(u16 *)dspi->rx = d) :
+						(*(u8 *)dspi->rx = d);
+			dspi->rx += rx_word + 1;
+		}
+	}
+
+	complete(&dma->cmd_rx_complete);
+}
+
+static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
+{
+	struct fsl_dspi_dma *dma = dspi->dma;
+	struct device *dev = &dspi->pdev->dev;
+	int time_left;
+	int tx_word;
+	int i, len;
+	u16 val;
+
+	tx_word = is_double_byte_mode(dspi);
+
+	len = tx_word ? (dma->curr_xfer_len / 2) : dma->curr_xfer_len;
+
+	for (i = 0; i < len - 1; i++) {
+		val = tx_word ? *(u16 *) dspi->tx : *(u8 *) dspi->tx;
+		dspi->dma->tx_dma_buf[i] =
+			SPI_PUSHR_TXDATA(val) | SPI_PUSHR_PCS(dspi->cs) |
+			SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
+		dspi->tx += tx_word + 1;
+	}
+
+	val = tx_word ? *(u16 *) dspi->tx : *(u8 *) dspi->tx;
+	dspi->dma->tx_dma_buf[i] = SPI_PUSHR_TXDATA(val) |
+					SPI_PUSHR_PCS(dspi->cs) |
+					SPI_PUSHR_CTAS(0);
+	dspi->tx += tx_word + 1;
+
+	dma->tx_desc = dmaengine_prep_slave_single(dma->chan_tx,
+					dma->tx_dma_phys,
+					DSPI_DMA_BUFSIZE, DMA_MEM_TO_DEV,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!dma->tx_desc) {
+		dev_err(dev, "Not able to get desc for DMA xfer\n");
+		return -EIO;
+	}
+
+	dma->tx_desc->callback = dspi_tx_dma_callback;
+	dma->tx_desc->callback_param = dspi;
+	if (dma_submit_error(dmaengine_submit(dma->tx_desc))) {
+		dev_err(dev, "DMA submit failed\n");
+		return -EINVAL;
+	}
+
+	dma->rx_desc = dmaengine_prep_slave_single(dma->chan_rx,
+					dma->rx_dma_phys,
+					DSPI_DMA_BUFSIZE, DMA_DEV_TO_MEM,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!dma->rx_desc) {
+		dev_err(dev, "Not able to get desc for DMA xfer\n");
+		return -EIO;
+	}
+
+	dma->rx_desc->callback = dspi_rx_dma_callback;
+	dma->rx_desc->callback_param = dspi;
+	if (dma_submit_error(dmaengine_submit(dma->rx_desc))) {
+		dev_err(dev, "DMA submit failed\n");
+		return -EINVAL;
+	}
+
+	reinit_completion(&dspi->dma->cmd_rx_complete);
+	reinit_completion(&dspi->dma->cmd_tx_complete);
+
+	dma_async_issue_pending(dma->chan_rx);
+	dma_async_issue_pending(dma->chan_tx);
+
+	time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete,
+					DMA_COMPLETION_TIMEOUT);
+	if (time_left == 0) {
+		dev_err(dev, "DMA tx timeout\n");
+		dmaengine_terminate_all(dma->chan_tx);
+		dmaengine_terminate_all(dma->chan_rx);
+		return -ETIMEDOUT;
+	}
+
+	time_left = wait_for_completion_timeout(&dspi->dma->cmd_rx_complete,
+					DMA_COMPLETION_TIMEOUT);
+	if (time_left == 0) {
+		dev_err(dev, "DMA rx timeout\n");
+		dmaengine_terminate_all(dma->chan_tx);
+		dmaengine_terminate_all(dma->chan_rx);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int dspi_dma_xfer(struct fsl_dspi *dspi)
+{
+	struct fsl_dspi_dma *dma = dspi->dma;
+	struct device *dev = &dspi->pdev->dev;
+	int curr_remaining_bytes;
+	int ret = 0;
+
+	curr_remaining_bytes = dspi->len;
+	while (curr_remaining_bytes) {
+		regmap_write(dspi->regmap, SPI_RSER, 0);
+		regmap_write(dspi->regmap, SPI_RSER,
+			SPI_RSER_TFFFE | SPI_RSER_TFFFD |
+			SPI_RSER_RFDFE | SPI_RSER_RFDFD);
+
+		/* Check if current transfer fits the DMA buffer */
+		dma->curr_xfer_len = curr_remaining_bytes;
+		if (curr_remaining_bytes > DSPI_DMA_BUFSIZE / sizeof(u32))
+			dma->curr_xfer_len = DSPI_DMA_BUFSIZE / sizeof(u32);
+
+		ret = dspi_next_xfer_dma_submit(dspi);
+		if (ret) {
+			dev_err(dev, "DMA transfer failed\n");
+			goto exit;
+
+		} else {
+			curr_remaining_bytes -= dma->curr_xfer_len;
+			if (curr_remaining_bytes < 0)
+				curr_remaining_bytes = 0;
+			dspi->len = curr_remaining_bytes;
+		}
+	}
+
+exit:
+	return ret;
+}
+
+static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
+{
+	struct fsl_dspi_dma *dma;
+	struct dma_slave_config cfg;
+	struct device *dev = &dspi->pdev->dev;
+	int ret;
+
+	dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
+	if (!dma)
+		return -ENOMEM;
+
+	dma->chan_rx = dma_request_slave_channel(dev, "rx");
+	if (!dma->chan_rx) {
+		dev_err(dev, "rx dma channel not available\n");
+		ret = -ENODEV;
+		return ret;
+	}
+
+	dma->chan_tx = dma_request_slave_channel(dev, "tx");
+	if (!dma->chan_tx) {
+		dev_err(dev, "tx dma channel not available\n");
+		ret = -ENODEV;
+		goto err_tx_channel;
+	}
+
+	dma->tx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE,
+					&dma->tx_dma_phys, GFP_KERNEL);
+	if (!dma->tx_dma_buf) {
+		ret = -ENOMEM;
+		goto err_tx_dma_buf;
+	}
+
+	dma->rx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE,
+					&dma->rx_dma_phys, GFP_KERNEL);
+	if (!dma->rx_dma_buf) {
+		ret = -ENOMEM;
+		goto err_rx_dma_buf;
+	}
+
+	cfg.src_addr = phy_addr + SPI_POPR;
+	cfg.dst_addr = phy_addr + SPI_PUSHR;
+	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.src_maxburst = 1;
+	cfg.dst_maxburst = 1;
+
+	cfg.direction = DMA_DEV_TO_MEM;
+	ret = dmaengine_slave_config(dma->chan_rx, &cfg);
+	if (ret) {
+		dev_err(dev, "can't configure rx dma channel\n");
+		ret = -EINVAL;
+		goto err_slave_config;
+	}
+
+	cfg.direction = DMA_MEM_TO_DEV;
+	ret = dmaengine_slave_config(dma->chan_tx, &cfg);
+	if (ret) {
+		dev_err(dev, "can't configure tx dma channel\n");
+		ret = -EINVAL;
+		goto err_slave_config;
+	}
+
+	dspi->dma = dma;
+	dspi->devtype_data->trans_mode = DSPI_DMA_MODE;
+	init_completion(&dma->cmd_tx_complete);
+	init_completion(&dma->cmd_rx_complete);
+
+	return 0;
+
+err_slave_config:
+	devm_kfree(dev, dma->rx_dma_buf);
+err_rx_dma_buf:
+	devm_kfree(dev, dma->tx_dma_buf);
+err_tx_dma_buf:
+	dma_release_channel(dma->chan_tx);
+err_tx_channel:
+	dma_release_channel(dma->chan_rx);
+
+	devm_kfree(dev, dma);
+	dspi->dma = NULL;
+
+	return ret;
+}
+
+static void dspi_release_dma(struct fsl_dspi *dspi)
+{
+	struct fsl_dspi_dma *dma = dspi->dma;
+	struct device *dev = &dspi->pdev->dev;
+
+	if (dma) {
+		if (dma->chan_tx) {
+			dma_unmap_single(dev, dma->tx_dma_phys,
+					DSPI_DMA_BUFSIZE, DMA_TO_DEVICE);
+			dma_release_channel(dma->chan_tx);
+		}
+
+		if (dma->chan_rx) {
+			dma_unmap_single(dev, dma->rx_dma_phys,
+					DSPI_DMA_BUFSIZE, DMA_FROM_DEVICE);
+			dma_release_channel(dma->chan_rx);
+		}
+	}
+}
+
 static int dspi_transfer_one_message(struct spi_master *master,
 		struct spi_message *message)
 {
@@ -424,6 +710,9 @@ static int dspi_transfer_one_message(struct spi_master *master,
 			regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE);
 			dspi_tcfq_write(dspi);
 			break;
+		case DSPI_DMA_MODE:
+			status = dspi_dma_xfer(dspi);
+			goto out;
 		default:
 			dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n",
 				trans_mode);
@@ -730,6 +1019,9 @@ static int dspi_probe(struct platform_device *pdev)
 	}
 	clk_prepare_enable(dspi->clk);
 
+	if (dspi_request_dma(dspi, res->start))
+		dev_warn(&pdev->dev, "can't get dma channels\n");
+
 	master->max_speed_hz =
 		clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor;
 
@@ -758,6 +1050,7 @@ static int dspi_remove(struct platform_device *pdev)
 	struct fsl_dspi *dspi = spi_master_get_devdata(master);
 
 	/* Disconnect from the SPI framework */
+	dspi_release_dma(dspi);
 	clk_disable_unprepare(dspi->clk);
 	spi_unregister_master(dspi->master);
 	spi_master_put(dspi->master);
-- 
2.10.0

^ permalink raw reply related

* [PATCH v1 1/2] ARM: dts: vfxxx: Enable DMA for DSPI on Vybrid
From: Sanchayan Maity @ 2016-10-03 12:50 UTC (permalink / raw)
  To: linux-arm-kernel

Enable DMA for DSPI on Vybrid.

Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
---
 arch/arm/boot/dts/vf-colibri.dtsi | 4 ++++
 arch/arm/boot/dts/vfxxx.dtsi      | 6 ++++++
 2 files changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi
index b741709..21bfef9 100644
--- a/arch/arm/boot/dts/vf-colibri.dtsi
+++ b/arch/arm/boot/dts/vf-colibri.dtsi
@@ -108,6 +108,10 @@
 	status = "okay";
 };
 
+&edma1 {
+	status = "okay";
+};
+
 &esdhc1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_esdhc1>;
diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 2c13ec6..eac4213 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -194,6 +194,9 @@
 				clocks = <&clks VF610_CLK_DSPI0>;
 				clock-names = "dspi";
 				spi-num-chipselects = <6>;
+				dmas = <&edma1 1 12>,
+					<&edma1 1 13>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -206,6 +209,9 @@
 				clocks = <&clks VF610_CLK_DSPI1>;
 				clock-names = "dspi";
 				spi-num-chipselects = <4>;
+				dmas = <&edma1 1 14>,
+					<&edma1 1 15>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
-- 
2.10.0

^ permalink raw reply related

* [PATCH v26 0/7] arm64: add kdump support
From: Manish Jaggi @ 2016-10-03 12:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003110424.GD14025@linaro.org>



On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
> Manish,
> 
> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
>> Hi Akashi,
>>
>> On 09/07/2016 09:59 AM, AKASHI Takahiro wrote:
>>>     v26-specific note: After a comment from Rob[0], an idea of adding
>>>     "linux,usable-memory-range" was dropped. Instead, an existing
>>>     "reserved-memory" node will be used to limit usable memory ranges
>>>     on crash dump kernel.
>>>     This works not only on UEFI/ACPI systems but also on DT-only systems,
>>>     but if he really insists on using DT-specific "usable-memory" property,
>>>     I will post additional patches for kexec-tools. Those would be
>>>     redundant, though.
>>>     Even in that case, the kernel will not have to be changed.
>>>
>>> This patch series adds kdump support on arm64.
>>> There are some prerequisite patches [1],[2].
>>>
>>> To load a crash-dump kernel to the systems, a series of patches to
>>> kexec-tools, which have not yet been merged upstream, are needed.
>>> Please always use my latest kdump patches, v3 [3].
>>>
>>> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
>>>   - crash utility (coming v7.1.6 or later) [4]
>>>     (Necessary patches have already been queued in the master.)
>>>
>>>
>>> [0] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/452582.html
>>> [1] "arm64: mark reserved memblock regions explicitly in iomem"
>>>     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/450433.html
>>> [2] "efi: arm64: treat regions with WT/WC set but WB cleared as memory"
>>>     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/451491.html
>>> [3] T.B.D.
>>> [4] https://github.com/crash-utility/crash.git
>>>
>>
>> With the v26 kdump and v3 kexec-tools and top of tree crash.git, below are the tests done
>> Attached is a patch in crash.git (symbols.c) to make crash utility work on my setup.
>> Can you please have a look and provide your comments.
>>
>> To generate a panic, i have a kernel module which on init calls panic.
>>
>> Observations:
>> 1.1. Dump capture kernel shows different memory map.
>> ---------------------------------------------------
>> In dump capture kernel /proc/meminfo and /proc/iomem differ
>>
>> root at arm64:/home/ubuntu/CODE/crash#
>> MemTotal:       65882432 kB
>> MemFree:        65507136 kB
>> MemAvailable:   60373632 kB
>> Buffers:           29248 kB
>> Cached:            46720 kB
>> SwapCached:            0 kB
>> Active:            63872 kB
>> Inactive:          19776 kB
>> Active(anon):       8256 kB
>> Inactive(anon):     7616 kB
>>
>> First kernel is booted with mem=2G crashkernel=1G command line option.
>> While the system has 64G memory.
>>
>> root at arm64:/home/ubuntu/CODE/crash# cat /proc/iomem
>> 41400000-fffeffff : System RAM
>>   41480000-420cffff : Kernel code
>>   42490000-4278ffff : Kernel data
>> ffff0000-ffffffff : reserved
>> 100000000-ffaa7ffff : System RAM
>> ffaa80000-ffaabffff : reserved
>> ffaac0000-fffa6ffff : System RAM
>> fffa70000-fffacffff : reserved
>> fffad0000-fffffffff : System RAM
> 
> Are you saying that "mem=..." doesn't have any effect?
What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
the memory for second kernel has to be withing the crashkernel size.
As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
much more than the first kernel had in first place.
> What about if you don't specify "crashkernel=...?"
> 
In that case the second kernel will not boot as kexec tools will complain that memory not reserved.
>> 1.2 Live crash dump fails with error
>> --------------------------------------
>> $crash vmlinux
>>
>> crash 7.1.5++
>> Copyright (C) 2002-2016  Red Hat, Inc.
>> Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
>> Copyright (C) 1999-2006  Hewlett-Packard Co
>> Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
>> Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
>> Copyright (C) 2005, 2011  NEC Corporation
>> Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
>> Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
>> This program is free software, covered by the GNU General Public License,
>> and you are welcome to change it and/or distribute copies of it under
>> certain conditions.  Enter "help copying" to see the conditions.
>> This program has absolutely no warranty.  Enter "help warranty" for details.
>>
>> GNU gdb (GDB) 7.6
>> Copyright (C) 2013 Free Software Foundation, Inc.
>> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
>> This is free software: you are free to change and redistribute it.
>> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
>> and "show warranty" for details.
>> This GDB was configured as "aarch64-unknown-linux-gnu"...
>>
>> crash: read error: kernel virtual address: ffff800ffffffcc0  type: "pglist node_id"
> 
> I have no ideas here.
If I run with debug logs phys address accessed is > 64G. (10413ffcc0)
Could be that somehow 64 + 1G + (addr) = 10413ffcc0 and actually addr was required.
addr = 413ffcc0 which seems in line with 424b0c50


Logs:
<read_dev_mem: addr: ffff0000090b3008 paddr: 424b3008 cnt: 8>
node_online_map: [1] -> nodes online: 1
<readmem: ffff0000090b0c50, KVADDR, ""node_data"", 8, (ROE), ffffc330eb00>
<read_dev_mem: addr: ffff0000090b0c50 paddr: 424b0c50 cnt: 8>
<readmem: ffff800ffffffcc0, KVADDR, ""pglist node_id"", 4, (FOE), ffffc330f1e4>
<read_dev_mem: addr: ffff800ffffffcc0 paddr: 10413ffcc0 cnt: 4>
/dev/mem: Bad address
crash: read(/dev/mem, 10413ffcc0, 4): 4294967295 (ffffffff)
crash: read error: kernel virtual address: ffff800ffffffcc0  type: ""pglist node_id""
"
> 
>> Observation 2
>> ------------
>> If saved vmcore file is used
>>
>> $crash vmlinux vmcore_saved
>> Got the below error.
>>
>> please wait... (gathering module symbol data)crash: malloc.c:2846: mremap_chunk: Assertion `((size + offset) & (_rtld_global_ro._dl_pagesize - 1)) == 0' failed.
>> Aborted
> 
> I have no ideas here.
> 
>> Experiment 3
>> ------------
>> If crash.git is modified with a hack patch in symbols.c. Crash utility works fine log, bt commands work.
> 
> In which case, "crash vmlinux" or "crash vmlinux vmcore_saved?"
> 
vmcore_saved
> I was able to reproduce this issue in the latter case
> (but with a different error message).
> It seems to be a crash util's bug.
> Please report it to crash-util mailing list.
> I will post a patch.
The same patch as below ?
Can you please share your patch
> 
> Thanks,
> -Takahiro AKASHI
> 
>> -------------------
>> Patch: symbols.c
>> git diff symbols.c
>> diff --git a/symbols.c b/symbols.c
>> index 13282f4..f7c6cac 100644
>> --- a/symbols.c
>> +++ b/symbols.c
>> @@ -2160,6 +2160,7 @@ store_module_kallsyms_v2(struct load_module *lm, int start
>>                  FREEBUF(module_buf);
>>                  return 0;
>>          }
>> +       lm->mod_init_size = 0;
>>
>>         if (lm->mod_init_size > 0) {
>>                 module_buf_init = GETBUF(lm->mod_init_size);
>> ------------------
>>
>> $ crash vmlinux vmcore_saved
>>     KERNEL: /home/ubuntu/CODE/linux/vmlinux
>>     DUMPFILE: vm
>>         CPUS: 48 [OFFLINE: 46]
>>         DATE: Mon Oct  3 00:11:47 2016
>>       UPTIME: 00:02:41
>> LOAD AVERAGE: 0.36, 0.14, 0.05
>>        TASKS: 171
>>     NODENAME: arm64
>>      RELEASE: 4.8.0-rc3-00044-g070a615-dirty
>>      VERSION: #63 SMP Sat Oct 1 01:39:45 PDT 2016
>>      MACHINE: aarch64  (unknown Mhz)
>>       MEMORY: 2 GB
>>        PANIC: "Kernel panic - not syncing: crash module starting"
>>          PID: 958
>>      COMMAND: "insmod"
>>         TASK: ffff800007859300  [THREAD_INFO: ffff80000c940000]
>>          CPU: 0
>>        STATE: TASK_RUNNING (PANIC)
>>
>> crash> bt
>> PID: 958    TASK: ffff800007859300  CPU: 0   COMMAND: "insmod"
>>  #0 [ffff80000c943980] __crash_kexec at ffff000008144fe8
>>  #1 [ffff80000c943ae0] panic at ffff0000081ae704
>>  #2 [ffff80000c943ba0] init_module at ffff000000900014 [crash]
>>  #3 [ffff80000c943bb0] do_one_initcall at ffff000008083bb4
>>  #4 [ffff80000c943c40] do_init_module at ffff0000081af6f0
>>  #5 [ffff80000c943c70] load_module at ffff000008140b7c
>>  #6 [ffff80000c943e10] sys_finit_module at ffff000008141634
>>  #7 [ffff80000c943ed0] el0_svc_naked at ffff0000080833ec
>>      PC: 00000003  LR: ffffaca050a0  SP: ffffaca865a0  PSTATE: 00000111
>>     X12: ffffac941a5c X11: 00000080 X10: 00000004  X9: 00000030
>>      X8: ffffffff  X7: fefefefefefeff40  X6: 00000111  X5: 00000001
>>      X4: 00000001  X3: 0002ed61  X2: 00000000  X1: 00000003
>>      X0: 00000000
>> crash>
>>
>>
>> ---
>> Thanks,
>> manish
>>

^ permalink raw reply

* [PATCH v2 1/1] crypto: atmel-aes: add support to the XTS mode
From: Cyrille Pitchen @ 2016-10-03 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the xts(aes) algorithm, which is supported from
hardware version 0x500 and above (sama5d2x).

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
ChangeLog:

v1 -> v2:
- fix typo in comment inside atmel_aes_xts_process_data():
  s/reverted/reversed/
- use xts_check_key() from atmel_aes_xts_setkey() as suggested by
  Stephan Mueller.

 drivers/crypto/atmel-aes-regs.h |   4 +
 drivers/crypto/atmel-aes.c      | 185 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 183 insertions(+), 6 deletions(-)

diff --git a/drivers/crypto/atmel-aes-regs.h b/drivers/crypto/atmel-aes-regs.h
index 6c2951bb70b1..0ec04407b533 100644
--- a/drivers/crypto/atmel-aes-regs.h
+++ b/drivers/crypto/atmel-aes-regs.h
@@ -28,6 +28,7 @@
 #define AES_MR_OPMOD_CFB		(0x3 << 12)
 #define AES_MR_OPMOD_CTR		(0x4 << 12)
 #define AES_MR_OPMOD_GCM		(0x5 << 12)
+#define AES_MR_OPMOD_XTS		(0x6 << 12)
 #define AES_MR_LOD				(0x1 << 15)
 #define AES_MR_CFBS_MASK		(0x7 << 16)
 #define AES_MR_CFBS_128b		(0x0 << 16)
@@ -67,6 +68,9 @@
 #define AES_CTRR	0x98
 #define AES_GCMHR(x)	(0x9c + ((x) * 0x04))
 
+#define AES_TWR(x)	(0xc0 + ((x) * 0x04))
+#define AES_ALPHAR(x)	(0xd0 + ((x) * 0x04))
+
 #define AES_HW_VERSION	0xFC
 
 #endif /* __ATMEL_AES_REGS_H__ */
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 1d9e7bd3f377..6b656f4a9378 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -36,6 +36,7 @@
 #include <crypto/scatterwalk.h>
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
+#include <crypto/xts.h>
 #include <crypto/internal/aead.h>
 #include <linux/platform_data/crypto-atmel.h>
 #include <dt-bindings/dma/at91.h>
@@ -68,6 +69,7 @@
 #define AES_FLAGS_CFB8		(AES_MR_OPMOD_CFB | AES_MR_CFBS_8b)
 #define AES_FLAGS_CTR		AES_MR_OPMOD_CTR
 #define AES_FLAGS_GCM		AES_MR_OPMOD_GCM
+#define AES_FLAGS_XTS		AES_MR_OPMOD_XTS
 
 #define AES_FLAGS_MODE_MASK	(AES_FLAGS_OPMODE_MASK |	\
 				 AES_FLAGS_ENCRYPT |		\
@@ -89,6 +91,7 @@ struct atmel_aes_caps {
 	bool			has_cfb64;
 	bool			has_ctr32;
 	bool			has_gcm;
+	bool			has_xts;
 	u32			max_burst_size;
 };
 
@@ -135,6 +138,12 @@ struct atmel_aes_gcm_ctx {
 	atmel_aes_fn_t		ghash_resume;
 };
 
+struct atmel_aes_xts_ctx {
+	struct atmel_aes_base_ctx	base;
+
+	u32			key2[AES_KEYSIZE_256 / sizeof(u32)];
+};
+
 struct atmel_aes_reqctx {
 	unsigned long		mode;
 };
@@ -282,6 +291,20 @@ static const char *atmel_aes_reg_name(u32 offset, char *tmp, size_t sz)
 		snprintf(tmp, sz, "GCMHR[%u]", (offset - AES_GCMHR(0)) >> 2);
 		break;
 
+	case AES_TWR(0):
+	case AES_TWR(1):
+	case AES_TWR(2):
+	case AES_TWR(3):
+		snprintf(tmp, sz, "TWR[%u]", (offset - AES_TWR(0)) >> 2);
+		break;
+
+	case AES_ALPHAR(0):
+	case AES_ALPHAR(1):
+	case AES_ALPHAR(2):
+	case AES_ALPHAR(3):
+		snprintf(tmp, sz, "ALPHAR[%u]", (offset - AES_ALPHAR(0)) >> 2);
+		break;
+
 	default:
 		snprintf(tmp, sz, "0x%02x", offset);
 		break;
@@ -453,15 +476,15 @@ static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err)
 	return err;
 }
 
-static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
-				 const u32 *iv)
+static void atmel_aes_write_ctrl_key(struct atmel_aes_dev *dd, bool use_dma,
+				     const u32 *iv, const u32 *key, int keylen)
 {
 	u32 valmr = 0;
 
 	/* MR register must be set before IV registers */
-	if (dd->ctx->keylen == AES_KEYSIZE_128)
+	if (keylen == AES_KEYSIZE_128)
 		valmr |= AES_MR_KEYSIZE_128;
-	else if (dd->ctx->keylen == AES_KEYSIZE_192)
+	else if (keylen == AES_KEYSIZE_192)
 		valmr |= AES_MR_KEYSIZE_192;
 	else
 		valmr |= AES_MR_KEYSIZE_256;
@@ -478,13 +501,19 @@ static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
 
 	atmel_aes_write(dd, AES_MR, valmr);
 
-	atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
-			  SIZE_IN_WORDS(dd->ctx->keylen));
+	atmel_aes_write_n(dd, AES_KEYWR(0), key, SIZE_IN_WORDS(keylen));
 
 	if (iv && (valmr & AES_MR_OPMOD_MASK) != AES_MR_OPMOD_ECB)
 		atmel_aes_write_block(dd, AES_IVR(0), iv);
 }
 
+static inline void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
+					const u32 *iv)
+
+{
+	atmel_aes_write_ctrl_key(dd, use_dma, iv,
+				 dd->ctx->key, dd->ctx->keylen);
+}
 
 /* CPU transfer */
 
@@ -1769,6 +1798,137 @@ static struct aead_alg aes_gcm_alg = {
 };
 
 
+/* xts functions */
+
+static inline struct atmel_aes_xts_ctx *
+atmel_aes_xts_ctx_cast(struct atmel_aes_base_ctx *ctx)
+{
+	return container_of(ctx, struct atmel_aes_xts_ctx, base);
+}
+
+static int atmel_aes_xts_process_data(struct atmel_aes_dev *dd);
+
+static int atmel_aes_xts_start(struct atmel_aes_dev *dd)
+{
+	struct atmel_aes_xts_ctx *ctx = atmel_aes_xts_ctx_cast(dd->ctx);
+	struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
+	struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
+	unsigned long flags;
+	int err;
+
+	atmel_aes_set_mode(dd, rctx);
+
+	err = atmel_aes_hw_init(dd);
+	if (err)
+		return atmel_aes_complete(dd, err);
+
+	/* Compute the tweak value from req->info with ecb(aes). */
+	flags = dd->flags;
+	dd->flags &= ~AES_FLAGS_MODE_MASK;
+	dd->flags |= (AES_FLAGS_ECB | AES_FLAGS_ENCRYPT);
+	atmel_aes_write_ctrl_key(dd, false, NULL,
+				 ctx->key2, ctx->base.keylen);
+	dd->flags = flags;
+
+	atmel_aes_write_block(dd, AES_IDATAR(0), req->info);
+	return atmel_aes_wait_for_data_ready(dd, atmel_aes_xts_process_data);
+}
+
+static int atmel_aes_xts_process_data(struct atmel_aes_dev *dd)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
+	bool use_dma = (req->nbytes >= ATMEL_AES_DMA_THRESHOLD);
+	u32 tweak[AES_BLOCK_SIZE / sizeof(u32)];
+	static const u32 one[AES_BLOCK_SIZE / sizeof(u32)] = {cpu_to_le32(1), };
+	u8 *tweak_bytes = (u8 *)tweak;
+	int i;
+
+	/* Read the computed ciphered tweak value. */
+	atmel_aes_read_block(dd, AES_ODATAR(0), tweak);
+	/*
+	 * Hardware quirk:
+	 * the order of the ciphered tweak bytes need to be reversed before
+	 * writing them into the ODATARx registers.
+	 */
+	for (i = 0; i < AES_BLOCK_SIZE/2; ++i) {
+		u8 tmp = tweak_bytes[AES_BLOCK_SIZE - 1 - i];
+
+		tweak_bytes[AES_BLOCK_SIZE - 1 - i] = tweak_bytes[i];
+		tweak_bytes[i] = tmp;
+	}
+
+	/* Process the data. */
+	atmel_aes_write_ctrl(dd, use_dma, NULL);
+	atmel_aes_write_block(dd, AES_TWR(0), tweak);
+	atmel_aes_write_block(dd, AES_ALPHAR(0), one);
+	if (use_dma)
+		return atmel_aes_dma_start(dd, req->src, req->dst, req->nbytes,
+					   atmel_aes_transfer_complete);
+
+	return atmel_aes_cpu_start(dd, req->src, req->dst, req->nbytes,
+				   atmel_aes_transfer_complete);
+}
+
+static int atmel_aes_xts_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+				unsigned int keylen)
+{
+	struct atmel_aes_xts_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	int err;
+
+	err = xts_check_key(crypto_ablkcipher_tfm(tfm), key, keylen);
+	if (err)
+		return err;
+
+	memcpy(ctx->base.key, key, keylen/2);
+	memcpy(ctx->key2, key + keylen/2, keylen/2);
+	ctx->base.keylen = keylen/2;
+
+	return 0;
+}
+
+static int atmel_aes_xts_encrypt(struct ablkcipher_request *req)
+{
+	return atmel_aes_crypt(req, AES_FLAGS_XTS | AES_FLAGS_ENCRYPT);
+}
+
+static int atmel_aes_xts_decrypt(struct ablkcipher_request *req)
+{
+	return atmel_aes_crypt(req, AES_FLAGS_XTS);
+}
+
+static int atmel_aes_xts_cra_init(struct crypto_tfm *tfm)
+{
+	struct atmel_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_aes_reqctx);
+	ctx->base.start = atmel_aes_xts_start;
+
+	return 0;
+}
+
+static struct crypto_alg aes_xts_alg = {
+	.cra_name		= "xts(aes)",
+	.cra_driver_name	= "atmel-xts-aes",
+	.cra_priority		= ATMEL_AES_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct atmel_aes_xts_ctx),
+	.cra_alignmask		= 0xf,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= atmel_aes_xts_cra_init,
+	.cra_exit		= atmel_aes_cra_exit,
+	.cra_u.ablkcipher = {
+		.min_keysize	= 2 * AES_MIN_KEY_SIZE,
+		.max_keysize	= 2 * AES_MAX_KEY_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.setkey		= atmel_aes_xts_setkey,
+		.encrypt	= atmel_aes_xts_encrypt,
+		.decrypt	= atmel_aes_xts_decrypt,
+	}
+};
+
+
 /* Probe functions */
 
 static int atmel_aes_buff_init(struct atmel_aes_dev *dd)
@@ -1877,6 +2037,9 @@ static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
 {
 	int i;
 
+	if (dd->caps.has_xts)
+		crypto_unregister_alg(&aes_xts_alg);
+
 	if (dd->caps.has_gcm)
 		crypto_unregister_aead(&aes_gcm_alg);
 
@@ -1909,8 +2072,16 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 			goto err_aes_gcm_alg;
 	}
 
+	if (dd->caps.has_xts) {
+		err = crypto_register_alg(&aes_xts_alg);
+		if (err)
+			goto err_aes_xts_alg;
+	}
+
 	return 0;
 
+err_aes_xts_alg:
+	crypto_unregister_aead(&aes_gcm_alg);
 err_aes_gcm_alg:
 	crypto_unregister_alg(&aes_cfb64_alg);
 err_aes_cfb64_alg:
@@ -1928,6 +2099,7 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
 	dd->caps.has_cfb64 = 0;
 	dd->caps.has_ctr32 = 0;
 	dd->caps.has_gcm = 0;
+	dd->caps.has_xts = 0;
 	dd->caps.max_burst_size = 1;
 
 	/* keep only major version number */
@@ -1937,6 +2109,7 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
 		dd->caps.has_cfb64 = 1;
 		dd->caps.has_ctr32 = 1;
 		dd->caps.has_gcm = 1;
+		dd->caps.has_xts = 1;
 		dd->caps.max_burst_size = 4;
 		break;
 	case 0x200:
-- 
2.7.4

^ permalink raw reply related

* [GIT PULL 1/3] ARM: soc: exynos: Drivers for v4.9
From: Kukjin Kim @ 2016-10-03 12:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003074825.GA2724@kozik-lap>

2016. 10. 3. 15:48 Krzysztof Kozlowski <krzk@kernel.org> wrote:

>> On Sun, Oct 02, 2016 at 05:25:07PM -0700, Olof Johansson wrote:
>>> On Mon, Sep 19, 2016 at 8:53 AM, Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>>> On Mon, Sep 19, 2016 at 05:02:40PM +0200, Arnd Bergmann wrote:
>>>>> On Sunday, September 18, 2016 6:39:46 PM CEST Krzysztof Kozlowski wrote:
>>>>> Samsung drivers/soc update for v4.9:
>>>>> 1. Allow compile testing of exynos-mct clocksource driver on ARM64.
>>>>> 2. Document Exynos5433 PMU compatible (already used by clkout driver and more
>>>>>   will be coming soon).
>>>> 
>>>> Pulled into next/drivers, thanks
>>>> 
>>>> Just for my understanding: why do we need the exynos-mct driver on ARM64
>>>> but not the delay-timer portion of it?
>>> 
>>> I think we want all of it but Doug's optimization 3252a646aa2c
>>> ("clocksource: exynos_mct: Only use 32-bits where possible") is not
>>> ARM64 friendly. One way of dealing with it would be to prepare two
>>> versions of exynos4_read_current_timer(). One reading only lower 32-bit
>>> value for ARMv7 and second (slow) reading lower and upper for ARMv8.
>>> 
>>>> 
>>>> Is there an advantage in using MCT over the architected timer on these
>>>> chips? If so, should we also have a way to use it as the delay timer?
>>> 
>>> No, there is no real advantage... except that the SoC has some
>>> interesting "characteristics"... The timers are tightly coupled. Very
>>> tightly. I spent a lot of time and failed to boot my ARMv8 board without
>>> some MCT magic.
>> 
>> What kind of magic is that?
> 
> Most notably: the arch timer starts when MCT forward running counter
> starts. Without kicking MCT, the arch timer seems to be frozen.
> 
>> I can understand that needing the MCT for
>> some system-level timer functionality might be true (wakeups, etc),
>> but for system timesource avoiding the MMIO timer and using the arch
>> ones is a substantial performance improvement for gettimeofday() and
>> friends.
>> 
>> There was extensive discussion last year over using arch timers on
>> 5420/5422, and it fizzled out with vague comments about something not
>> working right between A15/A7 on b.L. hardware. I'm presuming whatever
>> implementation details of that SoC has since been fixed on later chips
>> (including v8). Any chance you can confirm? It'd be very nice to leave
>> MCT behind on v8 as a system time source.
> 
> Unfortunately, I cannot confirm this, at least on Exynos5433 (ARMv8). I
> played with arch and MCT timers on it and failed to get the
> arch-timer-only setup working. I did not have access to newer Exynos
> designs (Exynos 7) so I do not know how it works there.

Hi guys,

I know what Olof want to know and actually several days ago someone asked me about that. As you guys talked, a couple of years ago there were some discussions...BTW I need to contact to hardware designer before let you guys know because something needs to be confirmed by them even I know roughly.

Note I'm in vacation with my family. Will be back on this in several days with exact information.

BRs,
Kukjin

^ permalink raw reply

* [PATCH 05/12] ASoC: sun4i-codec: Add support for A31 playback through headphone output
From: Maxime Ripard @ 2016-10-03 11:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003110804.28235-6-wens@csie.org>

Hi,

On Mon, Oct 03, 2016 at 07:07:57PM +0800, Chen-Yu Tsai wrote:
> The A31 has a similar codec to the A10/A20. The PCM parts are very
> similar, with just different register offsets. The analog paths are
> very different. There are more inputs and outputs.
> 
> The quirks structure is expanded to include different register offsets
> and separate callbacks for creating the ASoC card. Also the DMA burst
> length is increased to 8. While the A10 DMA engine supports bursts of
> 1, 4 and 8, the A31 engine only supports 1 and 8.
> 
> This patch adds support for the basic playback path of the A31 codec,
> from the DAC to the headphones. Headphone detection, microphone,
> signaling, other inputs/outputs and capture will be added later.
> 
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
>  .../devicetree/bindings/sound/sun4i-codec.txt      |   6 +-
>  sound/soc/sunxi/sun4i-codec.c                      | 396 +++++++++++++++++----
>  2 files changed, 334 insertions(+), 68 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/sound/sun4i-codec.txt b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
> index 0dce690f78f5..1d2411cea98d 100644
> --- a/Documentation/devicetree/bindings/sound/sun4i-codec.txt
> +++ b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
> @@ -1,8 +1,10 @@
>  * Allwinner A10 Codec
>  
>  Required properties:
> -- compatible: must be either "allwinner,sun4i-a10-codec" or
> -  "allwinner,sun7i-a20-codec"
> +- compatible: must be one of the following compatibles:
> +		- "allwinner,sun4i-a10-codec"
> +		- "allwinner,sun6i-a31-codec"
> +		- "allwinner,sun7i-a20-codec"

I'm guessing it needs a reset line?

>  - reg: must contain the registers location and length
>  - interrupts: must contain the codec interrupt
>  - dmas: DMA channels for tx and rx dma. See the DMA client binding,
> diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
> index e047ec06d538..9916714ecb71 100644
> --- a/sound/soc/sunxi/sun4i-codec.c
> +++ b/sound/soc/sunxi/sun4i-codec.c
> @@ -3,6 +3,7 @@
>   * Copyright 2014 Jon Smirl <jonsmirl@gmail.com>
>   * Copyright 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
>   * Copyright 2015 Adam Sampson <ats@offog.org>
> + * Copyright 2016 Chen-Yu Tsai <wens@csie.org>
>   *
>   * Based on the Allwinner SDK driver, released under the GPL.
>   *
> @@ -24,8 +25,9 @@
>  #include <linux/delay.h>
>  #include <linux/slab.h>
>  #include <linux/of.h>
> -#include <linux/of_platform.h>
>  #include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
>  #include <linux/clk.h>
>  #include <linux/regmap.h>
>  #include <linux/gpio/consumer.h>
> @@ -55,6 +57,8 @@
>  #define SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH		(0)
>  #define SUN4I_CODEC_DAC_FIFOS			(0x08)
>  #define SUN4I_CODEC_DAC_TXDATA			(0x0c)
> +
> +/* Codec DAC side analog signal controls */
>  #define SUN4I_CODEC_DAC_ACTL			(0x10)
>  #define SUN4I_CODEC_DAC_ACTL_DACAENR			(31)
>  #define SUN4I_CODEC_DAC_ACTL_DACAENL			(30)
> @@ -81,6 +85,8 @@
>  #define SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH		(0)
>  #define SUN4I_CODEC_ADC_FIFOS			(0x20)
>  #define SUN4I_CODEC_ADC_RXDATA			(0x24)
> +
> +/* Codec ADC side analog signal controls */
>  #define SUN4I_CODEC_ADC_ACTL			(0x28)
>  #define SUN4I_CODEC_ADC_ACTL_ADC_R_EN			(31)
>  #define SUN4I_CODEC_ADC_ACTL_ADC_L_EN			(30)
> @@ -93,18 +99,106 @@
>  #define SUN4I_CODEC_ADC_ACTL_DDE			(3)
>  #define SUN4I_CODEC_ADC_DEBUG			(0x2c)
>  
> -/* Other various ADC registers */
> +/* FIFO counters */
>  #define SUN4I_CODEC_DAC_TXCNT			(0x30)
>  #define SUN4I_CODEC_ADC_RXCNT			(0x34)
> +
> +/* Other various ADC registers */
>  #define SUN7I_CODEC_AC_DAC_CAL			(0x38)
>  #define SUN7I_CODEC_AC_MIC_PHONE_CAL		(0x3c)
>  
> +/*** sun6i specific register offsets ***/
> +#define SUN6I_CODEC_ADC_FIFOC			(0x10)
> +#define SUN6I_CODEC_ADC_FIFOC_EN_AD			(28)
> +#define SUN6I_CODEC_ADC_FIFOS			(0x14)
> +#define SUN6I_CODEC_ADC_RXDATA			(0x18)
> +#define SUN6I_CODEC_OM_DACA_CTRL		(0x20)
> +#define SUN6I_CODEC_OM_DACA_CTRL_DACAREN		(31)
> +#define SUN6I_CODEC_OM_DACA_CTRL_DACALEN		(30)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RMIXEN			(29)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LMIXEN			(28)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC1		(23)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC2		(22)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_PHONE		(21)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_PHONEP		(20)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_LINEINR		(19)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACR		(18)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACL		(17)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC1		(16)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC2		(15)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_PHONE		(14)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_PHONEN		(13)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_LINEINL		(12)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACL		(11)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACR		(10)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RHPIS			(9)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LHPIS			(8)
> +#define SUN6I_CODEC_OM_DACA_CTRL_RHPPAMUTE		(7)
> +#define SUN6I_CODEC_OM_DACA_CTRL_LHPPAMUTE		(6)
> +#define SUN6I_CODEC_OM_DACA_CTRL_HPVOL			(0)
> +#define SUN6I_CODEC_OM_PA_CTRL			(0x24)
> +#define SUN6I_CODEC_OM_PA_CTRL_HPPAEN			(31)
> +#define SUN6I_CODEC_OM_PA_CTRL_MIC1G			(15)
> +#define SUN6I_CODEC_OM_PA_CTRL_MIC2G			(12)
> +#define SUN6I_CODEC_OM_PA_CTRL_LINEING			(9)
> +#define SUN6I_CODEC_OM_PA_CTRL_PHONEG			(6)
> +#define SUN6I_CODEC_OM_PA_CTRL_PHONEPG			(3)
> +#define SUN6I_CODEC_OM_PA_CTRL_PHONENG			(0)
> +#define SUN6I_CODEC_MIC_CTRL			(0x28)
> +#define SUN6I_CODEC_MIC_CTRL_HBIASEN			(31)
> +#define SUN6I_CODEC_MIC_CTRL_MBIASEN			(30)
> +#define SUN6I_CODEC_MIC_CTRL_MIC1AMPEN			(28)
> +#define SUN6I_CODEC_MIC_CTRL_MIC1BOOST			(25)
> +#define SUN6I_CODEC_MIC_CTRL_MIC2AMPEN			(24)
> +#define SUN6I_CODEC_MIC_CTRL_MIC2BOOST			(21)
> +#define SUN6I_CODEC_MIC_CTRL_MIC2SLT			(20)
> +#define SUN6I_CODEC_MIC_CTRL_LINEOUTLEN			(19)
> +#define SUN6I_CODEC_MIC_CTRL_LINEOUTREN			(18)
> +#define SUN6I_CODEC_MIC_CTRL_LINEOUTLSRC		(17)
> +#define SUN6I_CODEC_MIC_CTRL_LINEOUTRSRC		(16)
> +#define SUN6I_CODEC_MIC_CTRL_LINEOUTVC			(11)
> +#define SUN6I_CODEC_MIC_CTRL_PHONEPREG			(8)
> +#define SUN6I_CODEC_ADC_ACTL			(0x2c)
> +#define SUN6I_CODEC_ADC_ACTL_ADCREN			(31)
> +#define SUN6I_CODEC_ADC_ACTL_ADCLEN			(30)
> +#define SUN6I_CODEC_ADC_ACTL_ADCRG			(27)
> +#define SUN6I_CODEC_ADC_ACTL_ADCLG			(24)
> +#define SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC1		(13)
> +#define SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC2		(12)
> +#define SUN6I_CODEC_ADC_ACTL_RADCMIX_PHONE		(11)
> +#define SUN6I_CODEC_ADC_ACTL_RADCMIX_PHONEP		(10)
> +#define SUN6I_CODEC_ADC_ACTL_RADCMIX_LINEINR		(9)
> +#define SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXR		(8)
> +#define SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXL		(7)
> +#define SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC1		(6)
> +#define SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC2		(5)
> +#define SUN6I_CODEC_ADC_ACTL_LADCMIX_PHONE		(4)
> +#define SUN6I_CODEC_ADC_ACTL_LADCMIX_PHONEN		(3)
> +#define SUN6I_CODEC_ADC_ACTL_LADCMIX_LINEINL		(2)
> +#define SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXL		(1)
> +#define SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXR		(0)
> +#define SUN6I_CODEC_ADDA_TUNE			(0x30)
> +#define SUN6I_CODEC_CALIBRATION			(0x34)
> +#define SUN6I_CODEC_DAC_TXCNT			(0x40)
> +#define SUN6I_CODEC_ADC_RXCNT			(0x44)
> +#define SUN6I_CODEC_HMIC_CTL			(0x50)
> +#define SUN6I_CODEC_HMIC_DATA			(0x54)
> +
> +/* TODO sun6i DAP (Digital Audio Processing) bits */
> +
> +struct sun4i_codec_regs {
> +	u32	adc_fifoc;
> +	u32	adc_fifos;
> +	u32	adc_rxdata;
> +};
> +
>  struct sun4i_codec {
>  	struct device	*dev;
>  	struct regmap	*regmap;
>  	struct clk	*clk_apb;
>  	struct clk	*clk_module;
>  	struct gpio_desc *gpio_pa;
> +	const struct sun4i_codec_regs *regs;

You're reimplementing reg_field here.

>  
>  	struct snd_dmaengine_dai_dma_data	capture_dma_data;
>  	struct snd_dmaengine_dai_dma_data	playback_dma_data;
> @@ -134,7 +228,7 @@ static void sun4i_codec_stop_playback(struct sun4i_codec *scodec)
>  static void sun4i_codec_start_capture(struct sun4i_codec *scodec)
>  {
>  	/* Enable ADC DRQ */
> -	regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
> +	regmap_update_bits(scodec->regmap, scodec->regs->adc_fifoc,
>  			   BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN),
>  			   BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN));
>  }
> @@ -142,7 +236,7 @@ static void sun4i_codec_start_capture(struct sun4i_codec *scodec)
>  static void sun4i_codec_stop_capture(struct sun4i_codec *scodec)
>  {
>  	/* Disable ADC DRQ */
> -	regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
> +	regmap_update_bits(scodec->regmap, scodec->regs->adc_fifoc,
>  			   BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN), 0);
>  }
>  
> @@ -186,13 +280,13 @@ static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream,
>  
>  
>  	/* Flush RX FIFO */
> -	regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
> +	regmap_update_bits(scodec->regmap, scodec->regs->adc_fifoc,
>  			   BIT(SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH),
>  			   BIT(SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH));
>  
>  
>  	/* Set RX FIFO trigger level */
> -	regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
> +	regmap_update_bits(scodec->regmap, scodec->regs->adc_fifoc,
>  			   0xf << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL,
>  			   0x7 << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL);
>  
> @@ -201,9 +295,12 @@ static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream,
>  	 *        Allwinner's code mentions that it is related
>  	 *        related to microphone gain
>  	 */
> -	regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL,
> -			   0x3 << 25,
> -			   0x1 << 25);
> +	if (!of_device_is_compatible(scodec->dev->of_node,
> +				     "allwinner,sun6i-a31-codec")) {
> +		regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL,
> +				   0x3 << 25,
> +				   0x1 << 25);
> +	}
>  
>  	if (of_device_is_compatible(scodec->dev->of_node,
>  				    "allwinner,sun7i-a20-codec"))
> @@ -213,7 +310,7 @@ static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream,
>  				   0x1 << 8);
>  
>  	/* Fill most significant bits with valid data MSB */
> -	regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
> +	regmap_update_bits(scodec->regmap, scodec->regs->adc_fifoc,
>  			   BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE),
>  			   BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE));
>  
> @@ -342,17 +439,17 @@ static int sun4i_codec_hw_params_capture(struct sun4i_codec *scodec,
>  					 unsigned int hwrate)
>  {
>  	/* Set ADC sample rate */
> -	regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
> +	regmap_update_bits(scodec->regmap, scodec->regs->adc_fifoc,
>  			   7 << SUN4I_CODEC_ADC_FIFOC_ADC_FS,
>  			   hwrate << SUN4I_CODEC_ADC_FIFOC_ADC_FS);
>  
>  	/* Set the number of channels we want to use */
>  	if (params_channels(params) == 1)
> -		regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
> +		regmap_update_bits(scodec->regmap, scodec->regs->adc_fifoc,
>  				   BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN),
>  				   BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN));
>  	else
> -		regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
> +		regmap_update_bits(scodec->regmap, scodec->regs->adc_fifoc,
>  				   BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN), 0);
>  
>  	return 0;
> @@ -385,7 +482,7 @@ static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
>  				   BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS),
>  				   BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
>  
> -		/* Set TX FIFO mode to padding the LSBs with 0 */
> +		/* Use higher 24 bits of TX FIFO */
>  		regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
>  				   BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE),
>  				   0);
> @@ -396,7 +493,7 @@ static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
>  				   BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS),
>  				   0);
>  
> -		/* Set TX FIFO mode to repeat the MSB */
> +		/* Use lower 16 bits of TX FIFO */
>  		regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
>  				   BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE),
>  				   BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
> @@ -502,7 +599,7 @@ static struct snd_soc_dai_driver sun4i_codec_dai = {
>  	},
>  };
>  
> -/*** Codec ***/
> +/*** sun4i Codec ***/
>  static const struct snd_kcontrol_new sun4i_codec_pa_mute =
>  	SOC_DAPM_SINGLE("Switch", SUN4I_CODEC_DAC_ACTL,
>  			SUN4I_CODEC_DAC_ACTL_PA_MUTE, 1, 0);
> @@ -638,6 +735,114 @@ static struct snd_soc_codec_driver sun4i_codec_codec = {
>  	},
>  };
>  
> +/*** sun6i Codec ***/
> +
> +/* mixer controls */
> +static const struct snd_kcontrol_new sun6i_codec_mixer_controls[] = {
> +	SOC_DAPM_DOUBLE("DAC Playback Switch",
> +			SUN6I_CODEC_OM_DACA_CTRL,
> +			SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACL,
> +			SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACR, 1, 0),
> +	SOC_DAPM_DOUBLE("DAC Reversed Playback Switch",
> +			SUN6I_CODEC_OM_DACA_CTRL,
> +			SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACR,
> +			SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACL, 1, 0),
> +};
> +
> +/* headphone controls */
> +static const char * const sun6i_codec_hp_src_enum_text[] = {
> +	"DAC", "Mixer",
> +};
> +
> +static SOC_ENUM_DOUBLE_DECL(sun6i_codec_hp_src_enum,
> +			    SUN6I_CODEC_OM_DACA_CTRL,
> +			    SUN6I_CODEC_OM_DACA_CTRL_LHPIS,
> +			    SUN6I_CODEC_OM_DACA_CTRL_RHPIS,
> +			    sun6i_codec_hp_src_enum_text);
> +
> +static const struct snd_kcontrol_new sun6i_codec_hp_src[] = {
> +	SOC_DAPM_ENUM("Headphone Source Playback Route", sun6i_codec_hp_src_enum),
> +};
> +
> +/* volume / mute controls */
> +static const DECLARE_TLV_DB_SCALE(sun6i_codec_dvol_scale, -7308, 116, 0);
> +static const DECLARE_TLV_DB_SCALE(sun6i_codec_hp_vol_scale, -6300, 100, 1);
> +
> +static const struct snd_kcontrol_new sun6i_codec_codec_widgets[] = {
> +	SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
> +		       SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
> +		       sun6i_codec_dvol_scale),
> +	SOC_SINGLE_TLV("Headphone Playback Volume",
> +		       SUN6I_CODEC_OM_DACA_CTRL,
> +		       SUN6I_CODEC_OM_DACA_CTRL_HPVOL, 0x3f, 0,
> +		       sun6i_codec_hp_vol_scale),
> +	SOC_DOUBLE("Headphone Playback Switch",
> +		   SUN6I_CODEC_OM_DACA_CTRL,
> +		   SUN6I_CODEC_OM_DACA_CTRL_LHPPAMUTE,
> +		   SUN6I_CODEC_OM_DACA_CTRL_RHPPAMUTE, 1, 0),
> +};
> +
> +static const struct snd_soc_dapm_widget sun6i_codec_codec_dapm_widgets[] = {
> +	/* Digital parts of the DACs */
> +	SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
> +			    SUN4I_CODEC_DAC_DPC_EN_DA, 0,
> +			    NULL, 0),
> +
> +	/* Analog parts of the DACs */
> +	SND_SOC_DAPM_DAC("Left DAC", "Codec Playback", SUN6I_CODEC_OM_DACA_CTRL,
> +			 SUN6I_CODEC_OM_DACA_CTRL_DACALEN, 0),
> +	SND_SOC_DAPM_DAC("Right DAC", "Codec Playback", SUN6I_CODEC_OM_DACA_CTRL,
> +			 SUN6I_CODEC_OM_DACA_CTRL_DACAREN, 0),
> +
> +	/* Mixers */
> +	SOC_MIXER_ARRAY("Left Mixer", SUN6I_CODEC_OM_DACA_CTRL,
> +			SUN6I_CODEC_OM_DACA_CTRL_LMIXEN, 0,
> +			sun6i_codec_mixer_controls),
> +	SOC_MIXER_ARRAY("Right Mixer", SUN6I_CODEC_OM_DACA_CTRL,
> +			SUN6I_CODEC_OM_DACA_CTRL_RMIXEN, 0,
> +			sun6i_codec_mixer_controls),
> +
> +	/* Headphone output path */
> +	SND_SOC_DAPM_MUX("Headphone Source Playback Route",
> +			 SND_SOC_NOPM, 0, 0, sun6i_codec_hp_src),
> +	SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN6I_CODEC_OM_PA_CTRL,
> +			     SUN6I_CODEC_OM_PA_CTRL_HPPAEN, 0, NULL, 0),
> +	SND_SOC_DAPM_OUTPUT("HP"),
> +};
> +
> +static const struct snd_soc_dapm_route sun6i_codec_codec_dapm_routes[] = {
> +	/* DAC Routes */
> +	{ "Left DAC", NULL, "DAC Enable" },
> +	{ "Right DAC", NULL, "DAC Enable" },
> +
> +	/* Left Mixer Routes */
> +	{ "Left Mixer", "DAC Playback Switch", "Left DAC" },
> +	{ "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
> +
> +	/* Right Mixer Routes */
> +	{ "Right Mixer", "DAC Playback Switch", "Right DAC" },
> +	{ "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
> +
> +	/* Headphone Routes */
> +	{ "Headphone Source Playback Route", "DAC", "Left DAC" },
> +	{ "Headphone Source Playback Route", "DAC", "Right DAC" },
> +	{ "Headphone Source Playback Route", "Mixer", "Left Mixer" },
> +	{ "Headphone Source Playback Route", "Mixer", "Right Mixer" },
> +	{ "Headphone Amp", NULL, "Headphone Source Playback Route" },
> +	{ "HP", NULL, "Headphone Amp" },
> +};
> +
> +static struct snd_soc_codec_driver sun6i_codec_codec = {
> +	.component_driver = {
> +		.controls		= sun6i_codec_codec_widgets,
> +		.num_controls		= ARRAY_SIZE(sun6i_codec_codec_widgets),
> +		.dapm_widgets		= sun6i_codec_codec_dapm_widgets,
> +		.num_dapm_widgets	= ARRAY_SIZE(sun6i_codec_codec_dapm_widgets),
> +		.dapm_routes		= sun6i_codec_codec_dapm_routes,
> +		.num_dapm_routes	= ARRAY_SIZE(sun6i_codec_codec_dapm_routes),
> +	},
> +};
> +
>  static const struct snd_soc_component_driver sun4i_codec_component = {
>  	.name = "sun4i-codec",
>  };
> @@ -678,45 +883,6 @@ static struct snd_soc_dai_driver dummy_cpu_dai = {
>  	 },
>  };
>  
> -static const struct regmap_config sun4i_codec_regmap_config = {
> -	.reg_bits	= 32,
> -	.reg_stride	= 4,
> -	.val_bits	= 32,
> -	.max_register	= SUN4I_CODEC_ADC_RXCNT,
> -};
> -
> -static const struct regmap_config sun7i_codec_regmap_config = {
> -	.reg_bits	= 32,
> -	.reg_stride	= 4,
> -	.val_bits	= 32,
> -	.max_register	= SUN7I_CODEC_AC_MIC_PHONE_CAL,
> -};
> -
> -struct sun4i_codec_quirks {
> -	const struct regmap_config *regmap_config;
> -};
> -
> -static const struct sun4i_codec_quirks sun4i_codec_quirks = {
> -	.regmap_config = &sun4i_codec_regmap_config,
> -};
> -
> -static const struct sun4i_codec_quirks sun7i_codec_quirks = {
> -	.regmap_config = &sun7i_codec_regmap_config,
> -};
> -
> -static const struct of_device_id sun4i_codec_of_match[] = {
> -	{
> -		.compatible = "allwinner,sun4i-a10-codec",
> -		.data = &sun4i_codec_quirks,
> -	},
> -	{
> -		.compatible = "allwinner,sun7i-a20-codec",
> -		.data = &sun7i_codec_quirks,
> -	},
> -	{}
> -};
> -MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
> -
>  static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
>  							int *num_links)
>  {
> @@ -781,6 +947,102 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
>  	return card;
>  };
>  
> +static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
> +{
> +	struct snd_soc_card *card;
> +
> +	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
> +	if (!card)
> +		return NULL;
> +
> +	card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
> +	if (!card->dai_link)
> +		return NULL;
> +
> +	card->dev	= dev;
> +	card->name	= "sun4i-codec";
> +
> +	return card;
> +};
> +
> +static const struct regmap_config sun4i_codec_regmap_config = {
> +	.reg_bits	= 32,
> +	.reg_stride	= 4,
> +	.val_bits	= 32,
> +	.max_register	= SUN4I_CODEC_ADC_RXCNT,
> +};
> +
> +static const struct regmap_config sun6i_codec_regmap_config = {
> +	.reg_bits	= 32,
> +	.reg_stride	= 4,
> +	.val_bits	= 32,
> +	.max_register	= SUN6I_CODEC_HMIC_DATA,
> +};
> +
> +static const struct regmap_config sun7i_codec_regmap_config = {
> +	.reg_bits	= 32,
> +	.reg_stride	= 4,
> +	.val_bits	= 32,
> +	.max_register	= SUN7I_CODEC_AC_MIC_PHONE_CAL,
> +};
> +
> +static const struct sun4i_codec_regs sun4i_codec_regs = {
> +	.adc_fifoc	= SUN4I_CODEC_ADC_FIFOC,
> +	.adc_fifos	= SUN4I_CODEC_ADC_FIFOS,
> +	.adc_rxdata	= SUN4I_CODEC_ADC_RXDATA,
> +};
> +
> +static const struct sun4i_codec_regs sun6i_codec_regs = {
> +	.adc_fifoc	= SUN6I_CODEC_ADC_FIFOC,
> +	.adc_fifos	= SUN6I_CODEC_ADC_FIFOS,
> +	.adc_rxdata	= SUN6I_CODEC_ADC_RXDATA,
> +};
> +
> +struct sun4i_codec_quirks {
> +	const struct regmap_config *regmap_config;
> +	const struct snd_soc_codec_driver *codec;
> +	const struct sun4i_codec_regs *regs;
> +	struct snd_soc_card * (*create_card)(struct device *dev);
> +};
> +
> +static const struct sun4i_codec_quirks sun4i_codec_quirks = {
> +	.regmap_config	= &sun4i_codec_regmap_config,
> +	.regs		= &sun4i_codec_regs,
> +	.codec		= &sun4i_codec_codec,
> +	.create_card	= sun4i_codec_create_card,
> +};
> +
> +static const struct sun4i_codec_quirks sun6i_a31_codec_quirks = {
> +	.regmap_config	= &sun6i_codec_regmap_config,
> +	.regs		= &sun6i_codec_regs,
> +	.codec		= &sun6i_codec_codec,
> +	.create_card	= sun6i_codec_create_card,
> +};
> +
> +static const struct sun4i_codec_quirks sun7i_codec_quirks = {
> +	.regmap_config	= &sun7i_codec_regmap_config,
> +	.regs		= &sun4i_codec_regs,
> +	.codec		= &sun4i_codec_codec,
> +	.create_card	= sun4i_codec_create_card,
> +};
> +
> +static const struct of_device_id sun4i_codec_of_match[] = {
> +	{
> +		.compatible = "allwinner,sun4i-a10-codec",
> +		.data = &sun4i_codec_quirks,
> +	},
> +	{
> +		.compatible = "allwinner,sun6i-a31-codec",
> +		.data = &sun6i_a31_codec_quirks,
> +	},
> +	{
> +		.compatible = "allwinner,sun7i-a20-codec",
> +		.data = &sun7i_codec_quirks,
> +	},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
> +

I don't really like moving blocks of code over and over again,
especially in the middle of an unrelated patch.

Thanks!
Maxime

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

^ permalink raw reply

* Coresight ETF trace dump failed in Juno r1 with 4.8-rc8
From: Venkatesh Vivekanandan @ 2016-10-03 11:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi All,

I am trying to collect ETF trace from Juno R1 and could see "cpu
stall" while dumping the trace. Attached is the log of sequence
followed. Was trying to collect the trace data from hardware and see
if it is any valid data. Am I missing anything here?.

cenaro-test [rc=0]# echo 0 > /sys/bus/coresight/devices/22140000.etm/enable_sour
[   89.609083] coresight-etm4x 22140000.etm: ETM tracing disabled
[   89.614892] coresight-funnel 220c0000.cluster0-funnel: FUNNEL
inport 1 disabled
[   89.622140] coresight-funnel 20040000.main-funnel: FUNNEL inport 0 disabled
[   89.629057] coresight-tmc 20010000.etf: TMC-ETB/ETF disabled
linaro-test [rc=0]# dd if=/dev/20010000.etf of=/cstrace.bin bs=1
[  128.876846] INFO: rcu_preempt detected stalls on CPUs/tasks:
[  128.882457]  3-...: (65 GPs behind) idle=a3f/140000000000000/0
softirq=314/315 fqs=2288
[  128.890462]  (detected by 1, t=5252 jiffies, g=0, c=-1, q=19)
[  128.896151] Task dump for CPU 3:
[  128.899340] dd              R  running task        0  1237   1234 0x00000002
[  128.906322] Call trace:
[  128.908745] [<ffff000008085560>] __switch_to+0xc8/0xd4
[  128.913826] [<0000000000020000>] 0x20000

This happens consistently with every boot.

Thanks,
Venkatesh.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: r1-trace-log
Type: application/octet-stream
Size: 4121 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161003/34981cfd/attachment-0001.obj>

^ permalink raw reply

* [PATCH 2/2] drm/rockchip: analogix_dp: Refuse to enable PSR if panel doesn't support it
From: Archit Taneja @ 2016-10-03 11:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAOw6vbL1fDpPbFeePEFqYZ+i0sbbsB+vu7fCC8U88HAj-1D2Ag@mail.gmail.com>



On 09/27/2016 06:58 PM, Sean Paul wrote:
> On Fri, Sep 23, 2016 at 10:06 AM, Tomeu Vizoso
> <tomeu.vizoso@collabora.com> wrote:
>> There's no point in enabling PSR when the panel doesn't support it.
>>
>> This also avoids a problem when PSR gets enabled when a CRTC is being
>> disabled, because sometimes in that situation the DSP_HOLD_VALID_INTR
>> interrupt on which we wait will never arrive. This was observed on
>> RK3288 with a panel without PSR (veyron-jaq Chromebook).
>>
>> It's very easy to reproduce by running the kms_rmfb test in IGT a few
>> times.
>>
>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>
> Thanks for digging into this.
>
> Reviewed-by: Sean Paul <seanpaul@chromium.org>
>

queued to drm-misc.

Archit


>
>
>> Cc: Sean Paul <seanpaul@chromium.org>
>> Cc: Yakir Yang <ykk@rock-chips.com>
>> Cc: Archit Taneja <architt@codeaurora.org>
>> ---
>>  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>> index e83be157cc2a..8548e8271639 100644
>> --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>> +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>> @@ -85,6 +85,9 @@ static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
>>         struct rockchip_dp_device *dp = to_dp(encoder);
>>         unsigned long flags;
>>
>> +       if (!analogix_dp_psr_supported(dp->dev))
>> +               return;
>> +
>>         dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
>>
>>         spin_lock_irqsave(&dp->psr_lock, flags);
>> --
>> 2.7.4
>>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH v5 2/5] drm/bridge: Add RGB to VGA bridge support
From: Archit Taneja @ 2016-10-03 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160930143709.1388-3-maxime.ripard@free-electrons.com>

Hi Maxime,

On 09/30/2016 08:07 PM, Maxime Ripard wrote:
> Some boards have an entirely passive RGB to VGA bridge, based on either
> DACs or resistor ladders.
>
> Those might or might not have an i2c bus routed to the VGA connector in
> order to access the screen EDIDs.
>
> Add a bridge that doesn't do anything but expose the modes available on the
> screen, either based on the EDIDs if available, or based on the XGA
> standards.
>
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  .../bindings/display/bridge/rgb-to-vga-bridge.txt  |  48 +++++
>  drivers/gpu/drm/bridge/Kconfig                     |   7 +
>  drivers/gpu/drm/bridge/Makefile                    |   1 +
>  drivers/gpu/drm/bridge/rgb-to-vga.c                | 229 +++++++++++++++++++++
>  4 files changed, 285 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
>  create mode 100644 drivers/gpu/drm/bridge/rgb-to-vga.c
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
> new file mode 100644
> index 000000000000..a8375bc1f9cb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
> @@ -0,0 +1,48 @@
> +Dumb RGB to VGA bridge
> +----------------------
> +
> +This binding is aimed for dumb RGB to VGA bridges that do not require
> +any configuration.
> +
> +Required properties:
> +
> +- compatible: Must be "rgb-to-vga-bridge"

I'd talked to Laurent on IRC if he's okay with this. And I guess you to
had discussed it during XDC too. He's suggested that it'd be better to
have the compatible string as "simple-vga-dac".

Some of the reasons behind having this:

- We don't need to specify "rgb" in the compatible string since most
simple VGA DACs can only work with an RGB input.
- Also, with "dac" specified in the string, we don't need to
specifically mention "bridge" in the string. Also, bridge is a drm
specific term.
- "simple" is considered because it's an unconfigurable bridge, and it
might be misleading for other VGA DACs to not use "vga-dac".

What do you think about this? If you think it's good, would it be
possible for you to change this? I guess it's okay for the rest of
the patch to stay the same.

Sorry about the churn.

Thanks,
Archit

> +
> +Required nodes:
> +
> +This device has two video ports. Their connections are modeled using the OF
> +graph bindings specified in Documentation/devicetree/bindings/graph.txt.
> +
> +- Video port 0 for RGB input
> +- Video port 1 for VGA output
> +
> +
> +Example
> +-------
> +
> +bridge {
> +	compatible = "rgb-to-vga-bridge";
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +
> +	ports {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		port at 0 {
> +			reg = <0>;
> +
> +			vga_bridge_in: endpoint {
> +				remote-endpoint = <&tcon0_out_vga>;
> +			};
> +		};
> +
> +		port at 1 {
> +			reg = <1>;
> +
> +			vga_bridge_out: endpoint {
> +				remote-endpoint = <&vga_con_in>;
> +			};
> +		};
> +	};
> +};
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index b590e678052d..d690398c541c 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -17,6 +17,13 @@ config DRM_ANALOGIX_ANX78XX
>  	  the HDMI output of an application processor to MyDP
>  	  or DisplayPort.
>
> +config DRM_RGB_TO_VGA
> +	tristate "Dumb RGB to VGA Bridge support"
> +	depends on OF
> +	select DRM_KMS_HELPER
> +	help
> +	  Support for passive RGB to VGA bridges
> +
>  config DRM_DW_HDMI
>  	tristate
>  	select DRM_KMS_HELPER
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> index efdb07e878f5..3bb8cbe09fe9 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -1,6 +1,7 @@
>  ccflags-y := -Iinclude/drm
>
>  obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
> +obj-$(CONFIG_DRM_RGB_TO_VGA) += rgb-to-vga.o
>  obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
>  obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
>  obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
> diff --git a/drivers/gpu/drm/bridge/rgb-to-vga.c b/drivers/gpu/drm/bridge/rgb-to-vga.c
> new file mode 100644
> index 000000000000..5ff4d4f3598f
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/rgb-to-vga.c
> @@ -0,0 +1,229 @@
> +/*
> + * Copyright (C) 2015-2016 Free Electrons
> + * Copyright (C) 2015-2016 NextThing Co
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/of_graph.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +
> +struct dumb_vga {
> +	struct drm_bridge	bridge;
> +	struct drm_connector	connector;
> +
> +	struct i2c_adapter	*ddc;
> +};
> +
> +static inline struct dumb_vga *
> +drm_bridge_to_dumb_vga(struct drm_bridge *bridge)
> +{
> +	return container_of(bridge, struct dumb_vga, bridge);
> +}
> +
> +static inline struct dumb_vga *
> +drm_connector_to_dumb_vga(struct drm_connector *connector)
> +{
> +	return container_of(connector, struct dumb_vga, connector);
> +}
> +
> +static int dumb_vga_get_modes(struct drm_connector *connector)
> +{
> +	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
> +	struct edid *edid;
> +	int ret;
> +
> +	if (IS_ERR(vga->ddc))
> +		goto fallback;
> +
> +	edid = drm_get_edid(connector, vga->ddc);
> +	if (!edid) {
> +		DRM_INFO("EDID readout failed, falling back to standard modes\n");
> +		goto fallback;
> +	}
> +
> +	drm_mode_connector_update_edid_property(connector, edid);
> +	return drm_add_edid_modes(connector, edid);
> +
> +fallback:
> +	/*
> +	 * In case we cannot retrieve the EDIDs (broken or missing i2c
> +	 * bus), fallback on the XGA standards
> +	 */
> +	ret = drm_add_modes_noedid(connector, 1920, 1200);
> +
> +	/* And prefer a mode pretty much anyone can handle */
> +	drm_set_preferred_mode(connector, 1024, 768);
> +
> +	return ret;
> +}
> +
> +static const struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
> +	.get_modes	= dumb_vga_get_modes,
> +};
> +
> +static enum drm_connector_status
> +dumb_vga_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
> +
> +	/*
> +	 * Even if we have an I2C bus, we can't assume that the cable
> +	 * is disconnected if drm_probe_ddc fails. Some cables don't
> +	 * wire the DDC pins, or the I2C bus might not be working at
> +	 * all.
> +	 */
> +	if (!IS_ERR(vga->ddc) && drm_probe_ddc(vga->ddc))
> +		return connector_status_connected;
> +
> +	return connector_status_unknown;
> +}
> +
> +static void
> +dumb_vga_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs dumb_vga_con_funcs = {
> +	.dpms			= drm_atomic_helper_connector_dpms,
> +	.detect			= dumb_vga_connector_detect,
> +	.fill_modes		= drm_helper_probe_single_connector_modes,
> +	.destroy		= dumb_vga_connector_destroy,
> +	.reset			= drm_atomic_helper_connector_reset,
> +	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int dumb_vga_attach(struct drm_bridge *bridge)
> +{
> +	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> +	int ret;
> +
> +	if (!bridge->encoder) {
> +		DRM_ERROR("Missing encoder\n");
> +		return -ENODEV;
> +	}
> +
> +	drm_connector_helper_add(&vga->connector,
> +				 &dumb_vga_con_helper_funcs);
> +	ret = drm_connector_init(bridge->dev, &vga->connector,
> +				 &dumb_vga_con_funcs, DRM_MODE_CONNECTOR_VGA);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize connector\n");
> +		return ret;
> +	}
> +
> +	drm_mode_connector_attach_encoder(&vga->connector,
> +					  bridge->encoder);
> +
> +	return 0;
> +}
> +
> +static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
> +	.attach		= dumb_vga_attach,
> +};
> +
> +static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
> +{
> +	struct device_node *end_node, *phandle, *remote;
> +	struct i2c_adapter *ddc;
> +
> +	end_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
> +	if (!end_node) {
> +		dev_err(dev, "Missing connector endpoint\n");
> +		return ERR_PTR(-ENODEV);
> +	}
> +
> +	remote = of_graph_get_remote_port_parent(end_node);
> +	of_node_put(end_node);
> +	if (!remote) {
> +		dev_err(dev, "Enable to parse remote node\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0);
> +	of_node_put(remote);
> +	if (!phandle)
> +		return ERR_PTR(-ENODEV);
> +
> +	ddc = of_get_i2c_adapter_by_node(phandle);
> +	of_node_put(phandle);
> +	if (!ddc)
> +		return ERR_PTR(-EPROBE_DEFER);
> +
> +	return ddc;
> +}
> +
> +static int dumb_vga_probe(struct platform_device *pdev)
> +{
> +	struct dumb_vga *vga;
> +	int ret;
> +
> +	vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL);
> +	if (!vga)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, vga);
> +
> +	vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
> +	if (IS_ERR(vga->ddc)) {
> +		if (PTR_ERR(vga->ddc) == -ENODEV) {
> +			dev_info(&pdev->dev,
> +				 "No i2c bus specified... Disabling EDID readout\n");
> +		} else {
> +			dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n");
> +			return PTR_ERR(vga->ddc);
> +		}
> +	}
> +
> +	vga->bridge.funcs = &dumb_vga_bridge_funcs;
> +	vga->bridge.of_node = pdev->dev.of_node;
> +
> +	ret = drm_bridge_add(&vga->bridge);
> +	if (ret && !IS_ERR(vga->ddc))
> +		i2c_put_adapter(vga->ddc);
> +
> +	return ret;
> +}
> +
> +static int dumb_vga_remove(struct platform_device *pdev)
> +{
> +	struct dumb_vga *vga = platform_get_drvdata(pdev);
> +
> +	drm_bridge_remove(&vga->bridge);
> +
> +	if (!IS_ERR(vga->ddc))
> +		i2c_put_adapter(vga->ddc);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id dumb_vga_match[] = {
> +	{ .compatible = "rgb-to-vga-bridge" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, dumb_vga_match);
> +
> +struct platform_driver dumb_vga_driver = {
> +	.probe	= dumb_vga_probe,
> +	.remove	= dumb_vga_remove,
> +	.driver		= {
> +		.name		= "rgb-to-vga-bridge",
> +		.of_match_table	= dumb_vga_match,
> +	},
> +};
> +module_platform_driver(dumb_vga_driver);
> +
> +MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
> +MODULE_DESCRIPTION("Dumb RGB to VGA bridge driver");
> +MODULE_LICENSE("GPL");
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply


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