Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
From: Arnd Bergmann @ 2016-09-14 12:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473855354-150093-3-git-send-email-yuanzhichang@hisilicon.com>

On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan wrote:

> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"
> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base address and length of the register set for the device.
> +- ranges: define a 1:1 mapping between the I/O space of the child device and
> +	  the parent.

Do we still need the "ranges" here? The property in your example seems
wrong.

> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;

You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?

> +/**
> + * hisilpc_children_map_sysio - setup the mapping between system Io and
> + *			physical IO
> + *
> + * @child: the device whose IO is handling
> + * @data: some device specific data. For ACPI device, should be NULL.
> + *
> + * Returns >=0 means the mapping is successfully created;
> + * others mean some failures.
> + */
> +static int hisilpc_children_map_sysio(struct device * child, void * data)
> +{
> +	struct resource *iores;
> +	unsigned long cpuio;
> +	struct extio_ops *opsnode;
> +	int ret;
> +	struct hisilpc_dev *lpcdev;
> +
> +	if (!child || !child->parent)
> +		return -EINVAL;
> +
> +	iores = platform_get_resource_byname(to_platform_device(child),
> +					IORESOURCE_IO, "dev_io");
> +	if (!iores)
> +		return -ENODEV;
> +
> +	/*
> +	 * can not use devm_kzalloc to allocate slab for child before its driver
> +	 * start probing. Here allocate the slab with the name of parent.
> +	 */
> +	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
> +	if (!opsnode)
> +		return -ENOMEM;
> +
> +	cpuio = data ? *((unsigned long *)data) : 0;
> +
> +	opsnode->start = iores->start;
> +	opsnode->end = iores->end;
> +	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
> +
> +	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
> +				(unsigned long)iores->start,
> +				(unsigned long)iores->end,
> +				opsnode->ptoffset);
> +
> +	opsnode->pfin = hisilpc_comm_inb;
> +	opsnode->pfout = hisilpc_comm_outb;
> +
> +	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
> +	opsnode->devpara = lpcdev;
> +
> +	/* only apply indirect-IO to ipmi child device */

I don't get this part. The bus driver should not care what its
children are, just register and PIO ranges that the bus can handle
in theory, i.e. from 0x000 to 0xfff.

	Arnd

^ permalink raw reply

* [PATCH V2 2/4] ARM64 LPC: LPC driver implementation on Hip06
From: Arnd Bergmann @ 2016-09-14 12:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57D79D31.8090607@gmail.com>

On Tuesday, September 13, 2016 2:31:13 PM CEST zhichang wrote:
> > 
> > What are the other LPC cycle types that could be supported?
> O. memory and firmware operations are supported too. But at this moment, we only use IO cycle.

What are firmware operations?

Are the memory operations directly mapped or do you also have to go through
an indirect function call?

	Arnd

^ permalink raw reply

* [PATCH v7 22/22] iommu/dma: Avoid PCI host bridge windows
From: Marek Szyprowski @ 2016-09-14 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <49c51c4f-cb00-445d-b8f8-b632babf2b3e@arm.com>

Hi Robin,


On 2016-09-14 13:10, Robin Murphy wrote:
> On 14/09/16 11:55, Marek Szyprowski wrote:
>> On 2016-09-12 18:14, Robin Murphy wrote:
>>> With our DMA ops enabled for PCI devices, we should avoid allocating
>>> IOVAs which a host bridge might misinterpret as peer-to-peer DMA and
>>> lead to faults, corruption or other badness. To be safe, punch out holes
>>> for all of the relevant host bridge's windows when initialising a DMA
>>> domain for a PCI device.
>>>
>>> CC: Marek Szyprowski <m.szyprowski@samsung.com>
>>> CC: Inki Dae <inki.dae@samsung.com>
>>> Reported-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>> I don't know much about PCI and their IOMMU integration, but can't we use
>> the direct mapping region feature of iommu core for it? There are already
>> iommu_get_dm_regions(), iommu_put_dm_regions() and
>> iommu_request_dm_for_dev()
>> functions for handling them...
> It's rather the opposite problem - in the direct-mapping case, we're
> making sure the iommu_domain has translations installed for the given
> IOVAs (which are also the corresponding physical address) before it goes
> live, whereas what we need to do here is make sure the these addresses
> never get used as IOVAs at all, because any attempt to do so them will
> likely go wrong. Thus we carve them out of the iova_domain such that
> they will never get near an actual IOMMU API call.
>
> This is a slightly generalised equivalent of e.g. amd_iommu.c's
> init_reserved_iova_ranges().

Hmmm. Each dm_region have protection parameter. Can't we reuse them to
create prohibited/reserved regions by setting it to 0 (no read / no write)
and mapping to physical 0 address? That's just a quick idea, because
dm_regions and the proposed code for pci looks a bit similar for me...

[...]

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

^ permalink raw reply

* [PATCH V2 4/4] ARM64 LPC: support earlycon for UART connected to LPC
From: Arnd Bergmann @ 2016-09-14 12:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <6e890161-0cd8-6027-f4e5-a222ceddd597@gmail.com>

On Wednesday, September 14, 2016 7:26:22 PM CEST zhichang wrote:
> 
> > 
> >> Hip06 LPC uart need two base addresses for earlycon.
> >> 2. the IO type is mmio to introduce a memory base address to access LPC register file. But the real uart
> >> IO type is UPIO_PORT. This is spcial...
> > 
> > This sounds like a deficiency in the of_setup_earlycon() function,
> > which can only handle MMIO addresses, and won't actually
> > be able to understand nodes without a "ranges" property like
> > you have here.
> > 
> Yes.
> The current of_setup_earlycon only support MMIO and the first reg property must be memory.
> 
> We can not support our LPC uart without any new code.
> But we can implement a private earlycon setup function and register
> it to the __earlycon_table, things will be ok.

I still think you should adapt of_setup_earlycon instead to handle IORESOURCE_IO
registers.

	Arnd

^ permalink raw reply

* [PATCH V6 2/5] PCI/ACPI: Check platform specific ECAM quirks
From: Lorenzo Pieralisi @ 2016-09-14 12:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57D7E53F.1000106@huawei.com>

