Re: [PATCH v8 11/14] iommu/rockchip: Use OF_IOMMU to attach devices automatically
roup, >dev, NULL); > + iommu_device_link(>iommu, dev); > return 0; > } > -static int rk_iommu_add_device(struct device *dev) > +static void rk_iommu_remove_device(struct device *dev) > { > - struct iommu_group *group; > struct rk_iommu *iommu; > - int ret; > - > - if (!rk_iommu_is_dev_iommu_master(dev)) > - return -ENODEV; > - > - group = iommu_group_get(dev); > - if (!group) { > - group = iommu_group_alloc(); > - if (IS_ERR(group)) { > - dev_err(dev, "Failed to allocate IOMMU group\n"); > - return PTR_ERR(group); > - } > - } > - > - ret = iommu_group_add_device(group, dev); > - if (ret) > - goto err_put_group; > - > - ret = rk_iommu_group_set_iommudata(group, dev); > - if (ret) > - goto err_remove_device; > iommu = rk_iommu_from_dev(dev); > - if (iommu) > - iommu_device_link(>iommu, dev); > - iommu_group_put(group); > - > - return 0; > - > -err_remove_device: > + iommu_device_unlink(>iommu, dev); > iommu_group_remove_device(dev); > -err_put_group: > - iommu_group_put(group); > - return ret; > } > -static void rk_iommu_remove_device(struct device *dev) > +static int rk_iommu_of_xlate(struct device *dev, > +struct of_phandle_args *args) > { > - struct rk_iommu *iommu; > + struct platform_device *iommu_dev; > + struct rk_iommudata *data; > - if (!rk_iommu_is_dev_iommu_master(dev)) > - return; > + data = devm_kzalloc(dma_dev, sizeof(*data), GFP_KERNEL); > + if (!data) > + return -ENOMEM; > - iommu = rk_iommu_from_dev(dev); > - if (iommu) > - iommu_device_unlink(>iommu, dev); > + iommu_dev = of_find_device_by_node(args->np); > - iommu_group_remove_device(dev); > + data->iommu = platform_get_drvdata(iommu_dev); > + dev->archdata.iommu = data; > + > + of_dev_put(iommu_dev); > + > + return 0; > } > static const struct iommu_ops rk_iommu_ops = { > @@ -1106,7 +1045,9 @@ static const struct iommu_ops rk_iommu_ops = { > .add_device = rk_iommu_add_device, > .remove_device = rk_iommu_remove_device, > .iova_to_phys = rk_iommu_iova_to_phys, > + .device_group = generic_device_group, > .pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP, > + .of_xlate = rk_iommu_of_xlate, > }; > static int rk_iommu_probe(struct platform_device *pdev) > @@ -1178,6 +1119,8 @@ static int rk_iommu_probe(struct platform_device *pdev) > goto err_unprepare_clocks; > iommu_device_set_ops(>iommu, _iommu_ops); > + iommu_device_set_fwnode(>iommu, >of_node->fwnode); > + > err = iommu_device_register(>iommu); > if (err) > goto err_remove_sysfs; > @@ -1250,6 +1193,8 @@ static int __init rk_iommu_init(void) > } > subsys_initcall(rk_iommu_init); > +IOMMU_OF_DECLARE(rk_iommu_of, "rockchip,iommu"); > + > MODULE_DESCRIPTION("IOMMU API for Rockchip"); > MODULE_AUTHOR("Simon Xue <x...@rock-chips.com> and Daniel Kurtz < djku...@chromium.org>"); > MODULE_ALIAS("platform:rockchip-iommu"); > -- > 2.11.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/dma: Map scatterlists more parsimoniously
On Thu, Dec 10, 2015 at 8:49 PM, Daniel Kurtz <djku...@chromium.org> wrote: > On Thu, Nov 12, 2015 at 1:47 PM, Yong Wu <yong...@mediatek.com> wrote: >> On Wed, 2015-11-11 at 14:54 +, Robin Murphy wrote: >>> Whilst blindly assuming the worst case for segment boundaries and >>> aligning every segment individually is safe from the point of view >>> of respecting the device's parameters, it is also undeniably a waste >>> of IOVA space. Futhermore, the knock-on effects of more pages than > > "Furthermore" (checkpatch actually caught this, not me ;-) ) > >>> necessary being exposed to device access, additional overhead in page >>> table updates and TLB invalidations, etc., are even more undesirable. >>> >>> Improve matters by taking the actual boundary mask into account to >>> actively detect the cases in which we really do need to adjust a >>> segment, and avoid wasting space in the remainder. >>> >>> Signed-off-by: Robin Murphy <robin.mur...@arm.com> >>> --- >>> >>> Hi all, >>> >>> I've given this some brief testing on Juno with USB and (via magic >>> PCI hacks) SATA to confirm that all the +1s and -1s at least seem to >>> be in the right places, so I'm throwing it out now for a head-start on >>> checking whether it also helps the media folks with the v4l portability >>> issues they're up against (I'm confident it should). If all goes well I >>> figure I'll repost next week based on rc1 instead of some random local >>> development commit. >>> >>> Robin. >> >> It works well on MT8173. containing >> VDA/VEA(VideoDecodeAccelerator/VideoEncodeAccelerator) unit test. >> >> Tested-by: Yong Wu <yong...@mediatek.com> > > Reviewed-by: Daniel Kurtz <djku...@chromium.org> Did this patch get lost? Can we pick it up as a fix for v4.5? ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v8 5/5] dts: mt8173: Add iommu/smi nodes for mt8173
On Tue, Jan 26, 2016 at 12:12 PM, Yong Wu <yong...@mediatek.com> wrote: > This patch add the iommu/larbs nodes for mt8173 > > Signed-off-by: Yong Wu <yong...@mediatek.com> Reviewed-by: Daniel Kurtz <djku...@chromium.org> ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v8 3/5] memory: mediatek: Add SMI driver
On Tue, Jan 26, 2016 at 12:12 PM, Yong Wu <yong...@mediatek.com> wrote: > This patch add SMI(Smart Multimedia Interface) driver. This driver > is responsible to enable/disable iommu and control the power domain > and clocks of each local arbiter. > > Signed-off-by: Yong Wu <yong...@mediatek.com> > Tested-by: Philipp Zabel <p.za...@pengutronix.de> Reviewed-by: Daniel Kurtz <djku...@chromium.org> Tested-by: Daniel Kurtz <djku...@chromium.org> Thanks! ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 3/5] memory: mediatek: Add SMI driver
Hi Yong, On Tue, Dec 15, 2015 at 10:38 AM, Yong Wuwrote: > On Mon, 2015-12-14 at 19:18 +0100, Matthias Brugger wrote: >> On Tuesday 08 Dec 2015 17:49:11 Yong Wu wrote: >> > This patch add SMI(Smart Multimedia Interface) driver. This driver >> > is responsible to enable/disable iommu and control the power domain >> > and clocks of each local arbiter. >> > >> > Signed-off-by: Yong Wu >> > --- >> > Currently SMI offer mtk_smi_larb_get/put to enable the power-domain >> > ,clocks and initialize the iommu configuration register for each a local >> > arbiter, The reason is: >> > a) If a device would like to disable iommu, it also need call >> > mtk_smi_larb_get/put to enable its power and clocks. >> > b) The iommu core don't support attach/detach a device within a >> > iommu-group. So we cann't use iommu_attach_device(iommu_detach_device) >> > instead >> > of mtk_smi_larb_get/put. >> > > [..] >> > +static int >> > +mtk_smi_enable(struct device *dev, struct clk *apb, struct clk *smi) >> > +{ >> > + int ret; >> > + >> > + ret = pm_runtime_get_sync(dev); >> > + if (ret < 0) >> > + return ret; >> > + >> > + ret = clk_prepare_enable(apb); >> > + if (ret) >> > + goto err_put_pm; >> > + >> > + ret = clk_prepare_enable(smi); >> > + if (ret) >> > + goto err_disable_apb; >> > + >> > + return 0; >> > + >> > +err_disable_apb: >> > + clk_disable_unprepare(apb); >> > +err_put_pm: >> > + pm_runtime_put_sync(dev); >> > + return ret; >> > +} >> > + >> > +static void >> > +mtk_smi_disable(struct device *dev, struct clk *apb, struct clk *smi) >> > +{ >> > + clk_disable_unprepare(smi); >> > + clk_disable_unprepare(apb); >> > + pm_runtime_put_sync(dev); >> > +} >> > + >> > +static int mtk_smi_common_enable(struct mtk_smi_common *common) >> > +{ >> > + return mtk_smi_enable(common->dev, common->clk_apb, common->clk_smi); >> > +} >> > + >> > +static void mtk_smi_common_disable(struct mtk_smi_common *common) >> > +{ >> > + mtk_smi_disable(common->dev, common->clk_apb, common->clk_smi); >> > +} >> > + >> > +static int mtk_smi_larb_enable(struct mtk_smi_larb *larb) >> > +{ >> > + return mtk_smi_enable(larb->dev, larb->clk_apb, larb->clk_smi); >> > +} >> > + >> > +static void mtk_smi_larb_disable(struct mtk_smi_larb *larb) >> > +{ >> > + mtk_smi_disable(larb->dev, larb->clk_apb, larb->clk_smi); >> > +} >> > + >> >> This is somehow over-engineered. Just use mtk_smi_enable and mtk_smi_disable >> instead of adding an extra indirection. > > I added this only for readable...then the code in mtk_smi_larb_get below > may looks simple and readable. > > If I use mtk_smi_enable/disable directly, the code will be like our > v5[1], is it OK? > Maybe I don't need these help function here, and only add more comment > based on v5. > > [1] > http://lists.linuxfoundation.org/pipermail/iommu/2015-October/014590.html bike-shedding... I like the fact that Yong is trying to make his helpers more type-safe. But, perhaps we can rename "struct mtk_smi_common" as "struct mtk_smi", and then make "struct mtk_smi_larb" contain a "struct mtk_smi": struct mtk_smi { struct device *dev; struct clk *clk_apb, *clk_smi; } struct mtk_smi_larb { struct mtk_smi; ... } Then, have: int mtk_smi_enable(struct mtk_smi *smi) { clk_enable(smi->clk_apb); ... } int mtk_smi_disable(struct mtk_smi *smi) { } int mtk_smi_larb_get(struct device *larbdev) { struct mtk_smi_larb *larb = dev_get_drvdata(larbdev); struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev); mtk_smi_enable(common); mtk_smi_enable(>smi); ... } >> >> > +int mtk_smi_larb_get(struct device *larbdev) >> > +{ >> > + struct mtk_smi_larb *larb = dev_get_drvdata(larbdev); >> > + struct mtk_smi_common *common = dev_get_drvdata(larb->smi_common_dev); >> > + int ret; >> > + >> > + ret = mtk_smi_common_enable(common); >> > + if (ret) >> > + return ret; >> > + >> > + ret = mtk_smi_larb_enable(larb); >> > + if (ret) >> > + goto err_put_smi; >> > + >> > + /* Configure the iommu info */ >> > + writel_relaxed(larb->mmu, larb->base + SMI_LARB_MMU_EN); I think this should probably be writel() not writel_relaxed, since you really do want the barrier to ensure all other register accesses have completed before enabling the MMU. >> > + >> > + return 0; >> > + >> > +err_put_smi: >> > + mtk_smi_common_disable(common); >> > + return ret; >> > +} >> > + >> > +void mtk_smi_larb_put(struct device *larbdev) >> > +{ >> > + struct mtk_smi_larb *larb = dev_get_drvdata(larbdev); >> > + struct mtk_smi_common *common = dev_get_drvdata(larb->smi_common_dev); >> > + >> > + writel_relaxed(0, larb->base + SMI_LARB_MMU_EN); >> > + mtk_smi_larb_disable(larb); >> > + mtk_smi_common_disable(common); >> > +} >> > + >> >> Looks strange that you just disable all MMUs while you only enable some of >> them at runtime. Unfortunately the datasheet I have
Re: [PATCH] iommu/dma: Map scatterlists more parsimoniously
On Thu, Nov 12, 2015 at 1:47 PM, Yong Wu <yong...@mediatek.com> wrote: > On Wed, 2015-11-11 at 14:54 +, Robin Murphy wrote: >> Whilst blindly assuming the worst case for segment boundaries and >> aligning every segment individually is safe from the point of view >> of respecting the device's parameters, it is also undeniably a waste >> of IOVA space. Futhermore, the knock-on effects of more pages than "Furthermore" (checkpatch actually caught this, not me ;-) ) >> necessary being exposed to device access, additional overhead in page >> table updates and TLB invalidations, etc., are even more undesirable. >> >> Improve matters by taking the actual boundary mask into account to >> actively detect the cases in which we really do need to adjust a >> segment, and avoid wasting space in the remainder. >> >> Signed-off-by: Robin Murphy <robin.mur...@arm.com> >> --- >> >> Hi all, >> >> I've given this some brief testing on Juno with USB and (via magic >> PCI hacks) SATA to confirm that all the +1s and -1s at least seem to >> be in the right places, so I'm throwing it out now for a head-start on >> checking whether it also helps the media folks with the v4l portability >> issues they're up against (I'm confident it should). If all goes well I >> figure I'll repost next week based on rc1 instead of some random local >> development commit. >> >> Robin. > > It works well on MT8173. containing > VDA/VEA(VideoDecodeAccelerator/VideoEncodeAccelerator) unit test. > > Tested-by: Yong Wu <yong...@mediatek.com> Reviewed-by: Daniel Kurtz <djku...@chromium.org> ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/3] iommu: Implement common IOMMU ops for DMA mapping
+Tomasz, so he can reply to the thread +Marek and Russell as recommended by Tomasz On Oct 30, 2015 22:27, "Robin Murphy" <robin.mur...@arm.com> wrote: > > Hi Dan, > > On 30/10/15 01:17, Daniel Kurtz wrote: >> >> +linux-media & VIDEOBUF2 FRAMEWORK maintainers since this is about the >> v4l2-contig's usage of the DMA API. >> >> Hi Robin, >> >> On Tue, Oct 27, 2015 at 12:55 AM, Robin Murphy <robin.mur...@arm.com> wrote: >>> >>> On 26/10/15 13:44, Yong Wu wrote: >>>> >>>> >>>> On Thu, 2015-10-01 at 20:13 +0100, Robin Murphy wrote: >>>> [...] >>>>> >>>>> >>>>> +/* >>>>> + * The DMA API client is passing in a scatterlist which could describe >>>>> + * any old buffer layout, but the IOMMU API requires everything to be >>>>> + * aligned to IOMMU pages. Hence the need for this complicated bit of >>>>> + * impedance-matching, to be able to hand off a suitably-aligned list, >>>>> + * but still preserve the original offsets and sizes for the caller. >>>>> + */ >>>>> +int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, >>>>> + int nents, int prot) >>>>> +{ >>>>> + struct iommu_domain *domain = iommu_get_domain_for_dev(dev); >>>>> + struct iova_domain *iovad = domain->iova_cookie; >>>>> + struct iova *iova; >>>>> + struct scatterlist *s, *prev = NULL; >>>>> + dma_addr_t dma_addr; >>>>> + size_t iova_len = 0; >>>>> + int i; >>>>> + >>>>> + /* >>>>> +* Work out how much IOVA space we need, and align the segments >>>>> to >>>>> +* IOVA granules for the IOMMU driver to handle. With some clever >>>>> +* trickery we can modify the list in-place, but reversibly, by >>>>> +* hiding the original data in the as-yet-unused DMA fields. >>>>> +*/ >>>>> + for_each_sg(sg, s, nents, i) { >>>>> + size_t s_offset = iova_offset(iovad, s->offset); >>>>> + size_t s_length = s->length; >>>>> + >>>>> + sg_dma_address(s) = s->offset; >>>>> + sg_dma_len(s) = s_length; >>>>> + s->offset -= s_offset; >>>>> + s_length = iova_align(iovad, s_length + s_offset); >>>>> + s->length = s_length; >>>>> + >>>>> + /* >>>>> +* The simple way to avoid the rare case of a segment >>>>> +* crossing the boundary mask is to pad the previous one >>>>> +* to end at a naturally-aligned IOVA for this one's >>>>> size, >>>>> +* at the cost of potentially over-allocating a little. >>>>> +*/ >>>>> + if (prev) { >>>>> + size_t pad_len = roundup_pow_of_two(s_length); >>>>> + >>>>> + pad_len = (pad_len - iova_len) & (pad_len - 1); >>>>> + prev->length += pad_len; >>>> >>>> >>>> >>>> Hi Robin, >>>> While our v4l2 testing, It seems that we met a problem here. >>>> Here we update prev->length again, Do we need update >>>> sg_dma_len(prev) again too? >>>> >>>> Some function like vb2_dc_get_contiguous_size[1] always get >>>> sg_dma_len(s) to compare instead of s->length. so it may break >>>> unexpectedly while sg_dma_len(s) is not same with s->length. >>> >>> >>> >>> This is just tweaking the faked-up length that we hand off to iommu_map_sg() >>> (see also the iova_align() above), to trick it into bumping this segment up >>> to a suitable starting IOVA. The real length at this point is stashed in >>> sg_dma_len(s), and will be copied back into s->length in __finalise_sg(), so >>> both will hold the same true length once we return to the caller. >>> >>> Yes, it does mean that if you have a list where the segment lengths are page >>> aligned but not monotonically decreasing, e.g. {64k, 16k, 64k}, then you'll >>> still end up with a
Re: [PATCH v6 1/3] iommu: Implement common IOMMU ops for DMA mapping
+linux-media & VIDEOBUF2 FRAMEWORK maintainers since this is about the v4l2-contig's usage of the DMA API. Hi Robin, On Tue, Oct 27, 2015 at 12:55 AM, Robin Murphywrote: > On 26/10/15 13:44, Yong Wu wrote: >> >> On Thu, 2015-10-01 at 20:13 +0100, Robin Murphy wrote: >> [...] >>> >>> +/* >>> + * The DMA API client is passing in a scatterlist which could describe >>> + * any old buffer layout, but the IOMMU API requires everything to be >>> + * aligned to IOMMU pages. Hence the need for this complicated bit of >>> + * impedance-matching, to be able to hand off a suitably-aligned list, >>> + * but still preserve the original offsets and sizes for the caller. >>> + */ >>> +int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, >>> + int nents, int prot) >>> +{ >>> + struct iommu_domain *domain = iommu_get_domain_for_dev(dev); >>> + struct iova_domain *iovad = domain->iova_cookie; >>> + struct iova *iova; >>> + struct scatterlist *s, *prev = NULL; >>> + dma_addr_t dma_addr; >>> + size_t iova_len = 0; >>> + int i; >>> + >>> + /* >>> +* Work out how much IOVA space we need, and align the segments >>> to >>> +* IOVA granules for the IOMMU driver to handle. With some clever >>> +* trickery we can modify the list in-place, but reversibly, by >>> +* hiding the original data in the as-yet-unused DMA fields. >>> +*/ >>> + for_each_sg(sg, s, nents, i) { >>> + size_t s_offset = iova_offset(iovad, s->offset); >>> + size_t s_length = s->length; >>> + >>> + sg_dma_address(s) = s->offset; >>> + sg_dma_len(s) = s_length; >>> + s->offset -= s_offset; >>> + s_length = iova_align(iovad, s_length + s_offset); >>> + s->length = s_length; >>> + >>> + /* >>> +* The simple way to avoid the rare case of a segment >>> +* crossing the boundary mask is to pad the previous one >>> +* to end at a naturally-aligned IOVA for this one's >>> size, >>> +* at the cost of potentially over-allocating a little. >>> +*/ >>> + if (prev) { >>> + size_t pad_len = roundup_pow_of_two(s_length); >>> + >>> + pad_len = (pad_len - iova_len) & (pad_len - 1); >>> + prev->length += pad_len; >> >> >> Hi Robin, >>While our v4l2 testing, It seems that we met a problem here. >>Here we update prev->length again, Do we need update >> sg_dma_len(prev) again too? >> >>Some function like vb2_dc_get_contiguous_size[1] always get >> sg_dma_len(s) to compare instead of s->length. so it may break >> unexpectedly while sg_dma_len(s) is not same with s->length. > > > This is just tweaking the faked-up length that we hand off to iommu_map_sg() > (see also the iova_align() above), to trick it into bumping this segment up > to a suitable starting IOVA. The real length at this point is stashed in > sg_dma_len(s), and will be copied back into s->length in __finalise_sg(), so > both will hold the same true length once we return to the caller. > > Yes, it does mean that if you have a list where the segment lengths are page > aligned but not monotonically decreasing, e.g. {64k, 16k, 64k}, then you'll > still end up with a gap between the second and third segments, but that's > fine because the DMA API offers no guarantees about what the resulting DMA > addresses will be (consider the no-IOMMU case where they would each just be > "mapped" to their physical address). If that breaks v4l, then it's probably > v4l's DMA API use that needs looking at (again). Hmm, I thought the DMA API maps a (possibly) non-contiguous set of memory pages into a contiguous block in device memory address space. This would allow passing a dma mapped buffer to device dma using just a device address and length. IIUC, the change above breaks this model by inserting gaps in how the buffer is mapped to device memory, such that the buffer is no longer contiguous in dma address space. Here is the code in question from drivers/media/v4l2-core/videobuf2-dma-contig.c : static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt) { struct scatterlist *s; dma_addr_t expected = sg_dma_address(sgt->sgl); unsigned int i; unsigned long size = 0; for_each_sg(sgt->sgl, s, sgt->nents, i) { if (sg_dma_address(s) != expected) break; expected = sg_dma_address(s) + sg_dma_len(s); size += sg_dma_len(s); } return size; } static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr, unsigned long size, enum dma_data_direction dma_dir) { struct vb2_dc_conf *conf = alloc_ctx; struct vb2_dc_buf *buf; struct frame_vector *vec;
Re: [PATCH v5 2/3] arm64: Add IOMMU dma_ops
Hi Robin, On Sat, Aug 1, 2015 at 1:18 AM, Robin Murphywrote: > Taking some inspiration from the arch/arm code, implement the > arch-specific side of the DMA mapping ops using the new IOMMU-DMA layer. > > Unfortunately the device setup code has to start out as a big ugly mess > in order to work usefully right now, as 'proper' operation depends on > changes to device probe and DMA configuration ordering, IOMMU groups for > platform devices, and default domain support in arm/arm64 IOMMU drivers. > The workarounds here need only exist until that work is finished. > > Signed-off-by: Robin Murphy > --- [snip] > +static void __iommu_sync_sg_for_cpu(struct device *dev, > + struct scatterlist *sgl, int nelems, > + enum dma_data_direction dir) > +{ > + struct scatterlist *sg; > + int i; > + > + if (is_device_dma_coherent(dev)) > + return; > + > + for_each_sg(sgl, sg, nelems, i) > + __dma_unmap_area(sg_virt(sg), sg->length, dir); > +} In an earlier review [0], Marek asked you to change the loop in __iommu_sync_sg_for_cpu loop() to loop over the virtual areas when invalidating/cleaning memory ranges. [0] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/328232.html However, this changed the meaning of the 'nelems' argument from what was for arm_iommu_sync_sg_for_cpu() in arch/arm/mm/dma-mapping.c: "number of buffers to sync (returned from dma_map_sg)" to: "number of virtual areas to sync (same as was passed to dma_map_sg)" This has caused some confusion by callers of dma_sync_sg_for_device() that must work for both arm & arm64 as illustrated by [1]. [1] https://lkml.org/lkml/2015/9/21/250 Based on the implementation of debug_dma_sync_sg_for_cpu() in lib/dma-debug.c, I think the arm interpretation of nelems (returned from dma_map_sg) is correct. Therefore, I think we need an outer iteration over dma chunks, and an inner iteration that calls __dma_map_area() over the set virtual areas that correspond to that dma chunk, both here and for __iommu_sync_sg_for_device(). This will be complicated by the fact that iommu pages could actually be smaller than PAGE_SIZE, and offset within a single physical page. Also, as an optimization, we would want to combine contiguous virtual areas into a single call to __dma_unmap_area(). -Dan ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] CHROMIUM: iommu: rockchip: Make sure that page table state is coherent
On Mon, Apr 20, 2015 at 7:43 PM, Tomasz Figa tf...@chromium.org wrote: To flush created mappings, current mapping code relies on the fact that during unmap the driver zaps every IOVA being unmapped and that it is enough to zap a single IOVA of page table to remove the entire page table from IOMMU cache. Based on these assumptions the driver was made to simply zap the first IOVA of the mapping being created. This is enough to invalidate first page table, which could be shared with another mapping (and thus could be already present in IOMMU cache), but unfortunately it does not do anything about the last page table that could be shared with other mappings as well. Moreover, the flushing is performed before page table contents are actually modified, so there is a race between the CPU updating the page tables and hardware that could be possibly running at the same time and triggering IOMMU look-ups, which could bring back the page tables back to the cache. To fix both issues, this patch makes the mapping code zap first and last (if they are different) IOVAs of new mapping after the page table is updated. Signed-off-by: Tomasz Figa tf...@chromium.org Reviewed-by: Daniel Kurtz djku...@chromium.org Tested-by: Heiko Stuebner he...@sntech.de You probably want to remove the CHROMIUM: label in the subject. Other than that, this is still: Reviewed-by: Daniel Kurtz djku...@chromium.org --- drivers/iommu/rockchip-iommu.c | 23 +-- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 4015560..31004c0 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -551,6 +551,15 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain *rk_domain, spin_unlock_irqrestore(rk_domain-iommus_lock, flags); } +static void rk_iommu_zap_iova_first_last(struct rk_iommu_domain *rk_domain, +dma_addr_t iova, size_t size) +{ + rk_iommu_zap_iova(rk_domain, iova, SPAGE_SIZE); + if (size SPAGE_SIZE) + rk_iommu_zap_iova(rk_domain, iova + size - SPAGE_SIZE, + SPAGE_SIZE); +} + static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain, dma_addr_t iova) { @@ -575,12 +584,6 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain, rk_table_flush(page_table, NUM_PT_ENTRIES); rk_table_flush(dte_addr, 1); - /* -* Zap the first iova of newly allocated page table so iommu evicts -* old cached value of new dte from the iotlb. -*/ - rk_iommu_zap_iova(rk_domain, iova, SPAGE_SIZE); - done: pt_phys = rk_dte_pt_address(dte); return (u32 *)phys_to_virt(pt_phys); @@ -630,6 +633,14 @@ static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr, rk_table_flush(pte_addr, pte_count); + /* +* Zap the first and last iova to evict from iotlb any previously +* mapped cachelines holding stale values for its dte and pte. +* We only zap the first and last iova, since only they could have +* dte or pte shared with an existing mapping. +*/ + rk_iommu_zap_iova_first_last(rk_domain, iova, size); + return 0; unwind: /* Unmap the range of iovas that we just mapped */ -- 2.2.0.rc0.207.ga3a616c ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/5] soc: mediatek: Add SMI driver
Hi Yong, On Fri, Mar 6, 2015 at 6:37 PM, yong...@mediatek.com wrote: From: Yong Wu yong...@mediatek.com This patch add SMI(Smart Multimedia Interface) driver. This driver is responsible to enable/disable iommu and control the clocks of each local arbiter. High-level: Is there more to the smi (or smi-larb) driver, or is it always just a 1:1 wrapper for a particular m4u consumer? In other words, instead of a separate driver, is it possible to move this functionality into the m4u driver and/or the m4u consumers directly? Signed-off-by: Yong Wu yong...@mediatek.com --- drivers/soc/mediatek/Kconfig | 7 ++ drivers/soc/mediatek/Makefile | 1 + drivers/soc/mediatek/mt8173-smi.c | 143 ++ include/linux/mtk-smi.h | 40 +++ 4 files changed, 191 insertions(+) create mode 100644 drivers/soc/mediatek/mt8173-smi.c create mode 100644 include/linux/mtk-smi.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index 729f93e..27fb26c 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -20,3 +20,10 @@ config MT8173_PMIC_WRAP PMIC wrapper is a proprietary hardware in MT8173 to make communication protocols to access PMIC device. This driver implement access protocols for MT8173. + +config MTK_SMI +bool + help + Smi help enable/disable iommu in mt8173 and control the + clock of each local arbiter. + It should be true while MTK_IOMMU enable. diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 9b5709b..cdfe95c 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_MT8135_PMIC_WRAP) += mt8135-pmic-wrap.o obj-$(CONFIG_MT8173_PMIC_WRAP) += mt8173-pmic-wrap.o +obj-$(CONFIG_MTK_SMI) += mt8173-smi.o diff --git a/drivers/soc/mediatek/mt8173-smi.c b/drivers/soc/mediatek/mt8173-smi.c new file mode 100644 index 000..4e3fab9 --- /dev/null +++ b/drivers/soc/mediatek/mt8173-smi.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014-2015 MediaTek Inc. + * Author: Yong Wu yong...@mediatek.com + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include linux/io.h +#include linux/interrupt.h +#include linux/platform_device.h +#include linux/clk.h +#include linux/err.h +#include linux/mm.h + +#define SMI_LARB_MMU_EN (0xf00) +#define F_SMI_MMU_EN(port) (1 (port)) + +struct mtk_smi_larb { + void __iomem *larb_base; + struct clk *larb_clk[3];/* each larb has 3 clk at most */ +}; + +static const char * const mtk_smi_clk_name[] = { + larb_sub0, larb_sub1, larb_sub2 +}; The order and meaning of these clocks do not seem particularly important. It seems a bit awkward to use these arbitrary names just so we can use devm_clk_get() to get a variably sized array of clocks from .dts. Can we eliminate the clock-names property, and just use a single .dts proprety that lists an array of clocks? Then you would also get an explicit clock count, and can remove the NULL checking when iterating. An example of a clock list without names is: Clock list in .dts: https://lkml.org/lkml/2014/11/17/115 Filling in the clocks from .dts: https://lkml.org/lkml/2014/11/17/114 Unfortunately, those patches never made it out of list discussion into a maintainer tree. + +static const struct of_device_id mtk_smi_of_ids[] = { + { .compatible = mediatek,mt8173-smi-larb, + }, + {} +}; I find it a bit redundant to call the struct mtk_smi_larb, and then to prepend larb_ to all of the fields. In fact this whole driver is a bit confusing because it isn't clear if this is an smi driver (of which only larb control has been implemented) or is this an smi_larb driver (and potentially there are other smi drivers). Perhaps we can just call this an smi_larb driver, rename this file to mt8173-smi-larb.c, and then doing something like: struct mtk_smi_larb { void __iomem *base; struct clk *clk[3];/* each smi_larb has at most 3 clocks */ }; static const struct of_device_id mtk_smi_larb_of_ids[] = { { .compatible = mediatek,mt8173-smi-larb }, {} }; + +int mtk_smi_larb_get(struct platform_device *plarbdev) Is there any reason to use struct platform_device here instead of just struct device? +{ + struct mtk_smi_larb *larbpriv = dev_get_drvdata(plarbdev-dev); + int i, ret = 0; + + for (i = 0; i
[PATCH v7 1/3] iommu/rockchip: rk3288 iommu driver
The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. v6: - add .add/remove_device() callbacks. - parse platform_device device tree nodes for iommus property - store platform device pointer as group iommudata - Check for existence of iommu group instead of relying on a dev_get_drvdata() to return NULL for a NULL device. v7: - fixup some strings. - In rk_iommu_disable_paging() # and % were reversed. Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com Reviewed-by: Grant Grundler grund...@chromium.org Reviewed-by: Stéphane Marchesin marc...@chromium.org Tested-by: Heiko Stuebner he...@sntech.de --- drivers/iommu/Kconfig | 12 + drivers/iommu/Makefile |1 + drivers/iommu/rockchip-iommu.c | 1038 3 files changed, 1051 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..d0a1261 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + select ARM_DMA_USE_IOMMU + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..b2023af --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,1038 @@ +/* + * 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 asm/cacheflush.h +#include asm/pgtable.h +#include linux/compiler.h +#include linux/delay.h +#include linux
Re: [PATCH v6 1/3] iommu/rockchip: rk3288 iommu driver
Heiko, Does this version work for you on 3.18-rc1? On Oct 27, 2014 8:44 PM, Daniel Kurtz djku...@chromium.org wrote: The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Changes in v6: - add .add/remove_device() callbacks. - parse platform_device device tree nodes for iommus property - store platform device pointer as group iommudata - Check for existence of iommu group instead of relying on a dev_get_drvdata() to return NULL for a NULL device. Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com Reviewed-by: Grant Grundler grund...@chromium.org Reviewed-by: Stéphane Marchesin marc...@chromium.org --- drivers/iommu/Kconfig | 12 + drivers/iommu/Makefile |1 + drivers/iommu/rockchip-iommu.c | 1038 3 files changed, 1051 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..d0a1261 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + select ARM_DMA_USE_IOMMU + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..61d6f87 --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,1038 @@ +/* + * 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 asm
Re: [PATCH v5 1/3] iommu/rockchip: rk3288 iommu driver
On Mon, Oct 27, 2014 at 4:32 AM, Heiko Stübner he...@sntech.de wrote: Hi Daniel, Am Freitag, 24. Oktober 2014, 15:33:47 schrieb Daniel Kurtz: [...] +static int rk_iommu_attach_device(struct iommu_domain *domain, + struct device *dev) +{ + struct rk_iommu *iommu = dev_get_drvdata(dev-archdata.iommu); Here I get a null-ptr dereference [0] when using the iommu driver with the pending drm changes. That's what I get for testing against a heavily modified v3.14-based kernel... In v3.14, dev_get_drvdata() would happily return NULL if dev=NULL. This feature was removed in v3.15 by this patch: commit d4332013919aa87dbdede67d677e4cf2cd32e898 Author: Jean Delvare jdelv...@suse.de Date: Mon Apr 14 12:57:43 2014 +0200 driver core: dev_get_drvdata: Don't check for NULL dev + struct rk_iommu_domain *rk_domain = domain-priv; + unsigned long flags; + int ret; + phys_addr_t dte_addr; + + /* + * Allow 'virtual devices' (e.g., drm) to attach to domain. + * Such a device has a NULL archdata.iommu. + */ + if (!iommu) When the comment is correct, the code should probably do something like the following? if (!dev-archdata.iommu) return 0; iommu = dev_get_drvdata(dev-archdata.iommu); Yes, that looks reasonable. + return 0; + + ret = rk_iommu_enable_stall(iommu); + if (ret) + return ret; + + ret = rk_iommu_force_reset(iommu); + if (ret) + return ret; + + iommu-domain = domain; + + ret = devm_request_irq(dev, iommu-irq, rk_iommu_irq, +IRQF_SHARED, dev_name(dev), iommu); + if (ret) + return ret; + + dte_addr = virt_to_phys(rk_domain-dt); + rk_iommu_write(iommu, RK_MMU_DTE_ADDR, dte_addr); + rk_iommu_command(iommu, RK_MMU_CMD_ZAP_CACHE); + rk_iommu_write(iommu, RK_MMU_INT_MASK, RK_MMU_IRQ_MASK); + + ret = rk_iommu_enable_paging(iommu); + if (ret) + return ret; + + spin_lock_irqsave(rk_domain-iommus_lock, flags); + list_add_tail(iommu-node, rk_domain-iommus); + spin_unlock_irqrestore(rk_domain-iommus_lock, flags); + + dev_info(dev, Attached to iommu domain\n); + + rk_iommu_disable_stall(iommu); + + return 0; +} [...] + +static struct platform_driver rk_iommu_driver = { + .probe = rk_iommu_probe, + .remove = rk_iommu_remove, + .driver = { +.name = rk_iommu, +.owner = THIS_MODULE, +.of_match_table = of_match_ptr(rk_iommu_dt_ids), + }, +}; + +static int __init rk_iommu_init(void) +{ + int ret; + + ret = bus_set_iommu(platform_bus_type, rk_iommu_ops); on 3.18-rc1 this fails with -ENODEV, as add_iommu_group() is missing the add_device callback in rk_iommu_ops, so the iommu driver actually never gets registered. v3.18-rc1 has patch [0] which changes bus_set_iommu()-iommu_bus_init() to propagate the return value of add_iommu_group(), whereas it was ignored in v3.17. [0] commit fb3e306515ba6a012364b698b8ca71c337424ed3 Author: Mark Salter msal...@redhat.com Date: Sun Sep 21 13:58:24 2014 -0400 iommu: Fix bus notifier breakage This patch made it mandatory that iommu drivers provide an add_group callback. I'm not exactly sure why. Iommu groups do not seem to be a good fit for the rockchip iommus, since the iommus are all 1:1 with their master device. The exynos add_group() is a possibility, however, it causes an iommu_group to be allocated for every single platform_device, even if they do not use an iommu. This seems very wasteful. Instead we can check the device's dt node for an iommus field to a phandle with a #iommu-cells field. Also, perhaps the add_device() is a good place to stick other generic device initialization code, which we are currently sprinkling in the drivers of rockchip iommu masters (drm/codec). Other drivers do this: * shmobile: sets up the iommu mapping with arm_iommu_create_mapping() / arm_iommu_attach_device() * omap: use of_parse_phandle()/of_find_device_by_node() to set a master device's dev-archdata.iommu. Or, perhaps we can just ignore iommu groups entirely and use dummy functions: static int rk_iommu_add_device(struct device *dev) { return 0; } static void rk_iommu_remove_device(struct device *dev) { } I'll investigate more. -Dan I've stolen the generic add_device and remove_device callbacks from the exynos iommu driver which makes the rk one at least probe. Can't say how far it goes, as I'm still struggling with the floating display subsystem parts. My current diff against this version can be found in [1]. Maybe the issue I had in attach_device also simply resulted from this one, not sure right now. Heiko + if (ret) + return ret; + + return platform_driver_register(rk_iommu_driver); +} +static void __exit rk_iommu_exit(void
[PATCH v6 1/3] iommu/rockchip: rk3288 iommu driver
The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Changes in v6: - add .add/remove_device() callbacks. - parse platform_device device tree nodes for iommus property - store platform device pointer as group iommudata - Check for existence of iommu group instead of relying on a dev_get_drvdata() to return NULL for a NULL device. Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com Reviewed-by: Grant Grundler grund...@chromium.org Reviewed-by: Stéphane Marchesin marc...@chromium.org --- drivers/iommu/Kconfig | 12 + drivers/iommu/Makefile |1 + drivers/iommu/rockchip-iommu.c | 1038 3 files changed, 1051 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..d0a1261 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + select ARM_DMA_USE_IOMMU + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..61d6f87 --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,1038 @@ +/* + * 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 asm/cacheflush.h +#include asm/pgtable.h +#include linux/compiler.h +#include linux/delay.h +#include linux/device.h +#include linux/errno.h +#include linux/interrupt.h +#include linux/io.h +#include linux/iommu.h +#include linux
[PATCH v5 1/3] iommu/rockchip: rk3288 iommu driver
The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com Reviewed-by: Grant Grundler grund...@chromium.org Reviewed-by: Stéphane Marchesin marc...@chromium.org --- drivers/iommu/Kconfig | 12 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 922 + 3 files changed, 935 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..d0a1261 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + select ARM_DMA_USE_IOMMU + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..56ffb76 --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,922 @@ +/* + * 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 asm/cacheflush.h +#include asm/pgtable.h +#include linux/compiler.h +#include linux/delay.h +#include linux/device.h +#include linux/errno.h +#include linux/interrupt.h +#include linux/io.h +#include linux/iommu.h +#include linux/jiffies.h +#include linux/list.h +#include linux/mm.h +#include linux/module.h +#include linux/of.h +#include linux/platform_device.h +#include linux/slab.h +#include linux/spinlock.h + +/** MMU register offsets */ +#define RK_MMU_DTE_ADDR0x00/* Directory table address
Re: [PATCH 0/3] Rockchip IOMMU driver and devicetree bindings
On Wed, Oct 22, 2014 at 11:20 PM, Joerg Roedel j...@8bytes.org wrote: On Wed, Oct 01, 2014 at 06:20:40PM +0800, Daniel Kurtz wrote: Add a driver and devicetree bindings for the IOMMU found in Rockchip RK3288 SoCs. Daniel Kurtz (3): iommu/rockchip: rk3288 iommu driver dt-bindings: iommu: Add documentation for rockchip iommu ARM: dts: rk3288: add VOP iommu nodes .../devicetree/bindings/iommu/rockchip,iommu.txt | 26 + arch/arm/boot/dts/rk3288.dtsi | 18 + drivers/iommu/Kconfig | 11 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 5 files changed, 980 insertions(+) create mode 100644 Documentation/devicetree/bindings/iommu/rockchip,iommu.txt create mode 100644 drivers/iommu/rockchip-iommu.c Please make sure you also get Acks for the DT bindings. With that and the issue I mentioned in the other email fixed, I will apply these patches? Hi Joerg, Thanks for your reviews. Can you help me get these DT bindings Acked? AFAICT, the DT maintainers are CC'ed on this patch, I'm not sure what else to do. Thanks, -Daniel Joerg ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/3] Rockchip IOMMU driver and devicetree bindings
On Wed, Oct 22, 2014 at 11:20 PM, Joerg Roedel j...@8bytes.org wrote: On Wed, Oct 01, 2014 at 06:20:40PM +0800, Daniel Kurtz wrote: Add a driver and devicetree bindings for the IOMMU found in Rockchip RK3288 SoCs. Daniel Kurtz (3): iommu/rockchip: rk3288 iommu driver dt-bindings: iommu: Add documentation for rockchip iommu ARM: dts: rk3288: add VOP iommu nodes .../devicetree/bindings/iommu/rockchip,iommu.txt | 26 + arch/arm/boot/dts/rk3288.dtsi | 18 + drivers/iommu/Kconfig | 11 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 5 files changed, 980 insertions(+) create mode 100644 Documentation/devicetree/bindings/iommu/rockchip,iommu.txt create mode 100644 drivers/iommu/rockchip-iommu.c Please make sure you also get Acks for the DT bindings. With that and the issue I mentioned in the other email fixed, I will apply these patches? Joerg Hi Joerg, Thanks for your reviews. Can you help get these DT bindings Acked? AFAICT, the DT maintainers are CC'ed on this patch, I'm not sure what else to do. Thanks, -Daniel ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v5 1/3] iommu/rockchip: rk3288 iommu driver
On Tue, Oct 14, 2014 at 4:02 PM, Daniel Kurtz djku...@chromium.org wrote: The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com Reviewed-by: Grant Grundler grund...@chromium.org Reviewed-by: Stéphane Marchesin marc...@chromium.org Gentle ping. Any more feedback on the rockchip iommu driver? Thanks, -Daniel --- drivers/iommu/Kconfig | 12 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 3 files changed, 937 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..d0a1261 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + select ARM_DMA_USE_IOMMU + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..08e50fc --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,924 @@ +/* + * 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 asm/cacheflush.h +#include asm/pgtable.h +#include linux/compiler.h +#include linux/delay.h +#include linux/device.h +#include linux/errno.h +#include linux/interrupt.h +#include linux/io.h +#include linux/iommu.h +#include linux/jiffies.h +#include linux/list.h
[PATCH v4 1/3] iommu/rockchip: rk3288 iommu driver
The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com Reviewed-by: Grant Grundler grund...@chromium.org Reviewed-by: Stéphane Marchesin marc...@chromium.org --- drivers/iommu/Kconfig | 12 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 3 files changed, 937 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..d0a1261 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + select ARM_DMA_USE_IOMMU + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..08e50fc --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,924 @@ +/* + * 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 asm/cacheflush.h +#include asm/pgtable.h +#include linux/compiler.h +#include linux/delay.h +#include linux/device.h +#include linux/errno.h +#include linux/interrupt.h +#include linux/io.h +#include linux/iommu.h +#include linux/jiffies.h +#include linux/list.h +#include linux/mm.h +#include linux/module.h +#include linux/of.h +#include linux/platform_device.h +#include linux/slab.h +#include linux/spinlock.h + +/** MMU register offsets */ +#define RK_MMU_DTE_ADDR0x00/* Directory table address
[PATCH v5 1/3] iommu/rockchip: rk3288 iommu driver
The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com Reviewed-by: Grant Grundler grund...@chromium.org Reviewed-by: Stéphane Marchesin marc...@chromium.org --- drivers/iommu/Kconfig | 12 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 3 files changed, 937 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..d0a1261 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + select ARM_DMA_USE_IOMMU + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..08e50fc --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,924 @@ +/* + * 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 asm/cacheflush.h +#include asm/pgtable.h +#include linux/compiler.h +#include linux/delay.h +#include linux/device.h +#include linux/errno.h +#include linux/interrupt.h +#include linux/io.h +#include linux/iommu.h +#include linux/jiffies.h +#include linux/list.h +#include linux/mm.h +#include linux/module.h +#include linux/of.h +#include linux/platform_device.h +#include linux/slab.h +#include linux/spinlock.h + +/** MMU register offsets */ +#define RK_MMU_DTE_ADDR0x00/* Directory table address
[PATCH v3 1/3] iommu/rockchip: rk3288 iommu driver
The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Changes in v2: - Allocate page tables using GFP_DMA32 - Reorder structs to put spinlocks together - Reword comment in map/unmap about 4MB mappings Changes in v3: - select ARM_DMA_USE_IOMMU Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com Reviewed-by: Grant Grundler grund...@chromium.org Reviewed-by: Stéphane Marchesin marc...@chromium.org --- drivers/iommu/Kconfig | 12 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 3 files changed, 937 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..d0a1261 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + select ARM_DMA_USE_IOMMU + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..08e50fc --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,924 @@ +/* + * 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 asm/cacheflush.h +#include asm/pgtable.h +#include linux/compiler.h +#include linux/delay.h +#include linux/device.h +#include linux/errno.h +#include linux/interrupt.h +#include linux/io.h +#include linux/iommu.h +#include linux/jiffies.h +#include linux/list.h +#include linux/mm.h +#include linux/module.h +#include linux/of.h
[PATCH v2 1/3] iommu/rockchip: rk3288 iommu driver
The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Changes in v2: - Allocate page tables using GFP_DMA32 - Reorder structs to put spinlocks together - Reword comment in map/unmap about 4MB mappings Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com Reviewed-by: Grant Grundler grund...@chromium.org Reviewed-by: Stéphane Marchesin marc...@chromium.org --- drivers/iommu/Kconfig | 11 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 3 files changed, 936 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..b80454c 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,17 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..08e50fc --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,924 @@ +/* + * 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 asm/cacheflush.h +#include asm/pgtable.h +#include linux/compiler.h +#include linux/delay.h +#include linux/device.h +#include linux/errno.h +#include linux/interrupt.h +#include linux/io.h +#include linux/iommu.h +#include linux/jiffies.h +#include linux/list.h +#include linux/mm.h +#include linux/module.h +#include linux/of.h +#include linux/platform_device.h +#include linux/slab.h +#include linux
[PATCH 2/3] dt-bindings: iommu: Add documentation for rockchip iommu
Add binding documentation for Rockchip IOMMU. Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com --- .../devicetree/bindings/iommu/rockchip,iommu.txt | 26 ++ 1 file changed, 26 insertions(+) create mode 100644 Documentation/devicetree/bindings/iommu/rockchip,iommu.txt diff --git a/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt b/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt new file mode 100644 index 000..810e058 --- /dev/null +++ b/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt @@ -0,0 +1,26 @@ +Rockchip IOMMU +== + +A Rockchip DRM iommu translates io virtual addresses to physical addresses for +its master device. Each slave device is bound to a single master device, and +shares its clocks, power domain and irq. + +Required properties: +- compatible : Should be rockchip,iommu +- reg : Address space for the configuration registers +- interrupts : Interrupt specifier for the IOMMU instance +- interrupt-names : Interrupt name for the IOMMU instance +- #iommu-cells: Should be 0. This indicates the iommu is a +single-master device, and needs no additional information +to associate with its master device. See: +Documentation/devicetree/bindings/iommu/iommu.txt + +Example: + + vopl_mmu: iommu@0xff940300 { + compatible = rockchip,iommu; + reg = 0xff940300 0x100; + interrupts = GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH; + interrupt-names = vopl_mmu; + #iommu-cells = 0; + }; -- 2.1.0.rc2.206.gedb03e5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/3] iommu/rockchip: rk3288 iommu driver
The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the iommus field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 directory_table has 1024 4-byte dte entries. Each dte points to a level 2 page_table. Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's Directory Table Entry (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com --- drivers/iommu/Kconfig | 11 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 3 files changed, 936 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..b80454c 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,17 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool Rockchip IOMMU Support + depends on ARCH_ROCKCHIP + select IOMMU_API + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool Tegra GART IOMMU Support depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..4116df1 --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,924 @@ +/* + * 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 asm/cacheflush.h +#include asm/pgtable.h +#include linux/compiler.h +#include linux/delay.h +#include linux/device.h +#include linux/errno.h +#include linux/interrupt.h +#include linux/io.h +#include linux/iommu.h +#include linux/jiffies.h +#include linux/list.h +#include linux/mm.h +#include linux/module.h +#include linux/of.h +#include linux/platform_device.h +#include linux/slab.h +#include linux/spinlock.h + +/** MMU register offsets */ +#define RK_MMU_DTE_ADDR0x00/* Directory table address */ +#define RK_MMU_STATUS 0x04 +#define RK_MMU_COMMAND 0x08 +#define RK_MMU_PAGE_FAULT_ADDR 0x0C/* IOVA of last page fault
[PATCH 3/3] ARM: dts: rk3288: add VOP iommu nodes
Add device nodes for the VOP iommus. Device nodes for other iommus will be added in later patches. The iommu nodes use the #iommu-cells property as described in: Documentation/devicetree/bindings/iommu/iommu.txt Signed-off-by: Daniel Kurtz djku...@chromium.org Signed-off-by: Simon Xue x...@rock-chips.com --- arch/arm/boot/dts/rk3288.dtsi | 18 ++ 1 file changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 5950b0a..cbc92fa 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -271,6 +271,24 @@ status = disabled; }; + vopb_mmu: iommu@0xff930300 { + compatible = rockchip,iommu; + reg = 0xff930300 0x100; + interrupts = GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH; + interrupt-names = vopb_mmu; + #iommu-cells = 0; + status = disabled; + }; + + vopl_mmu: iommu@0xff940300 { + compatible = rockchip,iommu; + reg = 0xff940300 0x100; + interrupts = GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH; + interrupt-names = vopl_mmu; + #iommu-cells = 0; + status = disabled; + }; + gic: interrupt-controller@ffc01000 { compatible = arm,gic-400; interrupt-controller; -- 2.1.0.rc2.206.gedb03e5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu