On 26.09.2017 19:08, Stephen Warren wrote: > On 09/26/2017 08:08 AM, Jon Hunter wrote: >> Hi Dmitry, >> >> On 25/09/17 23:35, Dmitry Osipenko wrote: >>> DMA config is incorrect, because of it DMA transfer is never issued and >>> tegra20_fuse_read() always returns 0x0. >>> >>> Signed-off-by: Dmitry Osipenko <digetx@xxxxxxxxx> >>> --- >>> drivers/soc/tegra/fuse/fuse-tegra.c | 1 + >>> drivers/soc/tegra/fuse/fuse-tegra20.c | 3 ++- >>> 2 files changed, 3 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c >>> b/drivers/soc/tegra/fuse/fuse-tegra.c >>> index b7c552e3133c..73a3a2c74021 100644 >>> --- a/drivers/soc/tegra/fuse/fuse-tegra.c >>> +++ b/drivers/soc/tegra/fuse/fuse-tegra.c >>> @@ -132,6 +132,7 @@ static int tegra_fuse_probe(struct platform_device *pdev) >>> /* take over the memory region from the early initialization */ >>> res = platform_get_resource(pdev, IORESOURCE_MEM, 0); >>> + fuse->phys = res->start; >>> fuse->base = devm_ioremap_resource(&pdev->dev, res); >>> if (IS_ERR(fuse->base)) >>> return PTR_ERR(fuse->base); >>> diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c >>> b/drivers/soc/tegra/fuse/fuse-tegra20.c >>> index 294413a969a0..a33f48c06771 100644 >>> --- a/drivers/soc/tegra/fuse/fuse-tegra20.c >>> +++ b/drivers/soc/tegra/fuse/fuse-tegra20.c >>> @@ -59,7 +59,7 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, >>> unsigned int offset) >>> mutex_lock(&fuse->apbdma.lock); >>> - fuse->apbdma.config.src_addr = fuse->apbdma.phys + FUSE_BEGIN + offset; >>> + fuse->apbdma.config.src_addr = fuse->phys + FUSE_BEGIN + offset; >>> err = dmaengine_slave_config(fuse->apbdma.chan, &fuse->apbdma.config); >>> if (err) >>> @@ -119,6 +119,7 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse) >>> fuse->apbdma.config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; >>> fuse->apbdma.config.src_maxburst = 1; >>> fuse->apbdma.config.dst_maxburst = 1; >>> + fuse->apbdma.config.direction = DMA_DEV_TO_MEM; >>> init_completion(&fuse->apbdma.wait); >>> mutex_init(&fuse->apbdma.lock); >> >> Thanks for the fix. >> >> When booting the mainline on Tegra20 Trimslice, I only see the >> tegra20_fuse_read_early() called and not the tegra20_fuse_read(). That's >> not to say it is not needed, but I am wondering if we really need this >> complex tegra20_fuse_read() using DMA and whether we should just have >> the normal fuse->read() call tegra20_fuse_read_early() as well to >> simplify matters? >> >> Maybe Thierry or Stephen know the history here? > > There's some HW bug related to reading the fuse registers from the CPU. The fix > was implemented long ago by Olof; see the git commit description pasted below. > IIRC, the code directly reads the fuse registers before the point where DMA is > available (the argument being we can't do anything else, and this period of time > is short so the risk hopefully low), but once DMA is available, it is used to > avoid the HW bug. The bug was apparently fixed in Tegra30; see the other commit > description pasted below. > >> commit e2f91578b35347341482f6af9e4fcf3174531efd >> Author: Olof Johansson <olof@xxxxxxxxx> >> Date: Wed Oct 12 23:52:29 2011 -0700 >> >> ARM: tegra: use APB DMA for accessing APB devices >> Tegra2 hangs if APB registers are accessed from the cpu during an >> apb dma operation. The workaround is to use apb dma to read/write the >> registers instead. >> There is a dependency loop between fuses, clocks, and APBDMA. If dma >> is enabled, fuse reads must go through APBDMA to avoid corruption due >> to a hw bug. APBDMA requires a clock to be enabled. Clocks must read >> a fuse to determine allowable cpu frequencies. >> Separate out the fuse DMA initialization, and allow the fuse read >> and write functions to be called without using DMA before the DMA >> initialization has been completed. Access to the fuses before APBDMA >> is initialized won't hit the hardware bug because nothing else can be >> using DMA. >> Original fuse registar access code from Varun Wadekar >> <vwadekar@xxxxxxxxxx>, improved by Colin Cross <ccross@xxxxxxxxxxx> >> and later moved to separate driver by Jon Mayo <jmayo@xxxxxxxxxx>. >> Major refactoring/cleanup by Olof Johansson <olof@xxxxxxxxx>. >> Changes since v1: >> * fix 'return false' on error condition >> * dequeue dma ops in case of timeout >> From: Jon Mayo <jmayo@xxxxxxxxxx>. >> Signed-off-by: Jon Mayo <jmayo@xxxxxxxxxx>. >> Signed-off-by: Olof Johansson <olof@xxxxxxxxx> >> Acked-by: Stephen Warren <swarren@xxxxxxxxxx> > >> commit b861c275ea5cfeab32241c3c92a203579d5699ff >> Author: Laxman Dewangan <ldewangan@xxxxxxxxxx> >> Date: Wed Jun 20 18:06:34 2012 +0530 >> >> ARM: tegra: apbio access using dma for tegra20 only >> The Tegra20 HW issue with accessing APBIO registers (such >> as fuse registers) directly from the CPU concurrently with >> APB DMA accesses has been fixed in Tegra30 and later chips. >> Access these registers directly from the CPU on Tegra30 >> and later, and apply the workaround only for Tegra20. >> Signed-off-by: Laxman Dewangan <ldewangan@xxxxxxxxxx> >> Tested-by: Chaitanya Bandi <bandik@xxxxxxxxxx> >> Signed-off-by: Stephen Warren <swarren@xxxxxxxxxx> Thank you very much for the clarification. -- Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html