On Tue, Sep 13, 2016 at 07:38:39PM +0800, Dongdong Liu wrote:
> Hi Tomasz
> 
> ?? 2016/9/13 14:32, Tomasz Nowicki ????:
> >Hi Liu,
> >
> >On 13.09.2016 04:36, Dongdong Liu wrote:
> >>Hi Tomasz
> >>
> >>?? 2016/9/10 3:24, Tomasz Nowicki ????:
> >>>Some platforms may not be fully compliant with generic set of PCI config
> >>>accessors. For these cases we implement the way to overwrite CFG
> >>>accessors
> >>>set and configuration space range.
> >>>
> >>>In first place pci_mcfg_parse() saves machine's IDs and revision number
> >>>(these come from MCFG header) in order to match against known quirk
> >>>entries.
> >>>Then the algorithm traverses available quirk list (static array),
> >>>matches against <oem_id, oem_table_id, rev, domain, bus number range> and
> >>>returns custom PCI config ops and/or CFG resource structure.
> >>>
> >>>When adding new quirk there are two possibilities:
> >>>1. Override default pci_generic_ecam_ops ops but CFG resource comes
> >>>from MCFG
> >>>{ "OEM_ID", "OEM_TABLE_ID", <REV>, <DOMAIN>, <BUS_NR>, &foo_ops,
> >>>MCFG_RES_EMPTY },
> >>>2. Override default pci_generic_ecam_ops ops and CFG resource. For
> >>>this case
> >>>it is also allowed get CFG resource from quirk entry w/o having it in
> >>>MCFG.
> >>>{ "OEM_ID", "OEM_TABLE_ID", <REV>, <DOMAIN>, <BUS_NR>, &boo_ops,
> >>>   DEFINE_RES_MEM(START, SIZE) },
> >>>
> >>>pci_generic_ecam_ops and MCFG entries will be used for platforms
> >>>free from quirks.
> >>>
> >>>Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> >>>Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
> >>>Signed-off-by: Christopher Covington <cov@codeaurora.org>
> >>>---
> >>>  drivers/acpi/pci_mcfg.c | 80
> >>>+++++++++++++++++++++++++++++++++++++++++++++----
> >>>  1 file changed, 74 insertions(+), 6 deletions(-)
> >>>
> >>>diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
> >>>index ffcc651..2b8acc7 100644
> >>>--- a/drivers/acpi/pci_mcfg.c
> >>>+++ b/drivers/acpi/pci_mcfg.c
> >>>@@ -32,6 +32,59 @@ struct mcfg_entry {
> >>>      u8            bus_start;
> >>>      u8            bus_end;
> >>>  };
> >>>+struct mcfg_fixup {
> >>>+    char oem_id[ACPI_OEM_ID_SIZE + 1];
> >>>+    char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
> >>>+    u32 oem_revision;
> >>>+    u16 seg;
> >>>+    struct resource bus_range;
> >>>+    struct pci_ecam_ops *ops;
> >>>+    struct resource cfgres;
> >>>+};
> >>>+
> >>>+#define MCFG_DOM_ANY            (-1)
> >>>+#define MCFG_BUS_RANGE(start, end)    DEFINE_RES_NAMED((start),    \
> >>>+                        ((end) - (start) + 1),    \
> >>>+                        NULL, IORESOURCE_BUS)
> >>>+#define MCFG_BUS_ANY        MCFG_BUS_RANGE(0x0, 0xff)
> >>>+#define MCFG_RES_EMPTY        DEFINE_RES_NAMED(0, 0, NULL, 0)
> >>>+
> >>>+static struct mcfg_fixup mcfg_quirks[] = {
> >>>+/*    { OEM_ID, OEM_TABLE_ID, REV, DOMAIN, BUS_RANGE, cfgres, ops }, */
> >>>+};
> >>>+
> >>>+static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
> >>>+static char mcfg_oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
> >>>+static u32 mcfg_oem_revision;
> >>>+
> >>>+static void pci_mcfg_match_quirks(struct acpi_pci_root *root,
> >>>+                  struct resource *cfgres,
> >>>+                  struct pci_ecam_ops **ecam_ops)
> >>>+{
> >>>+    struct mcfg_fixup *f;
> >>>+    int i;
> >>>+
> >>>+    /*
> >>>+     * First match against PCI topology <domain:bus> then use OEM ID,
> >>>OEM
> >>>+     * table ID, and OEM revision from MCFG table standard header.
> >>>+     */
> >>>+    for (i = 0, f = mcfg_quirks; i < ARRAY_SIZE(mcfg_quirks); i++,
> >>>f++) {
> >>>+        if (f->seg == root->segment &&
> >>
> >>why not use MCFG_DOM_RANGE, I think MCFG_DOM_RANGE is better.
> >>if drop MCFG_DOM_RANGE, mcfg_quirks[] will be more complex.
> >>
> >>static struct mcfg_fixup mcfg_quirks[] = {
> >>/*    { OEM_ID, OEM_TABLE_ID, REV, DOMAIN, BUS_RANGE, cfgres, ops }, */
> >>#ifdef CONFIG_PCI_HOST_THUNDER_ECAM
> >>    /* SoC pass1.x */
> >>    { "CAVIUM", "THUNDERX", 2, 0, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
> >>      MCFG_RES_EMPTY},
> >>    { "CAVIUM", "THUNDERX", 2, 1, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
> >>      MCFG_RES_EMPTY},
> >>    { "CAVIUM", "THUNDERX", 2, 2, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
> >>      MCFG_RES_EMPTY},
> >>    { "CAVIUM", "THUNDERX", 2, 3, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
> >>      MCFG_RES_EMPTY},
> >>    { "CAVIUM", "THUNDERX", 2, 10, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
> >>      MCFG_RES_EMPTY},
> >>    { "CAVIUM", "THUNDERX", 2, 11, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
> >>      MCFG_RES_EMPTY},
> >>    { "CAVIUM", "THUNDERX", 2, 12, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
> >>      MCFG_RES_EMPTY},
> >>    { "CAVIUM", "THUNDERX", 2, 13, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
> >>      MCFG_RES_EMPTY},
> >>#endif
> >>.....
> >>};
> >>
> >>As PATCH v5 we only need define mcfg_quirks as below, It looks better.
> >>static struct pci_cfg_fixup mcfg_quirks[] __initconst = {
> >>/*    { OEM_ID, OEM_TABLE_ID, REV, DOMAIN, BUS_RANGE, pci_ops, init_hook
> >>}, */
> >>#ifdef CONFIG_PCI_HOST_THUNDER_PEM
> >>    /* Pass2.0 */
> >>    { "CAVIUM", "THUNDERX", 1, MCFG_DOM_RANGE(4, 9), MCFG_BUS_ANY, NULL,
> >>      thunder_pem_cfg_init },
> >>    { "CAVIUM", "THUNDERX", 1, MCFG_DOM_RANGE(14, 19), MCFG_BUS_ANY, NULL,
> >>      thunder_pem_cfg_init },
> >>#endif
> >>#ifdef CONFIG_PCI_HISI_ACPI
> >>    { "HISI  ", "HIP05   ", 0, MCFG_DOM_RANGE(0, 3), MCFG_BUS_ANY,
> >>      NULL, hisi_pcie_acpi_hip05_init},
> >>    { "HISI  ", "HIP06   ", 0, MCFG_DOM_RANGE(0, 3), MCFG_BUS_ANY,
> >>      NULL, hisi_pcie_acpi_hip06_init},
> >>    { "HISI  ", "HIP07   ", 0, MCFG_DOM_RANGE(0, 15), MCFG_BUS_ANY,
> >>      NULL, hisi_pcie_acpi_hip07_init},
> >>#endif
> >>};
> >
> >Note this series disallow hisi_pcie_acpi_hip07_init() call. According to the Bjorn suggestion I rework quirk code to override ops and CFG resources only. Giving that I do not see the way to use MCFG_DOM_RANGE macro. For HISI you would need to get CFG range for each possible case:
> >
> >#ifdef CONFIG_PCI_HISI_ACPI
> >     { "HISI  ", "HIP05   ", 0, 0, MCFG_BUS_ANY, &hisi_pcie_ops,
> >       DEFINE_RES_MEM(start0, size0)},
> >     { "HISI  ", "HIP05   ", 0, 1, MCFG_BUS_ANY, &hisi_pcie_ops,
> >       DEFINE_RES_MEM(start1, size1)},
> >     { "HISI  ", "HIP05   ", 0, 2, MCFG_BUS_ANY, &hisi_pcie_ops,
> >       DEFINE_RES_MEM(start2, size2)},
> >     { "HISI  ", "HIP05   ", 0, 3, MCFG_BUS_ANY, &hisi_pcie_ops,
> >       DEFINE_RES_MEM(start3, size3)},
> >[...]
> >#endif
> >
> >Indeed there are more entries here but you do not have to define the same resource array in driver.
> 
> Our host bridge is non ECAM only for the RC bus config space;
> for any other bus underneath the root bus we support ECAM access.
> 
> RC config resource with hardcode as DEFINE_RES_MEM(0xb0070000, SZ_4K),
> EP config resource we get it from MCFG table.
> So we need to override ops, but config resource we only need to hardcode with RC config resource.
> 
> Our host controller ACPI support patch can be found:
> https://lkml.org/lkml/2016/8/31/340
> This patch is based on RFC V5 quirk mechanism.
> 
> Based on V6 quirk mechanism, we have to change it as below:

That's because you are hacking around the quirk mechanism to define
resources that have nothing to do with PCI config regions (that you
ioremap and use to check the PCI link status) and of top of that you are
*still* using the MCFG to describe config regions that are NOT ECAM
compliant, which is the exact opposite of what this patchset is meant
to achieve.

If a config region is not ECAM compliant having it defined in the MCFG
is a firmware bug and the way you are using this patchset is not what
we designed it for, please correct me if I am wrong.

Thanks,
Lorenzo

> 
> #ifdef CONFIG_PCI_HISI_ACPI
> 	{ "HISI ", "HIP05 ", 0, 0, MCFG_BUS_ANY, &hisi_pcie_hip05_ops,
> 	  MCFG_RES_EMPTY},
> 	{ "HISI ", "HIP05 ", 0, 1, MCFG_BUS_ANY, &hisi_pcie_hip05_ops,
> 	  MCFG_RES_EMPTY},
> 	{ "HISI ", "HIP05 ", 0, 2, MCFG_BUS_ANY, &hisi_pcie_hip05_ops,
> 	  MCFG_RES_EMPTY},
> 	{ "HISI ", "HIP05 ", 0, 3, MCFG_BUS_ANY, &hisi_pcie_hip05_ops,
> 	  MCFG_RES_EMPTY},
> 	{ "HISI ", "HIP06 ", 0, 0, MCFG_BUS_ANY, &hisi_pcie_hip06_ops,
> 	  MCFG_RES_EMPTY},
> 	{ "HISI ", "HIP06 ", 0, 1, MCFG_BUS_ANY, &hisi_pcie_hip06_ops,
> 	  MCFG_RES_EMPTY},
> 	{ "HISI ", "HIP06 ", 0, 2, MCFG_BUS_ANY, &hisi_pcie_hip06_ops,
> 	  MCFG_RES_EMPTY},
> 	{ "HISI ", "HIP06 ", 0, 3, MCFG_BUS_ANY, &hisi_pcie_hip06_ops,
>          MCFG_RES_EMPTY},
> 	{ "HISI ", "HIP07 ", 0, 0, MCFG_BUS_ANY, &hisi_pcie_hip07_ops,
> 	  MCFG_RES_EMPTY},
> 	{ "HISI ", "HIP07 ", 0, 1, MCFG_BUS_ANY, &hisi_pcie_hip07_ops,
> 	  MCFG_RES_EMPTY},
> 	....
> 	
> 	{ "HISI ", "HIP07 ", 0, 15, MCFG_BUS_ANY, &hisi_pcie_hip07_ops,
> 	  MCFG_RES_EMPTY},
> 
> #endif
> 
> struct pci_ecam_ops hisi_pci_hip05_ops = {
> 	.bus_shift	= 20,
> 	.init		=  hisi_pci_hip05_init,
> 	.pci_ops	= {
> 		.map_bus	= pci_ecam_map_bus,
> 		.read		= hisi_pcie_acpi_rd_conf,
> 		.write		= hisi_pcie_acpi_wr_conf,
> 	}
> };
> 
> struct pci_ecam_ops hisi_pci_hip06_ops = {
> 	.bus_shift = 20,
> 	.init = hisi_pci_hip06_init,
> 	.pci_ops = {
> 		.map_bus = pci_ecam_map_bus,
> 		.read = hisi_pcie_acpi_rd_conf,
> 		.write = hisi_pcie_acpi_wr_conf,
> 	}
> };
> 
> hisi_pci_hipxx_init function is used to get RC config resource with hardcode.
> .....
> 
> So I hope we can use MCFG_DOM_RANGE, Then I can change it as below.
> 
> #ifdef CONFIG_PCI_HISI_ACPI
> 	{ "HISI  ", "HIP05   ", 0, MCFG_DOM_RANGE(0, 3), MCFG_BUS_ANY,
> 	 &hisi_pcie_hip05_ops, MCFG_RES_EMPTY},
> 	{ "HISI  ", "HIP06   ", 0, MCFG_DOM_RANGE(0, 3), MCFG_BUS_ANY,
> 	 &hisi_pcie_hip06_ops, MCFG_RES_EMPTY},
> 	{ "HISI  ", "HIP07   ", 0, MCFG_DOM_RANGE(0, 15), MCFG_BUS_ANY,
> 	  &hisi_pcie_hip07_ops, MCFG_RES_EMPTY},
> #endif
> 
> Thanks
> Dongdong
> >
> >Thanks,
> >Tomasz
> >
> >.
> >
> 

^ permalink raw reply

* [PATCH v6 0/6] Add MT8173 MDP Driver
From: Hans Verkuil @ 2016-09-14 12:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473340146-6598-1-git-send-email-minghsiu.tsai@mediatek.com>

Hi Minghsiu,

v6 looks good, but I get these warnings when compiling it for i686:

linux-git-i686: WARNINGS

/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c: In function 'mtk_mdp_vpu_handle_init_ack':
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:28:28: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  struct mtk_mdp_vpu *vpu = (struct mtk_mdp_vpu *)msg->ap_inst;
                            ^
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c: In function 'mtk_mdp_vpu_ipi_handler':
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:40:28: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  struct mtk_mdp_vpu *vpu = (struct mtk_mdp_vpu *)msg->ap_inst;
                            ^
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c: In function 'mtk_mdp_vpu_send_ap_ipi':
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:111:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  msg.ap_inst = (uint64_t)vpu;
                ^
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c: In function 'mtk_mdp_vpu_init':
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:129:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  msg.ap_inst = (uint64_t)vpu;
                ^

This is not blocking, but if you can post a follow-up patch for this, then that
would be helpful.

Regards,

	Hans


On 09/08/2016 03:09 PM, Minghsiu Tsai wrote:
> Changes in v6:
> - s_selection() can't set the _DEFAULT and _BOUNDS targets
> - Add Maintainers entry
> 
> Changes in v5:
> - Add ack in the comment of dts patch
> - Fix s/g_selection()
> - Separate format V4L2_PIX_FMT_MT21C into new patch  
> 
> Changes in v4:
> - Add "depends on HAS_DMA" in Kconfig.
> - Fix s/g_selection()
> - Replace struct v4l2_crop with u32 and struct v4l2_rect
> - Remove VB2_USERPTR
> - Move mutex lock after ctx allocation in mtk_mdp_m2m_open()
> - Add new format V4L2_PIX_FMT_YVU420 to support software on Android platform.
> - Only width/height of image in format V4L2_PIX_FMT_MT21 is aligned to 16/16,
>   other ones are aligned to 2/2 by default
> 
> Changes in v3:
> - Modify device ndoe as structured one.
> - Fix conflict in dts on Linux 4.8-rc1
> 
> Changes in v2:
> - Add section to describe blocks function in dts-bindings
> - Remove the assignment of device_caps in querycap()
> - Remove format's name assignment
> - Copy colorspace-related parameters from OUTPUT to CAPTURE
> - Use m2m helper functions
> - Fix DMA allocation failure
> - Initialize lazily vpu instance in streamon()
> 
> ==============
>  Introduction
> ==============
> 
> The purpose of this series is to add the driver for Media Data Path HW embedded in the Mediatek's MT8173 SoC.
> MDP is used for scaling and color space conversion.
> 
> It could convert V4L2_PIX_FMT_MT21 to V4L2_PIX_FMT_NV12M or V4L2_PIX_FMT_YUV420M.
> 
> NV12M/YUV420M/MT21 -> MDP -> NV12M/YUV420M
> 
> This patch series rely on MTK VPU driver in patch series "Add MT8173 Video Encoder Driver and VPU Driver"[1] and "Add MT8173 Video Decoder Driver"[2].
> MDP driver rely on VPU driver to load, communicate with VPU.
> 
> Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
> 
> [1]https://patchwork.kernel.org/patch/9002171/
> [2]https://patchwork.kernel.org/patch/9141245/
> 
> ==================
>  Device interface
> ==================
> 
> In principle the driver bases on v4l2 memory-to-memory framework:
> it provides a single video node and each opened file handle gets its own private context with separate buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers) and CAPTURE (for destination buffers).
> OUTPUT and CAPTURE buffer could be MMAP or DMABUF memory type.
> 
> v4l2-compliance test output:
> v4l2-compliance SHA   : abc1453dfe89f244dccd3460d8e1a2e3091cbadb
> 
> Driver Info:
>         Driver name   : mtk-mdp
>         Card type     : soc:mdp
>         Bus info      : platform:mt8173
>         Driver version: 4.8.0
>         Capabilities  : 0x84204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
>                 Device Capabilities
>         Device Caps   : 0x04204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
> 
> Compliance test for device /dev/image-proc0 (not using libv4l2):
> 
> Required ioctls:
>         test VIDIOC_QUERYCAP: OK
> 
> Allow for multiple opens:
>         test second video open: OK
>         test VIDIOC_QUERYCAP: OK
>         test VIDIOC_G/S_PRIORITY: OK
>         test for unlimited opens: OK
> 
> Debug ioctls:
>         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>         test VIDIOC_LOG_STATUS: OK (Not Supported)
> 
> Input ioctls:
>         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>         test VIDIOC_ENUMAUDIO: OK (Not Supported)
>         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDIO: OK (Not Supported)
>         Inputs: 0 Audio Inputs: 0 Tuners: 0
> 
> Output ioctls:
>         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>         Outputs: 0 Audio Outputs: 0 Modulators: 0
> 
> Input/Output configuration ioctls:
>         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>         test VIDIOC_G/S_EDID: OK (Not Supported)
> 
>         Control ioctls:
>                 test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
>                 test VIDIOC_QUERYCTRL: OK
>                 test VIDIOC_G/S_CTRL: OK
>                 test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>                 test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>                 test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>                 Standard Controls: 5 Private Controls: 0
> 
>         Format ioctls:
>                 test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>                 test VIDIOC_G/S_PARM: OK (Not Supported)
>                 test VIDIOC_G_FBUF: OK (Not Supported)
>                 test VIDIOC_G_FMT: OK
>                 test VIDIOC_TRY_FMT: OK
>                 test VIDIOC_S_FMT: OK
>                 test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
>                 test Cropping: OK
>                 test Composing: OK
>                 test Scaling: OK
> 
>         Codec ioctls:
>                 test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
>                 test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>                 test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
> 
>         Buffer ioctls:
>                 test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>                 test VIDIOC_EXPBUF: OK
> 
> Test input 0:
> 
> 
> Total: 43, Succeeded: 43, Failed: 0, Warnings: 0
> 
> Minghsiu Tsai (6):
>   VPU: mediatek: Add mdp support
>   dt-bindings: Add a binding for Mediatek MDP
>   media: Add Mediatek MDP Driver
>   arm64: dts: mediatek: Add MDP for MT8173
>   media: mtk-mdp: support pixelformat V4L2_PIX_FMT_MT21C
>   media: mtk-mdp: add Maintainers entry for Mediatek MDP driver
> 
>  .../devicetree/bindings/media/mediatek-mdp.txt     |  109 ++
>  MAINTAINERS                                        |    9 +
>  arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   84 ++
>  drivers/media/platform/Kconfig                     |   17 +
>  drivers/media/platform/Makefile                    |    2 +
>  drivers/media/platform/mtk-mdp/Makefile            |    9 +
>  drivers/media/platform/mtk-mdp/mtk_mdp_comp.c      |  159 +++
>  drivers/media/platform/mtk-mdp/mtk_mdp_comp.h      |   72 ++
>  drivers/media/platform/mtk-mdp/mtk_mdp_core.c      |  294 +++++
>  drivers/media/platform/mtk-mdp/mtk_mdp_core.h      |  260 ++++
>  drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h       |  126 ++
>  drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c       | 1278 ++++++++++++++++++++
>  drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h       |   22 +
>  drivers/media/platform/mtk-mdp/mtk_mdp_regs.c      |  156 +++
>  drivers/media/platform/mtk-mdp/mtk_mdp_regs.h      |   31 +
>  drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c       |  145 +++
>  drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h       |   41 +
>  drivers/media/platform/mtk-vpu/mtk_vpu.h           |    5 +
>  18 files changed, 2819 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/mediatek-mdp.txt
>  create mode 100644 drivers/media/platform/mtk-mdp/Makefile
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.c
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.h
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.h
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
>  create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h
> 

^ permalink raw reply

* [RESEND PATCH] arm64: kgdb: fix single stepping
From: Giuseppe CAVALLARO @ 2016-09-14 12:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1429578793-3971-1-git-send-email-takahiro.akashi@linaro.org>

Hello

[snip]

> We can avoid this issue by specifying "nokgdbroundup" in kernel parameter,
> but this will also leave other cpus be in unknown state in terms of kgdb,
> and may result in interfering with kgdb activity.

> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org 
<http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>>

Tested-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>

[snip]

^ permalink raw reply

* [PATCH v7 00/22] Generic DT bindings for PCI IOMMUs and ARM SMMU
From: Robin Murphy @ 2016-09-14 12:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <04a0a682-4fdc-8d62-57cd-efdf730582c6@redhat.com>

On 14/09/16 13:32, Auger Eric wrote:
> Hi,
> On 14/09/2016 12:35, Robin Murphy wrote:
>> On 14/09/16 09:41, Auger Eric wrote:
>>> Hi,
>>>
>>> On 12/09/2016 18:13, Robin Murphy wrote:
>>>> Hi all,
>>>>
>>>> To any more confusing fixups and crazily numbered extra patches, here's
>>>> a quick v7 with everything rebased into the right order. The significant
>>>> change this time is to implement iommu_fwspec properly from the start,
>>>> which ends up being far simpler and more robust than faffing about
>>>> introducing it somewhere 'less intrusive' to move toward core code later.
>>>>
>>>> New branch in the logical place:
>>>>
>>>> git://linux-arm.org/linux-rm iommu/generic-v7
>>>
>>> For information, as discussed privately with Robin I experience some
>>> regressions with the former and now deprecated dt description.
>>>
>>> on my AMD Overdrive board and my old dt description I now only see a
>>> single group:
>>>
>>> /sys/kernel/iommu_groups/
>>> /sys/kernel/iommu_groups/0
>>> /sys/kernel/iommu_groups/0/devices
>>> /sys/kernel/iommu_groups/0/devices/e0700000.xgmac
>>>
>>> whereas I formerly see
>>>
>>> /sys/kernel/iommu_groups/
>>> /sys/kernel/iommu_groups/3
>>> /sys/kernel/iommu_groups/3/devices
>>> /sys/kernel/iommu_groups/3/devices/0000:00:00.0
>>> /sys/kernel/iommu_groups/1
>>> /sys/kernel/iommu_groups/1/devices
>>> /sys/kernel/iommu_groups/1/devices/e0700000.xgmac
>>> /sys/kernel/iommu_groups/4
>>> /sys/kernel/iommu_groups/4/devices
>>> /sys/kernel/iommu_groups/4/devices/0000:00:02.2
>>> /sys/kernel/iommu_groups/4/devices/0000:01:00.1
>>> /sys/kernel/iommu_groups/4/devices/0000:00:02.0
>>> /sys/kernel/iommu_groups/4/devices/0000:01:00.0
>>> /sys/kernel/iommu_groups/2
>>> /sys/kernel/iommu_groups/2/devices
>>> /sys/kernel/iommu_groups/2/devices/e0900000.xgmac
>>> /sys/kernel/iommu_groups/0
>>> /sys/kernel/iommu_groups/0/devices
>>> /sys/kernel/iommu_groups/0/devices/f0000000.pcie
>>>
>>> This is the group topology without ACS override. Applying the non
>>> upstreamed "pci: Enable overrides for missing ACS capabilities" I used
>>> to see separate groups for each PCIe components. Now I don't see any
>>> difference with and without ACS override.
>>
>> OK, having reproduced on my Juno, the problem looks to be that
>> of_for_each_phandle() leaves err set to -ENOENT after successfully
>> walking a phandle list, which makes __find_legacy_master_phandle()
>> always bail out after the first SMMU.
>>
>> Can you confirm that the following diff fixes things for you?
> 
> Well it improves but there are still differences in the group topology.
> The PFs now are in group 0.
> 
> root at trusty:~# lspci -nk
> 00:00.0 0600: 1022:1a00
>         Subsystem: 1022:1a00
> 00:02.0 0600: 1022:1a01
> 00:02.2 0604: 1022:1a02
>         Kernel driver in use: pcieport
> 01:00.0 0200: 8086:1521 (rev 01)
>         Subsystem: 8086:0002
>         Kernel driver in use: igb
> 01:00.1 0200: 8086:1521 (rev 01)
>         Subsystem: 8086:0002
>         Kernel driver in use: igb
> 
> 
> with your series + fix:
> /sys/kernel/iommu_groups/
> /sys/kernel/iommu_groups/3
> /sys/kernel/iommu_groups/3/devices
> /sys/kernel/iommu_groups/3/devices/0000:00:00.0
> /sys/kernel/iommu_groups/1
> /sys/kernel/iommu_groups/1/devices
> /sys/kernel/iommu_groups/1/devices/e0700000.xgmac
> /sys/kernel/iommu_groups/4
> /sys/kernel/iommu_groups/4/devices
> /sys/kernel/iommu_groups/4/devices/0000:00:02.2
> /sys/kernel/iommu_groups/4/devices/0000:00:02.0
> /sys/kernel/iommu_groups/2
> /sys/kernel/iommu_groups/2/devices
> /sys/kernel/iommu_groups/2/devices/e0900000.xgmac
> /sys/kernel/iommu_groups/0
> /sys/kernel/iommu_groups/0/devices
> /sys/kernel/iommu_groups/0/devices/0000:01:00.1
> /sys/kernel/iommu_groups/0/devices/f0000000.pcie
> /sys/kernel/iommu_groups/0/devices/0000:01:00.0
> 
> Before (4.8-rc5):
> 
> /sys/kernel/iommu_groups/
> /sys/kernel/iommu_groups/3
> /sys/kernel/iommu_groups/3/devices
> /sys/kernel/iommu_groups/3/devices/0000:00:00.0
> /sys/kernel/iommu_groups/1
> /sys/kernel/iommu_groups/1/devices
> /sys/kernel/iommu_groups/1/devices/e0700000.xgmac
> /sys/kernel/iommu_groups/4
> /sys/kernel/iommu_groups/4/devices
> /sys/kernel/iommu_groups/4/devices/0000:00:02.2
> /sys/kernel/iommu_groups/4/devices/0000:01:00.1
> /sys/kernel/iommu_groups/4/devices/0000:00:02.0
> /sys/kernel/iommu_groups/4/devices/0000:01:00.0
> /sys/kernel/iommu_groups/2
> /sys/kernel/iommu_groups/2/devices
> /sys/kernel/iommu_groups/2/devices/e0900000.xgmac
> /sys/kernel/iommu_groups/0
> /sys/kernel/iommu_groups/0/devices
> /sys/kernel/iommu_groups/0/devices/f0000000.pcie

Your DT claims that f0000000.pcie (i.e. the "platform device" side of
the host controller) owns the IDs 0x100 0x101 0x102 0x103 0x200 0x201
0x202 0x203 0x300 0x301 0x302 0x303 0x400 0x401 0x402 0x403. Thus when
new devices (the PCI PFs) come along *also* claiming those IDs (via the
RID-to-SID assumption), we now detect the aliasing and assign them to
the existing group.

The only way that DT worked without SMR conflicts before is that
f0000000.pcie wasn't actually getting attached to a domain, thus wasn't
getting SMRs allocated (ISTR you _did_ get conflicts back when we first
tried to switch on default domains; that was probably the reason).

Robin.

> 
> Thanks
> 
> Eric
> 
>>
>> Robin
>>
>> --->8---
>> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
>> index fa892d25004d..ac4aab97c93a 100644
>> --- a/drivers/iommu/arm-smmu.c
>> +++ b/drivers/iommu/arm-smmu.c
>> @@ -477,7 +477,7 @@ static int __find_legacy_master_phandle(struct
>> device *dev, void *data)
>>  			return 1;
>>  		}
>>  	it->node = np;
>> -	return err;
>> +	return err == -ENOENT ? 0 : err;
>>  }
>>
>>  static struct platform_driver arm_smmu_driver;
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
> 

^ permalink raw reply

* [PATCH 0/8] drm/rockchip: Flip wait clean-up
From: Tomasz Figa @ 2016-09-14 12:54 UTC (permalink / raw)
  To: linux-arm-kernel

The display controller found on Rockchip SoCs supported by Rockchip DRM
driver (VOP) is a bit problematic, because it does not provide hardware
vblank counter. Because vblank interrupt is used to feed the software
counter, the driver had custom code to wait for flip completion to avoid
race between atomic flush and vblank interrupt handler.

This, however, brought a different set of issues. In fact, even with the
custom wait code, there is stil a race between the handler and driver
state update (of the values used to compare with registers to determine
if flip has completed). On top of that, legacy cursor updates are not
implemented properly and have to wait for vblank to complete, which
is against the API specification.

This series attempts to clean up the driver from this custom waiting code,
eliminating related races and bringing correct handling of legacy cursor
plane. It also gives a nice effect of more than 100 lines of code removed.

This is a forward port of patches from 4.4 kernel used by ChromiumOS and
tested there. Even though the code base has not changed significantly, it
would be nice if someone with proper testing environment could give them
a try.

Based on for-next branch of Sean Paul's dogwood tree:
https://cgit.freedesktop.org/~seanpaul/dogwood/log/?h=for-next
git://people.freedesktop.org/~seanpaul/dogwood

Tomasz Figa (8):
  drm/rockchip: Clear interrupt status bits before enabling
  drm/rockchip: Get rid of some unnecessary code
  drm/rockchip: Avoid race with vblank count increment
  drm/rockchip: Unreference framebuffers from flip work
  drm/rockchip: Replace custom wait_for_vblanks with helper
  drm/rockchip: Do not enable vblank without event
  drm/rockchip: Always signal event in next vblank after cfg_done
  drm/rockchip: Kill vop_plane_state

 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 -
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  64 +------
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 247 +++++++++++-----------------
 3 files changed, 95 insertions(+), 217 deletions(-)

-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply

* [PATCH 1/8] drm/rockchip: Clear interrupt status bits before enabling
From: Tomasz Figa @ 2016-09-14 12:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857701-9250-1-git-send-email-tfiga@chromium.org>

The enable register only masks the raw status bits to signal CPU
interrupt only for enabled interrupts. The status bits are activated
regardless of the enable register. This means that we might have an old
interrupt event queued, which we are not interested in. To avoid getting
a spurious interrupt signalled, we have to clear the old bit before we
update the enable register.

Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 209167b..7e811cf 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -414,6 +414,7 @@ static void vop_dsp_hold_valid_irq_enable(struct vop *vop)
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
 
+	VOP_INTR_SET_TYPE(vop, clear, DSP_HOLD_VALID_INTR, 1);
 	VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 1);
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
@@ -479,6 +480,7 @@ static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
 	spin_lock_irqsave(&vop->irq_lock, flags);
 
 	VOP_CTRL_SET(vop, line_flag_num[0], line_num);
+	VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1);
 	VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
@@ -921,6 +923,7 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
 
+	VOP_INTR_SET_TYPE(vop, clear, FS_INTR, 1);
 	VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1);
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH 2/8] drm/rockchip: Get rid of some unnecessary code
From: Tomasz Figa @ 2016-09-14 12:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857701-9250-1-git-send-email-tfiga@chromium.org>

Current code implements prepare_fb and cleanup_fb callbacks only to
grab/release fb references, which is already done by atomic framework
when creating/destryoing plane state. Let's remove these
unused bits.

Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 7e811cf..68988c6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -641,22 +641,6 @@ static void vop_plane_destroy(struct drm_plane *plane)
 	drm_plane_cleanup(plane);
 }
 
-static int vop_plane_prepare_fb(struct drm_plane *plane,
-				struct drm_plane_state *new_state)
-{
-	if (plane->state->fb)
-		drm_framebuffer_reference(plane->state->fb);
-
-	return 0;
-}
-
-static void vop_plane_cleanup_fb(struct drm_plane *plane,
-				 struct drm_plane_state *old_state)
-{
-	if (old_state->fb)
-		drm_framebuffer_unreference(old_state->fb);
-}
-
 static int vop_plane_atomic_check(struct drm_plane *plane,
 			   struct drm_plane_state *state)
 {
@@ -849,8 +833,6 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 }
 
 static const struct drm_plane_helper_funcs plane_helper_funcs = {
-	.prepare_fb = vop_plane_prepare_fb,
-	.cleanup_fb = vop_plane_cleanup_fb,
 	.atomic_check = vop_plane_atomic_check,
 	.atomic_update = vop_plane_atomic_update,
 	.atomic_disable = vop_plane_atomic_disable,
-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH 3/8] drm/rockchip: Avoid race with vblank count increment
From: Tomasz Figa @ 2016-09-14 12:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857701-9250-1-git-send-email-tfiga@chromium.org>

Since VOP does not have a hardware vblank count register, the ongoing
commit might be racing with a requested vblank interrupt, which would
increment the software vblank counter before the changes being committed
actually happen.

To avoid this, we can extend .atomic_flush(), so after it sets cfg_done
bit, it polls the vblank interrupt bit until it's inactive to make sure
that any old vblank interrupt gets to the handler and then uses
synchronize_irq(vop->irq) to make sure the handler finishes running.

The polling case should happen very rarely, but even if, the total wait
time should be relatively low and in practice almost equal to the vop
hardirq handler running time.

Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 34 +++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 68988c6..f989440 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/iopoll.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/pm_runtime.h>
@@ -1063,6 +1064,32 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
 	rockchip_drm_psr_activate(&vop->crtc);
 }
 
+static bool vop_fs_irq_is_pending(struct vop *vop)
+{
+	return VOP_INTR_GET_TYPE(vop, status, FS_INTR);
+}
+
+static void vop_wait_for_irq_handler(struct vop *vop)
+{
+	bool pending;
+	int ret;
+
+	/*
+	 * Spin until frame start interrupt status bit goes low, which means
+	 * that interrupt handler was invoked and cleared it. The timeout of
+	 * 10 msecs is really too long, but it is just a safety measure if
+	 * something goes really wrong. The wait will only happen in the very
+	 * unlikely case of a vblank happening exactly at the same time and
+	 * shouldn't exceed microseconds range.
+	 */
+	ret = readx_poll_timeout_atomic(vop_fs_irq_is_pending, vop, pending,
+					!pending, 0, 10 * 1000);
+	if (ret)
+		DRM_DEV_ERROR(vop->dev, "VOP vblank IRQ stuck for 10 ms\n");
+
+	synchronize_irq(vop->irq);
+}
+
 static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 				  struct drm_crtc_state *old_crtc_state)
 {
@@ -1076,6 +1103,13 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 	vop_cfg_done(vop);
 
 	spin_unlock(&vop->reg_lock);
+
+	/*
+	 * There is a (rather unlikely) possiblity that a vblank interrupt
+	 * fired before we set the cfg_done bit. To avoid spuriously
+	 * signalling flip completion we need to wait for it to finish.
+	 */
+	vop_wait_for_irq_handler(vop);
 }
 
 static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH 4/8] drm/rockchip: Unreference framebuffers from flip work
