Re: [PATCH v7 3/5] memory: mediatek: Add SMI driver
From: Yong Wu
Date: Tue Jan 19 2016 - 04:43:57 EST
On Mon, 2016-01-18 at 11:11 +0100, Matthias Brugger wrote:
>
> On 18/12/15 09:09, 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 <yong.wu@xxxxxxxxxxxx>
[...]
> > +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);
> > + int ret;
> > +
> > + /* Enable the smi-common's power and clocks */
> > + ret = mtk_smi_enable(common);
> > + if (ret)
> > + return ret;
> > +
> > + /* Enable the larb's power and clocks */
> > + ret = mtk_smi_enable(&larb->smi);
> > + if (ret) {
> > + mtk_smi_disable(common);
> > + return ret;
> > + }
> > +
> > + /* Configure the iommu info */
> > + if (larb->mmu)
> > + writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
>
> Can there be a larb that does not have a mmu id defined?
> Phandles for the iommu need always to have a mtk_m4u_id defined, so I
> don't see the case where this can happen?
No. In current IC(mt8173), All the larbs have the mmu info register.
> Why did you changed this value to a pointer and added the if?
I changed it to a pointer in order to support
iommu_attach_device/iommu_detach_device dynamically.
In our v6, there is a interface called mtk_smi_config_port in which
the iommu(M4U) could tell SMI which ports should enable iommu.
In this version, we use the additional data of component to finish
this job(the third parameter of the mtk_smi_larb_bind). then we could
delete that interface.
larb->mmu is a pointer that point to the mmu in "struct mtk_smi_iommu
smi_imu" of "struct mtk_iommu_data". This "smi_imu" is used to record
that which ports has already enabled iommu for each larb and it will be
updated during the iommu_attach_device/iommu_detach_device.
Why add the if?
-> This pointer may be null in the mtk_smi_larb_unbind.
I'm also not sure when it will enter mtk_smi_larb_unbind, maybe while
the iommu device is removed, then it call component_master_del, or the
larb device itself is removed, or some other error case in component.
but there really is a path it will be null, so I add this *if*.
If you think it is unnecessary, I can delete it.
>
> > +
> > + return 0;
> > +}
> > +
> > +void mtk_smi_larb_put(struct device *larbdev)
> > +{
> > + struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
> > + struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
> > +
>
> Would it make sense to write SMI_LARB_MMU_EN here again to eventually
> turn off mmus?
I think no. As you know, there may be some modules in one larb, so we
cann't write 0 in SMI_LARB_MMU_EN here to turn off mmus for all modules.
mtk_smi_larb_get/mtk_smi_larb_put mainly enable/disable the power domain
and clocks for this local arbiter. And the larb is a unit here, SMI
cannât detect which module calls mtk_smi_larb_put and disable his
special iommu bits. so do mtk_smi_larb_get.
I know that the moduleâs special iommu bit wasnât wrote to 0 here, but
if this module would like to work again, he have to call
mtk_smi_larb_get again, and currently all the multimedia modules always
works via iommu, we donât need to write 0 here.
> Other then this, the driver looks fine to me.
Thanks very much for your reply. I could send the new version if we get
a conclusion for the two issue above here, like you really don't like
that *if*.
>
> Regards,
> Matthias
>
> > + mtk_smi_disable(&larb->smi);
> > + mtk_smi_disable(common);
> > +}
> > +
> > +static int
> > +mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
> > +{
> > + struct mtk_smi_larb *larb = dev_get_drvdata(dev);
> > + struct mtk_smi_iommu *smi_iommu = data;
> > + unsigned int i;
> > +
> > + for (i = 0; i < smi_iommu->larb_nr; i++) {
> > + if (dev == smi_iommu->larb_imu[i].dev) {
> > + larb->mmu = &smi_iommu->larb_imu[i].mmu;
> > + return 0;
> > + }
> > + }
> > + return -ENODEV;
> > +}
> > +
> > +static void
> > +mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data)
> > +{
> > + struct mtk_smi_larb *larb = dev_get_drvdata(dev);
> > +
> > + larb->mmu = NULL;
> > +}
> > +
> > +static const struct component_ops mtk_smi_larb_component_ops = {
> > + .bind = mtk_smi_larb_bind,
> > + .unbind = mtk_smi_larb_unbind,
> > +};
[...]