From: Tomasz Figa @ 2016-09-14 12:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857701-9250-1-git-send-email-tfiga@chromium.org>

Currently the driver waits for vblank and then unreferences old
framebuffers from atomic commit code path. This is however breaking the
legacy cursor API, which requires the updates to be fully asynchronous.
Instead of just adding a special case for cursor, we can have actually
smaller amount of code to unreference any changed framebuffer from a
flip work.

Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 41 +++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index f989440..86829f5 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -17,6 +17,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_flip_work.h>
 #include <drm/drm_plane_helper.h>
 
 #include <linux/kernel.h>
@@ -89,6 +90,10 @@
 #define to_vop_win(x) container_of(x, struct vop_win, base)
 #define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)
 
+enum vop_pending {
+	VOP_PENDING_FB_UNREF,
+};
+
 struct vop_plane_state {
 	struct drm_plane_state base;
 	int format;
@@ -122,6 +127,9 @@ struct vop {
 	/* protected by dev->event_lock */
 	struct drm_pending_vblank_event *event;
 
+	struct drm_flip_work fb_unref_work;
+	unsigned long pending;
+
 	struct completion line_flag_completion;
 
 	const struct vop_data *data;
@@ -1093,7 +1101,11 @@ static void vop_wait_for_irq_handler(struct vop *vop)
 static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 				  struct drm_crtc_state *old_crtc_state)
 {
+	struct drm_atomic_state *old_state = old_crtc_state->state;
+	struct drm_plane_state *old_plane_state;
 	struct vop *vop = to_vop(crtc);
+	struct drm_plane *plane;
+	int i;
 
 	if (WARN_ON(!vop->is_enabled))
 		return;
@@ -1110,6 +1122,19 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 	 * signalling flip completion we need to wait for it to finish.
 	 */
 	vop_wait_for_irq_handler(vop);
+
+	for_each_plane_in_state(old_state, plane, old_plane_state, i) {
+		if (!old_plane_state->fb)
+			continue;
+
+		if (old_plane_state->fb == plane->state->fb)
+			continue;
+
+		drm_framebuffer_reference(old_plane_state->fb);
+		drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
+		set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+	}
 }
 
 static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -1185,6 +1210,15 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {
 	.atomic_destroy_state = vop_crtc_destroy_state,
 };
 
+static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
+{
+	struct vop *vop = container_of(work, struct vop, fb_unref_work);
+	struct drm_framebuffer *fb = val;
+
+	drm_crtc_vblank_put(&vop->crtc);
+	drm_framebuffer_unreference(fb);
+}
+
 static bool vop_win_pending_is_complete(struct vop_win *vop_win)
 {
 	dma_addr_t yrgb_mst;
@@ -1223,6 +1257,9 @@ static void vop_handle_vblank(struct vop *vop)
 
 	if (!completion_done(&vop->wait_update_complete))
 		complete(&vop->wait_update_complete);
+
+	if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending))
+		drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq);
 }
 
 static irqreturn_t vop_isr(int irq, void *data)
@@ -1361,6 +1398,9 @@ static int vop_create_crtc(struct vop *vop)
 		goto err_cleanup_crtc;
 	}
 
+	drm_flip_work_init(&vop->fb_unref_work, "fb_unref",
+			   vop_fb_unref_worker);
+
 	init_completion(&vop->dsp_hold_completion);
 	init_completion(&vop->wait_update_complete);
 	init_completion(&vop->line_flag_completion);
@@ -1404,6 +1444,7 @@ static void vop_destroy_crtc(struct vop *vop)
 	 * references the CRTC.
 	 */
 	drm_crtc_cleanup(crtc);
+	drm_flip_work_cleanup(&vop->fb_unref_work);
 }
 
 static int vop_initial(struct vop *vop)
-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH 5/8] drm/rockchip: Replace custom wait_for_vblanks with helper
From: Tomasz Figa @ 2016-09-14 12:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857701-9250-1-git-send-email-tfiga@chromium.org>

Currently the driver uses a custom function to wait for flip to complete
after an atomic commit. It was needed before because of two problems:
 - there is no hardware vblank counter, so the original helper would
   have a race condition with the vblank interrupt,
 - the driver didn't support unreferencing cursor framebuffers
   asynchronously to the commit, which was what the helper expected.
Since both problems have been solved by previous patches, we can now
make the driver use the generic helper and remove custom waiting code.

Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 -
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 64 +----------------------------
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 14 -------
 3 files changed, 1 insertion(+), 78 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 5c69845..fb6226c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -39,7 +39,6 @@ struct drm_connector;
 struct rockchip_crtc_funcs {
 	int (*enable_vblank)(struct drm_crtc *crtc);
 	void (*disable_vblank)(struct drm_crtc *crtc);
-	void (*wait_for_update)(struct drm_crtc *crtc);
 };
 
 struct rockchip_crtc_state {
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 9890ecc..0f6eda0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -174,68 +174,6 @@ static void rockchip_drm_output_poll_changed(struct drm_device *dev)
 		drm_fb_helper_hotplug_event(fb_helper);
 }
 
-static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc)
-{
-	struct rockchip_drm_private *priv = crtc->dev->dev_private;
-	int pipe = drm_crtc_index(crtc);
-	const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe];
-
-	if (crtc_funcs && crtc_funcs->wait_for_update)
-		crtc_funcs->wait_for_update(crtc);
-}
-
-/*
- * We can't use drm_atomic_helper_wait_for_vblanks() because rk3288 and rk3066
- * have hardware counters for neither vblanks nor scanlines, which results in
- * a race where:
- *				| <-- HW vsync irq and reg take effect
- *	       plane_commit --> |
- *	get_vblank and wait --> |
- *				| <-- handle_vblank, vblank->count + 1
- *		 cleanup_fb --> |
- *		iommu crash --> |
- *				| <-- HW vsync irq and reg take effect
- *
- * This function is equivalent but uses rockchip_crtc_wait_for_update() instead
- * of waiting for vblank_count to change.
- */
-static void
-rockchip_atomic_wait_for_complete(struct drm_device *dev, struct drm_atomic_state *old_state)
-{
-	struct drm_crtc_state *old_crtc_state;
-	struct drm_crtc *crtc;
-	int i, ret;
-
-	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
-		/* No one cares about the old state, so abuse it for tracking
-		 * and store whether we hold a vblank reference (and should do a
-		 * vblank wait) in the ->enable boolean.
-		 */
-		old_crtc_state->enable = false;
-
-		if (!crtc->state->active)
-			continue;
-
-		if (!drm_atomic_helper_framebuffer_changed(dev,
-				old_state, crtc))
-			continue;
-
-		ret = drm_crtc_vblank_get(crtc);
-		if (ret != 0)
-			continue;
-
-		old_crtc_state->enable = true;
-	}
-
-	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
-		if (!old_crtc_state->enable)
-			continue;
-
-		rockchip_crtc_wait_for_update(crtc);
-		drm_crtc_vblank_put(crtc);
-	}
-}
-
 static void
 rockchip_atomic_commit_tail(struct drm_atomic_state *state)
 {
@@ -250,7 +188,7 @@ rockchip_atomic_commit_tail(struct drm_atomic_state *state)
 
 	drm_atomic_helper_commit_hw_done(state);
 
-	rockchip_atomic_wait_for_complete(dev, state);
+	drm_atomic_helper_wait_for_vblanks(dev, state);
 
 	drm_atomic_helper_cleanup_planes(dev, state);
 }
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 86829f5..af9ddbe 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -122,7 +122,6 @@ struct vop {
 	struct mutex vsync_mutex;
 	bool vsync_work_pending;
 	struct completion dsp_hold_completion;
-	struct completion wait_update_complete;
 
 	/* protected by dev->event_lock */
 	struct drm_pending_vblank_event *event;
@@ -937,18 +936,9 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 }
 
-static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
-{
-	struct vop *vop = to_vop(crtc);
-
-	reinit_completion(&vop->wait_update_complete);
-	WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100));
-}
-
 static const struct rockchip_crtc_funcs private_crtc_funcs = {
 	.enable_vblank = vop_crtc_enable_vblank,
 	.disable_vblank = vop_crtc_disable_vblank,
-	.wait_for_update = vop_crtc_wait_for_update,
 };
 
 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -1255,9 +1245,6 @@ static void vop_handle_vblank(struct vop *vop)
 	}
 	spin_unlock_irqrestore(&drm->event_lock, flags);
 
-	if (!completion_done(&vop->wait_update_complete))
-		complete(&vop->wait_update_complete);
-
 	if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending))
 		drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq);
 }
@@ -1402,7 +1389,6 @@ static int vop_create_crtc(struct vop *vop)
 			   vop_fb_unref_worker);
 
 	init_completion(&vop->dsp_hold_completion);
-	init_completion(&vop->wait_update_complete);
 	init_completion(&vop->line_flag_completion);
 	crtc->port = port;
 	rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH 6/8] drm/rockchip: Do not enable vblank without event
From: Tomasz Figa @ 2016-09-14 12:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857701-9250-1-git-send-email-tfiga@chromium.org>

Originally we needed to enable vblank for any atomic commit to kick the
PSR machine, but that was changed and we no longer need to do so from
a vblank interrupt. Let's return to original behavior of enabling
vblank only if it is really necessary.

This essentially reverts commit 5b6804034ae9 ("drm/rockchip: Enable
vblank without event").

Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index af9ddbe..bb7a865 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -116,7 +116,6 @@ struct vop {
 	struct device *dev;
 	struct drm_device *drm_dev;
 	bool is_enabled;
-	bool vblank_active;
 
 	/* mutex vsync_ work */
 	struct mutex vsync_mutex;
@@ -1135,11 +1134,10 @@ static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
 	rockchip_drm_psr_flush(crtc);
 
 	spin_lock_irq(&crtc->dev->event_lock);
-	vop->vblank_active = true;
-	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-	WARN_ON(vop->event);
-
 	if (crtc->state->event) {
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		WARN_ON(vop->event);
+
 		vop->event = crtc->state->event;
 		crtc->state->event = NULL;
 	}
@@ -1236,12 +1234,8 @@ static void vop_handle_vblank(struct vop *vop)
 	spin_lock_irqsave(&drm->event_lock, flags);
 	if (vop->event) {
 		drm_crtc_send_vblank_event(crtc, vop->event);
-		vop->event = NULL;
-
-	}
-	if (vop->vblank_active) {
-		vop->vblank_active = false;
 		drm_crtc_vblank_put(crtc);
+		vop->event = NULL;
 	}
 	spin_unlock_irqrestore(&drm->event_lock, flags);
 
@@ -1518,7 +1512,6 @@ static int vop_initial(struct vop *vop)
 	clk_disable(vop->aclk);
 
 	vop->is_enabled = false;
-	vop->vblank_active = false;
 
 	return 0;
 
-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH 7/8] drm/rockchip: Always signal event in next vblank after cfg_done
From: Tomasz Figa @ 2016-09-14 12:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857701-9250-1-git-send-email-tfiga@chromium.org>

This patch makes the driver send the pending vblank event in next vblank
following the commit, relying on vblank signalling improvements done in
previous patches. This gives us vblank events that always represent the
real moment of changes hitting on the screen (which was the case only
for complete FB changes before) and lets us remove the manual window
update check.

Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 54 ++++++-----------------------
 1 file changed, 10 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index bb7a865..cacdffb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -105,10 +105,6 @@ struct vop_win {
 	struct drm_plane base;
 	const struct vop_win_data *data;
 	struct vop *vop;
-
-	/* protected by dev->event_lock */
-	bool enable;
-	dma_addr_t yrgb_mst;
 };
 
 struct vop {
@@ -716,11 +712,6 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
 	if (!old_state->crtc)
 		return;
 
-	spin_lock_irq(&plane->dev->event_lock);
-	vop_win->enable = false;
-	vop_win->yrgb_mst = 0;
-	spin_unlock_irq(&plane->dev->event_lock);
-
 	spin_lock(&vop->reg_lock);
 
 	VOP_WIN_SET(vop, win, enable, 0);
@@ -784,11 +775,6 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 	offset += (src->y1 >> 16) * fb->pitches[0];
 	vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
 
-	spin_lock_irq(&plane->dev->event_lock);
-	vop_win->enable = true;
-	vop_win->yrgb_mst = vop_plane_state->yrgb_mst;
-	spin_unlock_irq(&plane->dev->event_lock);
-
 	spin_lock(&vop->reg_lock);
 
 	VOP_WIN_SET(vop, win, format, vop_plane_state->format);
@@ -1112,6 +1098,16 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 	 */
 	vop_wait_for_irq_handler(vop);
 
+	spin_lock_irq(&crtc->dev->event_lock);
+	if (crtc->state->event) {
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		WARN_ON(vop->event);
+
+		vop->event = crtc->state->event;
+		crtc->state->event = NULL;
+	}
+	spin_unlock_irq(&crtc->dev->event_lock);
+
 	for_each_plane_in_state(old_state, plane, old_plane_state, i) {
 		if (!old_plane_state->fb)
 			continue;
@@ -1129,19 +1125,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
 				  struct drm_crtc_state *old_crtc_state)
 {
-	struct vop *vop = to_vop(crtc);
-
 	rockchip_drm_psr_flush(crtc);
-
-	spin_lock_irq(&crtc->dev->event_lock);
-	if (crtc->state->event) {
-		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-		WARN_ON(vop->event);
-
-		vop->event = crtc->state->event;
-		crtc->state->event = NULL;
-	}
-	spin_unlock_irq(&crtc->dev->event_lock);
 }
 
 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
@@ -1207,29 +1191,11 @@ static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
 	drm_framebuffer_unreference(fb);
 }
 
-static bool vop_win_pending_is_complete(struct vop_win *vop_win)
-{
-	dma_addr_t yrgb_mst;
-
-	if (!vop_win->enable)
-		return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
-
-	yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
-
-	return yrgb_mst == vop_win->yrgb_mst;
-}
-
 static void vop_handle_vblank(struct vop *vop)
 {
 	struct drm_device *drm = vop->drm_dev;
 	struct drm_crtc *crtc = &vop->crtc;
 	unsigned long flags;
-	int i;
-
-	for (i = 0; i < vop->data->win_size; i++) {
-		if (!vop_win_pending_is_complete(&vop->win[i]))
-			return;
-	}
 
 	spin_lock_irqsave(&drm->event_lock, flags);
 	if (vop->event) {
-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH 8/8] drm/rockchip: Kill vop_plane_state
From: Tomasz Figa @ 2016-09-14 12:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857701-9250-1-git-send-email-tfiga@chromium.org>

After changes introduced by last patches, there is no useful data stored
in vop_plane_state struct.  Let's remove it and make the driver use
generic plane state alone.

Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 94 +++++------------------------
 1 file changed, 15 insertions(+), 79 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index cacdffb..57650c9 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -88,19 +88,11 @@
 
 #define to_vop(x) container_of(x, struct vop, crtc)
 #define to_vop_win(x) container_of(x, struct vop_win, base)
-#define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)
 
 enum vop_pending {
 	VOP_PENDING_FB_UNREF,
 };
 
-struct vop_plane_state {
-	struct drm_plane_state base;
-	int format;
-	dma_addr_t yrgb_mst;
-	bool enable;
-};
-
 struct vop_win {
 	struct drm_plane base;
 	const struct vop_win_data *data;
@@ -651,7 +643,6 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
 	struct drm_crtc_state *crtc_state;
 	struct drm_framebuffer *fb = state->fb;
 	struct vop_win *vop_win = to_vop_win(plane);
-	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
 	const struct vop_win_data *win = vop_win->data;
 	int ret;
 	struct drm_rect clip;
@@ -661,7 +652,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
 					DRM_PLANE_HELPER_NO_SCALING;
 
 	if (!crtc || !fb)
-		goto out_disable;
+		return 0;
 
 	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
 	if (WARN_ON(!crtc_state))
@@ -679,11 +670,11 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
 		return ret;
 
 	if (!state->visible)
-		goto out_disable;
+		return 0;
 
-	vop_plane_state->format = vop_convert_format(fb->pixel_format);
-	if (vop_plane_state->format < 0)
-		return vop_plane_state->format;
+	ret = vop_convert_format(fb->pixel_format);
+	if (ret < 0)
+		return ret;
 
 	/*
 	 * Src.x1 can be odd when do clip, but yuv plane start point
@@ -692,19 +683,12 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
 	if (is_yuv_support(fb->pixel_format) && ((state->src.x1 >> 16) % 2))
 		return -EINVAL;
 
-	vop_plane_state->enable = true;
-
-	return 0;
-
-out_disable:
-	vop_plane_state->enable = false;
 	return 0;
 }
 
 static void vop_plane_atomic_disable(struct drm_plane *plane,
 				     struct drm_plane_state *old_state)
 {
-	struct vop_plane_state *vop_plane_state = to_vop_plane_state(old_state);
 	struct vop_win *vop_win = to_vop_win(plane);
 	const struct vop_win_data *win = vop_win->data;
 	struct vop *vop = to_vop(old_state->crtc);
@@ -717,8 +701,6 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
 	VOP_WIN_SET(vop, win, enable, 0);
 
 	spin_unlock(&vop->reg_lock);
-
-	vop_plane_state->enable = false;
 }
 
 static void vop_plane_atomic_update(struct drm_plane *plane,
@@ -727,7 +709,6 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 	struct drm_plane_state *state = plane->state;
 	struct drm_crtc *crtc = state->crtc;
 	struct vop_win *vop_win = to_vop_win(plane);
-	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
 	const struct vop_win_data *win = vop_win->data;
 	struct vop *vop = to_vop(state->crtc);
 	struct drm_framebuffer *fb = state->fb;
@@ -742,6 +723,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 	dma_addr_t dma_addr;
 	uint32_t val;
 	bool rb_swap;
+	int format;
 
 	/*
 	 * can't update plane when vop is disabled.
@@ -752,7 +734,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 	if (WARN_ON(!vop->is_enabled))
 		return;
 
-	if (!vop_plane_state->enable) {
+	if (!state->visible) {
 		vop_plane_atomic_disable(plane, old_state);
 		return;
 	}
@@ -773,13 +755,15 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 
 	offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
 	offset += (src->y1 >> 16) * fb->pitches[0];
-	vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
+	dma_addr = rk_obj->dma_addr + offset + fb->offsets[0];
+
+	format = vop_convert_format(fb->pixel_format);
 
 	spin_lock(&vop->reg_lock);
 
-	VOP_WIN_SET(vop, win, format, vop_plane_state->format);
+	VOP_WIN_SET(vop, win, format, format);
 	VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2);
-	VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
+	VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
 	if (is_yuv_support(fb->pixel_format)) {
 		int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
 		int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
@@ -831,61 +815,13 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = {
 	.atomic_disable = vop_plane_atomic_disable,
 };
 
-static void vop_atomic_plane_reset(struct drm_plane *plane)
-{
-	struct vop_plane_state *vop_plane_state =
-					to_vop_plane_state(plane->state);
-
-	if (plane->state && plane->state->fb)
-		drm_framebuffer_unreference(plane->state->fb);
-
-	kfree(vop_plane_state);
-	vop_plane_state = kzalloc(sizeof(*vop_plane_state), GFP_KERNEL);
-	if (!vop_plane_state)
-		return;
-
-	plane->state = &vop_plane_state->base;
-	plane->state->plane = plane;
-}
-
-static struct drm_plane_state *
-vop_atomic_plane_duplicate_state(struct drm_plane *plane)
-{
-	struct vop_plane_state *old_vop_plane_state;
-	struct vop_plane_state *vop_plane_state;
-
-	if (WARN_ON(!plane->state))
-		return NULL;
-
-	old_vop_plane_state = to_vop_plane_state(plane->state);
-	vop_plane_state = kmemdup(old_vop_plane_state,
-				  sizeof(*vop_plane_state), GFP_KERNEL);
-	if (!vop_plane_state)
-		return NULL;
-
-	__drm_atomic_helper_plane_duplicate_state(plane,
-						  &vop_plane_state->base);
-
-	return &vop_plane_state->base;
-}
-
-static void vop_atomic_plane_destroy_state(struct drm_plane *plane,
-					   struct drm_plane_state *state)
-{
-	struct vop_plane_state *vop_state = to_vop_plane_state(state);
-
-	__drm_atomic_helper_plane_destroy_state(state);
-
-	kfree(vop_state);
-}
-
 static const struct drm_plane_funcs vop_plane_funcs = {
 	.update_plane	= drm_atomic_helper_update_plane,
 	.disable_plane	= drm_atomic_helper_disable_plane,
 	.destroy = vop_plane_destroy,
-	.reset = vop_atomic_plane_reset,
-	.atomic_duplicate_state = vop_atomic_plane_duplicate_state,
-	.atomic_destroy_state = vop_atomic_plane_destroy_state,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 };
 
 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH 00/19] Remove STiH415 and STiH416 SoC platform support
From: Peter Griffin @ 2016-09-14 12:59 UTC (permalink / raw)
  To: linux-arm-kernel

ST have sent patches which remove clock support for these SoCs [1]
which once applied mean the platform will no longer boot.

This series cleans up various STi platform drivers which have
support for these SoC's, by removing code, and updating the DT
documentation accordingly. Some drivers such as miphy365 and
stih41x-usb can be removed completely because the IP is only
found on these legacy SoC's.

Once this series is applied, drm display driver, and ALSA SoC
are the main two remaining references to the legacy SoCs, other
than clocks which already have patches on the ML.

regards,

Peter.

[1] https://patchwork.kernel.org/patch/9157571/

Peter Griffin (19):
  phy: phy-miphy365x: Remove miphy365 driver and dt binding
    documentation.
  phy: stih41x-usb: Remove usb phy driver and dt binding documentation.
  MAINTAINERS: Remove phy-miphy365x.c entry from STi arch
  MAINTAINERS: Remove phy-stih41x-usb.c entry from STi arch
  ARM: multi_v7_defconfig: Remove miphy365 phy.
  ARM: multi_v7_defconfig: Remove stih41x phy Kconfig symbol.
  ahci: st: Remove STiH416 dt example
  thermal: sti: Remove obsolete platforms from the DT doc.
  thermal: sti: Remove obsolete STiH416 platform support.
  watchdog: bindings: Remove obsolete platforms from dt doc.
  watchdog: st_wdt: Remove support for obsolete platforms
  reset: sti: Remove obsolete platforms from dt binding doc.
  pinctrl: st: Remove STiH415/6 SoC pinctrl driver support.
  pinctrl: st: Remove obsolete platforms from pinctrl-st dt doc
  reset: sti: Remove STiH415/6 reset support
  power: reset: st-poweroff: Remove obsolete platforms.
  power: reset: st: Remove obsolete platforms from dt doc
  stmmac: dwmac-sti: Remove obsolete STi platforms
  reset: sti: softreset: Remove obsolete platforms from dt binding doc.

 Documentation/devicetree/bindings/ata/ahci-st.txt  |  15 -
 .../devicetree/bindings/net/sti-dwmac.txt          |   3 +-
 .../devicetree/bindings/phy/phy-miphy365x.txt      |  77 ---
 .../devicetree/bindings/phy/phy-stih41x-usb.txt    |  24 -
 .../devicetree/bindings/pinctrl/pinctrl-st.txt     |  33 +-
 .../devicetree/bindings/power/reset/st-reset.txt   |   7 +-
 .../devicetree/bindings/reset/st,sti-powerdown.txt |  12 +-
 .../devicetree/bindings/reset/st,sti-softreset.txt |   8 +-
 .../devicetree/bindings/thermal/st-thermal.txt     |  28 +-
 .../devicetree/bindings/watchdog/st_lpc_wdt.txt    |   3 +-
 MAINTAINERS                                        |   2 -
 arch/arm/configs/multi_v7_defconfig                |   2 -
 arch/arm/mach-sti/Kconfig                          |   2 -
 drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c    |  37 --
 drivers/phy/Kconfig                                |  18 -
 drivers/phy/Makefile                               |   2 -
 drivers/phy/phy-miphy365x.c                        | 625 ---------------------
 drivers/phy/phy-stih41x-usb.c                      | 188 -------
 drivers/pinctrl/pinctrl-st.c                       |  76 +--
 drivers/power/reset/st-poweroff.c                  |  41 --
 drivers/reset/sti/Kconfig                          |   8 -
 drivers/reset/sti/Makefile                         |   2 -
 drivers/reset/sti/reset-stih415.c                  | 112 ----
 drivers/reset/sti/reset-stih416.c                  | 143 -----
 drivers/thermal/st/st_thermal_memmap.c             |  34 +-
 drivers/watchdog/st_lpc_wdt.c                      |  33 --
 26 files changed, 65 insertions(+), 1470 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/phy/phy-miphy365x.txt
 delete mode 100644 Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt
 delete mode 100644 drivers/phy/phy-miphy365x.c
 delete mode 100644 drivers/phy/phy-stih41x-usb.c
 delete mode 100644 drivers/reset/sti/reset-stih415.c
 delete mode 100644 drivers/reset/sti/reset-stih416.c

-- 
1.9.1

^ permalink raw reply

* [PATCH 01/19] phy: phy-miphy365x: Remove miphy365 driver and dt binding documentation.
From: Peter Griffin @ 2016-09-14 12:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857993-6386-1-git-send-email-peter.griffin@linaro.org>

This phy is only used on STiH415/6 based silicon, and support for
these SoC's is being removed from the kernel.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
To: kishon at ti.com
---
 .../devicetree/bindings/phy/phy-miphy365x.txt      |  77 ---
 drivers/phy/Kconfig                                |  10 -
 drivers/phy/Makefile                               |   1 -
 drivers/phy/phy-miphy365x.c                        | 625 ---------------------
 4 files changed, 713 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/phy/phy-miphy365x.txt
 delete mode 100644 drivers/phy/phy-miphy365x.c

diff --git a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
deleted file mode 100644
index 8772900..0000000
--- a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-STMicroelectronics STi MIPHY365x PHY binding
-============================================
-
-This binding describes a miphy device that is used to control PHY hardware
-for SATA and PCIe.
-
-Required properties (controller (parent) node):
-- compatible    : Should be "st,miphy365x-phy"
-- st,syscfg     : Phandle / integer array property. Phandle of sysconfig group
-		  containing the miphy registers and integer array should contain
-		  an entry for each port sub-node, specifying the control
-		  register offset inside the sysconfig group.
-
-Required nodes	:  A sub-node is required for each channel the controller
-		   provides. Address range information including the usual
-		   'reg' and 'reg-names' properties are used inside these
-		   nodes to describe the controller's topology. These nodes
-		   are translated by the driver's .xlate() function.
-
-Required properties (port (child) node):
-- #phy-cells 	: Should be 1 (See second example)
-		  Cell after port phandle is device type from:
-			- PHY_TYPE_SATA
-			- PHY_TYPE_PCI
-- reg        	: Address and length of register sets for each device in
-		  "reg-names"
-- reg-names     : The names of the register addresses corresponding to the
-		  registers filled in "reg":
-			- sata:   For SATA devices
-			- pcie:   For PCIe devices
-
-Optional properties (port (child) node):
-- st,sata-gen	     :	Generation of locally attached SATA IP. Expected values
-			are {1,2,3). If not supplied generation 1 hardware will
-			be expected
-- st,pcie-tx-pol-inv :	Bool property to invert the polarity PCIe Tx (Txn/Txp)
-- st,sata-tx-pol-inv :	Bool property to invert the polarity SATA Tx (Txn/Txp)
-
-Example:
-
-	miphy365x_phy: miphy365x at fe382000 {
-		compatible      = "st,miphy365x-phy";
-		st,syscfg  	= <&syscfg_rear 0x824 0x828>;
-		#address-cells	= <1>;
-		#size-cells	= <1>;
-		ranges;
-
-		phy_port0: port at fe382000 {
-			reg = <0xfe382000 0x100>, <0xfe394000 0x100>;
-			reg-names = "sata", "pcie";
-			#phy-cells = <1>;
-			st,sata-gen = <3>;
-		};
-
-		phy_port1: port at fe38a000 {
-			reg = <0xfe38a000 0x100>, <0xfe804000 0x100>;;
-			reg-names = "sata", "pcie", "syscfg";
-			#phy-cells = <1>;
-			st,pcie-tx-pol-inv;
-		};
-	};
-
-Specifying phy control of devices
-=================================
-
-Device nodes should specify the configuration required in their "phys"
-property, containing a phandle to the phy port node and a device type.
-
-Example:
-
-#include <dt-bindings/phy/phy.h>
-
-	sata0: sata at fe380000 {
-		...
-		phys	  = <&phy_port0 PHY_TYPE_SATA>;
-		...
-	};
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 19bff3a..d1f22ac 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -120,16 +120,6 @@ config PHY_MIPHY28LP
 	  Enable this to support the miphy transceiver (for SATA/PCIE/USB3)
 	  that is part of STMicroelectronics STiH407 SoC.
 
-config PHY_MIPHY365X
-	tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
-	depends on ARCH_STI
-	depends on HAS_IOMEM
-	depends on OF
-	select GENERIC_PHY
-	help
-	  Enable this to support the miphy transceiver (for SATA/PCIE)
-	  that is part of STMicroelectronics STiH41x SoC series.
-
 config PHY_RCAR_GEN2
 	tristate "Renesas R-Car generation 2 USB PHY driver"
 	depends on ARCH_RENESAS
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 90ae198..d169d80 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -17,7 +17,6 @@ obj-$(CONFIG_PHY_PXA_28NM_USB2)		+= phy-pxa-28nm-usb2.o
 obj-$(CONFIG_PHY_PXA_28NM_HSIC)		+= phy-pxa-28nm-hsic.o
 obj-$(CONFIG_PHY_MVEBU_SATA)		+= phy-mvebu-sata.o
 obj-$(CONFIG_PHY_MIPHY28LP) 		+= phy-miphy28lp.o
-obj-$(CONFIG_PHY_MIPHY365X)		+= phy-miphy365x.o
 obj-$(CONFIG_PHY_RCAR_GEN2)		+= phy-rcar-gen2.o
 obj-$(CONFIG_PHY_RCAR_GEN3_USB2)	+= phy-rcar-gen3-usb2.o
 obj-$(CONFIG_OMAP_CONTROL_PHY)		+= phy-omap-control.o
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
deleted file mode 100644
index e661f3b..0000000
--- a/drivers/phy/phy-miphy365x.c
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * Copyright (C) 2014 STMicroelectronics ? All Rights Reserved
- *
- * STMicroelectronics PHY driver MiPHY365 (for SoC STiH416).
- *
- * Authors: Alexandre Torgue <alexandre.torgue@st.com>
- *          Lee Jones <lee.jones@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/clk.h>
-#include <linux/phy/phy.h>
-#include <linux/delay.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-
-#include <dt-bindings/phy/phy.h>
-
-#define HFC_TIMEOUT		100
-
-#define SYSCFG_SELECT_SATA_MASK	BIT(1)
-#define SYSCFG_SELECT_SATA_POS	1
-
-/* MiPHY365x register definitions */
-#define RESET_REG		0x00
-#define RST_PLL			BIT(1)
-#define RST_PLL_CAL		BIT(2)
-#define RST_RX			BIT(4)
-#define RST_MACRO		BIT(7)
-
-#define STATUS_REG		0x01
-#define IDLL_RDY		BIT(0)
-#define PLL_RDY			BIT(1)
-#define DES_BIT_LOCK		BIT(2)
-#define DES_SYMBOL_LOCK		BIT(3)
-
-#define CTRL_REG		0x02
-#define TERM_EN			BIT(0)
-#define PCI_EN			BIT(2)
-#define DES_BIT_LOCK_EN		BIT(3)
-#define TX_POL			BIT(5)
-
-#define INT_CTRL_REG		0x03
-
-#define BOUNDARY1_REG		0x10
-#define SPDSEL_SEL		BIT(0)
-
-#define BOUNDARY3_REG		0x12
-#define TX_SPDSEL_GEN1_VAL	0
-#define TX_SPDSEL_GEN2_VAL	0x01
-#define TX_SPDSEL_GEN3_VAL	0x02
-#define RX_SPDSEL_GEN1_VAL	0
-#define RX_SPDSEL_GEN2_VAL	(0x01 << 3)
-#define RX_SPDSEL_GEN3_VAL	(0x02 << 3)
-
-#define PCIE_REG		0x16
-
-#define BUF_SEL_REG		0x20
-#define CONF_GEN_SEL_GEN3	0x02
-#define CONF_GEN_SEL_GEN2	0x01
-#define PD_VDDTFILTER		BIT(4)
-
-#define TXBUF1_REG		0x21
-#define SWING_VAL		0x04
-#define SWING_VAL_GEN1		0x03
-#define PREEMPH_VAL		(0x3 << 5)
-
-#define TXBUF2_REG		0x22
-#define TXSLEW_VAL		0x2
-#define TXSLEW_VAL_GEN1		0x4
-
-#define RXBUF_OFFSET_CTRL_REG	0x23
-
-#define RXBUF_REG		0x25
-#define SDTHRES_VAL		0x01
-#define EQ_ON3			(0x03 << 4)
-#define EQ_ON1			(0x01 << 4)
-
-#define COMP_CTRL1_REG		0x40
-#define START_COMSR		BIT(0)
-#define START_COMZC		BIT(1)
-#define COMSR_DONE		BIT(2)
-#define COMZC_DONE		BIT(3)
-#define COMP_AUTO_LOAD		BIT(4)
-
-#define COMP_CTRL2_REG		0x41
-#define COMP_2MHZ_RAT_GEN1	0x1e
-#define COMP_2MHZ_RAT		0xf
-
-#define COMP_CTRL3_REG		0x42
-#define COMSR_COMP_REF		0x33
-
-#define COMP_IDLL_REG		0x47
-#define COMZC_IDLL		0x2a
-
-#define PLL_CTRL1_REG		0x50
-#define PLL_START_CAL		BIT(0)
-#define BUF_EN			BIT(2)
-#define SYNCHRO_TX		BIT(3)
-#define SSC_EN			BIT(6)
-#define CONFIG_PLL		BIT(7)
-
-#define PLL_CTRL2_REG		0x51
-#define BYPASS_PLL_CAL		BIT(1)
-
-#define PLL_RAT_REG		0x52
-
-#define PLL_SSC_STEP_MSB_REG	0x56
-#define PLL_SSC_STEP_MSB_VAL	0x03
-
-#define PLL_SSC_STEP_LSB_REG	0x57
-#define PLL_SSC_STEP_LSB_VAL	0x63
-
-#define PLL_SSC_PER_MSB_REG	0x58
-#define PLL_SSC_PER_MSB_VAL	0
-
-#define PLL_SSC_PER_LSB_REG	0x59
-#define PLL_SSC_PER_LSB_VAL	0xf1
-
-#define IDLL_TEST_REG		0x72
-#define START_CLK_HF		BIT(6)
-
-#define DES_BITLOCK_REG		0x86
-#define BIT_LOCK_LEVEL		0x01
-#define BIT_LOCK_CNT_512	(0x03 << 5)
-
-struct miphy365x_phy {
-	struct phy *phy;
-	void __iomem *base;
-	bool pcie_tx_pol_inv;
-	bool sata_tx_pol_inv;
-	u32 sata_gen;
-	u32 ctrlreg;
-	u8 type;
-};
-
-struct miphy365x_dev {
-	struct device *dev;
-	struct regmap *regmap;
-	struct mutex miphy_mutex;
-	struct miphy365x_phy **phys;
-	int nphys;
-};
-
-/*
- * These values are represented in Device tree. They are considered to be ABI
- * and although they can be extended any existing values must not change.
- */
-enum miphy_sata_gen {
-	SATA_GEN1 = 1,
-	SATA_GEN2,
-	SATA_GEN3
-};
-
-static u8 rx_tx_spd[] = {
-	0, /* GEN0 doesn't exist. */
-	TX_SPDSEL_GEN1_VAL | RX_SPDSEL_GEN1_VAL,
-	TX_SPDSEL_GEN2_VAL | RX_SPDSEL_GEN2_VAL,
-	TX_SPDSEL_GEN3_VAL | RX_SPDSEL_GEN3_VAL
-};
-
-/*
- * This function selects the system configuration,
- * either two SATA, one SATA and one PCIe, or two PCIe lanes.
- */
-static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
-			      struct miphy365x_dev *miphy_dev)
-{
-	bool sata = (miphy_phy->type == PHY_TYPE_SATA);
-
-	return regmap_update_bits(miphy_dev->regmap,
-				  miphy_phy->ctrlreg,
-				  SYSCFG_SELECT_SATA_MASK,
-				  sata << SYSCFG_SELECT_SATA_POS);
-}
-
-static int miphy365x_init_pcie_port(struct miphy365x_phy *miphy_phy,
-				    struct miphy365x_dev *miphy_dev)
-{
-	u8 val;
-
-	if (miphy_phy->pcie_tx_pol_inv) {
-		/* Invert Tx polarity and clear pci_txdetect_pol bit */
-		val = TERM_EN | PCI_EN | DES_BIT_LOCK_EN | TX_POL;
-		writeb_relaxed(val, miphy_phy->base + CTRL_REG);
-		writeb_relaxed(0x00, miphy_phy->base + PCIE_REG);
-	}
-
-	return 0;
-}
-
-static inline int miphy365x_hfc_not_rdy(struct miphy365x_phy *miphy_phy,
-					struct miphy365x_dev *miphy_dev)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
-	u8 mask = IDLL_RDY | PLL_RDY;
-	u8 regval;
-
-	do {
-		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
-		if (!(regval & mask))
-			return 0;
-
-		usleep_range(2000, 2500);
-	} while (time_before(jiffies, timeout));
-
-	dev_err(miphy_dev->dev, "HFC ready timeout!\n");
-	return -EBUSY;
-}
-
-static inline int miphy365x_rdy(struct miphy365x_phy *miphy_phy,
-				struct miphy365x_dev *miphy_dev)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
-	u8 mask = IDLL_RDY | PLL_RDY;
-	u8 regval;
-
-	do {
-		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
-		if ((regval & mask) == mask)
-			return 0;
-
-		usleep_range(2000, 2500);
-	} while (time_before(jiffies, timeout));
-
-	dev_err(miphy_dev->dev, "PHY not ready timeout!\n");
-	return -EBUSY;
-}
-
-static inline void miphy365x_set_comp(struct miphy365x_phy *miphy_phy,
-				      struct miphy365x_dev *miphy_dev)
-{
-	u8 val, mask;
-
-	if (miphy_phy->sata_gen == SATA_GEN1)
-		writeb_relaxed(COMP_2MHZ_RAT_GEN1,
-			       miphy_phy->base + COMP_CTRL2_REG);
-	else
-		writeb_relaxed(COMP_2MHZ_RAT,
-			       miphy_phy->base + COMP_CTRL2_REG);
-
-	if (miphy_phy->sata_gen != SATA_GEN3) {
-		writeb_relaxed(COMSR_COMP_REF,
-			       miphy_phy->base + COMP_CTRL3_REG);
-		/*
-		 * Force VCO current to value defined by address 0x5A
-		 * and disable PCIe100Mref bit
-		 * Enable auto load compensation for pll_i_bias
-		 */
-		writeb_relaxed(BYPASS_PLL_CAL, miphy_phy->base + PLL_CTRL2_REG);
-		writeb_relaxed(COMZC_IDLL, miphy_phy->base + COMP_IDLL_REG);
-	}
-
-	/*
-	 * Force restart compensation and enable auto load
-	 * for Comzc_Tx, Comzc_Rx and Comsr on macro
-	 */
-	val = START_COMSR | START_COMZC | COMP_AUTO_LOAD;
-	writeb_relaxed(val, miphy_phy->base + COMP_CTRL1_REG);
-
-	mask = COMSR_DONE | COMZC_DONE;
-	while ((readb_relaxed(miphy_phy->base + COMP_CTRL1_REG) & mask)	!= mask)
-		cpu_relax();
-}
-
-static inline void miphy365x_set_ssc(struct miphy365x_phy *miphy_phy,
-				     struct miphy365x_dev *miphy_dev)
-{
-	u8 val;
-
-	/*
-	 * SSC Settings. SSC will be enabled through Link
-	 * SSC Ampl. = 0.4%
-	 * SSC Freq = 31KHz
-	 */
-	writeb_relaxed(PLL_SSC_STEP_MSB_VAL,
-		       miphy_phy->base + PLL_SSC_STEP_MSB_REG);
-	writeb_relaxed(PLL_SSC_STEP_LSB_VAL,
-		       miphy_phy->base + PLL_SSC_STEP_LSB_REG);
-	writeb_relaxed(PLL_SSC_PER_MSB_VAL,
-		       miphy_phy->base + PLL_SSC_PER_MSB_REG);
-	writeb_relaxed(PLL_SSC_PER_LSB_VAL,
-		       miphy_phy->base + PLL_SSC_PER_LSB_REG);
-
-	/* SSC Settings complete */
-	if (miphy_phy->sata_gen == SATA_GEN1) {
-		val = PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
-		writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
-	} else {
-		val = SSC_EN | PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
-		writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
-	}
-}
-
-static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
-				    struct miphy365x_dev *miphy_dev)
-{
-	int ret;
-	u8 val;
-
-	/*
-	 * Force PHY macro reset, PLL calibration reset, PLL reset
-	 * and assert Deserializer Reset
-	 */
-	val = RST_PLL | RST_PLL_CAL | RST_RX | RST_MACRO;
-	writeb_relaxed(val, miphy_phy->base + RESET_REG);
-
-	if (miphy_phy->sata_tx_pol_inv)
-		writeb_relaxed(TX_POL, miphy_phy->base + CTRL_REG);
-
-	/*
-	 * Force macro1 to use rx_lspd, tx_lspd
-	 * Force Rx_Clock on first I-DLL phase
-	 * Force Des in HP mode on macro, rx_lspd, tx_lspd for Gen2/3
-	 */
-	writeb_relaxed(SPDSEL_SEL, miphy_phy->base + BOUNDARY1_REG);
-	writeb_relaxed(START_CLK_HF, miphy_phy->base + IDLL_TEST_REG);
-	val = rx_tx_spd[miphy_phy->sata_gen];
-	writeb_relaxed(val, miphy_phy->base + BOUNDARY3_REG);
-
-	/* Wait for HFC_READY = 0 */
-	ret = miphy365x_hfc_not_rdy(miphy_phy, miphy_dev);
-	if (ret)
-		return ret;
-
-	/* Compensation Recalibration */
-	miphy365x_set_comp(miphy_phy, miphy_dev);
-
-	switch (miphy_phy->sata_gen) {
-	case SATA_GEN3:
-		/*
-		 * TX Swing target 550-600mv peak to peak diff
-		 * Tx Slew target 90-110ps rising/falling time
-		 * Rx Eq ON3, Sigdet threshold SDTH1
-		 */
-		val = PD_VDDTFILTER | CONF_GEN_SEL_GEN3;
-		writeb_relaxed(val, miphy_phy->base + BUF_SEL_REG);
-		val = SWING_VAL | PREEMPH_VAL;
-		writeb_relaxed(val, miphy_phy->base + TXBUF1_REG);
-		writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
-		writeb_relaxed(0x00, miphy_phy->base + RXBUF_OFFSET_CTRL_REG);
-		val = SDTHRES_VAL | EQ_ON3;
-		writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
-		break;
-	case SATA_GEN2:
-		/*
-		 * conf gen sel=0x1 to program Gen2 banked registers
-		 * VDDT filter ON
-		 * Tx Swing target 550-600mV peak-to-peak diff
-		 * Tx Slew target 90-110 ps rising/falling time
-		 * RX Equalization ON1, Sigdet threshold SDTH1
-		 */
-		writeb_relaxed(CONF_GEN_SEL_GEN2,
-			       miphy_phy->base + BUF_SEL_REG);
-		writeb_relaxed(SWING_VAL, miphy_phy->base + TXBUF1_REG);
-		writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
-		val = SDTHRES_VAL | EQ_ON1;
-		writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
-		break;
-	case SATA_GEN1:
-		/*
-		 * conf gen sel = 00b to program Gen1 banked registers
-		 * VDDT filter ON
-		 * Tx Swing target 500-550mV peak-to-peak diff
-		 * Tx Slew target120-140 ps rising/falling time
-		 */
-		writeb_relaxed(PD_VDDTFILTER, miphy_phy->base + BUF_SEL_REG);
-		writeb_relaxed(SWING_VAL_GEN1, miphy_phy->base + TXBUF1_REG);
-		writeb_relaxed(TXSLEW_VAL_GEN1,	miphy_phy->base + TXBUF2_REG);
-		break;
-	default:
-		break;
-	}
-
-	/* Force Macro1 in partial mode & release pll cal reset */
-	writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
-	usleep_range(100, 150);
-
-	miphy365x_set_ssc(miphy_phy, miphy_dev);
-
-	/* Wait for phy_ready */
-	ret = miphy365x_rdy(miphy_phy, miphy_dev);
-	if (ret)
-		return ret;
-
-	/*
-	 * Enable macro1 to use rx_lspd & tx_lspd
-	 * Release Rx_Clock on first I-DLL phase on macro1
-	 * Assert deserializer reset
-	 * des_bit_lock_en is set
-	 * bit lock detection strength
-	 * Deassert deserializer reset
-	 */
-	writeb_relaxed(0x00, miphy_phy->base + BOUNDARY1_REG);
-	writeb_relaxed(0x00, miphy_phy->base + IDLL_TEST_REG);
-	writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
-	val = miphy_phy->sata_tx_pol_inv ?
-		(TX_POL | DES_BIT_LOCK_EN) : DES_BIT_LOCK_EN;
-	writeb_relaxed(val, miphy_phy->base + CTRL_REG);
-
-	val = BIT_LOCK_CNT_512 | BIT_LOCK_LEVEL;
-	writeb_relaxed(val, miphy_phy->base + DES_BITLOCK_REG);
-	writeb_relaxed(0x00, miphy_phy->base + RESET_REG);
-
-	return 0;
-}
-
-static int miphy365x_init(struct phy *phy)
-{
-	struct miphy365x_phy *miphy_phy = phy_get_drvdata(phy);
-	struct miphy365x_dev *miphy_dev = dev_get_drvdata(phy->dev.parent);
-	int ret = 0;
-
-	mutex_lock(&miphy_dev->miphy_mutex);
-
-	ret = miphy365x_set_path(miphy_phy, miphy_dev);
-	if (ret) {
-		mutex_unlock(&miphy_dev->miphy_mutex);
-		return ret;
-	}
-
-	/* Initialise Miphy for PCIe or SATA */
-	if (miphy_phy->type == PHY_TYPE_PCIE)
-		ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev);
-	else
-		ret = miphy365x_init_sata_port(miphy_phy, miphy_dev);
-
-	mutex_unlock(&miphy_dev->miphy_mutex);
-
-	return ret;
-}
-
-static int miphy365x_get_addr(struct device *dev,
-		struct miphy365x_phy *miphy_phy, int index)
-{
-	struct device_node *phynode = miphy_phy->phy->dev.of_node;
-	const char *name;
-	int type = miphy_phy->type;
-	int ret;
-
-	ret = of_property_read_string_index(phynode, "reg-names", index, &name);
-	if (ret) {
-		dev_err(dev, "no reg-names property not found\n");
-		return ret;
-	}
-
-	if (!((!strncmp(name, "sata", 4) && type == PHY_TYPE_SATA) ||
-	      (!strncmp(name, "pcie", 4) && type == PHY_TYPE_PCIE)))
-		return 0;
-
-	miphy_phy->base = of_iomap(phynode, index);
-	if (!miphy_phy->base) {
-		dev_err(dev, "Failed to map %s\n", phynode->full_name);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct phy *miphy365x_xlate(struct device *dev,
-				   struct of_phandle_args *args)
-{
-	struct miphy365x_dev *miphy_dev = dev_get_drvdata(dev);
-	struct miphy365x_phy *miphy_phy = NULL;
-	struct device_node *phynode = args->np;
-	int ret, index;
-
-	if (args->args_count != 1) {
-		dev_err(dev, "Invalid number of cells in 'phy' property\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	for (index = 0; index < miphy_dev->nphys; index++)
-		if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
-			miphy_phy = miphy_dev->phys[index];
-			break;
-		}
-
-	if (!miphy_phy) {
-		dev_err(dev, "Failed to find appropriate phy\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	miphy_phy->type = args->args[0];
-
-	if (!(miphy_phy->type == PHY_TYPE_SATA ||
-	      miphy_phy->type == PHY_TYPE_PCIE)) {
-		dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type);
-		return ERR_PTR(-EINVAL);
-	}
-
-	/* Each port handles SATA and PCIE - third entry is always sysconf. */
-	for (index = 0; index < 3; index++) {
-		ret = miphy365x_get_addr(dev, miphy_phy, index);
-		if (ret < 0)
-			return ERR_PTR(ret);
-	}
-
-	return miphy_phy->phy;
-}
-
-static const struct phy_ops miphy365x_ops = {
-	.init		= miphy365x_init,
-	.owner		= THIS_MODULE,
-};
-
-static int miphy365x_of_probe(struct device_node *phynode,
-			      struct miphy365x_phy *miphy_phy)
-{
-	of_property_read_u32(phynode, "st,sata-gen", &miphy_phy->sata_gen);
-	if (!miphy_phy->sata_gen)
-		miphy_phy->sata_gen = SATA_GEN1;
-
-	miphy_phy->pcie_tx_pol_inv =
-		of_property_read_bool(phynode, "st,pcie-tx-pol-inv");
-
-	miphy_phy->sata_tx_pol_inv =
-		of_property_read_bool(phynode, "st,sata-tx-pol-inv");
-
-	return 0;
-}
-
-static int miphy365x_probe(struct platform_device *pdev)
-{
-	struct device_node *child, *np = pdev->dev.of_node;
-	struct miphy365x_dev *miphy_dev;
-	struct phy_provider *provider;
-	struct phy *phy;
-	int ret, port = 0;
-
-	miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
-	if (!miphy_dev)
-		return -ENOMEM;
-
-	miphy_dev->nphys = of_get_child_count(np);
-	miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys,
-				       sizeof(*miphy_dev->phys), GFP_KERNEL);
-	if (!miphy_dev->phys)
-		return -ENOMEM;
-
-	miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
-	if (IS_ERR(miphy_dev->regmap)) {
-		dev_err(miphy_dev->dev, "No syscfg phandle specified\n");
-		return PTR_ERR(miphy_dev->regmap);
-	}
-
-	miphy_dev->dev = &pdev->dev;
-
-	dev_set_drvdata(&pdev->dev, miphy_dev);
-
-	mutex_init(&miphy_dev->miphy_mutex);
-
-	for_each_child_of_node(np, child) {
-		struct miphy365x_phy *miphy_phy;
-
-		miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
-					 GFP_KERNEL);
-		if (!miphy_phy) {
-			ret = -ENOMEM;
-			goto put_child;
-		}
-
-		miphy_dev->phys[port] = miphy_phy;
-
-		phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops);
-		if (IS_ERR(phy)) {
-			dev_err(&pdev->dev, "failed to create PHY\n");
-			ret = PTR_ERR(phy);
-			goto put_child;
-		}
-
-		miphy_dev->phys[port]->phy = phy;
-
-		ret = miphy365x_of_probe(child, miphy_phy);
-		if (ret)
-			goto put_child;
-
-		phy_set_drvdata(phy, miphy_dev->phys[port]);
-
-		port++;
-		/* sysconfig offsets are indexed from 1 */
-		ret = of_property_read_u32_index(np, "st,syscfg", port,
-					&miphy_phy->ctrlreg);
-		if (ret) {
-			dev_err(&pdev->dev, "No sysconfig offset found\n");
-			goto put_child;
-		}
-	}
-
-	provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
-	return PTR_ERR_OR_ZERO(provider);
-put_child:
-	of_node_put(child);
-	return ret;
-}
-
-static const struct of_device_id miphy365x_of_match[] = {
-	{ .compatible = "st,miphy365x-phy", },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, miphy365x_of_match);
-
-static struct platform_driver miphy365x_driver = {
-	.probe	= miphy365x_probe,
-	.driver = {
-		.name	= "miphy365x-phy",
-		.of_match_table	= miphy365x_of_match,
-	}
-};
-module_platform_driver(miphy365x_driver);
-
-MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics miphy365x driver");
-MODULE_LICENSE("GPL v2");
-- 
1.9.1

^ permalink raw reply related

* [PATCH v5 2/9] drivers: irqchip: Add STM32 external interrupts support
From: Alexandre Torgue @ 2016-09-14 13:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.20.1609141103420.6233@nanos>

Hi Thomas,

On 09/14/2016 11:19 AM, Thomas Gleixner wrote:
> On Tue, 13 Sep 2016, Alexandre Torgue wrote:
>> On 09/13/2016 05:21 PM, Thomas Gleixner wrote:
>>> On Fri, 9 Sep 2016, Alexandre TORGUE wrote:
>>>> +static void stm32_exti_free(struct irq_domain *d, unsigned int virq,
>>>> +			    unsigned int nr_irqs)
>>>> +{
>>>> +	struct irq_data *data = irq_get_irq_data(virq);
>>>> +
>>>> +	irq_gc_mask_clr_bit(data->parent_data);
>>>
>>> I have a hard time to understand this. The irq domain is not hierarchical.
>>
>> Actually, I wanted to test ".free" callback function of gpio_irq_domain in
>> STM32 pinctrl driver. To do that I modified gpio driver: just after getting
>> virq through gpio_to_irq, I called "irq_dispose_mapping(virq)".
>> I know it is dirty but I thought it was the only way to test.
>>
>> Doing that, I see that ".free" callback of gpio domain is called but as it is
>> hirerchical ".free" callback for parent domain (exti one) is also called. I
>> observed that virq was well unmapped, but not masked at exti level. It is for
>> this reason than I added "irq_gc_mask_clr_bit(data->parent_data);" which mask
>> interrupt at exti level.
>
> Aargh. I really misread the patch, but this is entirely non obvious and you
> should do:
>
>        struct irq_data *data = irq_domain_get_irq_data(d, virq);
>
>        irq_gc_mask_clr_bit(d);
>
> Then it is entirely clear that you mask the interrupt of _this_ (the exti)
> domain.

Ok, it's easier to understand like that.

>
> Now what really bugs me is that you do that at all. An interrupt which is
> freed must be masked already. Why is it unmasked in the first place?

Honestly I don't know. When "devm_free_irq" is called to release virq, 
there is no issue and interrupt is well masked. But, when I tried to use
"irq_dispose_mapping(virq)" I observed that .free is called (child and 
parent domain) but interrupt is not masked.

Regards

Alex

>
> Thanks,
>
> 	tglx
>

^ permalink raw reply

* [PATCH 1/2 v3] bus: mvebu-mbus: Provide stub function for mvebu_mbus_get_io_win_info()
From: Gregory CLEMENT @ 2016-09-14 13:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160905072500.30112-1-sr@denx.de>

Hi,
 
 On lun., sept. 05 2016, Stefan Roese <sr@denx.de> wrote:

> This patch provides a stub function for mvebu_mbus_get_io_win_info(),
> which will be used for all non-Orion (ARM32 MVEBU) platforms for
> compile test coverage.
>
> On such platforms this function will return an error so that drivers
> might detect a potential problem.

Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>

Vinod, if you happy with the second patch of the series you can apply
both patches on your tree. It will allow to keep the bisactibility, and
as I didn't have any commit modifying these file in my trees it won't
generate merge conflict.

Thanks,

Gregory

>
> Signed-off-by: Stefan Roese <sr@denx.de>
> Cc: Gregory CLEMENT <gregory.clement@free-electrons.com>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Marcin Wojtas <mw@semihalf.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Vinod Koul <vinod.koul@intel.com>
> ---
> v3:
> - Include errno.h to fix the compile breakage on ARM64
> - Change comment as suggested by Andrew
> - Added Andrew to Cc
>
> v2:
> - Return error code in stub function. This may be useful on Armada 3700
>   boards. As Armada 3700 does not implement the MBus driver but some
>   device driver might call into these functions anyways (e.g. mvneta).
>
>  include/linux/mbus.h | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/mbus.h b/include/linux/mbus.h
> index d610232..2931aa4 100644
> --- a/include/linux/mbus.h
> +++ b/include/linux/mbus.h
> @@ -11,6 +11,8 @@
>  #ifndef __LINUX_MBUS_H
>  #define __LINUX_MBUS_H
>  
> +#include <linux/errno.h>
> +
>  struct resource;
>  
>  struct mbus_dram_target_info
> @@ -55,6 +57,8 @@ struct mbus_dram_target_info
>  #ifdef CONFIG_PLAT_ORION
>  extern const struct mbus_dram_target_info *mv_mbus_dram_info(void);
>  extern const struct mbus_dram_target_info *mv_mbus_dram_info_nooverlap(void);
> +int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size, u8 *target,
> +			       u8 *attr);
>  #else
>  static inline const struct mbus_dram_target_info *mv_mbus_dram_info(void)
>  {
> @@ -64,14 +68,24 @@ static inline const struct mbus_dram_target_info *mv_mbus_dram_info_nooverlap(vo
>  {
>  	return NULL;
>  }
> +static inline int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size,
> +					     u8 *target, u8 *attr)
> +{
> +	/*
> +	 * On all ARM32 MVEBU platforms with MBus support, this stub
> +	 * function will not get called. The real function from the
> +	 * MBus driver is called instead. ARM64 MVEBU platforms like
> +	 * the Armada 3700 could use the mv_xor device driver which calls
> +	 * into this function
> +	 */
> +	return -EINVAL;
> +}
>  #endif
>  
>  int mvebu_mbus_save_cpu_target(u32 __iomem *store_addr);
>  void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);
>  void mvebu_mbus_get_pcie_io_aperture(struct resource *res);
>  int mvebu_mbus_get_dram_win_info(phys_addr_t phyaddr, u8 *target, u8 *attr);
> -int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size, u8 *target,
> -			       u8 *attr);
>  int mvebu_mbus_add_window_remap_by_id(unsigned int target,
>  				      unsigned int attribute,
>  				      phys_addr_t base, size_t size,
> -- 
> 2.9.3
>

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [PATCH v9 00/19] Add support for FDMA DMA controller and slim core rproc found on STi chipsets
From: Vinod Koul @ 2016-09-14 13:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160913180616.GD21438@tuxbot>

On Tue, Sep 13, 2016 at 11:06:16AM -0700, Bjorn Andersson wrote:
> > I hate to send a ping,
> 
> Sorry about that.
> 
> > but do you think we can merge this fdma series? It has gone
> > through quite a few review rounds now.
> > 
> 
> I think the remoteproc part looks good.

yeah I was waiting for ack on other patches. But looks like at least
remoteproc ones have it


> Vinod, I don't have any changes queued in remoteproc that should cause
> merge issues. If you want to you could take the remoteproc patch
> through your tree.

I rechecked the dma part, they look good to me, so I should be able to apply
these. I will wait a day for ack/nacks. It is the time to speak up :)

-- 
~Vinod

^ permalink raw reply

* [GIT PULL] STi DT update for v4.9
From: Patrice Chotard @ 2016-09-14 13:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd, Kevin, Olof

PLease consider this next batch for v4.9

The following changes since commit ba5ba11906d5462993f5fd4e3da4d234505427a0:

  ARM: dts: STiH41x-b2020: Update gpio specifier (2016-09-02 15:15:14 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/pchotard/sti.git tags/sti-dt-for-v4.9-2

for you to fetch changes up to 443fd7c92f5a000796b02683157d17b2575450e1:

  ARM: DT: STi: stihxxx-b2120: Add DT nodes for STi audio card (2016-09-14 13:37:29 +0200)

----------------------------------------------------------------
STi dts update:

Update gpio-cells and gpio specifier for STiH415/416
Add PWM capture support for STiH416 and STiH407 family
Add USB3 support for B2260
Add HVA support for STiH410
Add clk_ignore_unused in bootargs of B2260
Add Flexible Direct Memory Access (FDMA) support for STiH407 family
Add internal audio codec IP spport for STiH407 family
Add uniperif player/reader IP blocks for STiH407 family

----------------------------------------------------------------
Jean-Christophe Trotin (1):
      ARM: dts: STiH410: Add hva dt nodes

Lee Jones (6):
      ARM: dts: STiH407: Supply PWM Capture IRQ
      ARM: dts: STiH407: Declare PWM Capture data lines via Pinctrl
      ARM: dts: STiH416: Supply PWM Capture IRQs
      ARM: dts: STiH416: Declare PWM Capture data lines via Pinctrl
      ARM: dts: STiH416: Define PWM Capture clock
      ARM: dts: STiH416: Define the number of PWM Capture channels

Patrice Chotard (7):
      ARM: dts: STiH415-pinctrl: update gpio-cells to 2
      ARM: dts: STiH416-pinctrl: update gpio-cells to 2
      ARM: dts: STiHxxx-b2120: update gpio specifier
      ARM: dts: STiH41x-b2000: update gpio specifier
      ARM: dts: STiH416-b2020e: update gpio specifier
      ARM: dts: STiH410-b2260: add USB3 node
      ARM: dts: STiH410-b2260: add clk_ignore_unused in bootargs

Peter Griffin (8):
      ARM: STi: DT: STiH407: Add FDMA driver dt nodes.
      ARM: DT: STiH407: Add i2s_out pinctrl configuration
      ARM: DT: STiH407: Add i2s_in pinctrl configuration
      ARM: DT: STiH407: Add spdif_out pinctrl config
      ARM: STi: DT: STiH407: Add sti-sasg-codec dt node
      ARM: STi: DT: STiH407: Add uniperif player dt nodes
      ARM: STi: DT: STiH407: Add uniperif reader dt nodes
      ARM: DT: STi: stihxxx-b2120: Add DT nodes for STi audio card

 arch/arm/boot/dts/stih407-family.dtsi  | 168 +++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/stih407-pinctrl.dtsi |  58 ++++++++++++
 arch/arm/boot/dts/stih410-b2260.dts    |   6 +-
 arch/arm/boot/dts/stih410.dtsi         |  10 ++
 arch/arm/boot/dts/stih415-pinctrl.dtsi |  54 +++++------
 arch/arm/boot/dts/stih416-b2020e.dts   |   6 +-
 arch/arm/boot/dts/stih416-pinctrl.dtsi |  65 +++++++------
 arch/arm/boot/dts/stih416.dtsi         |   8 +-
 arch/arm/boot/dts/stih41x-b2000.dtsi   |   5 +-
 arch/arm/boot/dts/stihxxx-b2120.dtsi   |  51 +++++++++-
 10 files changed, 362 insertions(+), 69 deletions(-)

^ permalink raw reply

* [RFC PATCH 00/11] pci: support for configurable PCI endpoint
From: Arnd Bergmann @ 2016-09-14 13:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473829927-20466-1-git-send-email-kishon@ti.com>

On Wednesday, September 14, 2016 10:41:56 AM CEST Kishon Vijay Abraham I wrote:
> This patch series
> 	*) adds PCI endpoint core layer
> 	*) modifies designware/dra7xx driver to be configured in EP mode
> 	*) adds a PCI endpoint *test* function driver

Hi Kishon,

I think this is a great start, thanks for posting early with a clear
list of limitations and TODO items.

I've added the drivers/ntb maintainers to Cc, given that there is
a certain degree of overlap between your work and the existing
code, I think they should be part of the discussion.
 
> Known Limitation:
> 	*) Does not support multi-function devices

If I understand it right, this was a problem for USB and adding
it later made it somewhat inconsistent. Maybe we can at least
try to come up with an idea of how multi-function devices
could be handled even if we don't implement it until someone
actually needs it.

Is your hardware able to make the PCIe endpoint look like
a device with multiple PCI functions, or would one have to
do this in software inside of a single PCI function if we
ever need it?

> TODO:
> 	*) access buffers in RC
> 	*) raise MSI interrupts
> 	*) Enable user space control for the RC side PCI driver

The user space control would end up just being one of several
gadget drivers, right? E.g. gadget drivers for standard hardware
(8250 uart, ATA, NVMe, some ethernet) could be done as kernel
drivers while a user space driver can be used for things that
are more unusual and that don't need to interface to another
part of the kernel?

> 	*) Adapt all other users of designware to use the new design (only
> 	   dra7xx has been adapted)

I don't fully understand this part. Does every designware based
driver need modifications, or are the changes to the
generic parts of the designware driver enough to make it
work for the simpler platforms?

> HOW TO:
> 
> ON THE EP SIDE:
> ***************
> 
> /* EP function is configured using configfs */
> # mount -t configfs none /sys/kernel/config
> 
> /* PCI EP core layer creates "pci_ep" entry in configfs */
> # cd /sys/kernel/config/pci_ep/
> 
> /*
>  * This is the 1st step in creating an endpoint function. This
>  * creates the endpoint function device *instance*. The string
>  * before the .<num> suffix will identify the driver this
>  * EP function will bind to.
>  * Just pci_epf_test is also valid. The .<num> suffix is used
>  * if there are multiple PCI controllers and all of them wants
>  * to use the same function.
>  */
> # mkdir pci_epf_test.0

I haven't used USB gadgets, but I assume this is modeled around
the same interface. If there are notable differences, please mention
what they are. Otherwise the general concept seems rather nice to me.

>  drivers/pci/{host => controller}/Kconfig           |  109 +++++-
>  drivers/pci/{host => controller}/Makefile          |    2 +
>  drivers/pci/{host => controller}/pci-aardvark.c    |    0
>  drivers/pci/{host => controller}/pci-dra7xx.c      |  340 +++++++++++++----
>  drivers/pci/{host => controller}/pci-exynos.c      |    0
>  drivers/pci/{host => controller}/pci-host-common.c |    0
>  .../pci/{host => controller}/pci-host-generic.c    |    0
>  drivers/pci/{host => controller}/pci-hyperv.c      |    0
>  drivers/pci/{host => controller}/pci-imx6.c        |    0
>  drivers/pci/{host => controller}/pci-keystone-dw.c |    0
>  drivers/pci/{host => controller}/pci-keystone.c    |    0
>  drivers/pci/{host => controller}/pci-keystone.h    |    0

Maybe it's better to wait before moving it around, this will make
it harder for you to rebase the patch series while you are working on
it and other people are working on the existing code.

I'd suggest dropping the rename patches for the moment and just work
in drivers/pci/host.

Let's talk (high-level) about the DT binding. I see that the way
you have done it here, one will need to have a different .dtb file
for a machine depending on whether the PCIe is used in host or
endpoint mode. The advantage of this way is that it's a much
cleaner binding (PCIe host bindings are a mess, and adding more
options to it will only make it worse), the downside is that
you can't decide at runtime what you want to use it for. E.g.
connecting two identical machines over PCIe requires deciding
in the bootloader which one is the endpoint, or using DT
overlays, which may be awkward for some users. Is this a realistic
use case, or do you expect that all machines will only ever be
used in one of the two ways?

	Arnd

^ permalink raw reply

* [PATCH v7 22/22] iommu/dma: Avoid PCI host bridge windows
From: Robin Murphy @ 2016-09-14 13:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <dc9f945f-2756-ab70-d061-9fdc7c5afdee@samsung.com>

On 14/09/16 13:35, Marek Szyprowski wrote:
> Hi Robin,
> 
> 
> On 2016-09-14 13:10, Robin Murphy wrote:
>> On 14/09/16 11:55, Marek Szyprowski wrote:
>>> On 2016-09-12 18:14, Robin Murphy wrote:
>>>> With our DMA ops enabled for PCI devices, we should avoid allocating
>>>> IOVAs which a host bridge might misinterpret as peer-to-peer DMA and
>>>> lead to faults, corruption or other badness. To be safe, punch out
>>>> holes
>>>> for all of the relevant host bridge's windows when initialising a DMA
>>>> domain for a PCI device.
>>>>
>>>> CC: Marek Szyprowski <m.szyprowski@samsung.com>
>>>> CC: Inki Dae <inki.dae@samsung.com>
>>>> Reported-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>>>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>>> I don't know much about PCI and their IOMMU integration, but can't we
>>> use
>>> the direct mapping region feature of iommu core for it? There are
>>> already
>>> iommu_get_dm_regions(), iommu_put_dm_regions() and
>>> iommu_request_dm_for_dev()
>>> functions for handling them...
>> It's rather the opposite problem - in the direct-mapping case, we're
>> making sure the iommu_domain has translations installed for the given
>> IOVAs (which are also the corresponding physical address) before it goes
>> live, whereas what we need to do here is make sure the these addresses
>> never get used as IOVAs at all, because any attempt to do so them will
>> likely go wrong. Thus we carve them out of the iova_domain such that
>> they will never get near an actual IOMMU API call.
>>
>> This is a slightly generalised equivalent of e.g. amd_iommu.c's
>> init_reserved_iova_ranges().
> 
> Hmmm. Each dm_region have protection parameter. Can't we reuse them to
> create prohibited/reserved regions by setting it to 0 (no read / no write)
> and mapping to physical 0 address? That's just a quick idea, because
> dm_regions and the proposed code for pci looks a bit similar for me...

It might look similar, but at different levels (iommu_domain vs.
iova_domain) and with the opposite intent. The dm_region prot flag is
just the standard flag as passed to iommu_map() - trying to map a region
with no access in an empty pagetable isn't going to achieve anything
anyway (it's effectively unmapping addresses that are already unmapped).

But for this case, even if you _did_ map something in the pagetable
(i.e. the iommu_domain), it wouldn't make any difference, because the
thing we're mitigating against is handing out addresses which are going
to cause a device's accesses to blow up inside the PCI root complex
without ever even reaching the IOMMU. In short, dm_regions are about
"these addresses are already being used for DMA, so make sure the IOMMU
API doesn't block them", whereas reserved ranges are about "these
addresses are unusable for DMA, so make sure the DMA API can't allocate
them".

Robin.

> 
> [...]
> 
> Best regards

^ 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