[PATCH] cpuidle: coupled: fix the potensial race condition and deadlock
Considering the chance that two CPU come into cpuidle_enter_state_coupled at very close time. The 1st CPU increases the waiting count and the 2nd CPU do the same thing right away. The 2nd CPU found the 1st CPU already in waiting then prepare to poke it. Before the 2nd CPU to poke 1st CPU, the 1st found the waiting count already same with cpu_online count. So the 1st won't go into waiting loop and the 2nd CPU didn't poke it yet. The 1st CPU will go into ready loop directly. Then the 2nd CPU set up the couple_cpuidle_mask for 1st CPU and poke it. But the 1st CPU already lost the chance to handle the poke and clear the couple_cpuidle_mask. Now whole MPcore are alredy to be coupled. The MPcore will go into the power saving idle mode. Because the poke was be implemented as a smp_call_function_single, it's a software intrrupt of IPI_SINGLE_FUNC. If the power saving idle mode of the platform can't retain the software interrupt of power saving idle mode, (e.g. Tegra's powerd-down idle mode will shut off cpu power that include the power of GIC) the software interrupt will got lost. When the CPU resumed from the power saving idle mode and the system still keep idle, it will go into idle mode again immediately. Because the smp_call_function_single not allow the same function be called for the same cpu twice, or it will got a lock. So the couple_cpuidle_mask can't be cleared by 1st CPU, the 2nd CPU also can't poke it again. Then the deadlock happens here. The fix here used different wake up mechanism. Because there are already two loops and a gloable variable ready_waiting_counts to sync the status of MPcore to coupled state, the coupled_cpuidle_mask was not really necessary. Just waking up the CPU from waiting and checking if the CPU need resched at outside world to take the CPU out of idle are enough. And this fix didn't modify the original behavior of coupled cpuidle framework. It should still compitable with the origianal. The cpuidle driver that already applies coupled cpuidle not need to change as well. Cc: Colin Cross ccr...@android.com Signed-off-by: Joseph Lo jose...@nvidia.com --- Please check the detail sequence about how race condition and deadlock be happened below: It could be reproduced on Tegra20 and Tegra30. (Suppose the last two cpu came into coupled_cpuidle_state at very close time) CPU_0 CPU_1 cpuidle_enter_state_coupled cpuidle_enter_state_coupled 1.increase waiting count 1. increase waiting count same time frame --- 2.before went into waiting loop, check the waiting count first 2.1 the waiting count was same with online count 2.2 so it won't go into waiting loop 2.in the procedure to prepare to send an smp_call_function_single to wake up CPU_0 next time frame --- 3.before go into ready loop 3.1 it will enable_irq 3.2 check if there is any IPI 3.3 if yes, clear the coupled_mask 3.4 then disable_irq 3. trigger the IPI to CPU_0 3.1 set up the coupled_mask for CPU_0 3.2 sent IPI to CPU_0 4. the IPI_SINGLE_FUNC been triggered from CPU_1 to CPU_0 and the coupled_mask of CPU_0 been set up 4.1 but the CPU_0 miss the IPI and the chance to clear coupled_mask next time frame --- 5. MPCores went into ready loop and been coupled 6. go into power saving idle mode (For Tegra, it's means the vdd_cpu rail be shut off. The GIC be powered off and the SW_INT(IPI) couldn't be retained.) 7. After the resume of power saving idle mode, the coupled_mask of CPU_0 not been cleared. 8. return to kernel If the system still idle, it will come back to idle immediately. CPU_0 CPU_1 cpuidle_enter_state_coupled cpuidle_enter_state_coupled 1. set itself to waiting 2. go into waiting loop 3. check the coupled_mask been set or not 3.1 enable_irq 3.2 waiting for the coupled_mask be cleared 1. found CPU_0 in waiting 2. prepare an IPI to poke CPU_0 2.1 check the coupled_mask of CPU_0 2.2 because it had been set 2.3 so it didn't trigger and smp_call_function_single to CPU_0 again 3. then go into ready loop 4. because there is no irq of IPI_SINGLE_FUNC be triggered
Re: CPU hotplug hang due to swap: make each swap partition have one address_space
On Mon, 2013-02-04 at 10:36 +0800, Shaohua Li wrote: On Fri, Feb 01, 2013 at 10:02:33PM -0700, Stephen Warren wrote: Shaohua, In next-20130128, commit 174f064 swap: make each swap partition have one address_space (from the mm/akpm tree) appears causes a hang/RCU stall for me when hot-unplugging a CPU. does this one work for you? http://marc.info/?l=linux-mmm=135929599505624w=2 Or try a more recent linux-next. The patch is in akpm's tree. Hi Shaohua, The patch you pointed out did fix the issue. Just verified on Tegra device. Thanks, Joseph -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/5] cpufreq: star/stop cpufreq timers on cpu hotplug
On Wed, 2013-01-30 at 12:52 +0800, Viresh Kumar wrote: Hi Fabio, Sorry for waking up very late :) The reason why i am starting this thread again is due to problem reported by Joseph, with latest linux-next/master branch (which contains few big patches from me :) ): After Viresh point me out what patch may cause the issue that I met below, I also try to just revert this patch on linux-next. Then everything that may trigger to disable_nonboot_cpus or hotplug back to normal. So just reverting this patch also fix the issues I saw. FYI. Thanks, Joseph Reboot is giving following to him: * Will now halt [ 193.756068] Disabling non-boot CPUs... [ 193.760088] BUG: scheduling while atomic: halt/780/0x0002 [ 193.765845] Modules linked in: brcmfmac brcmutil [ 193.770613] [c0014990] (unwind_backtrace+0x0/0xf8) from [c0049510] (__schedule_bug+0x44/0x5c) [ 193.779548] [c0049510] (__schedule_bug+0x44/0x5c) from [c04fa320] (__schedule+0x688/0x6ec) [ 193.788206] [c04fa320] (__schedule+0x688/0x6ec) from [c04fa75c] (schedule_preempt_disabled+0x24/0x34) [ 193.797811] [c04fa75c] (schedule_preempt_disabled+0x24/0x34) from [c04f916c] (__mutex_lock_slowpath+0x170/0x34c) [ 193.808367] [c04f916c] (__mutex_lock_slowpath+0x170/0x34c) from [c04f9354] (mutex_lock+0xc/0x24) [ 193.817554] [c04f9354] (mutex_lock+0xc/0x24) from [c04f1cdc] (unregister_cpu_notifier+0xc/0x24) [ 193.826640] [c04f1cdc] (unregister_cpu_notifier+0xc/0x24) from [c033a8a4] (cpufreq_governor_dbs+0x118/0x614) [ 193.836866] [c033a8a4] (cpufreq_governor_dbs+0x118/0x614) from [c033747c] (__cpufreq_governor+0x58/0xc0) [ 193.846737] [c033747c] (__cpufreq_governor+0x58/0xc0) from [c0339104] (__cpufreq_remove_dev.clone.7+0x58/0x320) [ 193.857207] [c0339104] (__cpufreq_remove_dev.clone.7+0x58/0x320) from [c04f7958] (cpufreq_cpu_callback+0x8c/0x9c) [ 193.867850] [c04f7958] (cpufreq_cpu_callback+0x8c/0x9c) from [c0044f4c] (notifier_call_chain+0x44/0x84) [ 193.877623] [c0044f4c] (notifier_call_chain+0x44/0x84) from [c0026e24] (__cpu_notify+0x2c/0x48) [ 193.886704] [c0026e24] (__cpu_notify+0x2c/0x48) from [c04f1b08] (_cpu_down+0xb0/0x23c) [ 193.895004] [c04f1b08] (_cpu_down+0xb0/0x23c) from [c00270ec] (disable_nonboot_cpus+0x68/0x104) [ 193.904089] [c00270ec] (disable_nonboot_cpus+0x68/0x104) from [c0034fbc] (kernel_power_off+0x24/0x48) [ 193.913688] [c0034fbc] (kernel_power_off+0x24/0x48) from [c0035810] (sys_reboot+0x104/0x1e0) [ 193.922517] [c0035810] (sys_reboot+0x104/0x1e0) from [c000e520] (ret_fast_syscall+0x0/0x30) And the crash log show this patch of yours somewhere :) First question: Is this patch still required? Because following patch from me is sending a STOP/START to governors on cpu hot-[un]plug ? commit dbcb63407c095af73f3464767e00902cdee55e8b Author: Viresh Kumar viresh.ku...@linaro.org Date: Sat Jan 12 05:14:39 2013 + cpufreq: Notify governors when cpus are hot-[un]plugged For me, the answer is NO. Over that, i tried these patches on ARM bigLITTLE TC2 (3 A7's and 2 A15's) and my system wasn't booting at all for ondemand governor. Reverting your patch does fix the issue: [2.613573] arm_big_little: bL_cpufreq_init: Initialized, cpu: 0, cluster 0 [2.635436] arm_big_little: bL_cpufreq_init: Initialized, cpu: 2, cluster 1 [ 23.650184] INFO: rcu_sched self-detected stall on CPU { 0} (t=2100 jiffies g=4294967088 c=4294967087 q=10) [ 23.679664] Backtrace for cpu 0 (current): [ 23.680239] INFO: rcu_sched detected stalls on CPUs/tasks: { 0} (detected by 2, t=2103 jiffies, g=4294967088, c=4294967087, q=10) [ 23.726839] [c0014020] (unwind_backtrace+0x0/0xf8) from [c0012f60] (smp_send_all_cpu_backtrace+0x60/0xcc) [ 23.756545] [c0012f60] (smp_send_all_cpu_backtrace+0x60/0xcc) from [c008232c] (rcu_pending+0x2c8/0x63c) [ 23.785731] [c008232c] (rcu_pending+0x2c8/0x63c) from [c0083854] (rcu_check_callbacks+0x7c/0x148) [ 23.813358] [c0083854] (rcu_check_callbacks+0x7c/0x148) from [c002d1e0] (update_process_times+0x38/0x68) [ 23.842808] [c002d1e0] (update_process_times+0x38/0x68) from [c0066b00] (tick_sched_handle+0x48/0x54) [ 23.871472] [c0066b00] (tick_sched_handle+0x48/0x54) from [c0066d6c] (tick_sched_timer+0x44/0x74) [ 23.899098] [c0066d6c] (tick_sched_timer+0x44/0x74) from [c00416d8] (__run_hrtimer+0x84/0x1b4) [ 23.925940] [c00416d8] (__run_hrtimer+0x84/0x1b4) from [c004224c] (hrtimer_interrupt+0x108/0x2d4) [ 23.953563] [c004224c] (hrtimer_interrupt+0x108/0x2d4) from [c0013990] (arch_timer_handler_virt+0x30/0x38) [ 23.983530] [c0013990] (arch_timer_handler_virt+0x30/0x38) from [c007e41c] (handle_percpu_devid_irq+0x74/0x110) [ 24.014799] [c007e41c] (handle_percpu_devid_irq+0x74/0x110) from [c007ac8c] (generic_handle_irq+0x20/0x30) [ 24.044765] [c007ac8c] (generic_handle_irq+0x20/0x30) from [c000e9f4] (handle_IRQ+0x38/0x94) [ 24.071085] [c000e9f4] (handle_IRQ+0x38/0x94) from [c0008570]
Re: [PATCH v3 0/9] Migrate Tegra to common clock framework
On Fri, 2013-01-04 at 17:40 +0800, Prashant Gaikwad wrote: This patchset does following: 1. Decompose single tegra clock structure into multiple clocks. 2. Try to use standard clock types supported by common clock framework. 3. Use dynamic initialization. 4. Move all clock code to drivers/clk/tegra from mach-tegra. 5. Add device tree support for Tegra20 and Tegra30 clocks. 6. Remove all legacy clock code from mach-tegra. Tested on Tegra30 (Cardhu) and Tegra20 (Ventana). Changes from v2: Removed APB MISC node. Fixed some issues reported by Joseph Lo. Added function to read chip id revision register. Changes from v1: Rebased on linux-next for 20121224. Prashant Gaikwad (8): ARM: tegra: Add function to read chipid clk: tegra: Add tegra specific clocks arm: tegra: Move tegra_cpu_car.h to linux/clk/tegra.h ARM: Tegra: Define Tegra30 CAR binding clk: tegra: add clock support for tegra20 clk: tegra: add clock support for tegra30 arm: tegra: Migrate to new clock code arm: tegra: Remove legacy clock code Stephen Warren (1): ARM: tegra: Define Tegra20 CAR binding Good job, Prashant. :-) This series : Tested-by: Joseph Lo jose...@nvidia.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/7] ARM: dt: tegra20: Add clock information
On Fri, 2013-01-04 at 17:46 +0800, Prashant Gaikwad wrote: Add clock information to device nodes. Signed-off-by: Prashant Gaikwad pgaik...@nvidia.com --- Tested on Ventana (Tegra20) and Cardhu (Tegra30). This series depends on ccf-rework patch series. --- This series : Tested-by: Joseph Lo jose...@nvidia.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/3] cpuidle: coupled: abort idle if pokes are pending
On Sat, 2013-08-24 at 03:45 +0800, Colin Cross wrote: Joseph Lo jose...@nvidia.com reported a lockup on Tegra3 caused by a race condition in coupled cpuidle. When two or more cpus Actually this issue can be reproduced on both Tegra20/30 platforms. And I suggest using Tegra20 to replace Tegra3 here, we only apply coupled CPU idle function on Tegra20 in the mainline right now. enter idle at the same time, the first cpus to arrive may go to the ready loop without processing pending pokes from the last cpu to arrive. This patch adds a check for pending pokes once all cpus have been synchronized in the ready loop and resets the coupled state and retries if any cpus failed to handle their pending poke. Retrying on all cpus may trigger the same issue again, so this patch also adds a check to ensure that each cpu has received at least one poke between when it enters the waiting loop and when it moves on to the ready loop. Reported-by: Joseph Lo jose...@nvidia.com CC: sta...@vger.kernel.org Signed-off-by: Colin Cross ccr...@android.com --- drivers/cpuidle/coupled.c | 107 +++--- 1 file changed, 82 insertions(+), 25 deletions(-) [snip] +/* + * The cpuidle_coupled_poke_pending mask is used to ensure that each cpu has s/cpuidle_coupled_poke_pending/cpuidle_coupled_poked/? :) + * been poked once to minimize entering the ready loop with a poke pending, + * which would require aborting and retrying. + */ +static cpumask_t cpuidle_coupled_poked; I fixed this issue by checking if there is a pending SGI, then abort the coupled state on Tegra20. It still can be reproduced easily if I remove the checking code. So I tested the case with this patch, the result is good. This patch can fix the issue indeed. I also tested with the other two patches. It didn't cause any regression. So this series: Tested-by: Joseph Lo jose...@nvidia.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 06/21] ARM: tegra: call cpu_do_idle from C code
On Wed, 2013-04-24 at 00:30 +0800, Arnd Bergmann wrote: When building a kernel for multiple CPU architecture levels, cpu_do_idle() is a macro for an indirect function call, which cannot be called from assembly code as Tegra does. Adding a trivial C wrapper for this function lets us build a tegra kernel with ARMv6 support enabled. Signed-off-by: Arnd Bergmann a...@arndb.de Cc: Joseph Lo jose...@nvidia.com Cc: Stephen Warren swar...@nvidia.com --- Hi Arnd, Thanks for fixing. Tested-by: Joseph Lo jose...@nvidia.com Joseph -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 07/21] ARM: tegra: unify tegra_idle_device definitions
On Wed, 2013-04-24 at 06:04 +0800, Daniel Lezcano wrote: On 04/23/2013 08:57 PM, Arnd Bergmann wrote: On Tuesday 23 April 2013, Daniel Lezcano wrote: the patch sounds good but I think the side effect of the consolidation patchset [1] fixed that. You can find these fixes in Rafael's tree: https://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-nextamp;id=4c637b2175a0dc65d533494225525c6c82d73293 https://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-nextamp;id=e158f9da6974cc11bfab2246a9b10021af0e0d8a https://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-nextamp;id=c5106c9dea9a6022ab84c6cb1d4a0b19fc5af0e2 https://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-nextamp;id=f040c26ffaa5e56f2bca427c719c9601a02e70e5 [1] http://www.spinics.net/lists/arm-kernel/msg239811.html Ah. Is that not in linux-next? I created the patch today based on the latest linux-next from today (Tuesday). Ah, ok. Actually the patches were taken by Rafael right today. So it is possible the changes were not reflected in linux-next yet. Hi Arnd and Daniel, Thanks for taking care this.:) Joseph -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/4] clk: tegra114: table driven PMC clock init
On Tue, 2013-09-03 at 21:31 +0800, Peter De Schrijver wrote: This patch converts the Tegra114 audio clock registration to be table driven like the periph clocks. s/audio/PMC/ :) Signed-off-by: Peter De Schrijver pdeschrij...@nvidia.com --- drivers/clk/tegra/clk-tegra114.c | 58 +++--- 1 files changed, 23 insertions(+), 35 deletions(-) [snip] -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 07/32] arm: delete __cpuinit/__CPUINIT usage from all ARM users
Adding linux-tegra in Cc. On Tue, 2013-06-25 at 03:30 +0800, Paul Gortmaker wrote: The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 (x86: Fix bit corruption at CPU resume time) is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) and are flagged as __cpuinit -- so if we remove the __cpuinit from the arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit related content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the ARM uses of the __cpuinit macros from C code, and all __CPUINIT from assembly code. It also had two .previous section statements that were paired off against __CPUINIT (aka .section .cpuinit.text) that also get removed here. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Russell King li...@arm.linux.org.uk Cc: Will Deacon will.dea...@arm.com Cc: linux-arm-ker...@lists.infradead.org Signed-off-by: Paul Gortmaker paul.gortma...@windriver.com --- [This commit is part of the __cpuinit removal work. If you don't see any problems with it, then you don't have to do anything ; it will be submitted with all the rest of the __cpuinit removal work. On the other hand, if you want to carry this patch in with your other pending changes so as to handle conflicts with other pending work yourself, then that is fine too, as the commits can largely be treated independently. For more information, please see: https://lkml.org/lkml/2013/6/20/513 ] Hi Paul, I just tested this series on Tegra platform. It looks broken CPU hotplug function for Tegra at least. The CPU can't plug-in after unplugging. And the system resume function also not working when enable_nonboot_cpus. Both of the issue cause system hang up. Are we missing something for __cpuinit removal work? Thanks, Joseph -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC 04/10] memory: Add Tegra124 memory controller support
Hi Thierry, On 06/27/2014 04:49 AM, Thierry Reding wrote: [snip] + +#define MC_INTSTATUS 0x000 +#define MC_INT_DECERR_MTS (1 16) +#define MC_INT_SECERR_SEC (1 13) +#define MC_INT_DECERR_VPR (1 12) +#define MC_INT_INVALID_APB_ASID_UPDATE (1 11) +#define MC_INT_INVALID_SMMU_PAGE (1 10) +#define MC_INT_ARBITRATION_EMEM (1 9) +#define MC_INT_SECURITY_VIOLATION (1 8) +#define MC_INT_DECERR_EMEM (1 6) +#define MC_INTMASK 0x004 +#define MC_ERR_STATUS 0x08 +#define MC_ERR_ADR 0x0c + [snip] + +#define SMMU_PDE_ATTR (SMMU_PDE_READABLE | SMMU_PDE_WRITABLE | \ +SMMU_PDE_NONSECURE) +#define SMMU_PTE_ATTR (SMMU_PTE_READABLE | SMMU_PTE_WRITABLE | \ +SMMU_PTE_NONSECURE) + +#define SMMU_PDE_VACANT(n) (((n) 10) | SMMU_PDE_ATTR) +#define SMMU_PTE_VACANT(n) (((n) 12) | SMMU_PTE_ATTR) There is an ISR to catch the invalid SMMU translation. Do you want to modify the identity mapping with read/write attribute of the unused SMMU pages? This can make sure we capture the invalid SMMU translation. And helps for driver to capture issues when using SMMU. -joseph +static irqreturn_t tegra124_mc_irq(int irq, void *data) +{ + struct tegra_mc *mc = data; + u32 value, status, mask; + + /* mask all interrupts to avoid flooding */ + mask = mc_readl(mc, MC_INTMASK); + mc_writel(mc, 0, MC_INTMASK); + + status = mc_readl(mc, MC_INTSTATUS); + mc_writel(mc, status, MC_INTSTATUS); + + dev_dbg(mc-dev, INTSTATUS: %08x\n, status); + + if (status MC_INT_DECERR_MTS) + dev_dbg(mc-dev, DECERR_MTS\n); + + if (status MC_INT_SECERR_SEC) + dev_dbg(mc-dev, SECERR_SEC\n); + + if (status MC_INT_DECERR_VPR) + dev_dbg(mc-dev, DECERR_VPR\n); + + if (status MC_INT_INVALID_APB_ASID_UPDATE) + dev_dbg(mc-dev, INVALID_APB_ASID_UPDATE\n); + + if (status MC_INT_INVALID_SMMU_PAGE) + dev_dbg(mc-dev, INVALID_SMMU_PAGE\n); + + if (status MC_INT_ARBITRATION_EMEM) + dev_dbg(mc-dev, ARBITRATION_EMEM\n); + + if (status MC_INT_SECURITY_VIOLATION) + dev_dbg(mc-dev, SECURITY_VIOLATION\n); + + if (status MC_INT_DECERR_EMEM) + dev_dbg(mc-dev, DECERR_EMEM\n); + + value = mc_readl(mc, MC_ERR_STATUS); + + dev_dbg(mc-dev, ERR_STATUS: %08x\n, value); + dev_dbg(mc-dev, type: %x\n, (value 28) 0x7); + dev_dbg(mc-dev, protection: %x\n, (value 25) 0x7); + dev_dbg(mc-dev, adr_hi: %x\n, (value 20) 0x3); + dev_dbg(mc-dev, swap: %x\n, (value 18) 0x1); + dev_dbg(mc-dev, security: %x\n, (value 17) 0x1); + dev_dbg(mc-dev, r/w: %x\n, (value 16) 0x1); + dev_dbg(mc-dev, adr1: %x\n, (value 12) 0x7); + dev_dbg(mc-dev, client: %x\n, value 0x7f); + + value = mc_readl(mc, MC_ERR_ADR); + dev_dbg(mc-dev, ERR_ADR: %08x\n, value); + + mc_writel(mc, mask, MC_INTMASK); + + return IRQ_HANDLED; +} + -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv4] serial: of-serial: fix up PM ops on no_console_suspend and port type
On 10/14/2014 04:42 PM, Jingchang Lu wrote: This patch fixes commit 2dea53bf57783f243c892e99c10c6921e956aa7e, serial: of-serial: add PM suspend/resume support, which disables the uart clock on suspend, but also causes a hardware hang on register access if no_console_suspend command line option is used. Also, not every of_serial device is an 8250 port, so the serial8250 suspend/resume functions should only be applied to a real 8250 port. Signed-off-by: Jingchang Lu jingchang...@freescale.com If you can make sure this patch can build without include linux/console.h, then this patch Tested-by: Joseph Lo jose...@nvidia.com And thanks for your fix. --- changes in v4: separate 8250 port suspend/resume from of_serial_suspend/resume. changes in v3: fix up point reference and deference. changes in v2: add switch selection on uart type. drivers/tty/serial/of_serial.c | 52 -- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 8bc2563..5281f8f 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -241,13 +241,48 @@ static int of_platform_serial_remove(struct platform_device *ofdev) } #ifdef CONFIG_PM_SLEEP -static int of_serial_suspend(struct device *dev) +#ifdef CONFIG_SERIAL_8250 +static void of_serial_suspend_8250(struct of_serial_info *info) { - struct of_serial_info *info = dev_get_drvdata(dev); + struct uart_8250_port *port8250 = serial8250_get_port(info-line); + struct uart_port *port = port8250-port; serial8250_suspend_port(info-line); - if (info-clk) + if (info-clk (!uart_console(port) || console_suspend_enabled)) clk_disable_unprepare(info-clk); +} + +static void of_serial_resume_8250(struct of_serial_info *info) +{ + struct uart_8250_port *port8250 = serial8250_get_port(info-line); + struct uart_port *port = port8250-port; + + if (info-clk (!uart_console(port) || console_suspend_enabled)) + clk_prepare_enable(info-clk); + + serial8250_resume_port(info-line); +} +#else +static inline void of_serial_suspend_8250(struct of_serial_info *info) +{ +} + +static inline void of_serial_resume_8250(struct of_serial_info *info) +{ +} +#endif + +static int of_serial_suspend(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + switch(info-type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_suspend_8250(info); + break; + default: + break; + } return 0; } @@ -256,10 +291,13 @@ static int of_serial_resume(struct device *dev) { struct of_serial_info *info = dev_get_drvdata(dev); - if (info-clk) - clk_prepare_enable(info-clk); - - serial8250_resume_port(info-line); + switch(info-type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_resume_8250(info); + break; + default: + break; + } return 0; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv4] serial: of-serial: fix up PM ops on no_console_suspend and port type
On 10/15/2014 02:32 PM, Jingchang Lu wrote: -Original Message- From: Joseph Lo [mailto:jose...@nvidia.com] Sent: Wednesday, October 15, 2014 9:01 AM To: Lu Jingchang-B35083; gre...@linuxfoundation.org Cc: pe...@hurleysoftware.com; a...@arndb.de; linux-kernel@vger.kernel.org; linux-ser...@vger.kernel.org; linux-arm-ker...@lists.infradead.org Subject: Re: [PATCHv4] serial: of-serial: fix up PM ops on no_console_suspend and port type On 10/14/2014 04:42 PM, Jingchang Lu wrote: This patch fixes commit 2dea53bf57783f243c892e99c10c6921e956aa7e, serial: of-serial: add PM suspend/resume support, which disables the uart clock on suspend, but also causes a hardware hang on register access if no_console_suspend command line option is used. Also, not every of_serial device is an 8250 port, so the serial8250 suspend/resume functions should only be applied to a real 8250 port. Signed-off-by: Jingchang Lu jingchang...@freescale.com If you can make sure this patch can build without include linux/console.h, then this patch The build passes on my cloned linux-next tree, include next-20141014, but is required on my another kernel-3.12+ based tree, then I didn't add this header file when upstream. Is the build broken on your source tree, and is the tree latest? If the header is needed, I will add it. I tested it on next-20141013 and k3.14, both of them need the fix. I can check it again against the latest linux-next tree later. Thanks. -Joseph Thanks. Best Regards, Jingchang Tested-by: Joseph Lo jose...@nvidia.com And thanks for your fix. --- changes in v4: separate 8250 port suspend/resume from of_serial_suspend/resume. changes in v3: fix up point reference and deference. changes in v2: add switch selection on uart type. drivers/tty/serial/of_serial.c | 52 -- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 8bc2563..5281f8f 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -241,13 +241,48 @@ static int of_platform_serial_remove(struct platform_device *ofdev) } #ifdef CONFIG_PM_SLEEP -static int of_serial_suspend(struct device *dev) +#ifdef CONFIG_SERIAL_8250 +static void of_serial_suspend_8250(struct of_serial_info *info) { - struct of_serial_info *info = dev_get_drvdata(dev); + struct uart_8250_port *port8250 = serial8250_get_port(info-line); + struct uart_port *port = port8250-port; serial8250_suspend_port(info-line); - if (info-clk) + if (info-clk (!uart_console(port) || console_suspend_enabled)) clk_disable_unprepare(info-clk); +} + +static void of_serial_resume_8250(struct of_serial_info *info) { + struct uart_8250_port *port8250 = serial8250_get_port(info-line); + struct uart_port *port = port8250-port; + + if (info-clk (!uart_console(port) || console_suspend_enabled)) + clk_prepare_enable(info-clk); + + serial8250_resume_port(info-line); +} +#else +static inline void of_serial_suspend_8250(struct of_serial_info +*info) { } + +static inline void of_serial_resume_8250(struct of_serial_info *info) +{ } #endif + +static int of_serial_suspend(struct device *dev) { + struct of_serial_info *info = dev_get_drvdata(dev); + + switch(info-type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_suspend_8250(info); + break; + default: + break; + } return 0; } @@ -256,10 +291,13 @@ static int of_serial_resume(struct device *dev) { struct of_serial_info *info = dev_get_drvdata(dev); - if (info-clk) - clk_prepare_enable(info-clk); - - serial8250_resume_port(info-line); + switch(info-type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_resume_8250(info); + break; + default: + break; + } return 0; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv4] serial: of-serial: fix up PM ops on no_console_suspend and port type
On 10/15/2014 02:41 PM, Joseph Lo wrote: On 10/15/2014 02:32 PM, Jingchang Lu wrote: -Original Message- From: Joseph Lo [mailto:jose...@nvidia.com] Sent: Wednesday, October 15, 2014 9:01 AM To: Lu Jingchang-B35083; gre...@linuxfoundation.org Cc: pe...@hurleysoftware.com; a...@arndb.de; linux-kernel@vger.kernel.org; linux-ser...@vger.kernel.org; linux-arm-ker...@lists.infradead.org Subject: Re: [PATCHv4] serial: of-serial: fix up PM ops on no_console_suspend and port type On 10/14/2014 04:42 PM, Jingchang Lu wrote: This patch fixes commit 2dea53bf57783f243c892e99c10c6921e956aa7e, serial: of-serial: add PM suspend/resume support, which disables the uart clock on suspend, but also causes a hardware hang on register access if no_console_suspend command line option is used. Also, not every of_serial device is an 8250 port, so the serial8250 suspend/resume functions should only be applied to a real 8250 port. Signed-off-by: Jingchang Lu jingchang...@freescale.com If you can make sure this patch can build without include linux/console.h, then this patch The build passes on my cloned linux-next tree, include next-20141014, but is required on my another kernel-3.12+ based tree, then I didn't add this header file when upstream. Is the build broken on your source tree, and is the tree latest? If the header is needed, I will add it. I tested it on next-20141013 and k3.14, both of them need the fix. I can check it again against the latest linux-next tree later. Thanks. OK, I confirmed it. You should add the header file. It also doesn't build for me with the latest linux-next tree. Maybe you missed to enable CONFIG_PM_SLEEP or CONFIG_SERIAL_8250 when doing the build test in linux-next tree. -Joseph -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv5] serial: of-serial: fix up PM ops on no_console_suspend and port type
On 10/15/2014 02:19 PM, Jingchang Lu wrote: This patch fixes commit 2dea53bf57783f243c892e99c10c6921e956aa7e, serial: of-serial: add PM suspend/resume support, which disables the uart clock on suspend, but also causes a hardware hang on register access if no_console_suspend command line option is used. Also, not every of_serial device is an 8250 port, so the serial8250 suspend/resume functions should only be applied to a real 8250 port. Signed-off-by: Jingchang Lu jingchang...@freescale.com --- changes in v5: add missing linux/console.h include. changes in v4: separate 8250 port suspend/resume from of_serial_suspend/resume. changes in v3: fix up point reference and deference. changes in v2: add switch selection on uart type. Hi Jingchang, Thanks for the fix. This patch Tested-by: Joseph Lo jose...@nvidia.com drivers/tty/serial/of_serial.c | 53 -- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 8bc2563..9c64ad2 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. * */ +#include linux/console.h #include linux/module.h #include linux/slab.h #include linux/delay.h @@ -241,13 +242,48 @@ static int of_platform_serial_remove(struct platform_device *ofdev) } #ifdef CONFIG_PM_SLEEP -static int of_serial_suspend(struct device *dev) +#ifdef CONFIG_SERIAL_8250 +static void of_serial_suspend_8250(struct of_serial_info *info) { - struct of_serial_info *info = dev_get_drvdata(dev); + struct uart_8250_port *port8250 = serial8250_get_port(info-line); + struct uart_port *port = port8250-port; serial8250_suspend_port(info-line); - if (info-clk) + if (info-clk (!uart_console(port) || console_suspend_enabled)) clk_disable_unprepare(info-clk); +} + +static void of_serial_resume_8250(struct of_serial_info *info) +{ + struct uart_8250_port *port8250 = serial8250_get_port(info-line); + struct uart_port *port = port8250-port; + + if (info-clk (!uart_console(port) || console_suspend_enabled)) + clk_prepare_enable(info-clk); + + serial8250_resume_port(info-line); +} +#else +static inline void of_serial_suspend_8250(struct of_serial_info *info) +{ +} + +static inline void of_serial_resume_8250(struct of_serial_info *info) +{ +} +#endif + +static int of_serial_suspend(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + switch(info-type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_suspend_8250(info); + break; + default: + break; + } return 0; } @@ -256,10 +292,13 @@ static int of_serial_resume(struct device *dev) { struct of_serial_info *info = dev_get_drvdata(dev); - if (info-clk) - clk_prepare_enable(info-clk); - - serial8250_resume_port(info-line); + switch(info-type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_resume_8250(info); + break; + default: + break; + } return 0; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] serial: of-serial: add PM suspend/resume support
Hi, This patch might have a potential issue that cause system hard hung immediately when it accesses to registers with no clock. This could happen on many chips that mainline kernel supporting with the setting no_console_suspend=1 during suspend time. On 09/23/2014 04:34 PM, Jingchang Lu wrote: This adds PM suspend/resume support for the of-serial driver to provide power management support on devices attatched to it. Signed-off-by: Jingchang Lu jingchang...@freescale.com --- drivers/tty/serial/of_serial.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 27981e2..8bc2563 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -240,6 +240,32 @@ static int of_platform_serial_remove(struct platform_device *ofdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int of_serial_suspend(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + serial8250_suspend_port(info-line); + if (info-clk) The fix would be something like this. if (info-clk console_suspend_enabled) + clk_disable_unprepare(info-clk); + + return 0; +} + +static int of_serial_resume(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + if (info-clk) Ditto. Thanks, -Joseph + clk_prepare_enable(info-clk); + + serial8250_resume_port(info-line); + + return 0; +} +#endif +static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume); + /* * A few common types, add more as needed. */ @@ -271,6 +297,7 @@ static struct platform_driver of_platform_serial_driver = { .name = of_serial, .owner = THIS_MODULE, .of_match_table = of_platform_serial_table, + .pm = of_serial_pm_ops, }, .probe = of_platform_serial_probe, .remove = of_platform_serial_remove, -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2] serial: of-serial: fix up PM ops on no_console_suspend and port type
Hi, On 10/13/2014 03:37 PM, Jingchang Lu wrote: This patch fixes commit 2dea53bf57783f243c892e99c10c6921e956aa7e, serial: of-serial: add PM suspend/resume support, which disables the uart clock on suspend, but also causes a hardware hang on register access if no_console_suspend command line option is used. Also, not every of_serial device is an 8250 port, so the serial8250 suspend/resume functions should only be applied to a real 8250 port. Signed-off-by: Jingchang Lu jingchang...@freescale.com --- changes in v2: add switch selection on uart type. After apply this, it can't build for me. I still need to apply the fix like something below. diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index e535f9c1563d..14c1ff4e7816 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. * */ +#include linux/console.h #include linux/module.h #include linux/slab.h #include linux/delay.h @@ -248,13 +249,13 @@ static int of_serial_suspend(struct device *dev) #ifdef CONFIG_SERIAL_8250 case PORT_8250 ... PORT_MAX_8250: { - struct uart_8250_port port8250; + struct uart_8250_port *port8250; port8250 = serial8250_get_port(info-line); serial8250_suspend_port(info-line); if (info-clk - (!uart_console(port8250) || -(uart_console(port8250) console_suspend_enabled))) + (!uart_console(port8250-port) || +(uart_console(port8250-port) console_suspend_enabled))) clk_disable_unprepare(info-clk); break; } @@ -274,12 +275,12 @@ static int of_serial_resume(struct device *dev) #ifdef CONFIG_SERIAL_8250 case PORT_8250 ... PORT_MAX_8250: { - struct uart_8250_port port8250; + struct uart_8250_port *port8250; port8250 = serial8250_get_port(info-line); if (info-clk - (!uart_console(port8250) || -(uart_console(port8250) console_suspend_enabled))) + (!uart_console(port8250-port) || +(uart_console(port8250-port) console_suspend_enabled))) clk_prepare_enable(info-clk); serial8250_resume_port(info-line); -Joseph drivers/tty/serial/of_serial.c | 42 -- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 8bc2563..b525383 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -245,9 +245,24 @@ static int of_serial_suspend(struct device *dev) { struct of_serial_info *info = dev_get_drvdata(dev); - serial8250_suspend_port(info-line); - if (info-clk) - clk_disable_unprepare(info-clk); + switch(info-type) { +#ifdef CONFIG_SERIAL_8250 + case PORT_8250 ... PORT_MAX_8250: + { + struct uart_8250_port port8250; + port8250 = serial8250_get_port(info-line); + + serial8250_suspend_port(info-line); + if (info-clk + (!uart_console(port8250) || +(uart_console(port8250) console_suspend_enabled))) + clk_disable_unprepare(info-clk); + break; + } +#endif + default: + break; + } return 0; } @@ -256,10 +271,25 @@ static int of_serial_resume(struct device *dev) { struct of_serial_info *info = dev_get_drvdata(dev); - if (info-clk) - clk_prepare_enable(info-clk); + switch(info-type) { +#ifdef CONFIG_SERIAL_8250 + case PORT_8250 ... PORT_MAX_8250: + { + struct uart_8250_port port8250; + port8250 = serial8250_get_port(info-line); + + if (info-clk + (!uart_console(port8250) || +(uart_console(port8250) console_suspend_enabled))) + clk_prepare_enable(info-clk); - serial8250_resume_port(info-line); + serial8250_resume_port(info-line); + break; + } +#endif + default: + break; + } return 0; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] ARM: tegra: Ensure entire dcache is flushed on entering LP0/1
Hi Jon, On 11/19/2015 10:19 PM, Jon Hunter wrote: Tegra support several low-power (LPx) states, which are: - LP0: CPU + Core voltage off and DRAM in self-refresh - LP1: CPU voltage off and DRAM in self-refresh - LP2: CPU voltage off When entering any of the above states the tegra_disable_clean_inv_dcache() function is called to flush the dcache. The function tegra_disable_clean_inv_dcache() will either flush the entire data cache or up to the Level of Unification Inner Shareable (LoUIS) depending on the value in r0. When tegra_disable_clean_inv_dcache() is called by tegra20_sleep_core_finish() or tegra30_sleep_core_finish(), to enter LP0 and LP1 power state, the r0 register contains a physical memory address which will not be equal to TEGRA_FLUSH_CACHE_ALL (1) and so the data cache will be only flushed to the LoUIS. However, when tegra_disable_clean_inv_dcache() called by tegra_sleep_cpu_finish() to enter to LP2 power state, r0 is set to TEGRA_FLUSH_CACHE_ALL to flush the entire dcache. Please note that tegra20_sleep_core_finish(), tegra30_sleep_core_finish() and tegra_sleep_cpu_finish() are called by the boot CPU once all other CPUs have been disabled and so it seems appropriate to flush the entire cache at this stage. Therefore, ensure that r0 is set to TEGRA_FLUSH_CACHE_ALL when calling tegra_disable_clean_inv_dcache() from tegra20_sleep_core_finish() and tegra30_sleep_core_finish(). Signed-off-by: Jon Hunter <jonath...@nvidia.com> --- Thanks for the fix. Reviewed-by: Joseph Lo <jose...@nvidia.com> Please note that I have not encountered any problems without this change so far, but I noticed this from reviewing the suspend sequence. I have tested this on tegra20, tegra30, tegra114 and tegra124 and verified that suspend/resume to LP1 is working fine. arch/arm/mach-tegra/sleep-tegra20.S | 3 +++ arch/arm/mach-tegra/sleep-tegra30.S | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S index e6b684e14322..f5d19667484e 100644 --- a/arch/arm/mach-tegra/sleep-tegra20.S +++ b/arch/arm/mach-tegra/sleep-tegra20.S @@ -231,8 +231,11 @@ ENDPROC(tegra20_cpu_is_resettable_soon) * tegra20_tear_down_core in IRAM */ ENTRY(tegra20_sleep_core_finish) + mov r4, r0 /* Flush, disable the L1 data cache and exit SMP */ + mov r0, #TEGRA_FLUSH_CACHE_ALL bl tegra_disable_clean_inv_dcache + mov r0, r4 mov32 r3, tegra_shut_off_mmu add r3, r3, r0 diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S index 9a2f0b051e10..16e5ff03383c 100644 --- a/arch/arm/mach-tegra/sleep-tegra30.S +++ b/arch/arm/mach-tegra/sleep-tegra30.S @@ -242,8 +242,11 @@ ENDPROC(tegra30_cpu_shutdown) * tegra30_tear_down_core in IRAM */ ENTRY(tegra30_sleep_core_finish) + mov r4, r0 /* Flush, disable the L1 data cache and exit SMP */ + mov r0, #TEGRA_FLUSH_CACHE_ALL bl tegra_disable_clean_inv_dcache + mov r0, r4 /* * Preload all the address literals that are needed for the -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/10] Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP
On 06/28/2016 12:08 AM, Stephen Warren wrote: On 06/27/2016 03:02 AM, Joseph Lo wrote: The BPMP is a specific processor in Tegra chip, which is designed for booting process handling and offloading the power management tasks from the CPU. The binding document defines the resources that would be used by the BPMP firmware driver, which can create the interprocessor communication (IPC) between the CPU and BPMP. diff --git a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt +The BPMP is a specific processor in Tegra chip, which is designed for +booting process handling and offloading the power management tasks from +the CPU. The binding document defines the resources that would be used by +the BPMP firmware driver, which can create the interprocessor +communication (IPC) between the CPU and BPMP. s/power management/power management, clock management, and reset control/? Yes. +Required properties: +- name : Should be bpmp +- compatible : Should be "nvidia,tegra-bpmp" Again, I'd suggest wording this as: - compatible Array of strings. One of: - "nvidia,tegra186-bpmp" Okay. +- mboxes : The phandle of mailbox controller and the channel ID s/channel ID/mailbox specifier/. + See "Documentation/devicetree/bindings/mailbox/ + nvidia,tegra186-hsp.txt" and "Documentation/devicetree/ + bindings/mailbox/mailbox.txt" for more details about the generic + mailbox controller and mailbox client driver bindings. I'd rather not split the filenames across lines, since that makes grep fail to match. Perhaps add the following text to the introductory section at the start of the file to avoid having to mention some of the filenames in an indented block of text: Thanks. == This node is a mailbox consumer. See the following file for details of the mailbox subsystem, and the specifiers implemented by the relevant provider(s): - Documentation/devicetree/bindings/mailbox/mailbox.txt - Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt This node is a clock and reset provider. See the following files for general documentation of those features, and the specifiers implemented by this node: - Documentation/devicetree/bindings/clock/clock-bindings.txt - include/dt-bindings/clock/tegra186-clock.h - Documentation/devicetree/bindings/reset/reset.txt - include/dt-bindings/reset/tegra186-reset.h == Related, I would expect those two header files (tegra186-clock.h and tegra186-reset.h) to be part of this patch, since they form part of the definition of this binding. Okay. Will add them. +The shared memory bindings for BPMP +--- + +The shared memory area for the IPC TX and RX between CPU and BPMP are +predefined and work on top of sysram, which is a sram inside the chip. s/a sram/an SRAM/. +Example: ... +bpmp@d000 { There should be no unit address ("@d000") in the node name, since there's no reg property. Thanks, -Joseph
Re: [PATCH 01/10] Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox
On 06/27/2016 11:55 PM, Stephen Warren wrote: On 06/27/2016 03:02 AM, Joseph Lo wrote: Add DT binding for the Hardware Synchronization Primitives (HSP). The HSP is designed for the processors to share resources and communicate together. It provides a set of hardware synchronization primitives for interprocessor communication. So the interprocessor communication (IPC) protocols can use hardware synchronization primitive, when operating between two processors not in an SMP relationship. This binding is quite different to the binding you sent to internal IP review. I wonder why it changed? Specific comments below: Due to some enhancements for supporting multiple functions of HSP sub-modules in the same driver, I re-wrote some parts of the bindings and driver. diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt +NVIDIA Tegra Hardware Synchronization Primitives (HSP) + +The HSP modules are used for the processors to share resources and communicate +together. It provides a set of hardware synchronization primitives for +interprocessor communication. So the interprocessor communication (IPC) +protocols can use hardware synchronization primitives, when operating between +two processors not in an SMP relationship. + +The features that HSP supported are shared mailboxes, shared semaphores, +arbitrated semaphores and doorbells. + +Required properties: +- name : Should be hsp +- compatible : Should be "nvidia,tegra-hsp" I think this should explicitly list the value values of the compatible property, rather than being a generic/wildcard description: - compatible Array of strings. One of: - "nvidia,tegra186-hsp" If/when this binding supports other SoCs in the future, we'll add more entries into that list. +- reg : Offset and length of the register set for the device +- interrupts : Should contain the HSP interrupts +- interrupt-names: Should contain the names of the HSP interrupts that the + client are using. + "doorbell" The binding should describe the HW, and not be affected by anything "that the client(s) are using". If there are multiple interrupts, we should list them all here, from the start. When revising this, I would consider the following wording canonical: Okay. - interrupt-names Array of strings. Contains a list of names for the interrupts described by the interrupts property. May contain the following entries, in any order: - "doorbell" - "..." (no doubt many more items will be listed here, e.g. for semaphores, etc.). I think I will just list "doorbell" for now. And adding more later once we add other HSP sub-module support. Users of this binding MUST look up entries in the interrupts property by name, using this interrupts-names property to do so. - interrupts Array of interrupt specifiers. Must contain one entry per entry in the interrupt-names property, in a matching order. +- nvidia,hsp-function : Specifies one of the HSP functions that the HSP unit +will be supported. The function ID can be found in the +header file . This property wasn't in the internal patch. This doesn't make sense. The HW feature-set is fixed. This sounds like some kind of software configuration option, or a way to allow different drivers to handle different aspects of the HW? In general, the binding shouldn't be influenced by software structure. Please delete this property. Now, if you're attempting to set up a binding where each function (semaphores, shared mailboxes, doorbells, etc.) has a different DT node, then (a) splitting up HW modules into sub-blocks has usually turned out to be a mistake in the past, and (b) the differences should likely be represented by using a different compatible property for each sub-component, rather than via a custom property. Currently the usage of HSP HW in the downstream kernel is something like the model below. remote_processor_A-\ remote_processor_B--->hsp@1000 (doorbell func) <-> host CPU remote_processor_C-/ remote_processor_D -> hsp@2000 (shared mailbox) <-> CPU remote_processor_E -> hsp@3000 (shared mailbox) <-> CPU I am thinking if we can just add the appropriate compatible strings for it to replace "nvidia,tegra186-hsp". e.g. "nvidia,tegra186-hsp-doorbell" and "nvidia,tegra186-hsp-sharedmailbox". So the driver can probe and initialize correctly depend on the compatible property. How do you think about it? Is this the same as the (b) you mentioned above? The following properties were included in the internal patch: nvidia,num-SM = <0x8>; nvidia,num-AS = <0x2>; nvidia,num-SS = <0x2>; nvidia,num-DB = <0x7>;
[PATCH V3 3/10] Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP
The BPMP is a specific processor in Tegra chip, which is designed for booting process handling and offloading the power management, clock management, and reset control tasks from the CPU. The binding document defines the resources that would be used by the BPMP firmware driver, which can create the interprocessor communication (IPC) between the CPU and BPMP. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V3: - s/mmio-ram/mmio-sram/ - revise the file path of the reference binding documents and header files for more generic viem in different SW projects Changes in V2: - update the message that the BPMP is clock and reset control provider - add tegra186-clock.h and tegra186-reset.h header files - revise the description of the required properties --- .../bindings/firmware/nvidia,tegra186-bpmp.txt | 77 ++ include/dt-bindings/clock/tegra186-clock.h | 940 + include/dt-bindings/reset/tegra186-reset.h | 217 + 3 files changed, 1234 insertions(+) create mode 100644 Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt create mode 100644 include/dt-bindings/clock/tegra186-clock.h create mode 100644 include/dt-bindings/reset/tegra186-reset.h diff --git a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt new file mode 100644 index ..23782c84d093 --- /dev/null +++ b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt @@ -0,0 +1,77 @@ +NVIDIA Tegra Boot and Power Management Processor (BPMP) + +The BPMP is a specific processor in Tegra chip, which is designed for +booting process handling and offloading the power management, clock +management, and reset control tasks from the CPU. The binding document +defines the resources that would be used by the BPMP firmware driver, +which can create the interprocessor communication (IPC) between the CPU +and BPMP. + +Required properties: +- name : Should be bpmp +- compatible +Array of strings +One of: +- "nvidia,tegra186-bpmp" +- mboxes : The phandle of mailbox controller and the mailbox specifier. +- shmem : List of the phandle of the TX and RX shared memory area that + the IPC between CPU and BPMP is based on. +- #clock-cells : Should be 1. +- #reset-cells : Should be 1. + +This node is a mailbox consumer. See the following files for details of +the mailbox subsystem, and the specifiers implemented by the relevant +provider(s): + +- .../mailbox/mailbox.txt +- .../mailbox/nvidia,tegra186-hsp.txt + +This node is a clock and reset provider. See the following files for +general documentation of those features, and the specifiers implemented +by this node: + +- .../clock/clock-bindings.txt +- +- .../reset/reset.txt +- + +The shared memory bindings for BPMP +--- + +The shared memory area for the IPC TX and RX between CPU and BPMP are +predefined and work on top of sysram, which is an SRAM inside the chip. + +See ".../sram/sram.txt" for the bindings. + +Example: + +hsp_top0: hsp@03c0 { + ... + #mbox-cells = <2>; +}; + +sysram@3000 { + compatible = "nvidia,tegra186-sysram", "mmio-sram"; + reg = <0x0 0x3000 0x0 0x5>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0x0 0x0 0x3000 0x0 0x5>; + + cpu_bpmp_tx: bpmp_shmem@4e000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4e000 0x0 0x1000>; + }; + + cpu_bpmp_rx: bpmp_shmem@4f000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4f000 0x0 0x1000>; + }; +}; + +bpmp { + compatible = "nvidia,tegra186-bpmp"; + mboxes = <_top0 HSP_MBOX_TYPE_DB HSP_DB_MASTER_BPMP>; + shmem = <_bpmp_tx _bpmp_rx>; + #clock-cells = <1>; + #reset-cells = <1>; +}; diff --git a/include/dt-bindings/clock/tegra186-clock.h b/include/dt-bindings/clock/tegra186-clock.h new file mode 100644 index ..f73d32098f99 --- /dev/null +++ b/include/dt-bindings/clock/tegra186-clock.h @@ -0,0 +1,940 @@ +/** @file */ + +#ifndef _MACH_T186_CLK_T186_H +#define _MACH_T186_CLK_T186_H + +/** + * @defgroup clock_ids Clock Identifiers + * @{ + * @defgroup extern_input external input clocks + * @{ + * @def TEGRA186_CLK_OSC + * @def TEGRA186_CLK_CLK_32K + * @def TEGRA186_CLK_DTV_INPUT + * @def TEGRA186_CLK_SOR0_PAD_CLKOUT + * @def TEGRA186_CLK_SOR1_PAD_CLKOUT + * @def TEGRA186_CLK_I2S1_SYNC_INPUT + * @def TEGRA186_CLK_I2S2_SYNC_INPUT + * @def TEGRA186_CLK_I2S3_SYNC_INPUT + * @def TEGRA186_CLK_I2S4_SYNC_INPUT + * @def TEGRA186_CLK_I2S5_SYNC_INPUT + * @def TEGRA186_CLK_I2S6_SYNC_INPUT + * @def TEGRA186_CLK_SPDIFIN_SYNC_INPUT + *
Re: [PATCH V2 01/10] Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox
On 07/19/2016 07:13 AM, Stephen Warren wrote: On 07/11/2016 10:08 AM, Stephen Warren wrote: On 07/11/2016 08:14 AM, Rob Herring wrote: On Thu, Jul 07, 2016 at 12:35:02PM -0600, Stephen Warren wrote: On 07/07/2016 12:13 PM, Sivaram Nair wrote: On Tue, Jul 05, 2016 at 05:04:22PM +0800, Joseph Lo wrote: Add DT binding for the Hardware Synchronization Primitives (HSP). The HSP is designed for the processors to share resources and communicate together. It provides a set of hardware synchronization primitives for interprocessor communication. So the interprocessor communication (IPC) protocols can use hardware synchronization primitive, when operating between two processors not in an SMP relationship. diff --git a/include/dt-bindings/mailbox/tegra186-hsp.h b/include/dt-bindings/mailbox/tegra186-hsp.h +#define HSP_MBOX_TYPE_DB 0x0 +#define HSP_MBOX_TYPE_SM 0x1 +#define HSP_MBOX_TYPE_SS 0x2 +#define HSP_MBOX_TYPE_AS 0x3 + +#define HSP_DB_MASTER_CCPLEX 17 +#define HSP_DB_MASTER_BPMP 19 + +#define HSP_MBOX_ID(type, ID) \ +(HSP_MBOX_TYPE_##type << 16 | ID) It will be nicer if you avoid the macro glue magic '##' for 'type'. I would also suggest to use braces around 'type' and 'ID'. This technique been used without issue in quite a few other places without issue, and has the benefit of simplifying the text wherever the macro is used. What issue do you foresee? I'm not a fan of using the macros to begin with and less so anything more complex than a single constant value. I'd rather see 2 cells here with the first being the id and the 2nd being the type. An issue with token pasting is grepping for DB, SM, etc. in kernel tree is probably noisy. Not such a big deal here, but a major PIA when you have more complex sets of includes. Is that a NAK or simply a suggestion? Having a single cell makes DT parsing a bit simpler, since pretty much every SW stack provides a default "one-cell" of_xlate implementation, whereas >1 cell means custom code for of_xlate. I didn't see a response to this. Joseph, let's just use two cells instead. I'm rather desperately waiting for this binding to be complete so I can finalize the U-Boot code that uses it, and it sounds like changing to two cells will get an ack faster. Can you post an updated version of this series today/ASAP to get things moving? Thanks. Okay, will use two cells instead.
[PATCH V3 01/10] Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox
Add DT binding for the Hardware Synchronization Primitives (HSP). The HSP is designed for the processors to share resources and communicate together. It provides a set of hardware synchronization primitives for interprocessor communication. So the interprocessor communication (IPC) protocols can use hardware synchronization primitive, when operating between two processors not in an SMP relationship. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Sorry. Please allow me just update the binding patches of this series. Want to make sure the binding is acceptable first. Thanks. Changes in V3: - use two cells for mboxes property Changes in V2: - revise the compatible string, interrupt-names, interrupts, and #mbox-cells properties - remove "nvidia,hsp-function" property - fix the header file name - the binding supports the concept of multiple HSP sub-modules on one HSP HW block now. --- .../bindings/mailbox/nvidia,tegra186-hsp.txt | 52 ++ include/dt-bindings/mailbox/tegra186-hsp.h | 20 + 2 files changed, 72 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt create mode 100644 include/dt-bindings/mailbox/tegra186-hsp.h diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt new file mode 100644 index ..a9152380642d --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt @@ -0,0 +1,52 @@ +NVIDIA Tegra Hardware Synchronization Primitives (HSP) + +The HSP modules are used for the processors to share resources and communicate +together. It provides a set of hardware synchronization primitives for +interprocessor communication. So the interprocessor communication (IPC) +protocols can use hardware synchronization primitives, when operating between +two processors not in an SMP relationship. + +The features that HSP supported are shared mailboxes, shared semaphores, +arbitrated semaphores and doorbells. + +Required properties: +- name : Should be hsp +- compatible +Array of strings. +one of: +- "nvidia,tegra186-hsp" +- reg : Offset and length of the register set for the device. +- interrupt-names +Array of strings. +Contains a list of names for the interrupts described by the interrupt +property. May contain the following entries, in any order: +- "doorbell" +Users of this binding MUST look up entries in the interrupt property +by name, using this interrupt-names property to do so. +- interrupts +Array of interrupt specifiers. +Must contain one entry per entry in the interrupt-names property, +in a matching order. +- #mbox-cells : Should be 2. + +The mbox specifier of the "mboxes" property in the client node should +contain two data. The first one should be the HSP type and the second +one should be the ID that the client is going to use. Those information +can be found in the following file. + +- . + +Example: + +hsp_top0: hsp@3c0 { + compatible = "nvidia,tegra186-hsp"; + reg = <0x0 0x03c0 0x0 0xa>; + interrupts = ; + interrupt-names = "doorbell"; + #mbox-cells = <2>; +}; + +client { + ... + mboxes = <_top0 HSP_MBOX_TYPE_DB HSP_DB_MASTER_XXX>; +}; diff --git a/include/dt-bindings/mailbox/tegra186-hsp.h b/include/dt-bindings/mailbox/tegra186-hsp.h new file mode 100644 index ..d1c1432707cd --- /dev/null +++ b/include/dt-bindings/mailbox/tegra186-hsp.h @@ -0,0 +1,20 @@ +/* + * This header provides constants for binding nvidia,tegra186-hsp. + * + * The number with HSP_DB_MASTER prefix indicates the bit that is + * associated with a master ID in the doorbell registers. + */ + + +#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H +#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H + +#define HSP_MBOX_TYPE_DB 0x0 +#define HSP_MBOX_TYPE_SM 0x1 +#define HSP_MBOX_TYPE_SS 0x2 +#define HSP_MBOX_TYPE_AS 0x3 + +#define HSP_DB_MASTER_CCPLEX 17 +#define HSP_DB_MASTER_BPMP 19 + +#endif /* _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H */ -- 2.9.2
Re: [PATCH V3 3/10] Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP
On 07/20/2016 09:22 AM, Rob Herring wrote: On Tue, Jul 19, 2016 at 05:17:23PM +0800, Joseph Lo wrote: The BPMP is a specific processor in Tegra chip, which is designed for booting process handling and offloading the power management, clock management, and reset control tasks from the CPU. The binding document defines the resources that would be used by the BPMP firmware driver, which can create the interprocessor communication (IPC) between the CPU and BPMP. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V3: - s/mmio-ram/mmio-sram/ - revise the file path of the reference binding documents and header files for more generic viem in different SW projects Changes in V2: - update the message that the BPMP is clock and reset control provider - add tegra186-clock.h and tegra186-reset.h header files - revise the description of the required properties --- .../bindings/firmware/nvidia,tegra186-bpmp.txt | 77 ++ include/dt-bindings/clock/tegra186-clock.h | 940 + include/dt-bindings/reset/tegra186-reset.h | 217 + 3 files changed, 1234 insertions(+) create mode 100644 Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt create mode 100644 include/dt-bindings/clock/tegra186-clock.h create mode 100644 include/dt-bindings/reset/tegra186-reset.h Acked-by: Rob Herring <r...@kernel.org> Rob, Stephen, Thanks for your review. -Joseph
Re: [PATCH V2 02/10] mailbox: tegra-hsp: Add HSP(Hardware Synchronization Primitives) driver
On 07/08/2016 05:10 AM, Sivaram Nair wrote: On Tue, Jul 05, 2016 at 05:04:23PM +0800, Joseph Lo wrote: The Tegra HSP mailbox driver implements the signaling doorbell-based interprocessor communication (IPC) for remote processors currently. The HSP HW modules support some different features for that, which are shared mailboxes, shared semaphores, arbitrated semaphores, and doorbells. And there are multiple HSP HW instances on the chip. So the driver is extendable to support more features for different IPC requirement. The driver of remote processor can use it as a mailbox client and deal with the IPC protocol to synchronize the data communications. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - Update the driver to support the binding changes in V2 - it's extendable to support multiple HSP sub-modules on the same HSP HW block now. --- drivers/mailbox/Kconfig | 9 + drivers/mailbox/Makefile| 2 + drivers/mailbox/tegra-hsp.c | 418 3 files changed, 429 insertions(+) create mode 100644 drivers/mailbox/tegra-hsp.c diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 5305923752d2..fe584cb54720 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -114,6 +114,15 @@ config MAILBOX_TEST Test client to help with testing new Controller driver implementations. +config TEGRA_HSP_MBOX + bool "Tegra HSP(Hardware Synchronization Primitives) Driver" + depends on ARCH_TEGRA_186_SOC + help + The Tegra HSP driver is used for the interprocessor communication + between different remote processors and host processors on Tegra186 + and later SoCs. Say Y here if you want to have this support. + If unsure say N. + config XGENE_SLIMPRO_MBOX tristate "APM SoC X-Gene SLIMpro Mailbox Controller" depends on ARCH_XGENE diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 0be3e742bb7d..26d8f91c7fea 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -25,3 +25,5 @@ obj-$(CONFIG_TI_MESSAGE_MANAGER) += ti-msgmgr.o obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o + +obj-${CONFIG_TEGRA_HSP_MBOX} += tegra-hsp.o diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c new file mode 100644 index ..93c3ef58f29f --- /dev/null +++ b/drivers/mailbox/tegra-hsp.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include +#include + +#define HSP_INT_DIMENSIONING 0x380 +#define HSP_nSM_OFFSET 0 +#define HSP_nSS_OFFSET 4 +#define HSP_nAS_OFFSET 8 +#define HSP_nDB_OFFSET 12 +#define HSP_nSI_OFFSET 16 +#define HSP_nINT_MASK 0xf + +#define HSP_DB_REG_TRIGGER 0x0 +#define HSP_DB_REG_ENABLE 0x4 +#define HSP_DB_REG_RAW 0x8 +#define HSP_DB_REG_PENDING 0xc + +#define HSP_DB_CCPLEX 1 +#define HSP_DB_BPMP3 + +#define MAX_NUM_HSP_CHAN 32 Is this an arbitrarily chosen number? Ah, this should be MAX_NUM_HSP_DB_CHAN now. But the mbox driver still needs a max channel number, I will check how to enhance it properly with multiple HSP modules support in the same driver. Maybe 4 channels for SM, AS, SS and DB. And the sub channels for different functions under them. Then it may able to fix the double loop issue in the hsp_db_irq function. +#define MAX_NUM_HSP_DB 7 + +#define hsp_db_offset(i, d) \ + (d->base + ((1 + (d->nr_sm >> 1) + d->nr_ss + d->nr_as) << 16) + \ + (i) * 0x100) + +struct tegra_hsp_db_chan { + int master_id; + int db_id; These should be unsigned? Yes, will fix them. +}; + +struct tegra_hsp_mbox_chan { + int type; This too... + union { + struct tegra_hsp_db_chan db_chan; + }; +}; Why do we need to use a union? Because we only support DB right now, there is only one member in the union. We can add something like sm_chan here when we need to support that later. + +struct tegra_hsp_mbox { + struct mbox_controller *mbox; + void __iomem *base; + void __iomem *db_base[MAX_NUM_HSP_DB]; + int db_irq; + int nr_sm; + int nr_as; + int nr_ss; + int nr_db; + int nr_si; + spinlock_t lock
Re: [PATCH V2 02/10] mailbox: tegra-hsp: Add HSP(Hardware Synchronization Primitives) driver
On 07/08/2016 05:33 AM, Sivaram Nair wrote: On Thu, Jul 07, 2016 at 02:37:27PM +0800, Joseph Lo wrote: On 07/06/2016 08:23 PM, Alexandre Courbot wrote: On Wed, Jul 6, 2016 at 6:06 PM, Joseph Lo <jose...@nvidia.com> wrote: On 07/06/2016 03:05 PM, Alexandre Courbot wrote: On Tue, Jul 5, 2016 at 6:04 PM, Joseph Lo <jose...@nvidia.com> wrote: The Tegra HSP mailbox driver implements the signaling doorbell-based interprocessor communication (IPC) for remote processors currently. The HSP HW modules support some different features for that, which are shared mailboxes, shared semaphores, arbitrated semaphores, and doorbells. And there are multiple HSP HW instances on the chip. So the driver is extendable to support more features for different IPC requirement. The driver of remote processor can use it as a mailbox client and deal with the IPC protocol to synchronize the data communications. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - Update the driver to support the binding changes in V2 - it's extendable to support multiple HSP sub-modules on the same HSP HW block now. --- drivers/mailbox/Kconfig | 9 + drivers/mailbox/Makefile| 2 + drivers/mailbox/tegra-hsp.c | 418 3 files changed, 429 insertions(+) create mode 100644 drivers/mailbox/tegra-hsp.c diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 5305923752d2..fe584cb54720 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -114,6 +114,15 @@ config MAILBOX_TEST Test client to help with testing new Controller driver implementations. +config TEGRA_HSP_MBOX + bool "Tegra HSP(Hardware Synchronization Primitives) Driver" Space missing before the opening parenthesis (same in the patch title btw). Okay. + depends on ARCH_TEGRA_186_SOC + help + The Tegra HSP driver is used for the interprocessor communication + between different remote processors and host processors on Tegra186 + and later SoCs. Say Y here if you want to have this support. + If unsure say N. Since this option is selected automatically by ARCH_TEGRA_186_SOC, you should probably drop the last 2 sentences. Okay. + config XGENE_SLIMPRO_MBOX tristate "APM SoC X-Gene SLIMpro Mailbox Controller" depends on ARCH_XGENE diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 0be3e742bb7d..26d8f91c7fea 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -25,3 +25,5 @@ obj-$(CONFIG_TI_MESSAGE_MANAGER) += ti-msgmgr.o obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o + +obj-${CONFIG_TEGRA_HSP_MBOX} += tegra-hsp.o diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c new file mode 100644 index ..93c3ef58f29f --- /dev/null +++ b/drivers/mailbox/tegra-hsp.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include +#include + +#define HSP_INT_DIMENSIONING 0x380 +#define HSP_nSM_OFFSET 0 +#define HSP_nSS_OFFSET 4 +#define HSP_nAS_OFFSET 8 +#define HSP_nDB_OFFSET 12 +#define HSP_nSI_OFFSET 16 Would be nice to have comments to understand what SM, SS, AS, etc. stand for (Shared Mailboxes, Shared Semaphores, Arbitrated Semaphores but you need to look at the patch description to understand that). A top-of-file comment explaning the necessary concepts to read this code would do the trick. Yes, will fix that. +#define HSP_nINT_MASK 0xf + +#define HSP_DB_REG_TRIGGER 0x0 +#define HSP_DB_REG_ENABLE 0x4 +#define HSP_DB_REG_RAW 0x8 +#define HSP_DB_REG_PENDING 0xc + +#define HSP_DB_CCPLEX 1 +#define HSP_DB_BPMP3 Maybe turn this into enum and use that type for tegra_hsp_db_chan::db_id? Also have MAX_NUM_HSP_DB here, since it is related to these values? Okay. + +#define MAX_NUM_HSP_CHAN 32 +#define MAX_NUM_HSP_DB 7 + +#define hsp_db_offset(i, d) \ + (d->base + ((1 + (d->nr_sm >> 1) + d->nr_ss + d->nr_as) << 16) + \ + (i) * 0x100) + +struct tegra_hsp_db_chan { + int master_id; + int db_id; +}; + +struct tegra_hsp_mbox_chan { + int type; + union { + struct tegra_hsp_db_chan db_
Re: [PATCH V2 03/10] Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP
Hi Rob, Thanks for your reviewing. On 07/12/2016 12:05 AM, Stephen Warren wrote: On 07/11/2016 08:22 AM, Rob Herring wrote: On Tue, Jul 05, 2016 at 05:04:24PM +0800, Joseph Lo wrote: The BPMP is a specific processor in Tegra chip, which is designed for booting process handling and offloading the power management, clock management, and reset control tasks from the CPU. The binding document defines the resources that would be used by the BPMP firmware driver, which can create the interprocessor communication (IPC) between the CPU and BPMP. diff --git a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt +NVIDIA Tegra Boot and Power Management Processor (BPMP) + +The BPMP is a specific processor in Tegra chip, which is designed for +booting process handling and offloading the power management, clock +management, and reset control tasks from the CPU. The binding document +defines the resources that would be used by the BPMP firmware driver, +which can create the interprocessor communication (IPC) between the CPU +and BPMP. + +Required properties: +- name : Should be bpmp +- compatible +Array of strings +One of: +- "nvidia,tegra186-bpmp" +- mboxes : The phandle of mailbox controller and the mailbox specifier. +- shmem : List of the phandle of the TX and RX shared memory area that + the IPC between CPU and BPMP is based on. I think you can use memory-region here. Isn't memory-region intended for references into the /reserved-memory node. If so, that isn't appropriate in this case since this property typically points at on-chip SRAM that isn't included in the OS's view of "system RAM". Agree with that. Or, should /reserved-memory be used even for (e.g. non-DRAM) memory regions that aren't represented by the /memory/reg property? For shmem, I follow the same concept of the binding for arm,scpi (.../arm/arm,scpi.txt) that is currently using in mainline. Do you think that is more appropriate here? diff --git a/include/dt-bindings/clock/tegra186-clock.h b/include/dt-bindings/clock/tegra186-clock.h +/** @file */ + +#ifndef _MACH_T186_CLK_T186_H +#define _MACH_T186_CLK_T186_H + +/** + * @defgroup clock_ids Clock Identifiers Aren't these doxygen markup? Does that work with docbook? If not, remove. These headers are part of the BPMP FW release. It's preferable not to edit them when incorporating them into the Linux kernel (or any other SW stack) to simplify integration of any updated versions of the header, by removing the need to edit the file when doing so. Given that, do you still object? How do you think of this, Rob? Thanks, -Joseph
Re: [PATCH V2 03/10] Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP
On 07/14/2016 03:41 AM, Stephen Warren wrote: On 07/05/2016 03:04 AM, Joseph Lo wrote: The BPMP is a specific processor in Tegra chip, which is designed for booting process handling and offloading the power management, clock management, and reset control tasks from the CPU. The binding document defines the resources that would be used by the BPMP firmware driver, which can create the interprocessor communication (IPC) between the CPU and BPMP. diff --git a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt +- Documentation/devicetree/bindings/mailbox/mailbox.txt +- Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt +- Documentation/devicetree/bindings/clock/clock-bindings.txt +- include/dt-bindings/clock/tegra186-clock.h +- Documentation/devicetree/bindings/reset/reset.txt +- include/dt-bindings/reset/tegra186-reset.h If you end up needing to repost this, it would be nice to make all those file references more generic. In particular, some SW projects store binding docs somewhere other than Documentation/devicetree/bindings/ (e.g. U-Boot uses doc/device-tree-bindings/), and it's possible that the header files aren't stored in include/ but somewhere else. To make these file references valid everywhere, I'd suggest using relative paths for the binding docs, and #include style paths for the headers, e.g.: ../clock/clock-bindings.txt OK. Will fix this. Thanks, -Joseph
[PATCH 05/10] firmware: tegra: add BPMP support
The Tegra BPMP (Boot and Power Management Processor) is designed for the booting process handling, offloading the power management tasks and some system control services from the CPU. It can be clock, DVFS, thermal/EDP, power gating operation and system suspend/resume handling. So the CPU and the drivers of these modules can base on the service that the BPMP firmware driver provided to signal the event for the specific PM action to BPMP and receive the status update from BPMP. Comparing to the ARM SCPI, the service provided by BPMP is message-based communication but not method-based. The BPMP firmware driver provides the send/receive service for the users, when the user concerns the response time. If the user needs to get the event or update from the firmware, it can request the MRQ service as well. The user needs to take care of the message format, which we call BPMP ABI. The BPMP ABI defines the message format for different modules or usages. For example, the clock operation needs an MRQ service code called MRQ_CLK with specific message format which includes different sub commands for various clock operations. This is the message format that BPMP can recognize. So the user needs two things to initiate IPC between BPMP. Get the service from the bpmp_ops structure and maintain the message format as the BPMP ABI defined. Based-on-the-work-by: Sivaram Nair <sivar...@nvidia.com> Signed-off-by: Joseph Lo <jose...@nvidia.com> --- drivers/firmware/tegra/Kconfig | 12 + drivers/firmware/tegra/Makefile |1 + drivers/firmware/tegra/bpmp.c | 713 + include/soc/tegra/bpmp.h| 29 + include/soc/tegra/bpmp_abi.h| 1601 +++ 5 files changed, 2356 insertions(+) create mode 100644 drivers/firmware/tegra/bpmp.c create mode 100644 include/soc/tegra/bpmp.h create mode 100644 include/soc/tegra/bpmp_abi.h diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig index 1fa3e4e136a5..ff2730d5c468 100644 --- a/drivers/firmware/tegra/Kconfig +++ b/drivers/firmware/tegra/Kconfig @@ -10,4 +10,16 @@ config TEGRA_IVC keeps the content is synchronization between host CPU and remote processors. +config TEGRA_BPMP + bool "Tegra BPMP driver" + depends on ARCH_TEGRA && TEGRA_HSP_MBOX && TEGRA_IVC + help + BPMP (Boot and Power Management Processor) is designed to off-loading + the PM functions which include clock/DVFS/thermal/power from the CPU. + It needs HSP as the HW synchronization and notification module and + IVC module as the message communication protocol. + + This driver manages the IPC interface between host CPU and the + firmware running on BPMP. + endmenu diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile index 92e2153e8173..e34a2f79e1ad 100644 --- a/drivers/firmware/tegra/Makefile +++ b/drivers/firmware/tegra/Makefile @@ -1 +1,2 @@ +obj-$(CONFIG_TEGRA_BPMP) += bpmp.o obj-$(CONFIG_TEGRA_IVC)+= ivc.o diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c new file mode 100644 index ..24fda626610e --- /dev/null +++ b/drivers/firmware/tegra/bpmp.c @@ -0,0 +1,713 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#define BPMP_MSG_SZ128 +#define BPMP_MSG_DATA_SZ 120 + +#define __MRQ_ATTRS0xff00 +#define __MRQ_INDEX(id)((id) & ~__MRQ_ATTRS) + +#define DO_ACK BIT(0) +#define RING_DOORBELL BIT(1) + +struct tegra_bpmp_soc_data { + u32 ch_index; /* channel index */ + u32 thread_ch_index;/* thread channel index */ + u32 cpu_rx_ch_index;/* CPU Rx channel index */ + u32 nr_ch; /* number of total channels */ + u32 nr_thread_ch; /* number of thread channels */ + u32 ch_timeout; /* channel timeout */ + u32 thread_ch_timeout; /* thread channel timeout */ +}; + +struct channel_info { + u32 tch_free; + u32 tch_to_complete; + struct semaphore tch_sem; +}; + +struct mb_data { + s32 code; + s32 flags; + u8 data[BPMP_MSG_DATA_SZ]; +} __packed; + +struct channel_data { + struct mb_data *ib; + struct mb_data *ob; +}; + +struct mrq { + s
[PATCH 06/10] soc/tegra: Add Tegra186 support
The Tegra186 has a combination of Denver and Cortex-A57 CPU cores and GPUs with Pascal architecture on it. It features with ADSP with Cortex-A9 CPU for audio processing, hardware video encoder/decoder with multi-format support, ISP for image capture processing and BPMP for the power managements. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- drivers/soc/tegra/Kconfig | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index 03089ad2fc65..88a71dfd466c 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -61,6 +61,20 @@ config ARCH_TEGRA_132_SOC but contains an NVIDIA Denver CPU complex in place of Tegra124's "4+1" Cortex-A15 CPU complex. +config ARCH_TEGRA_186_SOC + bool "NVIDIA Tegra186 SoC" + select MAILBOX + select TEGRA_BPMP + select TEGRA_HSP_MBOX + select TEGRA_IVC + help + Enable support for the NVIDIA Tegar186 SoC. The Tegra186 has a + combination of Denver and Cortex-A57 CPU cores and GPUs with Pascal + architecture on it. It features with ADSP with Cortex-A9 CPU for + audio processing, hardware video encoder/decoder with multi-format + support, ISP for image capture processing and BPMP for the power + managements. + config ARCH_TEGRA_210_SOC bool "NVIDIA Tegra210 SoC" select PINCTRL_TEGRA210 -- 2.9.0
[PATCH 04/10] firmware: tegra: add IVC library
The Inter-VM communication (IVC) is a communication protocol, which is designed for interprocessor communication (IPC) or the communication between the hypervisor and the virtual machine with a guest OS on it. So it can be translated as inter-virtual memory or inter-virtual machine communication. The message channels are maintained on the DRAM or SRAM and the data coherency should be considered. Or the data could be corrupted or out of date when the remote client checking it. Inside the IVC, it maintains memory-based descriptors for the TX/RX channels and the coherency issue of the counter and payloads. So the clients can use it to send/receive messages to/from remote ones. We introduce it as a library for the firmware drivers, which can use it for IPC. Based-on-the-work-by: Peter Newman <pnew...@nvidia.com> Signed-off-by: Joseph Lo <jose...@nvidia.com> --- drivers/firmware/Kconfig| 1 + drivers/firmware/Makefile | 1 + drivers/firmware/tegra/Kconfig | 13 + drivers/firmware/tegra/Makefile | 1 + drivers/firmware/tegra/ivc.c| 659 include/soc/tegra/ivc.h | 102 +++ 6 files changed, 777 insertions(+) create mode 100644 drivers/firmware/tegra/Kconfig create mode 100644 drivers/firmware/tegra/Makefile create mode 100644 drivers/firmware/tegra/ivc.c create mode 100644 include/soc/tegra/ivc.h diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 6664f1108c7c..8602d81a6072 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -199,5 +199,6 @@ config HAVE_ARM_SMCCC source "drivers/firmware/broadcom/Kconfig" source "drivers/firmware/google/Kconfig" source "drivers/firmware/efi/Kconfig" +source "drivers/firmware/tegra/Kconfig" endmenu diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 474bada56fcd..9a4df8171cc4 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -24,3 +24,4 @@ obj-y += broadcom/ obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ obj-$(CONFIG_EFI) += efi/ obj-$(CONFIG_UEFI_CPER)+= efi/ +obj-y += tegra/ diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig new file mode 100644 index ..1fa3e4e136a5 --- /dev/null +++ b/drivers/firmware/tegra/Kconfig @@ -0,0 +1,13 @@ +menu "Tegra firmware driver" + +config TEGRA_IVC + bool "Tegra IVC protocol" + depends on ARCH_TEGRA + help + IVC (Inter-VM Communication) protocol is part of the IPC + (Inter Processor Communication) framework on Tegra. It maintains the + data and the different commuication channels in SysRAM or RAM and + keeps the content is synchronization between host CPU and remote + processors. + +endmenu diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile new file mode 100644 index ..92e2153e8173 --- /dev/null +++ b/drivers/firmware/tegra/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_TEGRA_IVC)+= ivc.o diff --git a/drivers/firmware/tegra/ivc.c b/drivers/firmware/tegra/ivc.c new file mode 100644 index ..3e736bb9915a --- /dev/null +++ b/drivers/firmware/tegra/ivc.c @@ -0,0 +1,659 @@ +/* + * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 + +#include + +#define IVC_ALIGN 64 + +#ifdef CONFIG_SMP + +static inline void ivc_rmb(void) +{ + smp_rmb(); +} + +static inline void ivc_wmb(void) +{ + smp_wmb(); +} + +static inline void ivc_mb(void) +{ + smp_mb(); +} + +#else + +static inline void ivc_rmb(void) +{ + rmb(); +} + +static inline void ivc_wmb(void) +{ + wmb(); +} + +static inline void ivc_mb(void) +{ + mb(); +} + +#endif + +/* + * IVC channel reset protocol. + * + * Each end uses its tx_channel.state to indicate its synchronization state. + */ +enum ivc_state { + /* +* This value is zero for backwards compatibility with services that +* assume channels to be initially zeroed. Such channels are in an +* initially valid state, but cannot be asynchronously reset, and must +* maintain a valid state at all times. +* +* The transmitting end can enter the established state from the sync or +* ack state when it observes the receiving endpoint in the ack or +* established stat
[PATCH 02/10] mailbox: tegra-hsp: Add HSP(Hardware Synchronization Primitives) driver
The Tegra HSP mailbox driver implements the signaling doorbell-based interprocessor communication (IPC) for remote processors currently. The HSP HW modules support some different features for that, which are shared mailboxes, shared semaphores, arbitrated semaphores, and doorbells. And there are multiple HSP HW instances on the chip. So the driver is extendable to support more features for different IPC requirement. The driver of remote processor can use it as a mailbox client and deal with the IPC protocol to synchronize the data communications. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- drivers/mailbox/Kconfig | 9 ++ drivers/mailbox/Makefile| 2 + drivers/mailbox/tegra-hsp.c | 306 3 files changed, 317 insertions(+) create mode 100644 drivers/mailbox/tegra-hsp.c diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 5305923752d2..fe584cb54720 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -114,6 +114,15 @@ config MAILBOX_TEST Test client to help with testing new Controller driver implementations. +config TEGRA_HSP_MBOX + bool "Tegra HSP(Hardware Synchronization Primitives) Driver" + depends on ARCH_TEGRA_186_SOC + help + The Tegra HSP driver is used for the interprocessor communication + between different remote processors and host processors on Tegra186 + and later SoCs. Say Y here if you want to have this support. + If unsure say N. + config XGENE_SLIMPRO_MBOX tristate "APM SoC X-Gene SLIMpro Mailbox Controller" depends on ARCH_XGENE diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 0be3e742bb7d..26d8f91c7fea 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -25,3 +25,5 @@ obj-$(CONFIG_TI_MESSAGE_MANAGER) += ti-msgmgr.o obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o + +obj-${CONFIG_TEGRA_HSP_MBOX} += tegra-hsp.o diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c new file mode 100644 index ..85bf5372681d --- /dev/null +++ b/drivers/mailbox/tegra-hsp.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include + +#define HSP_INT_DIMENSIONING 0x380 +#define HSP_nSM_OFFSET 0 +#define HSP_nSS_OFFSET 4 +#define HSP_nAS_OFFSET 8 +#define HSP_nDB_OFFSET 12 +#define HSP_nSI_OFFSET 16 +#define HSP_nINT_MASK 0xf + +#define HSP_DB_REG_TRIGGER 0x0 +#define HSP_DB_REG_ENABLE 0x4 +#define HSP_DB_REG_RAW 0x8 +#define HSP_DB_REG_PENDING 0xc + +#define HSP_DB_CCPLEX 1 +#define HSP_DB_BPMP3 + +#define MAX_NUM_HSP_CHAN 32 +#define MAX_NUM_HSP_DB 7 + +#define hsp_db_offset(i, d) \ + (d->base + ((1 + (d->nr_sm >> 1) + d->nr_ss + d->nr_as) << 16) + \ + (i) * 0x100) + +struct tegra_hsp_db_chan { + int master_id; + int db_id; +}; + +struct tegra_hsp_mbox { + struct mbox_controller *db_mbox; + void __iomem *base; + void __iomem *db_base[MAX_NUM_HSP_DB]; + int nr_sm; + int nr_as; + int nr_ss; + int nr_db; + int nr_si; + spinlock_t lock; +}; + +static inline u32 hsp_readl(void __iomem *base, int reg) +{ + return readl(base + reg); +} + +static inline void hsp_writel(void __iomem *base, int reg, u32 val) +{ + writel(val, base + reg); + readl(base + reg); +} + +static int hsp_db_can_ring(void __iomem *db_base) +{ + u32 reg; + + reg = hsp_readl(db_base, HSP_DB_REG_ENABLE); + + return !!(reg & BIT(HSP_DB_MASTER_CCPLEX)); +} + +static irqreturn_t hsp_db_irq(int irq, void *p) +{ + struct tegra_hsp_mbox *hsp_mbox = p; + ulong val; + int master_id; + + val = (ulong)hsp_readl(hsp_mbox->db_base[HSP_DB_CCPLEX], + HSP_DB_REG_PENDING); + hsp_writel(hsp_mbox->db_base[HSP_DB_CCPLEX], HSP_DB_REG_PENDING, val); + + spin_lock(_mbox->lock); + for_each_set_bit(master_id, , MAX_NUM_HSP_CHAN) { + struct mbox_chan *chan = _mbox->db_mbox->chans[master_id]; + struct tegra_hsp_db_chan *db_chan = chan->con_priv; + + if (master_id == db_chan->master_id) + mbo
[PATCH 00/10] arm64: tegra: add BPMP support
Hi, This series introduce the first announced Boot and Power Management Processor (BPMP) for the new generation Tegra SoCs, which is designed for boot process handling and offloading the power management tasks from the CPU. We also add some very initial and basic support for Tegra186 SoC, which supports debug console and initrd for initial bring up currently. More drivers and functions can be supported based on this later. Thanks, Joseph Joseph Lo (10): Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox mailbox: tegra-hsp: Add HSP(Hardware Synchronization Primitives) driver Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP firmware: tegra: add IVC library firmware: tegra: add BPMP support soc/tegra: Add Tegra186 support arm64: defconfig: Enable Tegra186 SoC arm64: dts: tegra: Add Tegra186 support arm64: dts: tegra: Add NVIDIA Tegra186 P3310 main board support arm64: dts: tegra: Add NVIDIA P2771 board support .../bindings/firmware/nvidia,tegra186-bpmp.txt | 61 + .../bindings/mailbox/nvidia,tegra186-hsp.txt | 42 + arch/arm64/boot/dts/nvidia/Makefile|1 + arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts |8 + arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 30 + arch/arm64/boot/dts/nvidia/tegra186.dtsi | 77 + arch/arm64/configs/defconfig |1 + drivers/firmware/Kconfig |1 + drivers/firmware/Makefile |1 + drivers/firmware/tegra/Kconfig | 25 + drivers/firmware/tegra/Makefile|2 + drivers/firmware/tegra/bpmp.c | 713 + drivers/firmware/tegra/ivc.c | 659 drivers/mailbox/Kconfig|9 + drivers/mailbox/Makefile |2 + drivers/mailbox/tegra-hsp.c| 306 drivers/soc/tegra/Kconfig | 14 + include/dt-bindings/mailbox/tegra-hsp.h| 20 + include/soc/tegra/bpmp.h | 29 + include/soc/tegra/bpmp_abi.h | 1601 include/soc/tegra/ivc.h| 102 ++ 21 files changed, 3704 insertions(+) create mode 100644 Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi create mode 100644 arch/arm64/boot/dts/nvidia/tegra186.dtsi create mode 100644 drivers/firmware/tegra/Kconfig create mode 100644 drivers/firmware/tegra/Makefile create mode 100644 drivers/firmware/tegra/bpmp.c create mode 100644 drivers/firmware/tegra/ivc.c create mode 100644 drivers/mailbox/tegra-hsp.c create mode 100644 include/dt-bindings/mailbox/tegra-hsp.h create mode 100644 include/soc/tegra/bpmp.h create mode 100644 include/soc/tegra/bpmp_abi.h create mode 100644 include/soc/tegra/ivc.h -- 2.9.0
[PATCH 01/10] Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox
Add DT binding for the Hardware Synchronization Primitives (HSP). The HSP is designed for the processors to share resources and communicate together. It provides a set of hardware synchronization primitives for interprocessor communication. So the interprocessor communication (IPC) protocols can use hardware synchronization primitive, when operating between two processors not in an SMP relationship. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- .../bindings/mailbox/nvidia,tegra186-hsp.txt | 42 ++ include/dt-bindings/mailbox/tegra-hsp.h| 20 +++ 2 files changed, 62 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt create mode 100644 include/dt-bindings/mailbox/tegra-hsp.h diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt new file mode 100644 index ..ca07af2d951e --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt @@ -0,0 +1,42 @@ +NVIDIA Tegra Hardware Synchronization Primitives (HSP) + +The HSP modules are used for the processors to share resources and communicate +together. It provides a set of hardware synchronization primitives for +interprocessor communication. So the interprocessor communication (IPC) +protocols can use hardware synchronization primitives, when operating between +two processors not in an SMP relationship. + +The features that HSP supported are shared mailboxes, shared semaphores, +arbitrated semaphores and doorbells. + +Required properties: +- name : Should be hsp +- compatible : Should be "nvidia,tegra-hsp" +- reg : Offset and length of the register set for the device +- interrupts : Should contain the HSP interrupts +- interrupt-names: Should contain the names of the HSP interrupts that the + client are using. + "doorbell" +- nvidia,hsp-function : Specifies one of the HSP functions that the HSP unit + will be supported. The function ID can be found in the + header file . +- #mbox-cells : Should be 1. Specifies the HSP master that will be enabled of + the HSP client. The master ID constants can be found in the + header file . + +Example: + +hsp_top: hsp@3c0 { + compatible = "nvidia,tegra186-hsp"; + reg = <0x0 0x03c0 0x0 0xa>; + interrupts = ; + interrupt-names = "doorbell"; + nvidia,hsp-function = ; + #mbox-cells = <1>; +}; + +bpmp@d000 { + ... + mboxes = <_top HSP_DB_MASTER_BPMP>; + ... +}; diff --git a/include/dt-bindings/mailbox/tegra-hsp.h b/include/dt-bindings/mailbox/tegra-hsp.h new file mode 100644 index ..720c66784b72 --- /dev/null +++ b/include/dt-bindings/mailbox/tegra-hsp.h @@ -0,0 +1,20 @@ +/* + * This header provides constants for binding nvidia,tegra-hsp. + * + * The number with HSP_DB_MASTER prefix indicates the bit that is + * associated with a master ID in the doorbell registers. + */ + + +#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H +#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H + +#define HSP_SHARED_MAILBOX 0 +#define HSP_SHARED_SEMAPHORE 1 +#define HSP_ARBITRATED_SEMAPHORE 2 +#define HSP_DOORBELL 3 + +#define HSP_DB_MASTER_CCPLEX 17 +#define HSP_DB_MASTER_BPMP 19 + +#endif /* _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H */ -- 2.9.0
[PATCH 03/10] Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP
The BPMP is a specific processor in Tegra chip, which is designed for booting process handling and offloading the power management tasks from the CPU. The binding document defines the resources that would be used by the BPMP firmware driver, which can create the interprocessor communication (IPC) between the CPU and BPMP. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- .../bindings/firmware/nvidia,tegra186-bpmp.txt | 61 ++ 1 file changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt diff --git a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt new file mode 100644 index ..34a252d87e17 --- /dev/null +++ b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt @@ -0,0 +1,61 @@ +NVIDIA Tegra Boot and Power Management Processor (BPMP) + +The BPMP is a specific processor in Tegra chip, which is designed for +booting process handling and offloading the power management tasks from +the CPU. The binding document defines the resources that would be used by +the BPMP firmware driver, which can create the interprocessor +communication (IPC) between the CPU and BPMP. + +Required properties: +- name : Should be bpmp +- compatible : Should be "nvidia,tegra-bpmp" +- mboxes : The phandle of mailbox controller and the channel ID + See "Documentation/devicetree/bindings/mailbox/ + nvidia,tegra186-hsp.txt" and "Documentation/devicetree/ + bindings/mailbox/mailbox.txt" for more details about the generic + mailbox controller and mailbox client driver bindings. +- shmem : List of the phandle of the TX and RX shared memory area that + the IPC between CPU and BPMP is based on. +- #clock-cells : Should be 1. +- #reset-cells : Should be 1. + +The shared memory bindings for BPMP +--- + +The shared memory area for the IPC TX and RX between CPU and BPMP are +predefined and work on top of sysram, which is a sram inside the chip. + +See "Documentation/devicetree/bindings/sram/sram.txt" for the bindings. + +Example: + +hsp_top: hsp@03c0 { + ... + #mbox-cells = <1>; +}; + +bpmp@d000 { + compatible = "nvidia,tegra186-bpmp"; + mboxes = <_mbox HSP_DB_MASTER_BPMP>; + shmem = <_bpmp_tx _bpmp_rx>; + #clock-cells = <1>; + #reset-cells = <1>; +}; + +sysram@3000 { + compatible = "nvidia,tegra186-sysram", "mmio-ram"; + reg = <0x0 0x3000 0x0 0x5>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0x0 0x0 0x3000 0x0 0x5>; + + cpu_bpmp_tx: bpmp_shmem@4e000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4e000 0x0 0x1000>; + }; + + cpu_bpmp_rx: bpmp_shmem@4f000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4f000 0x0 0x1000>; + }; +}; -- 2.9.0
[PATCH 10/10] arm64: dts: tegra: Add NVIDIA P2771 board support
Add NVIDIA Tegra186 P2771 board support, which is a reference development board with P2597 I/O board and P3310 chip module on it. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- arch/arm64/boot/dts/nvidia/Makefile| 1 + arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts | 8 2 files changed, 9 insertions(+) create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts diff --git a/arch/arm64/boot/dts/nvidia/Makefile b/arch/arm64/boot/dts/nvidia/Makefile index 0f7cdf3e05c1..67234f3dc795 100644 --- a/arch/arm64/boot/dts/nvidia/Makefile +++ b/arch/arm64/boot/dts/nvidia/Makefile @@ -1,4 +1,5 @@ dtb-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra132-norrin.dtb +dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts b/arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts new file mode 100644 index ..66b936389fa7 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts @@ -0,0 +1,8 @@ +/dts-v1/; + +#include "tegra186-p3310.dtsi" + +/ { + model = "NVIDIA Tegra186 P2771- Board"; + compatible = "nvidia,p2771-", "nvidia,tegra186"; +}; -- 2.9.0
[PATCH 08/10] arm64: dts: tegra: Add Tegra186 support
This adds the initial support of Tegra186 SoC, which can help to bring up the debug console and initrd for further developing. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- arch/arm64/boot/dts/nvidia/tegra186.dtsi | 77 1 file changed, 77 insertions(+) create mode 100644 arch/arm64/boot/dts/nvidia/tegra186.dtsi diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi new file mode 100644 index ..bed30f30bb0b --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi @@ -0,0 +1,77 @@ +#include +#include + +/ { + compatible = "nvidia,tegra186"; + interrupt-parent = <>; + #address-cells = <2>; + #size-cells = <2>; + + uarta: serial@0310 { + compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart"; + reg = <0x0 0x0310 0x0 0x40>; + reg-shift = <2>; + interrupts = ; + status = "disabled"; + }; + + gic: interrupt-controller@03881000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x0 0x03881000 0x0 0x1000>, + <0x0 0x03882000 0x0 0x2000>; + interrupts = ; + interrupt-parent = <>; + }; + + hsp_top: hsp@03c0 { + compatible = "nvidia,tegra186-hsp"; + reg = <0x0 0x03c0 0x0 0xa>; + interrupts = ; + interrupt-names = "doorbell"; + nvidia,hsp-function = ; + #mbox-cells = <1>; + }; + + bpmp@d000 { + compatible = "nvidia,tegra186-bpmp"; + mboxes = <_top HSP_DB_MASTER_BPMP>; + shmem = <_bpmp_tx _bpmp_rx>; + #clock-cells = <1>; + #reset-cells = <1>; + status = "disabled"; + }; + + sysram@3000 { + compatible = "nvidia,tegra186-sysram", "mmio-ram"; + reg = <0x0 0x3000 0x0 0x4>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0x0 0x0 0x3000 0x0 0x4>; + + cpu_bpmp_tx: bpmp_shmem@4e000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4e000 0x0 0x1000>; + }; + + cpu_bpmp_rx: bpmp_shmem@4f000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4f000 0x0 0x1000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , +, +, +; + interrupt-parent = <>; + }; +}; -- 2.9.0
[PATCH 09/10] arm64: dts: tegra: Add NVIDIA Tegra186 P3310 main board support
Add NVIDIA Tegra186 P3310 main board support, which is a chip module with DRAM, nonvolatile storage, WiFi, ethernet and PMIC chips on it. It also needs an IO board and hooks on it to represent as an application platform. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 30 ++ 1 file changed, 30 insertions(+) create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi new file mode 100644 index ..5258ec0d6eef --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi @@ -0,0 +1,30 @@ +#include "tegra186.dtsi" + +/ { + model = "NVIDIA Tegra186 P3310 main Board"; + compatible = "nvidia,p3301", "nvidia,tegra186"; + + aliases { + serial0 = + }; + + chosen { + bootargs = "earlycon console=ttyS0,115200n8"; + stdout-path = "serial0:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x8000 0x2 0x>; + }; + + serial@0310 { + // HACK: before clk driver ready + clock-frequency = <40800>; + status = "okay"; + }; + + bpmp@d000 { + status = "okay"; + }; +}; -- 2.9.0
[PATCH 07/10] arm64: defconfig: Enable Tegra186 SoC
Enable Tegra186 SoC. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f267eea101a7..033d9cb1e983 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -312,6 +312,7 @@ CONFIG_QCOM_SMEM=y CONFIG_QCOM_SMD=y CONFIG_QCOM_SMD_RPM=y CONFIG_ARCH_TEGRA_132_SOC=y +CONFIG_ARCH_TEGRA_186_SOC=y CONFIG_ARCH_TEGRA_210_SOC=y CONFIG_EXTCON_USB_GPIO=y CONFIG_PWM=y -- 2.9.0
Re: [PATCH 01/10] Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox
On 06/29/2016 03:08 AM, Stephen Warren wrote: On 06/28/2016 03:15 AM, Joseph Lo wrote: On 06/27/2016 11:55 PM, Stephen Warren wrote: On 06/27/2016 03:02 AM, Joseph Lo wrote: snip. Currently the usage of HSP HW in the downstream kernel is something like the model below. remote_processor_A-\ remote_processor_B--->hsp@1000 (doorbell func) <-> host CPU remote_processor_C-/ remote_processor_D -> hsp@2000 (shared mailbox) <-> CPU remote_processor_E -> hsp@3000 (shared mailbox) <-> CPU I am thinking if we can just add the appropriate compatible strings for it to replace "nvidia,tegra186-hsp". e.g. "nvidia,tegra186-hsp-doorbell" and "nvidia,tegra186-hsp-sharedmailbox". So the driver can probe and initialize correctly depend on the compatible property. How do you think about it? Is this the same as the (b) you mentioned above? Yes, that would be (b) above. However, please do note (a): I expect that splitting things up will turn out to be a mistake, as it has for other HW modules in the past. I would far rather see a single hsp node in DT, since there is a single HSP block in HW. Sure that block has multiple sub-functions. However, there is common logic that affects all of those sub-functions and binds everything into a single HW module. If you represent the HW module using multiple different DT nodes, it will be hard to correctly represent that common logic. Conversely, I see no real advantage to splitting up the DT node. I strongly believe we should have a single "hsp" node in DT. We have 6 HSP block in HW. FYI. Internally, the SW driver for that node can be structured however you want; it could register with multiple subsystems (mailbox, ...) with just one struct device, or the HSP driver could be an MFD device with sub-drivers for each separate piece of functionality the HW implements. All this can easily be done even while using a single DT node. And furthermore, we can add this SW structure later if/when we actually need it; in other words, there's no need to change your current patches right now, except to remove the nvidia,hsp-function DT property. Thanks, -Joseph
[PATCH V2 00/10] arm64: tegra: add BPMP support
Hi, This series introduce the first announced Boot and Power Management Processor (BPMP) for the new generation Tegra SoCs, which is designed for boot process handling and offloading the power management tasks from the CPU. We also add some very initial and basic support for Tegra186 SoC, which supports debug console and initrd for initial bring up currently. More drivers and functions can be supported based on this later. Thanks, Joseph Changes in V2 - revise the HSP mailbox and bpmp DT binding documents - fix the HSP mailbox driver according to the binding update - update the dts files to represent the binding update Joseph Lo (10): Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox mailbox: tegra-hsp: Add HSP(Hardware Synchronization Primitives) driver Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP firmware: tegra: add IVC library firmware: tegra: add BPMP support soc/tegra: Add Tegra186 support arm64: defconfig: Enable Tegra186 SoC arm64: dts: tegra: Add Tegra186 support arm64: dts: tegra: Add NVIDIA Tegra186 P3310 main board support arm64: dts: tegra: Add NVIDIA P2771 board support .../bindings/firmware/nvidia,tegra186-bpmp.txt | 77 + .../bindings/mailbox/nvidia,tegra186-hsp.txt | 51 + arch/arm64/boot/dts/nvidia/Makefile|1 + arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts |8 + arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 34 + arch/arm64/boot/dts/nvidia/tegra186.dtsi | 77 + arch/arm64/configs/defconfig |1 + drivers/firmware/Kconfig |1 + drivers/firmware/Makefile |1 + drivers/firmware/tegra/Kconfig | 25 + drivers/firmware/tegra/Makefile|2 + drivers/firmware/tegra/bpmp.c | 713 + drivers/firmware/tegra/ivc.c | 659 drivers/mailbox/Kconfig|9 + drivers/mailbox/Makefile |2 + drivers/mailbox/tegra-hsp.c| 418 + drivers/soc/tegra/Kconfig | 14 + include/dt-bindings/clock/tegra186-clock.h | 940 include/dt-bindings/mailbox/tegra186-hsp.h | 23 + include/dt-bindings/reset/tegra186-reset.h | 217 +++ include/soc/tegra/bpmp.h | 29 + include/soc/tegra/bpmp_abi.h | 1601 include/soc/tegra/ivc.h| 102 ++ 23 files changed, 5005 insertions(+) create mode 100644 Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi create mode 100644 arch/arm64/boot/dts/nvidia/tegra186.dtsi create mode 100644 drivers/firmware/tegra/Kconfig create mode 100644 drivers/firmware/tegra/Makefile create mode 100644 drivers/firmware/tegra/bpmp.c create mode 100644 drivers/firmware/tegra/ivc.c create mode 100644 drivers/mailbox/tegra-hsp.c create mode 100644 include/dt-bindings/clock/tegra186-clock.h create mode 100644 include/dt-bindings/mailbox/tegra186-hsp.h create mode 100644 include/dt-bindings/reset/tegra186-reset.h create mode 100644 include/soc/tegra/bpmp.h create mode 100644 include/soc/tegra/bpmp_abi.h create mode 100644 include/soc/tegra/ivc.h -- 2.9.0
[PATCH V2 01/10] Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox
Add DT binding for the Hardware Synchronization Primitives (HSP). The HSP is designed for the processors to share resources and communicate together. It provides a set of hardware synchronization primitives for interprocessor communication. So the interprocessor communication (IPC) protocols can use hardware synchronization primitive, when operating between two processors not in an SMP relationship. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - revise the compatible string, interrupt-names, interrupts, and #mbox-cells properties - remove "nvidia,hsp-function" property - fix the header file name - the binding supports the concept of multiple HSP sub-modules on one HSP HW block now. --- .../bindings/mailbox/nvidia,tegra186-hsp.txt | 51 ++ include/dt-bindings/mailbox/tegra186-hsp.h | 23 ++ 2 files changed, 74 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt create mode 100644 include/dt-bindings/mailbox/tegra186-hsp.h diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt new file mode 100644 index ..10e53edbe1c7 --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt @@ -0,0 +1,51 @@ +NVIDIA Tegra Hardware Synchronization Primitives (HSP) + +The HSP modules are used for the processors to share resources and communicate +together. It provides a set of hardware synchronization primitives for +interprocessor communication. So the interprocessor communication (IPC) +protocols can use hardware synchronization primitives, when operating between +two processors not in an SMP relationship. + +The features that HSP supported are shared mailboxes, shared semaphores, +arbitrated semaphores and doorbells. + +Required properties: +- name : Should be hsp +- compatible +Array of strings. +one of: +- "nvidia,tegra186-hsp" +- reg : Offset and length of the register set for the device. +- interrupt-names +Array of strings. +Contains a list of names for the interrupts described by the interrupt +property. May contain the following entries, in any order: +- "doorbell" +Users of this binding MUST look up entries in the interrupt property +by name, using this interrupt-names property to do so. +- interrupts +Array of interrupt specifiers. +Must contain one entry per entry in the interrupt-names property, +in a matching order. +- #mbox-cells : Should be 1. + +The mbox specifier of the "mboxes" property in the client node should use +the "HSP_MBOX_ID" macro which integrates the HSP type and master ID data. +Those information can be found in the following file. + +- . + +Example: + +hsp_top0: hsp@3c0 { + compatible = "nvidia,tegra186-hsp"; + reg = <0x0 0x03c0 0x0 0xa>; + interrupts = ; + interrupt-names = "doorbell"; + #mbox-cells = <1>; +}; + +client { + ... + mboxes = <_top0 HSP_MBOX_ID(DB, HSP_DB_MASTER_XXX)>; +}; diff --git a/include/dt-bindings/mailbox/tegra186-hsp.h b/include/dt-bindings/mailbox/tegra186-hsp.h new file mode 100644 index ..365dbeb5d894 --- /dev/null +++ b/include/dt-bindings/mailbox/tegra186-hsp.h @@ -0,0 +1,23 @@ +/* + * This header provides constants for binding nvidia,tegra186-hsp. + * + * The number with HSP_DB_MASTER prefix indicates the bit that is + * associated with a master ID in the doorbell registers. + */ + + +#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H +#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H + +#define HSP_MBOX_TYPE_DB 0x0 +#define HSP_MBOX_TYPE_SM 0x1 +#define HSP_MBOX_TYPE_SS 0x2 +#define HSP_MBOX_TYPE_AS 0x3 + +#define HSP_DB_MASTER_CCPLEX 17 +#define HSP_DB_MASTER_BPMP 19 + +#define HSP_MBOX_ID(type, ID) \ + (HSP_MBOX_TYPE_##type << 16 | ID) + +#endif /* _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H */ -- 2.9.0
[PATCH V2 06/10] soc/tegra: Add Tegra186 support
The Tegra186 has a combination of Denver and Cortex-A57 CPU cores and GPUs with Pascal architecture on it. It features with ADSP with Cortex-A9 CPU for audio processing, hardware video encoder/decoder with multi-format support, ISP for image capture processing and BPMP for the power managements. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - None --- drivers/soc/tegra/Kconfig | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index 03089ad2fc65..88a71dfd466c 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -61,6 +61,20 @@ config ARCH_TEGRA_132_SOC but contains an NVIDIA Denver CPU complex in place of Tegra124's "4+1" Cortex-A15 CPU complex. +config ARCH_TEGRA_186_SOC + bool "NVIDIA Tegra186 SoC" + select MAILBOX + select TEGRA_BPMP + select TEGRA_HSP_MBOX + select TEGRA_IVC + help + Enable support for the NVIDIA Tegar186 SoC. The Tegra186 has a + combination of Denver and Cortex-A57 CPU cores and GPUs with Pascal + architecture on it. It features with ADSP with Cortex-A9 CPU for + audio processing, hardware video encoder/decoder with multi-format + support, ISP for image capture processing and BPMP for the power + managements. + config ARCH_TEGRA_210_SOC bool "NVIDIA Tegra210 SoC" select PINCTRL_TEGRA210 -- 2.9.0
[PATCH V2 05/10] firmware: tegra: add BPMP support
The Tegra BPMP (Boot and Power Management Processor) is designed for the booting process handling, offloading the power management tasks and some system control services from the CPU. It can be clock, DVFS, thermal/EDP, power gating operation and system suspend/resume handling. So the CPU and the drivers of these modules can base on the service that the BPMP firmware driver provided to signal the event for the specific PM action to BPMP and receive the status update from BPMP. Comparing to the ARM SCPI, the service provided by BPMP is message-based communication but not method-based. The BPMP firmware driver provides the send/receive service for the users, when the user concerns the response time. If the user needs to get the event or update from the firmware, it can request the MRQ service as well. The user needs to take care of the message format, which we call BPMP ABI. The BPMP ABI defines the message format for different modules or usages. For example, the clock operation needs an MRQ service code called MRQ_CLK with specific message format which includes different sub commands for various clock operations. This is the message format that BPMP can recognize. So the user needs two things to initiate IPC between BPMP. Get the service from the bpmp_ops structure and maintain the message format as the BPMP ABI defined. Based-on-the-work-by: Sivaram Nair <sivar...@nvidia.com> Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - None --- drivers/firmware/tegra/Kconfig | 12 + drivers/firmware/tegra/Makefile |1 + drivers/firmware/tegra/bpmp.c | 713 + include/soc/tegra/bpmp.h| 29 + include/soc/tegra/bpmp_abi.h| 1601 +++ 5 files changed, 2356 insertions(+) create mode 100644 drivers/firmware/tegra/bpmp.c create mode 100644 include/soc/tegra/bpmp.h create mode 100644 include/soc/tegra/bpmp_abi.h diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig index 1fa3e4e136a5..ff2730d5c468 100644 --- a/drivers/firmware/tegra/Kconfig +++ b/drivers/firmware/tegra/Kconfig @@ -10,4 +10,16 @@ config TEGRA_IVC keeps the content is synchronization between host CPU and remote processors. +config TEGRA_BPMP + bool "Tegra BPMP driver" + depends on ARCH_TEGRA && TEGRA_HSP_MBOX && TEGRA_IVC + help + BPMP (Boot and Power Management Processor) is designed to off-loading + the PM functions which include clock/DVFS/thermal/power from the CPU. + It needs HSP as the HW synchronization and notification module and + IVC module as the message communication protocol. + + This driver manages the IPC interface between host CPU and the + firmware running on BPMP. + endmenu diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile index 92e2153e8173..e34a2f79e1ad 100644 --- a/drivers/firmware/tegra/Makefile +++ b/drivers/firmware/tegra/Makefile @@ -1 +1,2 @@ +obj-$(CONFIG_TEGRA_BPMP) += bpmp.o obj-$(CONFIG_TEGRA_IVC)+= ivc.o diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c new file mode 100644 index ..24fda626610e --- /dev/null +++ b/drivers/firmware/tegra/bpmp.c @@ -0,0 +1,713 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#define BPMP_MSG_SZ128 +#define BPMP_MSG_DATA_SZ 120 + +#define __MRQ_ATTRS0xff00 +#define __MRQ_INDEX(id)((id) & ~__MRQ_ATTRS) + +#define DO_ACK BIT(0) +#define RING_DOORBELL BIT(1) + +struct tegra_bpmp_soc_data { + u32 ch_index; /* channel index */ + u32 thread_ch_index;/* thread channel index */ + u32 cpu_rx_ch_index;/* CPU Rx channel index */ + u32 nr_ch; /* number of total channels */ + u32 nr_thread_ch; /* number of thread channels */ + u32 ch_timeout; /* channel timeout */ + u32 thread_ch_timeout; /* thread channel timeout */ +}; + +struct channel_info { + u32 tch_free; + u32 tch_to_complete; + struct semaphore tch_sem; +}; + +struct mb_data { + s32 code; + s32 flags; + u8 data[BPMP_MSG_DATA_SZ]; +} __packed; + +struct channel_data { + struct mb_data *ib; + struct mb_data *ob; +}; + +
[PATCH V2 03/10] Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP
The BPMP is a specific processor in Tegra chip, which is designed for booting process handling and offloading the power management, clock management, and reset control tasks from the CPU. The binding document defines the resources that would be used by the BPMP firmware driver, which can create the interprocessor communication (IPC) between the CPU and BPMP. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - update the message that the BPMP is clock and reset control provider - add tegra186-clock.h and tegra186-reset.h header files - revise the description of the required properties --- .../bindings/firmware/nvidia,tegra186-bpmp.txt | 77 ++ include/dt-bindings/clock/tegra186-clock.h | 940 + include/dt-bindings/reset/tegra186-reset.h | 217 + 3 files changed, 1234 insertions(+) create mode 100644 Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt create mode 100644 include/dt-bindings/clock/tegra186-clock.h create mode 100644 include/dt-bindings/reset/tegra186-reset.h diff --git a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt new file mode 100644 index ..4d0b6eba56c5 --- /dev/null +++ b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt @@ -0,0 +1,77 @@ +NVIDIA Tegra Boot and Power Management Processor (BPMP) + +The BPMP is a specific processor in Tegra chip, which is designed for +booting process handling and offloading the power management, clock +management, and reset control tasks from the CPU. The binding document +defines the resources that would be used by the BPMP firmware driver, +which can create the interprocessor communication (IPC) between the CPU +and BPMP. + +Required properties: +- name : Should be bpmp +- compatible +Array of strings +One of: +- "nvidia,tegra186-bpmp" +- mboxes : The phandle of mailbox controller and the mailbox specifier. +- shmem : List of the phandle of the TX and RX shared memory area that + the IPC between CPU and BPMP is based on. +- #clock-cells : Should be 1. +- #reset-cells : Should be 1. + +This node is a mailbox consumer. See the following files for details of +the mailbox subsystem, and the specifiers implemented by the relevant +provider(s): + +- Documentation/devicetree/bindings/mailbox/mailbox.txt +- Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt + +This node is a clock and reset provider. See the following files for +general documentation of those features, and the specifiers implemented +by this node: + +- Documentation/devicetree/bindings/clock/clock-bindings.txt +- include/dt-bindings/clock/tegra186-clock.h +- Documentation/devicetree/bindings/reset/reset.txt +- include/dt-bindings/reset/tegra186-reset.h + +The shared memory bindings for BPMP +--- + +The shared memory area for the IPC TX and RX between CPU and BPMP are +predefined and work on top of sysram, which is an SRAM inside the chip. + +See "Documentation/devicetree/bindings/sram/sram.txt" for the bindings. + +Example: + +hsp_top0: hsp@03c0 { + ... + #mbox-cells = <1>; +}; + +sysram@3000 { + compatible = "nvidia,tegra186-sysram", "mmio-ram"; + reg = <0x0 0x3000 0x0 0x5>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0x0 0x0 0x3000 0x0 0x5>; + + cpu_bpmp_tx: bpmp_shmem@4e000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4e000 0x0 0x1000>; + }; + + cpu_bpmp_rx: bpmp_shmem@4f000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4f000 0x0 0x1000>; + }; +}; + +bpmp { + compatible = "nvidia,tegra186-bpmp"; + mboxes = <_top0 HSP_MBOX_ID(DB, HSP_DB_MASTER_BPMP)>; + shmem = <_bpmp_tx _bpmp_rx>; + #clock-cells = <1>; + #reset-cells = <1>; +}; diff --git a/include/dt-bindings/clock/tegra186-clock.h b/include/dt-bindings/clock/tegra186-clock.h new file mode 100644 index ..f73d32098f99 --- /dev/null +++ b/include/dt-bindings/clock/tegra186-clock.h @@ -0,0 +1,940 @@ +/** @file */ + +#ifndef _MACH_T186_CLK_T186_H +#define _MACH_T186_CLK_T186_H + +/** + * @defgroup clock_ids Clock Identifiers + * @{ + * @defgroup extern_input external input clocks + * @{ + * @def TEGRA186_CLK_OSC + * @def TEGRA186_CLK_CLK_32K + * @def TEGRA186_CLK_DTV_INPUT + * @def TEGRA186_CLK_SOR0_PAD_CLKOUT + * @def TEGRA186_CLK_SOR1_PAD_CLKOUT + * @def TEGRA186_CLK_I2S1_SYNC_INPUT + * @def TEGRA186_CLK_I2S2_SYNC_INPUT + * @def TEGRA186_CLK_I2S3_SYNC_INPUT + * @def TEGRA186_CLK_I2S4_SYNC_INPUT + * @def TEGRA186_CLK_I2S5_SYNC_INPUT + * @d
[PATCH V2 04/10] firmware: tegra: add IVC library
The Inter-VM communication (IVC) is a communication protocol, which is designed for interprocessor communication (IPC) or the communication between the hypervisor and the virtual machine with a guest OS on it. So it can be translated as inter-virtual memory or inter-virtual machine communication. The message channels are maintained on the DRAM or SRAM and the data coherency should be considered. Or the data could be corrupted or out of date when the remote client checking it. Inside the IVC, it maintains memory-based descriptors for the TX/RX channels and the coherency issue of the counter and payloads. So the clients can use it to send/receive messages to/from remote ones. We introduce it as a library for the firmware drivers, which can use it for IPC. Based-on-the-work-by: Peter Newman <pnew...@nvidia.com> Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - None --- drivers/firmware/Kconfig| 1 + drivers/firmware/Makefile | 1 + drivers/firmware/tegra/Kconfig | 13 + drivers/firmware/tegra/Makefile | 1 + drivers/firmware/tegra/ivc.c| 659 include/soc/tegra/ivc.h | 102 +++ 6 files changed, 777 insertions(+) create mode 100644 drivers/firmware/tegra/Kconfig create mode 100644 drivers/firmware/tegra/Makefile create mode 100644 drivers/firmware/tegra/ivc.c create mode 100644 include/soc/tegra/ivc.h diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 5e618058defe..bbd64ae8c4c6 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -200,5 +200,6 @@ config HAVE_ARM_SMCCC source "drivers/firmware/broadcom/Kconfig" source "drivers/firmware/google/Kconfig" source "drivers/firmware/efi/Kconfig" +source "drivers/firmware/tegra/Kconfig" endmenu diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 474bada56fcd..9a4df8171cc4 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -24,3 +24,4 @@ obj-y += broadcom/ obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ obj-$(CONFIG_EFI) += efi/ obj-$(CONFIG_UEFI_CPER)+= efi/ +obj-y += tegra/ diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig new file mode 100644 index ..1fa3e4e136a5 --- /dev/null +++ b/drivers/firmware/tegra/Kconfig @@ -0,0 +1,13 @@ +menu "Tegra firmware driver" + +config TEGRA_IVC + bool "Tegra IVC protocol" + depends on ARCH_TEGRA + help + IVC (Inter-VM Communication) protocol is part of the IPC + (Inter Processor Communication) framework on Tegra. It maintains the + data and the different commuication channels in SysRAM or RAM and + keeps the content is synchronization between host CPU and remote + processors. + +endmenu diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile new file mode 100644 index ..92e2153e8173 --- /dev/null +++ b/drivers/firmware/tegra/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_TEGRA_IVC)+= ivc.o diff --git a/drivers/firmware/tegra/ivc.c b/drivers/firmware/tegra/ivc.c new file mode 100644 index ..3e736bb9915a --- /dev/null +++ b/drivers/firmware/tegra/ivc.c @@ -0,0 +1,659 @@ +/* + * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 + +#include + +#define IVC_ALIGN 64 + +#ifdef CONFIG_SMP + +static inline void ivc_rmb(void) +{ + smp_rmb(); +} + +static inline void ivc_wmb(void) +{ + smp_wmb(); +} + +static inline void ivc_mb(void) +{ + smp_mb(); +} + +#else + +static inline void ivc_rmb(void) +{ + rmb(); +} + +static inline void ivc_wmb(void) +{ + wmb(); +} + +static inline void ivc_mb(void) +{ + mb(); +} + +#endif + +/* + * IVC channel reset protocol. + * + * Each end uses its tx_channel.state to indicate its synchronization state. + */ +enum ivc_state { + /* +* This value is zero for backwards compatibility with services that +* assume channels to be initially zeroed. Such channels are in an +* initially valid state, but cannot be asynchronously reset, and must +* maintain a valid state at all times. +* +* The transmitting end can enter the established state from the sync or +* ack state when it observes the receiving endpoint in the ack or +* established stat
[PATCH V2 07/10] arm64: defconfig: Enable Tegra186 SoC
Enable Tegra186 SoC. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - None --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index e69051098435..64d767ec142c 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -326,6 +326,7 @@ CONFIG_QCOM_SMEM=y CONFIG_QCOM_SMD=y CONFIG_QCOM_SMD_RPM=y CONFIG_ARCH_TEGRA_132_SOC=y +CONFIG_ARCH_TEGRA_186_SOC=y CONFIG_ARCH_TEGRA_210_SOC=y CONFIG_EXTCON_USB_GPIO=y CONFIG_PWM=y -- 2.9.0
[PATCH V2 02/10] mailbox: tegra-hsp: Add HSP(Hardware Synchronization Primitives) driver
The Tegra HSP mailbox driver implements the signaling doorbell-based interprocessor communication (IPC) for remote processors currently. The HSP HW modules support some different features for that, which are shared mailboxes, shared semaphores, arbitrated semaphores, and doorbells. And there are multiple HSP HW instances on the chip. So the driver is extendable to support more features for different IPC requirement. The driver of remote processor can use it as a mailbox client and deal with the IPC protocol to synchronize the data communications. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - Update the driver to support the binding changes in V2 - it's extendable to support multiple HSP sub-modules on the same HSP HW block now. --- drivers/mailbox/Kconfig | 9 + drivers/mailbox/Makefile| 2 + drivers/mailbox/tegra-hsp.c | 418 3 files changed, 429 insertions(+) create mode 100644 drivers/mailbox/tegra-hsp.c diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 5305923752d2..fe584cb54720 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -114,6 +114,15 @@ config MAILBOX_TEST Test client to help with testing new Controller driver implementations. +config TEGRA_HSP_MBOX + bool "Tegra HSP(Hardware Synchronization Primitives) Driver" + depends on ARCH_TEGRA_186_SOC + help + The Tegra HSP driver is used for the interprocessor communication + between different remote processors and host processors on Tegra186 + and later SoCs. Say Y here if you want to have this support. + If unsure say N. + config XGENE_SLIMPRO_MBOX tristate "APM SoC X-Gene SLIMpro Mailbox Controller" depends on ARCH_XGENE diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 0be3e742bb7d..26d8f91c7fea 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -25,3 +25,5 @@ obj-$(CONFIG_TI_MESSAGE_MANAGER) += ti-msgmgr.o obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o + +obj-${CONFIG_TEGRA_HSP_MBOX} += tegra-hsp.o diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c new file mode 100644 index ..93c3ef58f29f --- /dev/null +++ b/drivers/mailbox/tegra-hsp.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include +#include + +#define HSP_INT_DIMENSIONING 0x380 +#define HSP_nSM_OFFSET 0 +#define HSP_nSS_OFFSET 4 +#define HSP_nAS_OFFSET 8 +#define HSP_nDB_OFFSET 12 +#define HSP_nSI_OFFSET 16 +#define HSP_nINT_MASK 0xf + +#define HSP_DB_REG_TRIGGER 0x0 +#define HSP_DB_REG_ENABLE 0x4 +#define HSP_DB_REG_RAW 0x8 +#define HSP_DB_REG_PENDING 0xc + +#define HSP_DB_CCPLEX 1 +#define HSP_DB_BPMP3 + +#define MAX_NUM_HSP_CHAN 32 +#define MAX_NUM_HSP_DB 7 + +#define hsp_db_offset(i, d) \ + (d->base + ((1 + (d->nr_sm >> 1) + d->nr_ss + d->nr_as) << 16) + \ + (i) * 0x100) + +struct tegra_hsp_db_chan { + int master_id; + int db_id; +}; + +struct tegra_hsp_mbox_chan { + int type; + union { + struct tegra_hsp_db_chan db_chan; + }; +}; + +struct tegra_hsp_mbox { + struct mbox_controller *mbox; + void __iomem *base; + void __iomem *db_base[MAX_NUM_HSP_DB]; + int db_irq; + int nr_sm; + int nr_as; + int nr_ss; + int nr_db; + int nr_si; + spinlock_t lock; +}; + +static inline u32 hsp_readl(void __iomem *base, int reg) +{ + return readl(base + reg); +} + +static inline void hsp_writel(void __iomem *base, int reg, u32 val) +{ + writel(val, base + reg); + readl(base + reg); +} + +static int hsp_db_can_ring(void __iomem *db_base) +{ + u32 reg; + + reg = hsp_readl(db_base, HSP_DB_REG_ENABLE); + + return !!(reg & BIT(HSP_DB_MASTER_CCPLEX)); +} + +static irqreturn_t hsp_db_irq(int irq, void *p) +{ + struct tegra_hsp_mbox *hsp_mbox = p; + ulong val; + int master_id; + + val = (ulong)hsp_readl(hsp_mbox->db_base[HSP_DB_CCPLEX], + HSP_DB_REG_PENDING); + hsp_writel(hsp_mbox->db_base[HSP_DB_CCPLEX], HSP_DB_REG_PENDING, val); + +
[PATCH V2 09/10] arm64: dts: tegra: Add NVIDIA Tegra186 P3310 main board support
Add NVIDIA Tegra186 P3310 main board support, which is a chip module with DRAM, nonvolatile storage, WiFi, ethernet and PMIC chips on it. It also needs an IO board and hooks on it to represent as an application platform. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - update according to the binding fix in V2 --- arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 34 ++ 1 file changed, 34 insertions(+) create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi new file mode 100644 index ..f5238866d321 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi @@ -0,0 +1,34 @@ +#include "tegra186.dtsi" + +/ { + model = "NVIDIA Tegra186 P3310 main Board"; + compatible = "nvidia,p3301", "nvidia,tegra186"; + + aliases { + serial0 = + }; + + chosen { + bootargs = "earlycon console=ttyS0,115200n8"; + stdout-path = "serial0:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x8000 0x2 0x>; + }; + + serial@0310 { + // HACK: before clk driver ready + clock-frequency = <40800>; + status = "okay"; + }; + + hsp@03c0 { + status = "okay"; + }; + + bpmp { + status = "okay"; + }; +}; -- 2.9.0
[PATCH V2 10/10] arm64: dts: tegra: Add NVIDIA P2771 board support
Add NVIDIA Tegra186 P2771 board support, which is a reference development board with P2597 I/O board and P3310 chip module on it. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - None --- arch/arm64/boot/dts/nvidia/Makefile| 1 + arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts | 8 2 files changed, 9 insertions(+) create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts diff --git a/arch/arm64/boot/dts/nvidia/Makefile b/arch/arm64/boot/dts/nvidia/Makefile index 0f7cdf3e05c1..67234f3dc795 100644 --- a/arch/arm64/boot/dts/nvidia/Makefile +++ b/arch/arm64/boot/dts/nvidia/Makefile @@ -1,4 +1,5 @@ dtb-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra132-norrin.dtb +dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts b/arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts new file mode 100644 index ..66b936389fa7 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra186-p2771-.dts @@ -0,0 +1,8 @@ +/dts-v1/; + +#include "tegra186-p3310.dtsi" + +/ { + model = "NVIDIA Tegra186 P2771- Board"; + compatible = "nvidia,p2771-", "nvidia,tegra186"; +}; -- 2.9.0
[PATCH V2 08/10] arm64: dts: tegra: Add Tegra186 support
This adds the initial support of Tegra186 SoC, which can help to bring up the debug console and initrd for further developing. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - update the file according the HSP and BPMP binding fix in V2 --- arch/arm64/boot/dts/nvidia/tegra186.dtsi | 77 1 file changed, 77 insertions(+) create mode 100644 arch/arm64/boot/dts/nvidia/tegra186.dtsi diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi new file mode 100644 index ..57badd5de9b4 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi @@ -0,0 +1,77 @@ +#include +#include + +/ { + compatible = "nvidia,tegra186"; + interrupt-parent = <>; + #address-cells = <2>; + #size-cells = <2>; + + uarta: serial@0310 { + compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart"; + reg = <0x0 0x0310 0x0 0x40>; + reg-shift = <2>; + interrupts = ; + status = "disabled"; + }; + + gic: interrupt-controller@03881000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x0 0x03881000 0x0 0x1000>, + <0x0 0x03882000 0x0 0x2000>; + interrupts = ; + interrupt-parent = <>; + }; + + hsp_top0: hsp@03c0 { + compatible = "nvidia,tegra186-hsp"; + reg = <0x0 0x03c0 0x0 0xa>; + interrupts = ; + interrupt-names = "doorbell"; + #mbox-cells = <1>; + status = "disabled"; + }; + + sysram@3000 { + compatible = "nvidia,tegra186-sysram", "mmio-ram"; + reg = <0x0 0x3000 0x0 0x4>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0x0 0x0 0x3000 0x0 0x4>; + + cpu_bpmp_tx: bpmp_shmem@4e000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4e000 0x0 0x1000>; + }; + + cpu_bpmp_rx: bpmp_shmem@4f000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4f000 0x0 0x1000>; + }; + }; + + bpmp { + compatible = "nvidia,tegra186-bpmp"; + mboxes = <_top0 HSP_MBOX_ID(DB, HSP_DB_MASTER_BPMP)>; + shmem = <_bpmp_tx _bpmp_rx>; + #clock-cells = <1>; + #reset-cells = <1>; + status = "disabled"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , +, +, +; + interrupt-parent = <>; + }; +}; -- 2.9.0
Re: [PATCH V2 03/10] Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP
On 07/06/2016 07:42 PM, Alexandre Courbot wrote: On Tue, Jul 5, 2016 at 6:04 PM, Joseph Lo <jose...@nvidia.com> wrote: The BPMP is a specific processor in Tegra chip, which is designed for booting process handling and offloading the power management, clock management, and reset control tasks from the CPU. The binding document defines the resources that would be used by the BPMP firmware driver, which can create the interprocessor communication (IPC) between the CPU and BPMP. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - update the message that the BPMP is clock and reset control provider - add tegra186-clock.h and tegra186-reset.h header files - revise the description of the required properties --- .../bindings/firmware/nvidia,tegra186-bpmp.txt | 77 ++ include/dt-bindings/clock/tegra186-clock.h | 940 + include/dt-bindings/reset/tegra186-reset.h | 217 + 3 files changed, 1234 insertions(+) create mode 100644 Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt create mode 100644 include/dt-bindings/clock/tegra186-clock.h create mode 100644 include/dt-bindings/reset/tegra186-reset.h diff --git a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt new file mode 100644 index ..4d0b6eba56c5 --- /dev/null +++ b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt @@ -0,0 +1,77 @@ +NVIDIA Tegra Boot and Power Management Processor (BPMP) + +The BPMP is a specific processor in Tegra chip, which is designed for +booting process handling and offloading the power management, clock +management, and reset control tasks from the CPU. The binding document +defines the resources that would be used by the BPMP firmware driver, +which can create the interprocessor communication (IPC) between the CPU +and BPMP. + +Required properties: +- name : Should be bpmp +- compatible +Array of strings +One of: +- "nvidia,tegra186-bpmp" +- mboxes : The phandle of mailbox controller and the mailbox specifier. +- shmem : List of the phandle of the TX and RX shared memory area that + the IPC between CPU and BPMP is based on. +- #clock-cells : Should be 1. +- #reset-cells : Should be 1. + +This node is a mailbox consumer. See the following files for details of +the mailbox subsystem, and the specifiers implemented by the relevant +provider(s): + +- Documentation/devicetree/bindings/mailbox/mailbox.txt +- Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt + +This node is a clock and reset provider. See the following files for +general documentation of those features, and the specifiers implemented +by this node: + +- Documentation/devicetree/bindings/clock/clock-bindings.txt +- include/dt-bindings/clock/tegra186-clock.h +- Documentation/devicetree/bindings/reset/reset.txt +- include/dt-bindings/reset/tegra186-reset.h + +The shared memory bindings for BPMP +--- + +The shared memory area for the IPC TX and RX between CPU and BPMP are +predefined and work on top of sysram, which is an SRAM inside the chip. + +See "Documentation/devicetree/bindings/sram/sram.txt" for the bindings. + +Example: + +hsp_top0: hsp@03c0 { + ... + #mbox-cells = <1>; +}; + +sysram@3000 { + compatible = "nvidia,tegra186-sysram", "mmio-ram"; Shouldn't the second compatible be "mmio-sram"? If so, then you have the same typo in tegra186.dtsi as well. Good catch, will fix. Thanks, -Joseph
Re: [PATCH V2 03/10] Documentation: dt-bindings: firmware: tegra: add bindings of the BPMP
On 07/07/2016 01:03 AM, Stephen Warren wrote: On 07/05/2016 03:04 AM, Joseph Lo wrote: The BPMP is a specific processor in Tegra chip, which is designed for booting process handling and offloading the power management, clock management, and reset control tasks from the CPU. The binding document defines the resources that would be used by the BPMP firmware driver, which can create the interprocessor communication (IPC) between the CPU and BPMP. Acked-by: Stephen Warren <swar...@nvidia.com> Thanks, -Joseph
Re: [PATCH V2 01/10] Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox
On 07/07/2016 01:02 AM, Stephen Warren wrote: On 07/05/2016 03:04 AM, Joseph Lo wrote: Add DT binding for the Hardware Synchronization Primitives (HSP). The HSP is designed for the processors to share resources and communicate together. It provides a set of hardware synchronization primitives for interprocessor communication. So the interprocessor communication (IPC) protocols can use hardware synchronization primitive, when operating between two processors not in an SMP relationship. Acked-by: Stephen Warren <swar...@nvidia.com> Thanks, -Joseph -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V2 02/10] mailbox: tegra-hsp: Add HSP(Hardware Synchronization Primitives) driver
On 07/06/2016 08:23 PM, Alexandre Courbot wrote: On Wed, Jul 6, 2016 at 6:06 PM, Joseph Lo <jose...@nvidia.com> wrote: On 07/06/2016 03:05 PM, Alexandre Courbot wrote: On Tue, Jul 5, 2016 at 6:04 PM, Joseph Lo <jose...@nvidia.com> wrote: The Tegra HSP mailbox driver implements the signaling doorbell-based interprocessor communication (IPC) for remote processors currently. The HSP HW modules support some different features for that, which are shared mailboxes, shared semaphores, arbitrated semaphores, and doorbells. And there are multiple HSP HW instances on the chip. So the driver is extendable to support more features for different IPC requirement. The driver of remote processor can use it as a mailbox client and deal with the IPC protocol to synchronize the data communications. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - Update the driver to support the binding changes in V2 - it's extendable to support multiple HSP sub-modules on the same HSP HW block now. --- drivers/mailbox/Kconfig | 9 + drivers/mailbox/Makefile| 2 + drivers/mailbox/tegra-hsp.c | 418 3 files changed, 429 insertions(+) create mode 100644 drivers/mailbox/tegra-hsp.c diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 5305923752d2..fe584cb54720 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -114,6 +114,15 @@ config MAILBOX_TEST Test client to help with testing new Controller driver implementations. +config TEGRA_HSP_MBOX + bool "Tegra HSP(Hardware Synchronization Primitives) Driver" Space missing before the opening parenthesis (same in the patch title btw). Okay. + depends on ARCH_TEGRA_186_SOC + help + The Tegra HSP driver is used for the interprocessor communication + between different remote processors and host processors on Tegra186 + and later SoCs. Say Y here if you want to have this support. + If unsure say N. Since this option is selected automatically by ARCH_TEGRA_186_SOC, you should probably drop the last 2 sentences. Okay. + config XGENE_SLIMPRO_MBOX tristate "APM SoC X-Gene SLIMpro Mailbox Controller" depends on ARCH_XGENE diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 0be3e742bb7d..26d8f91c7fea 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -25,3 +25,5 @@ obj-$(CONFIG_TI_MESSAGE_MANAGER) += ti-msgmgr.o obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o + +obj-${CONFIG_TEGRA_HSP_MBOX} += tegra-hsp.o diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c new file mode 100644 index ..93c3ef58f29f --- /dev/null +++ b/drivers/mailbox/tegra-hsp.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include +#include + +#define HSP_INT_DIMENSIONING 0x380 +#define HSP_nSM_OFFSET 0 +#define HSP_nSS_OFFSET 4 +#define HSP_nAS_OFFSET 8 +#define HSP_nDB_OFFSET 12 +#define HSP_nSI_OFFSET 16 Would be nice to have comments to understand what SM, SS, AS, etc. stand for (Shared Mailboxes, Shared Semaphores, Arbitrated Semaphores but you need to look at the patch description to understand that). A top-of-file comment explaning the necessary concepts to read this code would do the trick. Yes, will fix that. +#define HSP_nINT_MASK 0xf + +#define HSP_DB_REG_TRIGGER 0x0 +#define HSP_DB_REG_ENABLE 0x4 +#define HSP_DB_REG_RAW 0x8 +#define HSP_DB_REG_PENDING 0xc + +#define HSP_DB_CCPLEX 1 +#define HSP_DB_BPMP3 Maybe turn this into enum and use that type for tegra_hsp_db_chan::db_id? Also have MAX_NUM_HSP_DB here, since it is related to these values? Okay. + +#define MAX_NUM_HSP_CHAN 32 +#define MAX_NUM_HSP_DB 7 + +#define hsp_db_offset(i, d) \ + (d->base + ((1 + (d->nr_sm >> 1) + d->nr_ss + d->nr_as) << 16) + \ + (i) * 0x100) + +struct tegra_hsp_db_chan { + int master_id; + int db_id; +}; + +struct tegra_hsp_mbox_chan { + int type; + union { + struct tegra_hsp_db_chan db_chan; + }; +}; + +struct tegra_hsp_mbox { + struct mbox_controller *mbox; + vo
Re: [PATCH V2 02/10] mailbox: tegra-hsp: Add HSP(Hardware Synchronization Primitives) driver
On 07/07/2016 12:50 AM, Stephen Warren wrote: On 07/06/2016 03:06 AM, Joseph Lo wrote: On 07/06/2016 03:05 PM, Alexandre Courbot wrote: On Tue, Jul 5, 2016 at 6:04 PM, Joseph Lo <jose...@nvidia.com> wrote: The Tegra HSP mailbox driver implements the signaling doorbell-based interprocessor communication (IPC) for remote processors currently. The HSP HW modules support some different features for that, which are shared mailboxes, shared semaphores, arbitrated semaphores, and doorbells. And there are multiple HSP HW instances on the chip. So the driver is extendable to support more features for different IPC requirement. The driver of remote processor can use it as a mailbox client and deal with the IPC protocol to synchronize the data communications. diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c +static irqreturn_t hsp_db_irq(int irq, void *p) +{ + struct tegra_hsp_mbox *hsp_mbox = p; + ulong val; + int master_id; + + val = (ulong)hsp_readl(hsp_mbox->db_base[HSP_DB_CCPLEX], + HSP_DB_REG_PENDING); + hsp_writel(hsp_mbox->db_base[HSP_DB_CCPLEX], HSP_DB_REG_PENDING, val); + + spin_lock(_mbox->lock); + for_each_set_bit(master_id, , MAX_NUM_HSP_CHAN) { + struct mbox_chan *chan; + struct tegra_hsp_mbox_chan *mchan; + int i; + + for (i = 0; i < MAX_NUM_HSP_CHAN; i++) { I wonder if this could not be optimized. You are doing a double loop on MAX_NUM_HSP_CHAN to look for an identical master_id. Since it seems like the same master_id cannot be used twice (considering that the inner loop only processes the first match), couldn't you just select the free channel in of_hsp_mbox_xlate() by doing >chans[master_id] (and returning an error if it is already used), then simply getting chan as _mbox->mbox->chans[master_id] instead of having the inner loop below? That would remove the need for the second loop. That was exactly what I did in the V1, which only supported one HSP sub-module per HSP HW block. So we can just use the master_id as the mbox channel ID. Meanwhile, the V2 is purposed to support multiple HSP sub-modules to be running on the same HSP HW block. The "ID" between different modules could be conflict. So I dropped the mechanism that used the master_id as the mbox channel ID. I haven't looked at the code in this patch since I'm mainly concerned about the DT bindings. However, I will say that nothing in the change to the mailbox specifier in DT should have required /any/ changes to the code, except to add a single check to validate that the "mailbox type" encoded into the top 16 bits of the mailbox ID were 0, and hence represented a doorbell rather than anything else. Any enhancements to support other mailbox types could have happened later, and I doubt would require anything dynamic even then. Yes, I only add the code for that change. Maybe some glue code for the extend-ability to support more HSP modules in the future. +static int tegra_hsp_db_init(struct tegra_hsp_mbox *hsp_mbox, +struct mbox_chan *mchan, int master_id) +{ + struct platform_device *pdev = to_platform_device(hsp_mbox->mbox->dev); + struct tegra_hsp_mbox_chan *hsp_mbox_chan; + int ret; + + if (!hsp_mbox->db_irq) { + int i; + + hsp_mbox->db_irq = platform_get_irq_byname(pdev, "doorbell"); Getting the IRQ sounds more like a job for probe() - I don't see the benefit of lazy-doing it? We only need the IRQ when the client is requesting the DB service. For other HSP sub-modules, they are using different IRQ. So I didn't do that at probe time. All resources provided by other devices/drivers must be acquired at probe time, since that's the only time it's possible to defer probe if the provider of the resource is not available. If you don't follow that rule, what happens is: 1) This driver probes. 2) Some other driver calls tegra_hsp_db_init(), and it fails since the provider of the IRQ is not yet available. This likely ends up returning something other than -EPROBE_DEFER since the HSP driver was found successfully (thus there is no deferred probe situation as far as the mailbox core is concerned), it's just that the mailbox channel lookup/init/... failed. 3) The other driver's probe() fails due to this, but since the error wasn't a probe deferral, the other driver's probe() is never retried. Agree, will fix this. Thanks, -Joseph
Re: [PATCH V2 05/10] firmware: tegra: add BPMP support
On 07/06/2016 07:39 PM, Alexandre Courbot wrote: Sorry, I will probably need to do several passes on this one to understand everything, but here is what I can say after a first look: On Tue, Jul 5, 2016 at 6:04 PM, Joseph Lo <jose...@nvidia.com> wrote: The Tegra BPMP (Boot and Power Management Processor) is designed for the booting process handling, offloading the power management tasks and some system control services from the CPU. It can be clock, DVFS, thermal/EDP, power gating operation and system suspend/resume handling. So the CPU and the drivers of these modules can base on the service that the BPMP firmware driver provided to signal the event for the specific PM action to BPMP and receive the status update from BPMP. Comparing to the ARM SCPI, the service provided by BPMP is message-based communication but not method-based. The BPMP firmware driver provides the send/receive service for the users, when the user concerns the response time. If the user needs to get the event or update from the firmware, it can request the MRQ service as well. The user needs to take care of the message format, which we call BPMP ABI. The BPMP ABI defines the message format for different modules or usages. For example, the clock operation needs an MRQ service code called MRQ_CLK with specific message format which includes different sub commands for various clock operations. This is the message format that BPMP can recognize. So the user needs two things to initiate IPC between BPMP. Get the service from the bpmp_ops structure and maintain the message format as the BPMP ABI defined. Based-on-the-work-by: Sivaram Nair <sivar...@nvidia.com> Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - None --- drivers/firmware/tegra/Kconfig | 12 + drivers/firmware/tegra/Makefile |1 + drivers/firmware/tegra/bpmp.c | 713 + include/soc/tegra/bpmp.h| 29 + include/soc/tegra/bpmp_abi.h| 1601 +++ 5 files changed, 2356 insertions(+) create mode 100644 drivers/firmware/tegra/bpmp.c create mode 100644 include/soc/tegra/bpmp.h create mode 100644 include/soc/tegra/bpmp_abi.h diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig index 1fa3e4e136a5..ff2730d5c468 100644 --- a/drivers/firmware/tegra/Kconfig +++ b/drivers/firmware/tegra/Kconfig @@ -10,4 +10,16 @@ config TEGRA_IVC keeps the content is synchronization between host CPU and remote processors. +config TEGRA_BPMP + bool "Tegra BPMP driver" + depends on ARCH_TEGRA && TEGRA_HSP_MBOX && TEGRA_IVC + help + BPMP (Boot and Power Management Processor) is designed to off-loading s/off-loading/off-load + the PM functions which include clock/DVFS/thermal/power from the CPU. + It needs HSP as the HW synchronization and notification module and + IVC module as the message communication protocol. + + This driver manages the IPC interface between host CPU and the + firmware running on BPMP. + endmenu diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile index 92e2153e8173..e34a2f79e1ad 100644 --- a/drivers/firmware/tegra/Makefile +++ b/drivers/firmware/tegra/Makefile @@ -1 +1,2 @@ +obj-$(CONFIG_TEGRA_BPMP) += bpmp.o obj-$(CONFIG_TEGRA_IVC)+= ivc.o diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c new file mode 100644 index ..24fda626610e --- /dev/null +++ b/drivers/firmware/tegra/bpmp.c @@ -0,0 +1,713 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#define BPMP_MSG_SZ128 +#define BPMP_MSG_DATA_SZ 120 + +#define __MRQ_ATTRS0xff00 +#define __MRQ_INDEX(id)((id) & ~__MRQ_ATTRS) + +#define DO_ACK BIT(0) +#define RING_DOORBELL BIT(1) + +struct tegra_bpmp_soc_data { + u32 ch_index; /* channel index */ + u32 thread_ch_index;/* thread channel index */ + u32 cpu_rx_ch_index;/* CPU Rx channel index */ + u32 nr_ch; /* number of total channels */ + u32 nr_thread_ch; /* number of thread channels */ + u32 ch_timeout; /* channel timeout */ + u32 thread_ch_timeout; /* thread channel timeout */ +}; With jus
Re: [PATCH V2 02/10] mailbox: tegra-hsp: Add HSP(Hardware Synchronization Primitives) driver
On 07/06/2016 03:05 PM, Alexandre Courbot wrote: On Tue, Jul 5, 2016 at 6:04 PM, Joseph Lo <jose...@nvidia.com> wrote: The Tegra HSP mailbox driver implements the signaling doorbell-based interprocessor communication (IPC) for remote processors currently. The HSP HW modules support some different features for that, which are shared mailboxes, shared semaphores, arbitrated semaphores, and doorbells. And there are multiple HSP HW instances on the chip. So the driver is extendable to support more features for different IPC requirement. The driver of remote processor can use it as a mailbox client and deal with the IPC protocol to synchronize the data communications. Signed-off-by: Joseph Lo <jose...@nvidia.com> --- Changes in V2: - Update the driver to support the binding changes in V2 - it's extendable to support multiple HSP sub-modules on the same HSP HW block now. --- drivers/mailbox/Kconfig | 9 + drivers/mailbox/Makefile| 2 + drivers/mailbox/tegra-hsp.c | 418 3 files changed, 429 insertions(+) create mode 100644 drivers/mailbox/tegra-hsp.c diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 5305923752d2..fe584cb54720 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -114,6 +114,15 @@ config MAILBOX_TEST Test client to help with testing new Controller driver implementations. +config TEGRA_HSP_MBOX + bool "Tegra HSP(Hardware Synchronization Primitives) Driver" Space missing before the opening parenthesis (same in the patch title btw). Okay. + depends on ARCH_TEGRA_186_SOC + help + The Tegra HSP driver is used for the interprocessor communication + between different remote processors and host processors on Tegra186 + and later SoCs. Say Y here if you want to have this support. + If unsure say N. Since this option is selected automatically by ARCH_TEGRA_186_SOC, you should probably drop the last 2 sentences. Okay. + config XGENE_SLIMPRO_MBOX tristate "APM SoC X-Gene SLIMpro Mailbox Controller" depends on ARCH_XGENE diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 0be3e742bb7d..26d8f91c7fea 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -25,3 +25,5 @@ obj-$(CONFIG_TI_MESSAGE_MANAGER) += ti-msgmgr.o obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o + +obj-${CONFIG_TEGRA_HSP_MBOX} += tegra-hsp.o diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c new file mode 100644 index ..93c3ef58f29f --- /dev/null +++ b/drivers/mailbox/tegra-hsp.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include +#include + +#define HSP_INT_DIMENSIONING 0x380 +#define HSP_nSM_OFFSET 0 +#define HSP_nSS_OFFSET 4 +#define HSP_nAS_OFFSET 8 +#define HSP_nDB_OFFSET 12 +#define HSP_nSI_OFFSET 16 Would be nice to have comments to understand what SM, SS, AS, etc. stand for (Shared Mailboxes, Shared Semaphores, Arbitrated Semaphores but you need to look at the patch description to understand that). A top-of-file comment explaning the necessary concepts to read this code would do the trick. Yes, will fix that. +#define HSP_nINT_MASK 0xf + +#define HSP_DB_REG_TRIGGER 0x0 +#define HSP_DB_REG_ENABLE 0x4 +#define HSP_DB_REG_RAW 0x8 +#define HSP_DB_REG_PENDING 0xc + +#define HSP_DB_CCPLEX 1 +#define HSP_DB_BPMP3 Maybe turn this into enum and use that type for tegra_hsp_db_chan::db_id? Also have MAX_NUM_HSP_DB here, since it is related to these values? Okay. + +#define MAX_NUM_HSP_CHAN 32 +#define MAX_NUM_HSP_DB 7 + +#define hsp_db_offset(i, d) \ + (d->base + ((1 + (d->nr_sm >> 1) + d->nr_ss + d->nr_as) << 16) + \ + (i) * 0x100) + +struct tegra_hsp_db_chan { + int master_id; + int db_id; +}; + +struct tegra_hsp_mbox_chan { + int type; + union { + struct tegra_hsp_db_chan db_chan; + }; +}; + +struct tegra_hsp_mbox { + struct mbox_controller *mbox; + void __iomem *base; + void __iomem *db_base[MAX_NUM_HSP_DB]; + int db_irq; + int nr_sm; + int nr_as; + int nr_ss; + int nr_db; +
Re: [PATCH 01/10] Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox
On 06/29/2016 11:28 PM, Stephen Warren wrote: On 06/28/2016 11:56 PM, Joseph Lo wrote: On 06/29/2016 03:08 AM, Stephen Warren wrote: On 06/28/2016 03:15 AM, Joseph Lo wrote: On 06/27/2016 11:55 PM, Stephen Warren wrote: On 06/27/2016 03:02 AM, Joseph Lo wrote: snip. Currently the usage of HSP HW in the downstream kernel is something like the model below. remote_processor_A-\ remote_processor_B--->hsp@1000 (doorbell func) <-> host CPU remote_processor_C-/ remote_processor_D -> hsp@2000 (shared mailbox) <-> CPU remote_processor_E -> hsp@3000 (shared mailbox) <-> CPU I am thinking if we can just add the appropriate compatible strings for it to replace "nvidia,tegra186-hsp". e.g. "nvidia,tegra186-hsp-doorbell" and "nvidia,tegra186-hsp-sharedmailbox". So the driver can probe and initialize correctly depend on the compatible property. How do you think about it? Is this the same as the (b) you mentioned above? Yes, that would be (b) above. However, please do note (a): I expect that splitting things up will turn out to be a mistake, as it has for other HW modules in the past. I would far rather see a single hsp node in DT, since there is a single HSP block in HW. Sure that block has multiple sub-functions. However, there is common logic that affects all of those sub-functions and binds everything into a single HW module. If you represent the HW module using multiple different DT nodes, it will be hard to correctly represent that common logic. Conversely, I see no real advantage to splitting up the DT node. I strongly believe we should have a single "hsp" node in DT. We have 6 HSP block in HW. FYI. Yes, we have 6 /instances/ of the overall HSP block. Those should each have their own node, since they're entirely separate modules, all instances of the same configurable IP block. Above, I was talking about the sub-blocks within each HSP instance, which should all be represented into a single node per instance, for a total of 6 DT nodes overall. Yes. So, one thing still concerns me is that the binding and driver still can't work with multiple HSP sub-modules per HSP block. It only supports one HSP module per HSP block right how. Although, I said it matches the model that we are using in the downstream kernel. But I still concern if we need to enable and work with multiple HSP modules per HSP block at sometime in future, then the binding and driver need lots of change to achieve that. And the binding is not back-ward compatible obviously. So I want to revise it again. #mbox-cells: should be 2. The mobxes property in the client node should contain the phandle of the HSP block, HSP sub-module ID and the specifier of the module. Ex. hsp_top0: hsp@1000 { ... #mbox-cells = <2>; }; clientA { mboxes = <_top0 HSP_DOORBELL DB_MASTER_XXX>; }; clientB { ... mboxes = <_top0 HSP_SHARED_MAILBOX SM_MASTER_XXX>; }; Stephen, How do you think of this change? Thanks, -Joseph
Re: [PATCH 01/10] Documentation: dt-bindings: mailbox: tegra: Add binding for HSP mailbox
On 07/01/2016 12:02 AM, Stephen Warren wrote: On 06/30/2016 03:25 AM, Joseph Lo wrote: On 06/29/2016 11:28 PM, Stephen Warren wrote: On 06/28/2016 11:56 PM, Joseph Lo wrote: On 06/29/2016 03:08 AM, Stephen Warren wrote: On 06/28/2016 03:15 AM, Joseph Lo wrote: On 06/27/2016 11:55 PM, Stephen Warren wrote: On 06/27/2016 03:02 AM, Joseph Lo wrote: snip. Currently the usage of HSP HW in the downstream kernel is something like the model below. remote_processor_A-\ remote_processor_B--->hsp@1000 (doorbell func) <-> host CPU remote_processor_C-/ remote_processor_D -> hsp@2000 (shared mailbox) <-> CPU remote_processor_E -> hsp@3000 (shared mailbox) <-> CPU I am thinking if we can just add the appropriate compatible strings for it to replace "nvidia,tegra186-hsp". e.g. "nvidia,tegra186-hsp-doorbell" and "nvidia,tegra186-hsp-sharedmailbox". So the driver can probe and initialize correctly depend on the compatible property. How do you think about it? Is this the same as the (b) you mentioned above? Yes, that would be (b) above. However, please do note (a): I expect that splitting things up will turn out to be a mistake, as it has for other HW modules in the past. I would far rather see a single hsp node in DT, since there is a single HSP block in HW. Sure that block has multiple sub-functions. However, there is common logic that affects all of those sub-functions and binds everything into a single HW module. If you represent the HW module using multiple different DT nodes, it will be hard to correctly represent that common logic. Conversely, I see no real advantage to splitting up the DT node. I strongly believe we should have a single "hsp" node in DT. We have 6 HSP block in HW. FYI. Yes, we have 6 /instances/ of the overall HSP block. Those should each have their own node, since they're entirely separate modules, all instances of the same configurable IP block. Above, I was talking about the sub-blocks within each HSP instance, which should all be represented into a single node per instance, for a total of 6 DT nodes overall. Yes. So, one thing still concerns me is that the binding and driver still can't work with multiple HSP sub-modules per HSP block. It only supports one HSP module per HSP block right how. The driver can be enhanced without affecting the DT binding, providing the binding is reasonably designed, as I believe it is. I believe the existing binding can work fine for multiple HSP sub-modules, or at least be extended in a backwards-compatible way. Aside from the mailbox cells issue you mention below, is there any other reason you believe the binding can't be extended in a backwards-compatible way? Interrupts are already accessed solely by name, so we can add more later without issue. The node can become a provider for any other resource type besides mailboxes in a backwards-compatible way without issue. Because the mbox client has no idea to know which hsb sub-module to bind with. However, the way you suggested below should solve my concern and back-ward compatible indeed. Although, I said it matches the model that we are using in the downstream kernel. But I still concern if we need to enable and work with multiple HSP modules per HSP block at sometime in future, then the binding and driver need lots of change to achieve that. And the binding is not back-ward compatible obviously. So I want to revise it again. #mbox-cells: should be 2. The mobxes property in the client node should contain the phandle of the HSP block, HSP sub-module ID and the specifier of the module. Ex. hsp_top0: hsp@1000 { ... #mbox-cells = <2>; }; clientA { mboxes = <_top0 HSP_DOORBELL DB_MASTER_XXX>; }; clientB { ... mboxes = <_top0 HSP_SHARED_MAILBOX SM_MASTER_XXX>; }; Stephen, How do you think of this change? Well, we could do that. Or, since we won't have 2^32 instances of doorbells, we could also have #mbox-cells=<1> as we do now, and encode mailbox IDs as "(type << 16) | id" where TEGRA186_HSP_MAILBOX_TYPE_DB is 0. That would be backwards-compatible with no change to the binding. I think either way is fine. I have a slight preference for keeping #mbox-cells=<1> to avoid revising the U-Boot driver code I wrote, but I can deal with changing it if I have to. Ah, yes. I think the U-Boot doesn't need to deal with the multiple HSP sub-module supporting issue, and the binding I purposed was more complicate for that. The idea with "#mbox-cells=<1>" and "mboxes=<(type<<16)|id>" is fine with me. I will revise the hsp driver for this. Thanks, -Joseph
Re: [PATCH 2/5] cpufreq: star/stop cpufreq timers on cpu hotplug
On Wed, 2013-01-30 at 12:52 +0800, Viresh Kumar wrote: > Hi Fabio, > > Sorry for waking up very late :) > > The reason why i am starting this thread again is due to problem > reported by Joseph, > with latest linux-next/master branch (which contains few big patches > from me :) ): > After Viresh point me out what patch may cause the issue that I met below, I also try to just revert this patch on linux-next. Then everything that may trigger to disable_nonboot_cpus or hotplug back to normal. So just reverting this patch also fix the issues I saw. FYI. Thanks, Joseph > Reboot is giving following to him: > > * Will now halt > [ 193.756068] Disabling non-boot CPUs... > [ 193.760088] BUG: scheduling while atomic: halt/780/0x0002 > [ 193.765845] Modules linked in: brcmfmac brcmutil > [ 193.770613] [] (unwind_backtrace+0x0/0xf8) from [] > (__schedule_bug+0x44/0x5c) > [ 193.779548] [] (__schedule_bug+0x44/0x5c) from [] > (__schedule+0x688/0x6ec) > [ 193.788206] [] (__schedule+0x688/0x6ec) from [] > (schedule_preempt_disabled+0x24/0x34) > [ 193.797811] [] (schedule_preempt_disabled+0x24/0x34) from > [] (__mutex_lock_slowpath+0x170/0x34c) > [ 193.808367] [] (__mutex_lock_slowpath+0x170/0x34c) from > [] (mutex_lock+0xc/0x24) > [ 193.817554] [] (mutex_lock+0xc/0x24) from [] > (unregister_cpu_notifier+0xc/0x24) > [ 193.826640] [] (unregister_cpu_notifier+0xc/0x24) from > [] (cpufreq_governor_dbs+0x118/0x614) > [ 193.836866] [] (cpufreq_governor_dbs+0x118/0x614) from > [] (__cpufreq_governor+0x58/0xc0) > [ 193.846737] [] (__cpufreq_governor+0x58/0xc0) from > [] (__cpufreq_remove_dev.clone.7+0x58/0x320) > [ 193.857207] [] (__cpufreq_remove_dev.clone.7+0x58/0x320) > from [] (cpufreq_cpu_callback+0x8c/0x9c) > [ 193.867850] [] (cpufreq_cpu_callback+0x8c/0x9c) from > [] (notifier_call_chain+0x44/0x84) > [ 193.877623] [] (notifier_call_chain+0x44/0x84) from > [] (__cpu_notify+0x2c/0x48) > [ 193.886704] [] (__cpu_notify+0x2c/0x48) from [] > (_cpu_down+0xb0/0x23c) > [ 193.895004] [] (_cpu_down+0xb0/0x23c) from [] > (disable_nonboot_cpus+0x68/0x104) > [ 193.904089] [] (disable_nonboot_cpus+0x68/0x104) from > [] (kernel_power_off+0x24/0x48) > [ 193.913688] [] (kernel_power_off+0x24/0x48) from > [] (sys_reboot+0x104/0x1e0) > [ 193.922517] [] (sys_reboot+0x104/0x1e0) from [] > (ret_fast_syscall+0x0/0x30) > > > And the crash log show this patch of yours somewhere :) > > First question: Is this patch still required? Because following patch from me > is > sending a STOP/START to governors on cpu hot-[un]plug ? > > commit dbcb63407c095af73f3464767e00902cdee55e8b > Author: Viresh Kumar > Date: Sat Jan 12 05:14:39 2013 + > > cpufreq: Notify governors when cpus are hot-[un]plugged > > > For me, the answer is NO. > > Over that, i tried these patches on ARM bigLITTLE TC2 (3 A7's and 2 A15's) > and > my system wasn't booting at all for ondemand governor. Reverting your patch > does > fix the issue: > > [2.613573] arm_big_little: bL_cpufreq_init: Initialized, cpu: 0, cluster 0 > [2.635436] arm_big_little: bL_cpufreq_init: Initialized, cpu: 2, cluster 1 > [ 23.650184] INFO: rcu_sched self-detected stall on CPU { 0} > (t=2100 jiffies g=4294967088 c=4294967087 q=10) > [ 23.679664] Backtrace for cpu 0 (current): > [ 23.680239] INFO: rcu_sched detected stalls on CPUs/tasks: { 0} > (detected by 2, t=2103 jiffies, g=4294967088, c=4294967087, q=10) > [ 23.726839] [] (unwind_backtrace+0x0/0xf8) from > [] (smp_send_all_cpu_backtrace+0x60/0xcc) > [ 23.756545] [] (smp_send_all_cpu_backtrace+0x60/0xcc) > from [] (rcu_pending+0x2c8/0x63c) > [ 23.785731] [] (rcu_pending+0x2c8/0x63c) from > [] (rcu_check_callbacks+0x7c/0x148) > [ 23.813358] [] (rcu_check_callbacks+0x7c/0x148) from > [] (update_process_times+0x38/0x68) > [ 23.842808] [] (update_process_times+0x38/0x68) from > [] (tick_sched_handle+0x48/0x54) > [ 23.871472] [] (tick_sched_handle+0x48/0x54) from > [] (tick_sched_timer+0x44/0x74) > [ 23.899098] [] (tick_sched_timer+0x44/0x74) from > [] (__run_hrtimer+0x84/0x1b4) > [ 23.925940] [] (__run_hrtimer+0x84/0x1b4) from > [] (hrtimer_interrupt+0x108/0x2d4) > [ 23.953563] [] (hrtimer_interrupt+0x108/0x2d4) from > [] (arch_timer_handler_virt+0x30/0x38) > [ 23.983530] [] (arch_timer_handler_virt+0x30/0x38) from > [] (handle_percpu_devid_irq+0x74/0x110) > [ 24.014799] [] (handle_percpu_devid_irq+0x74/0x110) from > [] (generic_handle_irq+0x20/0x30) > [ 24.044765] [] (generic_handle_irq+0x20/0x30) from > [] (handle_IRQ+0x38/0x94) > [ 24.071085] [] (handle_IRQ+0x38/0x94) from [] > (gic_handle_irq+0x28/0x5c) > [ 24.096362] [] (gic_handle_irq+0x28/0x5c) from > [] (__irq_svc+0x40/0x50) > [ 24.121374] Exception stack(0xef047ec0 to 0xef047f08) > [ 24.136492] 7ec0: c0591780 c0591798 c0591780 > c05d5d60 c0593280 > [ 24.160986] 7ee0: c0552c98 c02b1df4 ef046000 c059179c > ef047f08 c03b5f84 c0043698 > [ 24.185477] 7f00: a113 > [
Re: CPU hotplug hang due to "swap: make each swap partition have one address_space"
On Mon, 2013-02-04 at 10:36 +0800, Shaohua Li wrote: > On Fri, Feb 01, 2013 at 10:02:33PM -0700, Stephen Warren wrote: > > Shaohua, > > > > In next-20130128, commit 174f064 "swap: make each swap partition have > > one address_space" (from the mm/akpm tree) appears causes a hang/RCU > > stall for me when hot-unplugging a CPU. > > does this one work for you? > http://marc.info/?l=linux-mm=135929599505624=2 > Or try a more recent linux-next. The patch is in akpm's tree. > Hi Shaohua, The patch you pointed out did fix the issue. Just verified on Tegra device. Thanks, Joseph -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 06/21] ARM: tegra: call cpu_do_idle from C code
On Wed, 2013-04-24 at 00:30 +0800, Arnd Bergmann wrote: > When building a kernel for multiple CPU architecture levels, > cpu_do_idle() is a macro for an indirect function call, which > cannot be called from assembly code as Tegra does. > > Adding a trivial C wrapper for this function lets us build > a tegra kernel with ARMv6 support enabled. > > Signed-off-by: Arnd Bergmann > Cc: Joseph Lo > Cc: Stephen Warren > --- Hi Arnd, Thanks for fixing. Tested-by: Joseph Lo Joseph -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 07/21] ARM: tegra: unify tegra_idle_device definitions
On Wed, 2013-04-24 at 06:04 +0800, Daniel Lezcano wrote: > On 04/23/2013 08:57 PM, Arnd Bergmann wrote: > > On Tuesday 23 April 2013, Daniel Lezcano wrote: > >> the patch sounds good but I think the side effect of the consolidation > >> patchset [1] fixed that. > >> > >> You can find these fixes in Rafael's tree: > >> > >> https://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-nextid=4c637b2175a0dc65d533494225525c6c82d73293 > >> > >> https://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-nextid=e158f9da6974cc11bfab2246a9b10021af0e0d8a > >> > >> https://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-nextid=c5106c9dea9a6022ab84c6cb1d4a0b19fc5af0e2 > >> > >> https://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-nextid=f040c26ffaa5e56f2bca427c719c9601a02e70e5 > >> > >> [1] http://www.spinics.net/lists/arm-kernel/msg239811.html > >> > > > > Ah. Is that not in linux-next? I created the patch today based on the latest > > linux-next from today (Tuesday). > > Ah, ok. Actually the patches were taken by Rafael right today. So it is > possible the changes were not reflected in linux-next yet. > Hi Arnd and Daniel, Thanks for taking care this.:) Joseph -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/4] clk: tegra114: table driven PMC clock init
On Tue, 2013-09-03 at 21:31 +0800, Peter De Schrijver wrote: > This patch converts the Tegra114 audio clock registration to be table driven > like the periph clocks. s/audio/PMC/ :) > > Signed-off-by: Peter De Schrijver > --- > drivers/clk/tegra/clk-tegra114.c | 58 > +++--- > 1 files changed, 23 insertions(+), 35 deletions(-) > [snip] -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 07/32] arm: delete __cpuinit/__CPUINIT usage from all ARM users
Adding linux-tegra in Cc. On Tue, 2013-06-25 at 03:30 +0800, Paul Gortmaker wrote: > The __cpuinit type of throwaway sections might have made sense > some time ago when RAM was more constrained, but now the savings > do not offset the cost and complications. For example, the fix in > commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") > is a good example of the nasty type of bugs that can be created > with improper use of the various __init prefixes. > > After a discussion on LKML[1] it was decided that cpuinit should go > the way of devinit and be phased out. Once all the users are gone, > we can then finally remove the macros themselves from linux/init.h. > > Note that some harmless section mismatch warnings may result, since > notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) > and are flagged as __cpuinit -- so if we remove the __cpuinit from > the arch specific callers, we will also get section mismatch warnings. > As an intermediate step, we intend to turn the linux/init.h cpuinit > related content into no-ops as early as possible, since that will get > rid of these warnings. In any case, they are temporary and harmless. > > This removes all the ARM uses of the __cpuinit macros from C code, > and all __CPUINIT from assembly code. It also had two ".previous" > section statements that were paired off against __CPUINIT > (aka .section ".cpuinit.text") that also get removed here. > > [1] https://lkml.org/lkml/2013/5/20/589 > > Cc: Russell King > Cc: Will Deacon > Cc: linux-arm-ker...@lists.infradead.org > Signed-off-by: Paul Gortmaker > --- > > [This commit is part of the __cpuinit removal work. If you don't see > any problems with it, then you don't have to do anything ; it will be > submitted with all the rest of the __cpuinit removal work. On the > other hand, if you want to carry this patch in with your other pending > changes so as to handle conflicts with other pending work yourself, then > that is fine too, as the commits can largely be treated independently. > For more information, please see: https://lkml.org/lkml/2013/6/20/513 ] > Hi Paul, I just tested this series on Tegra platform. It looks broken CPU hotplug function for Tegra at least. The CPU can't plug-in after unplugging. And the system resume function also not working when "enable_nonboot_cpus". Both of the issue cause system hang up. Are we missing something for __cpuinit removal work? Thanks, Joseph -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC 04/10] memory: Add Tegra124 memory controller support
Hi Thierry, On 06/27/2014 04:49 AM, Thierry Reding wrote: [snip] + +#define MC_INTSTATUS 0x000 +#define MC_INT_DECERR_MTS (1 << 16) +#define MC_INT_SECERR_SEC (1 << 13) +#define MC_INT_DECERR_VPR (1 << 12) +#define MC_INT_INVALID_APB_ASID_UPDATE (1 << 11) +#define MC_INT_INVALID_SMMU_PAGE (1 << 10) +#define MC_INT_ARBITRATION_EMEM (1 << 9) +#define MC_INT_SECURITY_VIOLATION (1 << 8) +#define MC_INT_DECERR_EMEM (1 << 6) +#define MC_INTMASK 0x004 +#define MC_ERR_STATUS 0x08 +#define MC_ERR_ADR 0x0c + [snip] + +#define SMMU_PDE_ATTR (SMMU_PDE_READABLE | SMMU_PDE_WRITABLE | \ +SMMU_PDE_NONSECURE) +#define SMMU_PTE_ATTR (SMMU_PTE_READABLE | SMMU_PTE_WRITABLE | \ +SMMU_PTE_NONSECURE) + +#define SMMU_PDE_VACANT(n) (((n) << 10) | SMMU_PDE_ATTR) +#define SMMU_PTE_VACANT(n) (((n) << 12) | SMMU_PTE_ATTR) There is an ISR to catch the invalid SMMU translation. Do you want to modify the identity mapping with read/write attribute of the unused SMMU pages? This can make sure we capture the invalid SMMU translation. And helps for driver to capture issues when using SMMU. -joseph +static irqreturn_t tegra124_mc_irq(int irq, void *data) +{ + struct tegra_mc *mc = data; + u32 value, status, mask; + + /* mask all interrupts to avoid flooding */ + mask = mc_readl(mc, MC_INTMASK); + mc_writel(mc, 0, MC_INTMASK); + + status = mc_readl(mc, MC_INTSTATUS); + mc_writel(mc, status, MC_INTSTATUS); + + dev_dbg(mc->dev, "INTSTATUS: %08x\n", status); + + if (status & MC_INT_DECERR_MTS) + dev_dbg(mc->dev, " DECERR_MTS\n"); + + if (status & MC_INT_SECERR_SEC) + dev_dbg(mc->dev, " SECERR_SEC\n"); + + if (status & MC_INT_DECERR_VPR) + dev_dbg(mc->dev, " DECERR_VPR\n"); + + if (status & MC_INT_INVALID_APB_ASID_UPDATE) + dev_dbg(mc->dev, " INVALID_APB_ASID_UPDATE\n"); + + if (status & MC_INT_INVALID_SMMU_PAGE) + dev_dbg(mc->dev, " INVALID_SMMU_PAGE\n"); + + if (status & MC_INT_ARBITRATION_EMEM) + dev_dbg(mc->dev, " ARBITRATION_EMEM\n"); + + if (status & MC_INT_SECURITY_VIOLATION) + dev_dbg(mc->dev, " SECURITY_VIOLATION\n"); + + if (status & MC_INT_DECERR_EMEM) + dev_dbg(mc->dev, " DECERR_EMEM\n"); + + value = mc_readl(mc, MC_ERR_STATUS); + + dev_dbg(mc->dev, "ERR_STATUS: %08x\n", value); + dev_dbg(mc->dev, " type: %x\n", (value >> 28) & 0x7); + dev_dbg(mc->dev, " protection: %x\n", (value >> 25) & 0x7); + dev_dbg(mc->dev, " adr_hi: %x\n", (value >> 20) & 0x3); + dev_dbg(mc->dev, " swap: %x\n", (value >> 18) & 0x1); + dev_dbg(mc->dev, " security: %x\n", (value >> 17) & 0x1); + dev_dbg(mc->dev, " r/w: %x\n", (value >> 16) & 0x1); + dev_dbg(mc->dev, " adr1: %x\n", (value >> 12) & 0x7); + dev_dbg(mc->dev, " client: %x\n", value & 0x7f); + + value = mc_readl(mc, MC_ERR_ADR); + dev_dbg(mc->dev, "ERR_ADR: %08x\n", value); + + mc_writel(mc, mask, MC_INTMASK); + + return IRQ_HANDLED; +} + -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] cpuidle: coupled: fix the potensial race condition and deadlock
Considering the chance that two CPU come into cpuidle_enter_state_coupled at very close time. The 1st CPU increases the waiting count and the 2nd CPU do the same thing right away. The 2nd CPU found the 1st CPU already in waiting then prepare to poke it. Before the 2nd CPU to poke 1st CPU, the 1st found the waiting count already same with cpu_online count. So the 1st won't go into waiting loop and the 2nd CPU didn't poke it yet. The 1st CPU will go into ready loop directly. Then the 2nd CPU set up the couple_cpuidle_mask for 1st CPU and poke it. But the 1st CPU already lost the chance to handle the poke and clear the couple_cpuidle_mask. Now whole MPcore are alredy to be coupled. The MPcore will go into the power saving idle mode. Because the poke was be implemented as a "smp_call_function_single", it's a software intrrupt of "IPI_SINGLE_FUNC". If the power saving idle mode of the platform can't retain the software interrupt of power saving idle mode, (e.g. Tegra's powerd-down idle mode will shut off cpu power that include the power of GIC) the software interrupt will got lost. When the CPU resumed from the power saving idle mode and the system still keep idle, it will go into idle mode again immediately. Because the "smp_call_function_single" not allow the same function be called for the same cpu twice, or it will got a lock. So the "couple_cpuidle_mask" can't be cleared by 1st CPU, the 2nd CPU also can't poke it again. Then the deadlock happens here. The fix here used different wake up mechanism. Because there are already two loops and a gloable variable "ready_waiting_counts" to sync the status of MPcore to coupled state, the "coupled_cpuidle_mask" was not really necessary. Just waking up the CPU from waiting and checking if the CPU need resched at outside world to take the CPU out of idle are enough. And this fix didn't modify the original behavior of coupled cpuidle framework. It should still compitable with the origianal. The cpuidle driver that already applies coupled cpuidle not need to change as well. Cc: Colin Cross Signed-off-by: Joseph Lo --- Please check the detail sequence about how race condition and deadlock be happened below: It could be reproduced on Tegra20 and Tegra30. (Suppose the last two cpu came into coupled_cpuidle_state at very close time) CPU_0 CPU_1 cpuidle_enter_state_coupled cpuidle_enter_state_coupled 1.increase waiting count 1. increase waiting count same time frame --- 2.before went into waiting loop, check the waiting count first 2.1 the waiting count was same with online count 2.2 so it won't go into waiting loop 2.in the procedure to prepare to send an "smp_call_function_single" to wake up CPU_0 next time frame --- 3.before go into ready loop 3.1 it will enable_irq 3.2 check if there is any IPI 3.3 if yes, clear the coupled_mask 3.4 then disable_irq 3. trigger the IPI to CPU_0 3.1 set up the coupled_mask for CPU_0 3.2 sent IPI to CPU_0 4. the IPI_SINGLE_FUNC been triggered from CPU_1 to CPU_0 and the coupled_mask of CPU_0 been set up 4.1 but the CPU_0 miss the IPI and the chance to clear coupled_mask next time frame --- 5. MPCores went into ready loop and been coupled 6. go into power saving idle mode (For Tegra, it's means the vdd_cpu rail be shut off. The GIC be powered off and the SW_INT(IPI) couldn't be retained.) 7. After the resume of power saving idle mode, the coupled_mask of CPU_0 not been cleared. 8. return to kernel If the system still idle, it will come back to idle immediately. CPU_0 CPU_1 cpuidle_enter_state_coupled cpuidle_enter_state_coupled 1. set itself to waiting 2. go into waiting loop 3. check the coupled_mask been set or not 3.1 enable_irq 3.2 waiting for the coupled_mask be cleared 1. found CPU_0 in waiting 2. prepare an IPI to poke CPU_0 2.1 check the coupled_mask of CPU_0 2.2 because it had been set 2.3 so it didn't trigger and "smp_call_function_single" to CPU_0 again 3. then go into ready loop
Re: [PATCH v3 0/9] Migrate Tegra to common clock framework
On Fri, 2013-01-04 at 17:40 +0800, Prashant Gaikwad wrote: > This patchset does following: > 1. Decompose single tegra clock structure into multiple clocks. > 2. Try to use standard clock types supported by common clock framework. > 3. Use dynamic initialization. > 4. Move all clock code to drivers/clk/tegra from mach-tegra. > 5. Add device tree support for Tegra20 and Tegra30 clocks. > 6. Remove all legacy clock code from mach-tegra. > > Tested on Tegra30 (Cardhu) and Tegra20 (Ventana). > > Changes from v2: > Removed APB MISC node. > Fixed some issues reported by Joseph Lo. > Added function to read chip id revision register. > > Changes from v1: > Rebased on linux-next for 20121224. > > Prashant Gaikwad (8): > ARM: tegra: Add function to read chipid > clk: tegra: Add tegra specific clocks > arm: tegra: Move tegra_cpu_car.h to linux/clk/tegra.h > ARM: Tegra: Define Tegra30 CAR binding > clk: tegra: add clock support for tegra20 > clk: tegra: add clock support for tegra30 > arm: tegra: Migrate to new clock code > arm: tegra: Remove legacy clock code > > Stephen Warren (1): > ARM: tegra: Define Tegra20 CAR binding > Good job, Prashant. :-) This series : Tested-by: Joseph Lo -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/7] ARM: dt: tegra20: Add clock information
On Fri, 2013-01-04 at 17:46 +0800, Prashant Gaikwad wrote: > Add clock information to device nodes. > > Signed-off-by: Prashant Gaikwad > --- > Tested on Ventana (Tegra20) and Cardhu (Tegra30). > This series depends on ccf-rework patch series. > --- This series : Tested-by: Joseph Lo -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH V5 11/18] clk: tegra210: Add support for Tegra210 clocks
On 7/16/19 2:35 PM, Sowjanya Komatineni wrote: On 7/15/19 10:37 PM, Dmitry Osipenko wrote: В Mon, 15 Jul 2019 21:37:09 -0700 Sowjanya Komatineni пишет: On 7/15/19 8:50 PM, Dmitry Osipenko wrote: 16.07.2019 6:00, Sowjanya Komatineni пишет: On 7/15/19 5:35 PM, Sowjanya Komatineni wrote: On 7/14/19 2:41 PM, Dmitry Osipenko wrote: 13.07.2019 8:54, Sowjanya Komatineni пишет: On 6/29/19 8:10 AM, Dmitry Osipenko wrote: 28.06.2019 5:12, Sowjanya Komatineni пишет: This patch adds system suspend and resume support for Tegra210 clocks. All the CAR controller settings are lost on suspend when core power goes off. This patch has implementation for saving and restoring all the PLLs and clocks context during system suspend and resume to have the clocks back to same state for normal operation. Acked-by: Thierry Reding Signed-off-by: Sowjanya Komatineni --- drivers/clk/tegra/clk-tegra210.c | 115 ++- drivers/clk/tegra/clk.c | 14 + drivers/clk/tegra/clk.h | 1 + 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 1c08c53482a5..1b839544e086 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -9,10 +9,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -20,6 +22,7 @@ #include #include "clk.h" +#include "clk-dfll.h" #include "clk-id.h" /* @@ -225,6 +228,7 @@ #define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8 #define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac +#define CPU_SOFTRST_CTRL 0x380 #define LVL2_CLK_GATE_OVRA 0xf8 #define LVL2_CLK_GATE_OVRC 0x3a0 @@ -2820,6 +2824,7 @@ static int tegra210_enable_pllu(void) struct tegra_clk_pll_freq_table *fentry; struct tegra_clk_pll pllu; u32 reg; + int ret; for (fentry = pll_u_freq_table; fentry->input_rate; fentry++) { if (fentry->input_rate == pll_ref_freq) @@ -2847,10 +2852,10 @@ static int tegra210_enable_pllu(void) fence_udelay(1, clk_base); reg |= PLL_ENABLE; writel(reg, clk_base + PLLU_BASE); + fence_udelay(1, clk_base); - readl_relaxed_poll_timeout_atomic(clk_base + PLLU_BASE, reg, - reg & PLL_BASE_LOCK, 2, 1000); - if (!(reg & PLL_BASE_LOCK)) { + ret = tegra210_wait_for_mask(, PLLU_BASE, PLL_BASE_LOCK); + if (ret) { pr_err("Timed out waiting for PLL_U to lock\n"); return -ETIMEDOUT; } @@ -3283,6 +3288,103 @@ static void tegra210_disable_cpu_clock(u32 cpu) } #ifdef CONFIG_PM_SLEEP +static u32 cpu_softrst_ctx[3]; +static struct platform_device *dfll_pdev; +#define car_readl(_base, _off) readl_relaxed(clk_base + (_base) + ((_off) * 4)) +#define car_writel(_val, _base, _off) \ + writel_relaxed(_val, clk_base + (_base) + ((_off) * 4)) + +static int tegra210_clk_suspend(void) +{ + unsigned int i; + struct device_node *node; + + tegra_cclkg_burst_policy_save_context(); + + if (!dfll_pdev) { + node = of_find_compatible_node(NULL, NULL, + "nvidia,tegra210-dfll"); + if (node) + dfll_pdev = of_find_device_by_node(node); + + of_node_put(node); + if (!dfll_pdev) + pr_err("dfll node not found. no suspend for dfll\n"); + } + + if (dfll_pdev) + tegra_dfll_suspend(dfll_pdev); + + /* Enable PLLP_OUT_CPU after dfll suspend */ + tegra_clk_set_pllp_out_cpu(true); + + tegra_sclk_cclklp_burst_policy_save_context(); + + clk_save_context(); + + for (i = 0; i < ARRAY_SIZE(cpu_softrst_ctx); i++) + cpu_softrst_ctx[i] = car_readl(CPU_SOFTRST_CTRL, i); + + return 0; +} + +static void tegra210_clk_resume(void) +{ + unsigned int i; + struct clk_hw *parent; + struct clk *clk; + + /* + * clk_restore_context restores clocks as per the clock tree. + * + * dfllCPU_out is first in the clock tree to get restored and it + * involves programming DFLL controller along with restoring CPUG + * clock burst policy. + * + * DFLL programming needs dfll_ref and dfll_soc peripheral clocks + * to be restores which are part ofthe peripheral clocks. ^ white-space Please use spellchecker to avoid typos. + * So, peripheral clocks restore should happen prior to dfll clock + * restore. + */ + + tegra_clk_osc_resume(clk_base); + for (i = 0; i < ARRAY_SIZE(cpu_softrst_ctx); i++) + car_writel(cpu_softrst_ctx[i], CPU_SOFTRST_CTRL, i); + + /* restore all plls and peripheral clocks */ + tegra210_init_pllu(); + clk_restore_context(); + + fence_udelay(5, clk_base); + + /* resume SCLK and CPULP clocks */ +
Re: [PATCH 1/6] dt-bindings: timer: add Tegra210 timer
On 1/25/19 8:01 PM, Jon Hunter wrote: On 25/01/2019 03:23, Joseph Lo wrote: Hi Jon, Thanks for reviewing. On 1/24/19 6:30 PM, Jon Hunter wrote: On 07/01/2019 03:28, Joseph Lo wrote: The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock (TMR10-TMR13). Each TMR can be programmed to generate one-shot periodic, or watchdog interrupts. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: devicet...@vger.kernel.org Signed-off-by: Joseph Lo --- .../bindings/timer/nvidia,tegra210-timer.txt | 25 +++ 1 file changed, 25 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt new file mode 100644 index ..ba511220a669 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt @@ -0,0 +1,25 @@ +NVIDIA Tegra210 timer + +The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit +timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived +from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock +(TMR10-TMR13). Each TMR can be programmed to generate one-shot, periodic, +or watchdog interrupts. + +Required properties: +- compatible : "nvidia,tegra210-timer". +- reg : Specifies base physical address and size of the registers. +- interrupts : A list of 4 interrupts; one per each of TMR10 through TMR13. [snip] And notice that only TMR10-TMR13 are running at the oscillator clock (clk_m). With the Tegra210 timer driver, we introduce in this series, which only replace the clock event device function that was originally owned by the arch timer (armv8 timer) and it also running at the oscillator clock. The sched_timer still owns by the arch timer. So the timer resolution will be the same. That's why we choose TMR10-TMR13 as the timer for Tegra210. That maybe fine, but DT should describe the hardware and so I don't see why we would not list all the interrupts. We can still only use TMR10-13 in the driver. Okay, will list all the interrupts for each timer channel. Thanks, Joseph
[PATCH V2 2/6] clocksource: tegra: add Tegra210 timer driver
Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Based on the work of Antti P Miettinen Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo --- v2: * add error clean-up code --- drivers/clocksource/Kconfig | 3 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-tegra210.c | 268 +++ include/linux/cpuhotplug.h | 1 + 4 files changed, 273 insertions(+) create mode 100644 drivers/clocksource/timer-tegra210.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..e6e3e64b6320 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -135,6 +135,9 @@ config TEGRA_TIMER help Enables support for the Tegra driver. +config TEGRA210_TIMER + def_bool ARCH_TEGRA_210_SOC + config VT8500_TIMER bool "VT8500 timer driver" if COMPILE_TEST depends on HAS_IOMEM diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index cdd210ff89ea..95de59c8a47b 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_SUN4I_TIMER) += timer-sun4i.o obj-$(CONFIG_SUN5I_HSTIMER)+= timer-sun5i.o obj-$(CONFIG_MESON6_TIMER) += timer-meson6.o obj-$(CONFIG_TEGRA_TIMER) += timer-tegra20.o +obj-$(CONFIG_TEGRA210_TIMER) += timer-tegra210.o obj-$(CONFIG_VT8500_TIMER) += timer-vt8500.o obj-$(CONFIG_NSPIRE_TIMER) += timer-zevio.o obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o diff --git a/drivers/clocksource/timer-tegra210.c b/drivers/clocksource/timer-tegra210.c new file mode 100644 index ..477b164e540b --- /dev/null +++ b/drivers/clocksource/timer-tegra210.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static u32 tegra210_timer_freq; +static void __iomem *tegra210_timer_reg_base; +static u32 usec_config; + +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) +#define TIMERUS_CNTR_1US 0x10 +#define TIMERUS_USEC_CFG 0x14 + +#define TIMER10_OFFSET 0x90 +#define TIMER10_IRQ_IDX10 + +#define TIMER_FOR_CPU(cpu) (TIMER10_OFFSET + (cpu) * 8) +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) + +struct tegra210_clockevent { + struct clock_event_device evt; + char name[20]; + void __iomem *reg_base; +}; +#define to_tegra_cevt(p) (container_of(p, struct tegra210_clockevent, evt)) + +static struct tegra210_clockevent __percpu *tegra210_evt; + +static int tegra210_timer_set_next_event(unsigned long cycles, +struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + tevt->reg_base + TIMER_PTV); + + return 0; +} + +static inline void timer_shutdown(struct tegra210_clockevent *tevt) +{ + writel(0, tevt->reg_base + TIMER_PTV); +} + +static int tegra210_timer_shutdown(struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + timer_shutdown(tevt); + + return 0; +} + +static int tegra210_timer_set_periodic(struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + writel(TIMER_PTV_EN | TIMER_PTV_PER | ((tegra210_timer_freq / HZ) - 1), + tevt->reg_base + TIMER_PTV); + + return 0; +} + +static irqreturn_t tegra210_timer_isr(int irq, void *dev_id) +{ + struct tegra210_clockevent *tevt; + + tevt = dev_id; + writel(TIMER_PCR_INTR_CLR, tevt->reg_base + TIMER_PCR); + tevt->evt.event_handler(>evt); + + return IRQ_HANDLED; +} + +static int tegra210_timer_setup(unsigned int cpu) +{ + struct tegra210_clockevent *tevt = per_cpu_ptr(tegra210_evt, cpu); + + irq_force_affinity(tevt->evt.irq, cpumask_of(cpu)); + enable_irq(tevt->evt.irq); + + clockevents_config_and_register(>evt, tegra210_timer_freq, + 1, /* min */ + 0x1fff); /* 29 bits */ + + return 0; +} + +static int tegra210_timer_stop(unsigned int cpu) +{ + struct
[PATCH V2 1/6] dt-bindings: timer: add Tegra210 timer
The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock (TMR10-TMR13). Each TMR can be programmed to generate one-shot periodic, or watchdog interrupts. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: devicet...@vger.kernel.org Signed-off-by: Joseph Lo Reviewed-by: Rob Herring --- v2: * list all the interrupts that are supported by tegra210 timers block * add RB tag from Rob. --- .../bindings/timer/nvidia,tegra210-timer.txt | 36 +++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt new file mode 100644 index ..032cda96fe0d --- /dev/null +++ b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt @@ -0,0 +1,36 @@ +NVIDIA Tegra210 timer + +The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit +timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived +from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock +(TMR10-TMR13). Each TMR can be programmed to generate one-shot, periodic, +or watchdog interrupts. + +Required properties: +- compatible : "nvidia,tegra210-timer". +- reg : Specifies base physical address and size of the registers. +- interrupts : A list of 14 interrupts; one per each timer channels 0 through + 13. +- clocks : Must contain one entry, for the module clock. + See ../clocks/clock-bindings.txt for details. + +timer@60005000 { + compatible = "nvidia,tegra210-timer"; + reg = <0x0 0x60005000 0x0 0x400>; + interrupts = , +, +, +, +, +, +, +, +, +, +, +, +, +; + clocks = <_car TEGRA210_CLK_TIMER>; + clock-names = "timer"; +}; -- 2.20.1
Re: [PATCH V2 2/6] clocksource: tegra: add Tegra210 timer driver
Hi Daniel, Thanks for your review. On 1/28/19 9:00 PM, Daniel Lezcano wrote: On 28/01/2019 10:18, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Based on the work of Antti P Miettinen Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo --- v2: * add error clean-up code --- drivers/clocksource/Kconfig | 3 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-tegra210.c | 268 +++ include/linux/cpuhotplug.h | 1 + 4 files changed, 273 insertions(+) create mode 100644 drivers/clocksource/timer-tegra210.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..e6e3e64b6320 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -135,6 +135,9 @@ config TEGRA_TIMER help Enables support for the Tegra driver. +config TEGRA210_TIMER + def_bool ARCH_TEGRA_210_SOC + Please make the option consistent with the option below (VT8500_TIMER or similar). Okay, will check. config VT8500_TIMER bool "VT8500 timer driver" if COMPILE_TEST depends on HAS_IOMEM diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index cdd210ff89ea..95de59c8a47b 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_SUN4I_TIMER) += timer-sun4i.o obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o obj-$(CONFIG_MESON6_TIMER)+= timer-meson6.o obj-$(CONFIG_TEGRA_TIMER) += timer-tegra20.o +obj-$(CONFIG_TEGRA210_TIMER) += timer-tegra210.o obj-$(CONFIG_VT8500_TIMER)+= timer-vt8500.o obj-$(CONFIG_NSPIRE_TIMER)+= timer-zevio.o obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o diff --git a/drivers/clocksource/timer-tegra210.c b/drivers/clocksource/timer-tegra210.c new file mode 100644 index ..477b164e540b --- /dev/null +++ b/drivers/clocksource/timer-tegra210.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static u32 tegra210_timer_freq; +static void __iomem *tegra210_timer_reg_base; +static u32 usec_config; + +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) +#define TIMERUS_CNTR_1US 0x10 +#define TIMERUS_USEC_CFG 0x14 + +#define TIMER10_OFFSET 0x90 +#define TIMER10_IRQ_IDX10 + +#define TIMER_FOR_CPU(cpu) (TIMER10_OFFSET + (cpu) * 8) +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) + +struct tegra210_clockevent { + struct clock_event_device evt; + char name[20]; + void __iomem *reg_base; +}; +#define to_tegra_cevt(p) (container_of(p, struct tegra210_clockevent, evt)) + +static struct tegra210_clockevent __percpu *tegra210_evt; + +static int tegra210_timer_set_next_event(unsigned long cycles, +struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + tevt->reg_base + TIMER_PTV); + + return 0; +} + +static inline void timer_shutdown(struct tegra210_clockevent *tevt) +{ + writel(0, tevt->reg_base + TIMER_PTV); +} + +static int tegra210_timer_shutdown(struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + timer_shutdown(tevt); + + return 0; +} + +static int tegra210_timer_set_periodic(struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + writel(TIMER_PTV_EN | TIMER_PTV_PER | ((tegra210_timer_freq / HZ) - 1), + tevt->reg_base + TIMER_PTV); + + return 0; +} + +static irqreturn_t tegra210_timer_isr(int irq, void *dev_id) +{ + struct tegra210_clockevent *tevt; + + tevt = dev_id; + writel(TIMER_PCR_INTR_CLR, tevt->reg_base + TIMER_PCR); + tevt->evt.event_handler(>evt); + + return IRQ_HANDLED; +} + +static int tegra210_timer_setup(unsigned int cpu) +{ + struct tegra210_clockevent *tevt = per_cpu_ptr(tegra210_evt, cpu); + + irq_force_affinity(tevt->evt.irq, cpumask_of(cpu)); + enable_irq(tevt->evt.irq); + + clockevents_config_a
Re: [PATCH V2 2/6] clocksource: tegra: add Tegra210 timer driver
On 1/28/19 11:09 PM, Thierry Reding wrote: On Mon, Jan 28, 2019 at 05:18:11PM +0800, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Based on the work of Antti P Miettinen Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo --- v2: * add error clean-up code --- drivers/clocksource/Kconfig | 3 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-tegra210.c | 268 +++ include/linux/cpuhotplug.h | 1 + 4 files changed, 273 insertions(+) create mode 100644 drivers/clocksource/timer-tegra210.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..e6e3e64b6320 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -135,6 +135,9 @@ config TEGRA_TIMER help Enables support for the Tegra driver. +config TEGRA210_TIMER + def_bool ARCH_TEGRA_210_SOC + config VT8500_TIMER bool "VT8500 timer driver" if COMPILE_TEST depends on HAS_IOMEM diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index cdd210ff89ea..95de59c8a47b 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_SUN4I_TIMER) += timer-sun4i.o obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o obj-$(CONFIG_MESON6_TIMER)+= timer-meson6.o obj-$(CONFIG_TEGRA_TIMER) += timer-tegra20.o +obj-$(CONFIG_TEGRA210_TIMER) += timer-tegra210.o obj-$(CONFIG_VT8500_TIMER)+= timer-vt8500.o obj-$(CONFIG_NSPIRE_TIMER)+= timer-zevio.o obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o diff --git a/drivers/clocksource/timer-tegra210.c b/drivers/clocksource/timer-tegra210.c new file mode 100644 index ..477b164e540b --- /dev/null +++ b/drivers/clocksource/timer-tegra210.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static u32 tegra210_timer_freq; +static void __iomem *tegra210_timer_reg_base; +static u32 usec_config; + +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) +#define TIMERUS_CNTR_1US 0x10 +#define TIMERUS_USEC_CFG 0x14 + +#define TIMER10_OFFSET 0x90 +#define TIMER10_IRQ_IDX10 + +#define TIMER_FOR_CPU(cpu) (TIMER10_OFFSET + (cpu) * 8) +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) + +struct tegra210_clockevent { + struct clock_event_device evt; + char name[20]; + void __iomem *reg_base; +}; +#define to_tegra_cevt(p) (container_of(p, struct tegra210_clockevent, evt)) + +static struct tegra210_clockevent __percpu *tegra210_evt; + +static int tegra210_timer_set_next_event(unsigned long cycles, +struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + tevt->reg_base + TIMER_PTV); + + return 0; +} + +static inline void timer_shutdown(struct tegra210_clockevent *tevt) +{ + writel(0, tevt->reg_base + TIMER_PTV); +} + +static int tegra210_timer_shutdown(struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + timer_shutdown(tevt); + + return 0; +} + +static int tegra210_timer_set_periodic(struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + writel(TIMER_PTV_EN | TIMER_PTV_PER | ((tegra210_timer_freq / HZ) - 1), + tevt->reg_base + TIMER_PTV); + + return 0; +} + +static irqreturn_t tegra210_timer_isr(int irq, void *dev_id) +{ + struct tegra210_clockevent *tevt; + + tevt = dev_id; + writel(TIMER_PCR_INTR_CLR, tevt->reg_base + TIMER_PCR); + tevt->evt.event_handler(>evt); + + return IRQ_HANDLED; +} Up to here this is a duplicate of timer-tegra20.c. And a lot of tegra210_timer_init() is the same as tegra20_timer_init() as well. Can't we unify the two drivers instead? I still prefer to remove the timer-tegra20 driver, because it didn't been used for Tegra 32 bit chips for quite a long time. So currently it just compiles OK, I also doubt the functionality still can achieve the same what
[PATCH V3 2/6] clocksource: tegra: add Tegra210 timer driver
Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Based on the work of Antti P Miettinen Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo --- v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 8 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-tegra210.c | 246 +++ include/linux/cpuhotplug.h | 1 + 4 files changed, 256 insertions(+) create mode 100644 drivers/clocksource/timer-tegra210.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..059b1b3f2adb 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -135,6 +135,14 @@ config TEGRA_TIMER help Enables support for the Tegra driver. +config TEGRA210_TIMER + bool "Tegra210 timer driver" + default y if ARCH_TEGRA_210_SOC + depends on ARCH_TEGRA_210_SOC + select TIMER_OF + help + Enable support for the Tegra210 driver. + config VT8500_TIMER bool "VT8500 timer driver" if COMPILE_TEST depends on HAS_IOMEM diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index cdd210ff89ea..95de59c8a47b 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_SUN4I_TIMER) += timer-sun4i.o obj-$(CONFIG_SUN5I_HSTIMER)+= timer-sun5i.o obj-$(CONFIG_MESON6_TIMER) += timer-meson6.o obj-$(CONFIG_TEGRA_TIMER) += timer-tegra20.o +obj-$(CONFIG_TEGRA210_TIMER) += timer-tegra210.o obj-$(CONFIG_VT8500_TIMER) += timer-vt8500.o obj-$(CONFIG_NSPIRE_TIMER) += timer-zevio.o obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o diff --git a/drivers/clocksource/timer-tegra210.c b/drivers/clocksource/timer-tegra210.c new file mode 100644 index ..7bc751c7da99 --- /dev/null +++ b/drivers/clocksource/timer-tegra210.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "timer-of.h" + +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) +#define TIMERUS_CNTR_1US 0x10 +#define TIMERUS_USEC_CFG 0x14 + +#define TIMER10_OFFSET 0x90 +#define TIMER10_IRQ_IDX10 + +#define TIMER_FOR_CPU(cpu) (TIMER10_OFFSET + (cpu) * 8) +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) +#define get_cpu_timer_reg_base(evt)\ +({ \ + struct timer_of *to = to_timer_of(evt); \ + timer_of_base(to) + TIMER_FOR_CPU(smp_processor_id()); \ +}) + +static u32 usec_config; + +static int tegra210_timer_set_next_event(unsigned long cycles, +struct clock_event_device *evt) +{ + void __iomem *reg_base = get_cpu_timer_reg_base(evt); + + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + reg_base + TIMER_PTV); + + return 0; +} + +static int tegra210_timer_shutdown(struct clock_event_device *evt) +{ + void __iomem *reg_base = get_cpu_timer_reg_base(evt); + + writel(0, reg_base + TIMER_PTV); + + return 0; +} + +static int tegra210_timer_set_periodic(struct clock_event_device *evt) +{ + void __iomem *reg_base = get_cpu_timer_reg_base(evt); + + writel(TIMER_PTV_EN | TIMER_PTV_PER | + ((timer_of_rate(to_timer_of(evt)) / HZ) - 1), + reg_base + TIMER_PTV); + + return 0; +} + +static irqreturn_t tegra210_timer_isr(int irq, void *dev_id) +{ + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + void __iomem *reg_base = get_cpu_timer_reg_base(evt); + + writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static DEFINE_PER_CPU(struct timer_of, tegra_to) = { + .flags = TIMER_OF_CLOCK | TIMER_OF_BASE, + .clkevt = { + .name = "tegra_timer", + .rating = 460, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = tegra210_timer_set_next_event, + .set_state_shutdown = tegra210_timer_shutdown, + .se
[PATCH V3 1/6] dt-bindings: timer: add Tegra210 timer
The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock (TMR10-TMR13). Each TMR can be programmed to generate one-shot periodic, or watchdog interrupts. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: devicet...@vger.kernel.org Signed-off-by: Joseph Lo Reviewed-by: Rob Herring --- v3: * no change v2: * list all the interrupts that are supported by tegra210 timers block * add RB tag from Rob. --- .../bindings/timer/nvidia,tegra210-timer.txt | 36 +++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt new file mode 100644 index ..032cda96fe0d --- /dev/null +++ b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt @@ -0,0 +1,36 @@ +NVIDIA Tegra210 timer + +The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit +timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived +from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock +(TMR10-TMR13). Each TMR can be programmed to generate one-shot, periodic, +or watchdog interrupts. + +Required properties: +- compatible : "nvidia,tegra210-timer". +- reg : Specifies base physical address and size of the registers. +- interrupts : A list of 14 interrupts; one per each timer channels 0 through + 13. +- clocks : Must contain one entry, for the module clock. + See ../clocks/clock-bindings.txt for details. + +timer@60005000 { + compatible = "nvidia,tegra210-timer"; + reg = <0x0 0x60005000 0x0 0x400>; + interrupts = , +, +, +, +, +, +, +, +, +, +, +, +, +; + clocks = <_car TEGRA210_CLK_TIMER>; + clock-names = "timer"; +}; -- 2.20.1
Re: [PATCH V2 2/6] clocksource: tegra: add Tegra210 timer driver
On 1/29/19 6:29 PM, Thierry Reding wrote: On Tue, Jan 29, 2019 at 10:41:55AM +0200, Peter De Schrijver wrote: On Mon, Jan 28, 2019 at 04:09:08PM +0100, Thierry Reding wrote: ... Up to here this is a duplicate of timer-tegra20.c. And a lot of tegra210_timer_init() is the same as tegra20_timer_init() as well. Can't we unify the two drivers instead? The power cycle restrictions of the architected timer, do they not apply to chips earlier than Tegra210 either? So don't we need all of these additional features on the timer-tegra20.c driver as well? If so that No. Chips prior to Tegra114 do not have an arch timer and the arch timer does work correctly on Cortex-A15 so Tegra114 and Tegra124 can use it. It's broken on Cortex-A57 though, so we can't use it as a wakeup source on Tegra210. If chips prior to Tegra114 don't have an architected timer, then we can't remove the timer-tegra20 driver, because we still need it on Tegra20 and Tegra30, right? For Tegra20/30, it's Cortext-A9 with TWD timer. (arch/arm/kernel/smp_twd.c) Originally, I thought the functionality of timer-tegra20 would be fully replaced by TWD timer driver. But from the log in the kernelci test farm[1][2], it looks to me the timer-tegra20 driver still works as clocksource driver for Tegra20/30. I cannot confirm if the clock event device has been replaced by TWD timer in the log. It could be replaced in the background. And by looking into the driver, it should be. Compare to the log of Tegra124[3], it has been fully replaced by arch timer driver. Note, "timer_us" is the name of Tegra20 timer. [1]: https://storage.kernelci.org/mainline/master/v5.0-rc4-1-g4aa9fc2a435a/arm/tegra_defconfig/lab-baylibre-seattle/boot-tegra30-beaver.html [2]: https://storage.kernelci.org/stable-rc/linux-4.9.y/v4.9.153-43-g6674590d15d2/arm/tegra_defconfig/lab-baylibre-seattle/boot-tegra20-iris-512.html [3]: https://storage.kernelci.org/lsk/linux-linaro-lsk-v4.9/lsk-v4.9-18.09-1494-gde3059d32f93/arm/tegra_defconfig/lab-collabora/boot-tegra124-nyan-big.html Thanks, Joseph
[PATCH V4 1/7] dt-bindings: timer: add Tegra210 timer
The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock (TMR10-TMR13). Each TMR can be programmed to generate one-shot periodic, or watchdog interrupts. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: devicet...@vger.kernel.org Signed-off-by: Joseph Lo Reviewed-by: Rob Herring --- V4: * no change v3: * no change v2: * list all the interrupts that are supported by tegra210 timers block * add RB tag from Rob. --- .../bindings/timer/nvidia,tegra210-timer.txt | 36 +++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt new file mode 100644 index ..032cda96fe0d --- /dev/null +++ b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt @@ -0,0 +1,36 @@ +NVIDIA Tegra210 timer + +The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit +timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived +from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock +(TMR10-TMR13). Each TMR can be programmed to generate one-shot, periodic, +or watchdog interrupts. + +Required properties: +- compatible : "nvidia,tegra210-timer". +- reg : Specifies base physical address and size of the registers. +- interrupts : A list of 14 interrupts; one per each timer channels 0 through + 13. +- clocks : Must contain one entry, for the module clock. + See ../clocks/clock-bindings.txt for details. + +timer@60005000 { + compatible = "nvidia,tegra210-timer"; + reg = <0x0 0x60005000 0x0 0x400>; + interrupts = , +, +, +, +, +, +, +, +, +, +, +, +, +; + clocks = <_car TEGRA210_CLK_TIMER>; + clock-names = "timer"; +}; -- 2.20.1
[PATCH V4 2/7] clocksource: tegra: add Tegra210 timer support
Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo --- v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 2 +- drivers/clocksource/timer-tegra20.c | 369 include/linux/cpuhotplug.h | 1 + 3 files changed, 272 insertions(+), 100 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..6af78534a285 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,7 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM + select TIMER_OF help Enables support for the Tegra driver. diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 4293943f4e2b..96a809341c9b 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -15,21 +15,24 @@ * */ -#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include -#include #include #include -#include -#include +#include +#include +#include + +#include "timer-of.h" +#ifdef CONFIG_ARM #include +#endif #define RTC_SECONDS0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -43,70 +46,147 @@ #define TIMER2_BASE 0x8 #define TIMER3_BASE 0x50 #define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - +#define TIMER10_BASE 0x90 + +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) + +#ifdef CONFIG_ARM +#define TIMER_BASE TIMER3_BASE +#else +#define TIMER_BASE TIMER10_BASE +#endif +#define TIMER10_IRQ_IDX10 +#define TIMER_FOR_CPU(cpu) (TIMER_BASE + (cpu) * 8) +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) + +static u32 usec_config; static void __iomem *timer_reg_base; +#ifdef CONFIG_ARM static void __iomem *rtc_base; - static struct timespec64 persistent_ts; static u64 persistent_ms, last_persistent_ms; - static struct delay_timer tegra_delay_timer; - -#define timer_writel(value, reg) \ - writel_relaxed(value, timer_reg_base + (reg)) -#define timer_readl(reg) \ - readl_relaxed(timer_reg_base + (reg)) +#endif static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - u32 reg; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); - reg = 0x8000 | ((cycles > 1) ? (cycles-1) : 0); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + reg_base + TIMER_PTV); return 0; } -static inline void timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_shutdown(struct clock_event_device *evt) { - timer_writel(0, TIMER3_BASE + TIMER_PTV); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(0, reg_base + TIMER_PTV); + + return 0; } -static int tegra_timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_set_periodic(struct clock_event_device *evt) { - timer_shutdown(evt); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PTV_EN | TIMER_PTV_PER | + ((timer_of_rate(to_timer_of(evt)) / HZ) - 1), + reg_base + TIMER_PTV); + return 0; } -static int tegra_timer_set_periodic(struct clock_event_device *evt) +static irqreturn_t tegra_timer_isr(int irq, void *dev_id) { - u32 reg = 0xC000 | ((100 / HZ) - 1); + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_ARM64 +static DEFINE_PER_CPU(struct timer_of, tegra_to) = { + .flags = TIMER_OF_CLOCK | TIMER_OF_BASE, + + .clkevt = { + .name = "tegra_timer", + .rating = 460, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = tegra_timer_set_next_eve
Re: [PATCH 1/6] dt-bindings: timer: add Tegra210 timer
Hi Jon, Thanks for reviewing. On 1/24/19 6:30 PM, Jon Hunter wrote: On 07/01/2019 03:28, Joseph Lo wrote: The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock (TMR10-TMR13). Each TMR can be programmed to generate one-shot periodic, or watchdog interrupts. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: devicet...@vger.kernel.org Signed-off-by: Joseph Lo --- .../bindings/timer/nvidia,tegra210-timer.txt | 25 +++ 1 file changed, 25 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt new file mode 100644 index ..ba511220a669 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt @@ -0,0 +1,25 @@ +NVIDIA Tegra210 timer + +The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit +timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived +from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock +(TMR10-TMR13). Each TMR can be programmed to generate one-shot, periodic, +or watchdog interrupts. + +Required properties: +- compatible : "nvidia,tegra210-timer". +- reg : Specifies base physical address and size of the registers. +- interrupts : A list of 4 interrupts; one per each of TMR10 through TMR13. Why do we only add the interrupts for TMR10 - TMR13? What about the others? The others (TMR0-TMR9) are occupied for other usages. TMR5 is occupied for the watchdog timer in the upstream kernel. And others (still in TMR0-TMR9) are occupied for different usages in our downstream kernel. And notice that only TMR10-TMR13 are running at the oscillator clock (clk_m). With the Tegra210 timer driver, we introduce in this series, which only replace the clock event device function that was originally owned by the arch timer (armv8 timer) and it also running at the oscillator clock. The sched_timer still owns by the arch timer. So the timer resolution will be the same. That's why we choose TMR10-TMR13 as the timer for Tegra210. Thanks, Joseph
Re: [PATCH 2/6] clocksource: tegra: add Tegra210 timer driver
On 1/24/19 7:09 PM, Jon Hunter wrote: On 07/01/2019 03:28, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Based on the work of Antti P Miettinen Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo --- drivers/clocksource/Kconfig | 3 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-tegra210.c | 240 +++ include/linux/cpuhotplug.h | 1 + 4 files changed, 245 insertions(+) create mode 100644 drivers/clocksource/timer-tegra210.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..e6e3e64b6320 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -135,6 +135,9 @@ config TEGRA_TIMER help Enables support for the Tegra driver. +config TEGRA210_TIMER + def_bool ARCH_TEGRA_210_SOC + config VT8500_TIMER bool "VT8500 timer driver" if COMPILE_TEST depends on HAS_IOMEM diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index cdd210ff89ea..95de59c8a47b 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_SUN4I_TIMER) += timer-sun4i.o obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o obj-$(CONFIG_MESON6_TIMER)+= timer-meson6.o obj-$(CONFIG_TEGRA_TIMER) += timer-tegra20.o +obj-$(CONFIG_TEGRA210_TIMER) += timer-tegra210.o obj-$(CONFIG_VT8500_TIMER)+= timer-vt8500.o obj-$(CONFIG_NSPIRE_TIMER)+= timer-zevio.o obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o diff --git a/drivers/clocksource/timer-tegra210.c b/drivers/clocksource/timer-tegra210.c new file mode 100644 index ..d88c127d3b3b --- /dev/null +++ b/drivers/clocksource/timer-tegra210.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static u32 tegra210_timer_freq; +static void __iomem *tegra210_timer_reg_base; +static u32 usec_config; + +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) +#define TIMERUS_CNTR_1US 0x10 +#define TIMERUS_USEC_CFG 0x14 + +#define TIMER10_OFFSET 0x90 + +#define TIMER_FOR_CPU(cpu) (TIMER10_OFFSET + (cpu) * 8) + +struct tegra210_clockevent { + struct clock_event_device evt; + char name[20]; + void __iomem *reg_base; +}; +#define to_tegra_cevt(p) (container_of(p, struct tegra210_clockevent, evt)) + +static struct tegra210_clockevent __percpu *tegra210_evt; + +static int tegra210_timer_set_next_event(unsigned long cycles, +struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + tevt->reg_base + TIMER_PTV); + + return 0; +} + +static inline void timer_shutdown(struct tegra210_clockevent *tevt) +{ + writel(0, tevt->reg_base + TIMER_PTV); +} + +static int tegra210_timer_shutdown(struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + timer_shutdown(tevt); + + return 0; +} + +static int tegra210_timer_set_periodic(struct clock_event_device *evt) +{ + struct tegra210_clockevent *tevt; + + tevt = to_tegra_cevt(evt); + writel(TIMER_PTV_EN | TIMER_PTV_PER | ((tegra210_timer_freq / HZ) - 1), + tevt->reg_base + TIMER_PTV); + + return 0; +} + +static irqreturn_t tegra210_timer_isr(int irq, void *dev_id) +{ + struct tegra210_clockevent *tevt; + + tevt = dev_id; + writel(TIMER_PCR_INTR_CLR, tevt->reg_base + TIMER_PCR); + tevt->evt.event_handler(>evt); + + return IRQ_HANDLED; +} + +static int tegra210_timer_setup(unsigned int cpu) +{ + struct tegra210_clockevent *tevt = per_cpu_ptr(tegra210_evt, cpu); + + irq_force_affinity(tevt->evt.irq, cpumask_of(cpu)); + enable_irq(tevt->evt.irq); + + clockevents_config_and_register(>evt, tegra210_timer_freq, + 1, /* min */ + 0x1fff); /* 29 bits */ + + return 0; +} + +static int tegra210_timer_stop(unsigned int cpu) +{ + struct tegra210_clockevent *tevt = per_cp
Re: [PATCH V6 2/7] clocksource: tegra: add Tegra210 timer support
Hi Daniel & Thomas, Do we have the chance to get this patch merged for K5.1? Thanks, Joseph On 2/2/19 12:16 AM, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding Acked-by: Jon Hunter --- v6: * refine the timer defines * add ack tag from Jon. v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 2 +- drivers/clocksource/timer-tegra20.c | 371 include/linux/cpuhotplug.h | 1 + 3 files changed, 270 insertions(+), 104 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..6af78534a285 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,7 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM + select TIMER_OF help Enables support for the Tegra driver. diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 4293943f4e2b..f66edd63d7f4 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -15,21 +15,24 @@ * */ -#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include -#include #include #include -#include -#include +#include +#include +#include + +#include "timer-of.h" +#ifdef CONFIG_ARM #include +#endif #define RTC_SECONDS0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -39,74 +42,145 @@ #define TIMERUS_USEC_CFG 0x14 #define TIMERUS_CNTR_FREEZE 0x4c -#define TIMER1_BASE 0x0 -#define TIMER2_BASE 0x8 -#define TIMER3_BASE 0x50 -#define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) + +#ifdef CONFIG_ARM +#define TIMER_CPU0 0x50 /* TIMER3 */ +#else +#define TIMER_CPU0 0x90 /* TIMER10 */ +#define TIMER10_IRQ_IDX10 +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) +#endif +#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8) + +static u32 usec_config; static void __iomem *timer_reg_base; +#ifdef CONFIG_ARM static void __iomem *rtc_base; - static struct timespec64 persistent_ts; static u64 persistent_ms, last_persistent_ms; - static struct delay_timer tegra_delay_timer; - -#define timer_writel(value, reg) \ - writel_relaxed(value, timer_reg_base + (reg)) -#define timer_readl(reg) \ - readl_relaxed(timer_reg_base + (reg)) +#endif static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - u32 reg; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); - reg = 0x8000 | ((cycles > 1) ? (cycles-1) : 0); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + reg_base + TIMER_PTV); return 0; } -static inline void timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_shutdown(struct clock_event_device *evt) { - timer_writel(0, TIMER3_BASE + TIMER_PTV); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(0, reg_base + TIMER_PTV); + + return 0; } -static int tegra_timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_set_periodic(struct clock_event_device *evt) { - timer_shutdown(evt); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PTV_EN | TIMER_PTV_PER | + ((timer_of_rate(to_timer_of(evt)) / HZ) - 1), + reg_base + TIMER_PTV); + return 0; } -static int tegra_timer_set_periodic(struct clock_event_device *evt) +static irqreturn_t tegra_timer_isr(int irq, void *dev_id) { - u32 reg = 0xC000 | ((100 / HZ) - 1); + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR);
[PATCH] clocksource/drivers/tegra: rework for compensation of suspend time
Since the clocksource framework has the support for suspend time compensation. Re-work the driver to use that, so we can reduce the duplicate code. Suggested-by: Daniel Lezcano Signed-off-by: Joseph Lo --- drivers/clocksource/timer-tegra20.c | 63 + 1 file changed, 20 insertions(+), 43 deletions(-) diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index fdb3d795a409..919b3568c495 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -60,9 +60,6 @@ static u32 usec_config; static void __iomem *timer_reg_base; #ifdef CONFIG_ARM -static void __iomem *rtc_base; -static struct timespec64 persistent_ts; -static u64 persistent_ms, last_persistent_ms; static struct delay_timer tegra_delay_timer; #endif @@ -199,40 +196,30 @@ static unsigned long tegra_delay_timer_read_counter_long(void) return readl(timer_reg_base + TIMERUS_CNTR_1US); } +static struct timer_of suspend_rtc_to = { + .flags = TIMER_OF_BASE | TIMER_OF_CLOCK, +}; + /* * tegra_rtc_read - Reads the Tegra RTC registers * Care must be taken that this funciton is not called while the * tegra_rtc driver could be executing to avoid race conditions * on the RTC shadow register */ -static u64 tegra_rtc_read_ms(void) +static u64 tegra_rtc_read_ms(struct clocksource *cs) { - u32 ms = readl(rtc_base + RTC_MILLISECONDS); - u32 s = readl(rtc_base + RTC_SHADOW_SECONDS); + u32 ms = readl(timer_of_base(_rtc_to) + RTC_MILLISECONDS); + u32 s = readl(timer_of_base(_rtc_to) + RTC_SHADOW_SECONDS); return (u64)s * MSEC_PER_SEC + ms; } -/* - * tegra_read_persistent_clock64 - Return time from a persistent clock. - * - * Reads the time from a source which isn't disabled during PM, the - * 32k sync timer. Convert the cycles elapsed since last read into - * nsecs and adds to a monotonically increasing timespec64. - * Care must be taken that this funciton is not called while the - * tegra_rtc driver could be executing to avoid race conditions - * on the RTC shadow register - */ -static void tegra_read_persistent_clock64(struct timespec64 *ts) -{ - u64 delta; - - last_persistent_ms = persistent_ms; - persistent_ms = tegra_rtc_read_ms(); - delta = persistent_ms - last_persistent_ms; - - timespec64_add_ns(_ts, delta * NSEC_PER_MSEC); - *ts = persistent_ts; -} +static struct clocksource suspend_rtc_clocksource = { + .name = "tegra_suspend_timer", + .rating = 200, + .read = tegra_rtc_read_ms, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP, +}; #endif static int tegra_timer_common_init(struct device_node *np, struct timer_of *to) @@ -385,25 +372,15 @@ static int __init tegra_init_timer(struct device_node *np) static int __init tegra20_init_rtc(struct device_node *np) { - struct clk *clk; + int ret; - rtc_base = of_iomap(np, 0); - if (!rtc_base) { - pr_err("Can't map RTC registers\n"); - return -ENXIO; - } + ret = timer_of_init(np, _rtc_to); + if (ret) + return ret; - /* -* rtc registers are used by read_persistent_clock, keep the rtc clock -* enabled -*/ - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) - pr_warn("Unable to get rtc-tegra clock\n"); - else - clk_prepare_enable(clk); + clocksource_register_hz(_rtc_clocksource, 1000); - return register_persistent_clock(tegra_read_persistent_clock64); + return 0; } TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); #endif -- 2.21.0
Re: [PATCH] clocksource/drivers/tegra: rework for compensation of suspend time
On 4/2/19 10:46 PM, Thierry Reding wrote: On Tue, Apr 02, 2019 at 11:02:34AM +0800, Joseph Lo wrote: Since the clocksource framework has the support for suspend time compensation. Re-work the driver to use that, so we can reduce the duplicate code. Suggested-by: Daniel Lezcano Signed-off-by: Joseph Lo --- drivers/clocksource/timer-tegra20.c | 63 + 1 file changed, 20 insertions(+), 43 deletions(-) Nice! diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index fdb3d795a409..919b3568c495 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -60,9 +60,6 @@ static u32 usec_config; static void __iomem *timer_reg_base; #ifdef CONFIG_ARM -static void __iomem *rtc_base; -static struct timespec64 persistent_ts; -static u64 persistent_ms, last_persistent_ms; static struct delay_timer tegra_delay_timer; #endif @@ -199,40 +196,30 @@ static unsigned long tegra_delay_timer_read_counter_long(void) return readl(timer_reg_base + TIMERUS_CNTR_1US); } +static struct timer_of suspend_rtc_to = { + .flags = TIMER_OF_BASE | TIMER_OF_CLOCK, +}; + /* * tegra_rtc_read - Reads the Tegra RTC registers * Care must be taken that this funciton is not called while the * tegra_rtc driver could be executing to avoid race conditions * on the RTC shadow register */ -static u64 tegra_rtc_read_ms(void) +static u64 tegra_rtc_read_ms(struct clocksource *cs) { - u32 ms = readl(rtc_base + RTC_MILLISECONDS); - u32 s = readl(rtc_base + RTC_SHADOW_SECONDS); + u32 ms = readl(timer_of_base(_rtc_to) + RTC_MILLISECONDS); + u32 s = readl(timer_of_base(_rtc_to) + RTC_SHADOW_SECONDS); return (u64)s * MSEC_PER_SEC + ms; } -/* - * tegra_read_persistent_clock64 - Return time from a persistent clock. - * - * Reads the time from a source which isn't disabled during PM, the - * 32k sync timer. Convert the cycles elapsed since last read into - * nsecs and adds to a monotonically increasing timespec64. - * Care must be taken that this funciton is not called while the - * tegra_rtc driver could be executing to avoid race conditions - * on the RTC shadow register - */ -static void tegra_read_persistent_clock64(struct timespec64 *ts) -{ - u64 delta; - - last_persistent_ms = persistent_ms; - persistent_ms = tegra_rtc_read_ms(); - delta = persistent_ms - last_persistent_ms; - - timespec64_add_ns(_ts, delta * NSEC_PER_MSEC); - *ts = persistent_ts; -} +static struct clocksource suspend_rtc_clocksource = { + .name = "tegra_suspend_timer", + .rating = 200, + .read = tegra_rtc_read_ms, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP, +}; #endif static int tegra_timer_common_init(struct device_node *np, struct timer_of *to) @@ -385,25 +372,15 @@ static int __init tegra_init_timer(struct device_node *np) static int __init tegra20_init_rtc(struct device_node *np) { - struct clk *clk; + int ret; - rtc_base = of_iomap(np, 0); - if (!rtc_base) { - pr_err("Can't map RTC registers\n"); - return -ENXIO; - } + ret = timer_of_init(np, _rtc_to); + if (ret) + return ret; - /* -* rtc registers are used by read_persistent_clock, keep the rtc clock -* enabled -*/ - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) - pr_warn("Unable to get rtc-tegra clock\n"); - else - clk_prepare_enable(clk); + clocksource_register_hz(_rtc_clocksource, 1000); - return register_persistent_clock(tegra_read_persistent_clock64); + return 0; } TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); #endif I wonder if there's any reason left for the #ifdefs now. My recollection is that these were only needed because register_persistent_clock() was not available on 64-bit ARM. The new APIs seem to be available regardless of architecture, so do we still need to differentiate? Actually, only Tegra20/30 that doesn't have ARM arch timer support need this. The latter Tegra chips which have ARM arch timer support use TSC ( time stamp counter or timer system counter depends on the chip it has different name) as the timer source in the PMC. And it uses OSC during runtime and switches to 32KHz always-on clock source to keep counting when the chip is in the SC7 or LP0 state. So I didn't change that for this reason. Thanks, Joseph
Re: [PATCH V6 2/7] clocksource: tegra: add Tegra210 timer support
On 2/18/19 5:39 PM, Daniel Lezcano wrote: On 18/02/2019 10:01, Joseph Lo wrote: On 2/15/19 11:14 PM, Daniel Lezcano wrote: On 01/02/2019 17:16, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding Acked-by: Jon Hunter --- v6: * refine the timer defines * add ack tag from Jon. v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- [snip] + for_each_possible_cpu(cpu) { + struct timer_of *cpu_to; + + cpu_to = per_cpu_ptr(_to, cpu); + cpu_to->of_base.base = timer_reg_base + TIMER_BASE_FOR_CPU(cpu); + cpu_to->of_clk.rate = timer_of_rate(to); + cpu_to->clkevt.cpumask = cpumask_of(cpu); + + cpu_to->clkevt.irq = + irq_of_parse_and_map(np, IRQ_IDX_FOR_CPU(cpu)); + if (!cpu_to->clkevt.irq) { + pr_err("%s: can't map IRQ for CPU%d\n", + __func__, cpu); + ret = -EINVAL; + goto out; + } + + irq_set_status_flags(cpu_to->clkevt.irq, IRQ_NOAUTOEN); + ret = request_irq(cpu_to->clkevt.irq, tegra_timer_isr, + IRQF_TIMER | IRQF_NOBALANCING, + cpu_to->clkevt.name, _to->clkevt); + if (ret) { + pr_err("%s: cannot setup irq %d for CPU%d\n", + __func__, cpu_to->clkevt.irq, cpu); + ret = -EINVAL; + goto out_irq; + } + } You should configure the timer in the tegra_timer_setup() function instead of using this cpu loop. I think I still need to leave 'irq_of_parse_and_map' and 'request_irq' here. Is that ok? Perhaps you can store the np pointer in the private data structure of timer-of and let the timer_of API to retrieve the irq in the cpuhp callbacks. irq_of_parse_and_map will be called by timer-of. I'm not sure irq_set_status_flags really operates on the irq because it is called after request_irq. I did some experiments today. The 'irq_of_parse_and_map', 'request_irq' and 'setup_irq' are not able to run in the atomic section that tegra_timer_setup would be triggered in. So I think I still need to leave the IRQ configuration code here in the loop. Should I move others to 'tegra_timer_setup' or just keep as the same in this patch? Thanks, Joseph
[PATCH V7 2/8] clocksource: tegra: add Tegra210 timer support
Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding Acked-by: Jon Hunter --- v7: * kconfig fix for 'depends on ARM || ARM64' * move suspend/resume to clkevt * refine the usage for the macro of TIMER_OF_DECLARE v6: * refine the timer defines * add ack tag from Jon. v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 3 +- drivers/clocksource/timer-tegra20.c | 370 +++- include/linux/cpuhotplug.h | 1 + 3 files changed, 262 insertions(+), 112 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 8dfd3bc448d0..5d93e580e5dc 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,8 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM + select TIMER_OF + depends on ARM || ARM64 help Enables support for the Tegra driver. diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 4293943f4e2b..fdb3d795a409 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -15,21 +15,24 @@ * */ -#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include -#include #include #include +#include #include -#include +#include + +#include "timer-of.h" +#ifdef CONFIG_ARM #include +#endif #define RTC_SECONDS0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -39,74 +42,161 @@ #define TIMERUS_USEC_CFG 0x14 #define TIMERUS_CNTR_FREEZE 0x4c -#define TIMER1_BASE 0x0 -#define TIMER2_BASE 0x8 -#define TIMER3_BASE 0x50 -#define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) + +#ifdef CONFIG_ARM +#define TIMER_CPU0 0x50 /* TIMER3 */ +#else +#define TIMER_CPU0 0x90 /* TIMER10 */ +#define TIMER10_IRQ_IDX10 +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) +#endif +#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8) + +static u32 usec_config; static void __iomem *timer_reg_base; +#ifdef CONFIG_ARM static void __iomem *rtc_base; - static struct timespec64 persistent_ts; static u64 persistent_ms, last_persistent_ms; - static struct delay_timer tegra_delay_timer; - -#define timer_writel(value, reg) \ - writel_relaxed(value, timer_reg_base + (reg)) -#define timer_readl(reg) \ - readl_relaxed(timer_reg_base + (reg)) +#endif static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - u32 reg; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); - reg = 0x8000 | ((cycles > 1) ? (cycles-1) : 0); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + reg_base + TIMER_PTV); return 0; } -static inline void timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_shutdown(struct clock_event_device *evt) { - timer_writel(0, TIMER3_BASE + TIMER_PTV); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(0, reg_base + TIMER_PTV); + + return 0; } -static int tegra_timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_set_periodic(struct clock_event_device *evt) { - timer_shutdown(evt); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PTV_EN | TIMER_PTV_PER | + ((timer_of_rate(to_timer_of(evt)) / HZ) - 1), + reg_base + TIMER_PTV); + return 0; } -static int tegra_timer_set_periodic(struct clock_event_device *evt) +static irqreturn_t tegra_timer_isr(int irq, void *dev_id) +{ + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static vo
[PATCH V7 1/8] dt-bindings: timer: add Tegra210 timer
The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock (TMR10-TMR13). Each TMR can be programmed to generate one-shot periodic, or watchdog interrupts. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: devicet...@vger.kernel.org Signed-off-by: Joseph Lo Reviewed-by: Rob Herring Acked-by: Jon Hunter --- v7: * no change v6: * add ack tag from Jon. v5: * no change v4: * no change v3: * no change v2: * list all the interrupts that are supported by tegra210 timers block * add RB tag from Rob. --- .../bindings/timer/nvidia,tegra210-timer.txt | 36 +++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt new file mode 100644 index ..032cda96fe0d --- /dev/null +++ b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt @@ -0,0 +1,36 @@ +NVIDIA Tegra210 timer + +The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit +timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived +from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock +(TMR10-TMR13). Each TMR can be programmed to generate one-shot, periodic, +or watchdog interrupts. + +Required properties: +- compatible : "nvidia,tegra210-timer". +- reg : Specifies base physical address and size of the registers. +- interrupts : A list of 14 interrupts; one per each timer channels 0 through + 13. +- clocks : Must contain one entry, for the module clock. + See ../clocks/clock-bindings.txt for details. + +timer@60005000 { + compatible = "nvidia,tegra210-timer"; + reg = <0x0 0x60005000 0x0 0x400>; + interrupts = , +, +, +, +, +, +, +, +, +, +, +, +, +; + clocks = <_car TEGRA210_CLK_TIMER>; + clock-names = "timer"; +}; -- 2.20.1
Re: [PATCH V7 2/8] clocksource: tegra: add Tegra210 timer support
On 2/22/19 4:43 PM, Daniel Lezcano wrote: On 21/02/2019 08:21, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding Acked-by: Jon Hunter --- Acked-by: Daniel Lezcano Hi Daniel, Thanks for your review again. Regarding to Thierry's suggestion in [1], could you help to pick up patch 1~3 in this series in clocksource tree? [1]: https://patchwork.ozlabs.org/patch/1034075/ If not, I'll let him know this series needs to go with Tegra tree. Will you take care of dropping the persistent clocksource code in this driver? Yes, will do. Thanks, Joseph v7: * kconfig fix for 'depends on ARM || ARM64' * move suspend/resume to clkevt * refine the usage for the macro of TIMER_OF_DECLARE v6: * refine the timer defines * add ack tag from Jon. v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 3 +- drivers/clocksource/timer-tegra20.c | 370 +++- include/linux/cpuhotplug.h | 1 + 3 files changed, 262 insertions(+), 112 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 8dfd3bc448d0..5d93e580e5dc 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,8 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM + select TIMER_OF + depends on ARM || ARM64 help Enables support for the Tegra driver. diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 4293943f4e2b..fdb3d795a409 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -15,21 +15,24 @@ * */ -#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include -#include #include #include +#include #include -#include +#include + +#include "timer-of.h" +#ifdef CONFIG_ARM #include +#endif #define RTC_SECONDS0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -39,74 +42,161 @@ #define TIMERUS_USEC_CFG 0x14 #define TIMERUS_CNTR_FREEZE 0x4c -#define TIMER1_BASE 0x0 -#define TIMER2_BASE 0x8 -#define TIMER3_BASE 0x50 -#define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) + +#ifdef CONFIG_ARM +#define TIMER_CPU0 0x50 /* TIMER3 */ +#else +#define TIMER_CPU0 0x90 /* TIMER10 */ +#define TIMER10_IRQ_IDX10 +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) +#endif +#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8) + +static u32 usec_config; static void __iomem *timer_reg_base; +#ifdef CONFIG_ARM static void __iomem *rtc_base; - static struct timespec64 persistent_ts; static u64 persistent_ms, last_persistent_ms; - static struct delay_timer tegra_delay_timer; - -#define timer_writel(value, reg) \ - writel_relaxed(value, timer_reg_base + (reg)) -#define timer_readl(reg) \ - readl_relaxed(timer_reg_base + (reg)) +#endif static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - u32 reg; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); - reg = 0x8000 | ((cycles > 1) ? (cycles-1) : 0); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + reg_base + TIMER_PTV); return 0; } -static inline void timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_shutdown(struct clock_event_device *evt) { - timer_writel(0, TIMER3_BASE + TIMER_PTV); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(0, reg_base + TIMER_PTV); + + return 0; } -static int tegra_timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_set_periodic(struct clock_event_device *evt) { - timer_shutdown(evt); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TI
Re: [PATCH V6 2/7] clocksource: tegra: add Tegra210 timer support
On 2/13/19 4:55 PM, Daniel Lezcano wrote: On 08/02/2019 14:23, Joseph Lo wrote: Hi Daniel & Thomas, Do we have the chance to get this patch merged for K5.1? Hi Jospeh, sorry for the delay, I was overbooked these past two weeks. Overall it looks ok but give me a couple of days to review the driver more deeply. No problem, thanks. On 2/2/19 12:16 AM, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding Acked-by: Jon Hunter --- v6: * refine the timer defines * add ack tag from Jon. v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 2 +- drivers/clocksource/timer-tegra20.c | 371 include/linux/cpuhotplug.h | 1 + 3 files changed, 270 insertions(+), 104 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..6af78534a285 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,7 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM + select TIMER_OF help Enables support for the Tegra driver. diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 4293943f4e2b..f66edd63d7f4 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -15,21 +15,24 @@ * */ -#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include -#include #include #include -#include -#include +#include +#include +#include + +#include "timer-of.h" +#ifdef CONFIG_ARM #include +#endif #define RTC_SECONDS 0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -39,74 +42,145 @@ #define TIMERUS_USEC_CFG 0x14 #define TIMERUS_CNTR_FREEZE 0x4c -#define TIMER1_BASE 0x0 -#define TIMER2_BASE 0x8 -#define TIMER3_BASE 0x50 -#define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) + +#ifdef CONFIG_ARM +#define TIMER_CPU0 0x50 /* TIMER3 */ +#else +#define TIMER_CPU0 0x90 /* TIMER10 */ +#define TIMER10_IRQ_IDX 10 +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) +#endif +#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8) + +static u32 usec_config; static void __iomem *timer_reg_base; +#ifdef CONFIG_ARM static void __iomem *rtc_base; - static struct timespec64 persistent_ts; static u64 persistent_ms, last_persistent_ms; - static struct delay_timer tegra_delay_timer; - -#define timer_writel(value, reg) \ - writel_relaxed(value, timer_reg_base + (reg)) -#define timer_readl(reg) \ - readl_relaxed(timer_reg_base + (reg)) +#endif static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - u32 reg; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); - reg = 0x8000 | ((cycles > 1) ? (cycles-1) : 0); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + reg_base + TIMER_PTV); return 0; } -static inline void timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_shutdown(struct clock_event_device *evt) { - timer_writel(0, TIMER3_BASE + TIMER_PTV); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(0, reg_base + TIMER_PTV); + + return 0; } -static int tegra_timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_set_periodic(struct clock_event_device *evt) { - timer_shutdown(evt); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PTV_EN | TIMER_PTV_PER | + ((timer_of_rate(to_timer_of(evt)) / HZ) - 1), + reg_base + TIMER_PTV); + return 0; } -static int tegra_timer_set_periodic(struct clock_event_device *evt) +static irqreturn_t tegra_timer_isr(int irq, void *dev_id) { - u32 reg = 0xC000 | ((100 / HZ) - 1); + struct clock_event_device *evt = (struct clock_ev
Re: [PATCH V6 2/7] clocksource: tegra: add Tegra210 timer support
On 2/15/19 11:14 PM, Daniel Lezcano wrote: On 01/02/2019 17:16, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding Acked-by: Jon Hunter --- v6: * refine the timer defines * add ack tag from Jon. v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 2 +- drivers/clocksource/timer-tegra20.c | 371 include/linux/cpuhotplug.h | 1 + 3 files changed, 270 insertions(+), 104 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..6af78534a285 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,7 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM This will break because the delay functions are defined in arch/arm/include/asm/delay.h and the 01.org will try to compile the driver on x86. You may want to add 'depends on ARM && ARM64' OK, I think it's 'depends on ARM || ARM64'. Will fix. + select TIMER_OF help Enables support for the Tegra driver. [snip] - static struct timespec64 persistent_ts; static u64 persistent_ms, last_persistent_ms; Did you check the above changes are still relevant after commit 39232ed5a1793f67 and after doing a change similar to commit 1569557549697207e523 ? Yes, just check both commits. I think it's okay to use the same. But need another patch to do that, this patch only adds new support for Tegra210. Doesn't touch the original code. static struct delay_timer tegra_delay_timer; [snip] +#ifdef CONFIG_ARM64 +static DEFINE_PER_CPU(struct timer_of, tegra_to) = { + .flags = TIMER_OF_CLOCK | TIMER_OF_BASE, + + .clkevt = { + .name = "tegra_timer", + .rating = 460, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, CLOCK_EVT_FEAT_DYNIRQ ? Yes, good catch. + .set_next_event = tegra_timer_set_next_event, + .set_state_shutdown = tegra_timer_shutdown, + .set_state_periodic = tegra_timer_set_periodic, + .set_state_oneshot = tegra_timer_shutdown, + .tick_resume = tegra_timer_shutdown, + }, +}; [snip] -static unsigned long tegra_delay_timer_read_counter_long(void) +static int tegra_timer_suspend(void) { - return readl(timer_reg_base + TIMERUS_CNTR_1US); +#ifdef CONFIG_ARM64 Please do not add those #ifdef but function stubs. + int cpu; + + for_each_possible_cpu(cpu) { + struct timer_of *to = per_cpu_ptr(_to, cpu); + void __iomem *reg_base = timer_of_base(to); + + writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); + } +#else + void __iomem *reg_base = timer_of_base(_to); + + writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); +#endif + + return 0; } -static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) +static void tegra_timer_resume(void) { - struct clock_event_device *evt = (struct clock_event_device *)dev_id; - timer_writel(1<<30, TIMER3_BASE + TIMER_PCR); - evt->event_handler(evt); - return IRQ_HANDLED; + writel(usec_config, timer_reg_base + TIMERUS_USEC_CFG); } -static struct irqaction tegra_timer_irq = { - .name = "timer0", - .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH, - .handler= tegra_timer_interrupt, - .dev_id = _clockevent, +static struct syscore_ops tegra_timer_syscore_ops = { + .suspend = tegra_timer_suspend, + .resume = tegra_timer_resume, }; It will be nicer to use the suspend/resume callbacks defined in the clockevent structure, so you can use generic as there are multiple clockevents defined for the tegra210, thus multiple timer-of encapsulating them. When the suspend/resume callbacks are called, they have the clock_event pointer and you can use it to retrieve the timer-of and then the base address. At the end, the callbacks will end up the same for tegra20 and tegra210. Very good suggestion, will follow up. -static int __init tegra20_init_timer(struct device_node *np) +static int tegra_timer_init(struct device_node *np, struct timer_of
[PATCH V5 2/7] clocksource: tegra: add Tegra210 timer support
Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding --- v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 2 +- drivers/clocksource/timer-tegra20.c | 369 include/linux/cpuhotplug.h | 1 + 3 files changed, 272 insertions(+), 100 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..6af78534a285 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,7 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM + select TIMER_OF help Enables support for the Tegra driver. diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 4293943f4e2b..96a809341c9b 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -15,21 +15,24 @@ * */ -#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include -#include #include #include -#include -#include +#include +#include +#include + +#include "timer-of.h" +#ifdef CONFIG_ARM #include +#endif #define RTC_SECONDS0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -43,70 +46,147 @@ #define TIMER2_BASE 0x8 #define TIMER3_BASE 0x50 #define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - +#define TIMER10_BASE 0x90 + +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) + +#ifdef CONFIG_ARM +#define TIMER_BASE TIMER3_BASE +#else +#define TIMER_BASE TIMER10_BASE +#endif +#define TIMER10_IRQ_IDX10 +#define TIMER_FOR_CPU(cpu) (TIMER_BASE + (cpu) * 8) +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) + +static u32 usec_config; static void __iomem *timer_reg_base; +#ifdef CONFIG_ARM static void __iomem *rtc_base; - static struct timespec64 persistent_ts; static u64 persistent_ms, last_persistent_ms; - static struct delay_timer tegra_delay_timer; - -#define timer_writel(value, reg) \ - writel_relaxed(value, timer_reg_base + (reg)) -#define timer_readl(reg) \ - readl_relaxed(timer_reg_base + (reg)) +#endif static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - u32 reg; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); - reg = 0x8000 | ((cycles > 1) ? (cycles-1) : 0); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + reg_base + TIMER_PTV); return 0; } -static inline void timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_shutdown(struct clock_event_device *evt) { - timer_writel(0, TIMER3_BASE + TIMER_PTV); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(0, reg_base + TIMER_PTV); + + return 0; } -static int tegra_timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_set_periodic(struct clock_event_device *evt) { - timer_shutdown(evt); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PTV_EN | TIMER_PTV_PER | + ((timer_of_rate(to_timer_of(evt)) / HZ) - 1), + reg_base + TIMER_PTV); + return 0; } -static int tegra_timer_set_periodic(struct clock_event_device *evt) +static irqreturn_t tegra_timer_isr(int irq, void *dev_id) { - u32 reg = 0xC000 | ((100 / HZ) - 1); + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_ARM64 +static DEFINE_PER_CPU(struct timer_of, tegra_to) = { + .flags = TIMER_OF_CLOCK | TIMER_OF_BASE, + + .clkevt = { + .name = "tegra_timer", + .rating = 460, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_O
[PATCH V5 1/7] dt-bindings: timer: add Tegra210 timer
The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock (TMR10-TMR13). Each TMR can be programmed to generate one-shot periodic, or watchdog interrupts. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: devicet...@vger.kernel.org Signed-off-by: Joseph Lo Reviewed-by: Rob Herring --- v5: * no change v4: * no change v3: * no change v2: * list all the interrupts that are supported by tegra210 timers block * add RB tag from Rob. --- .../bindings/timer/nvidia,tegra210-timer.txt | 36 +++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt new file mode 100644 index ..032cda96fe0d --- /dev/null +++ b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt @@ -0,0 +1,36 @@ +NVIDIA Tegra210 timer + +The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit +timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived +from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock +(TMR10-TMR13). Each TMR can be programmed to generate one-shot, periodic, +or watchdog interrupts. + +Required properties: +- compatible : "nvidia,tegra210-timer". +- reg : Specifies base physical address and size of the registers. +- interrupts : A list of 14 interrupts; one per each timer channels 0 through + 13. +- clocks : Must contain one entry, for the module clock. + See ../clocks/clock-bindings.txt for details. + +timer@60005000 { + compatible = "nvidia,tegra210-timer"; + reg = <0x0 0x60005000 0x0 0x400>; + interrupts = , +, +, +, +, +, +, +, +, +, +, +, +, +; + clocks = <_car TEGRA210_CLK_TIMER>; + clock-names = "timer"; +}; -- 2.20.1
Re: [PATCH V5 2/7] clocksource: tegra: add Tegra210 timer support
On 2/1/19 9:54 PM, Jon Hunter wrote: On 01/02/2019 13:11, Dmitry Osipenko wrote: 01.02.2019 16:06, Dmitry Osipenko пишет: 01.02.2019 6:36, Joseph Lo пишет: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding --- v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 2 +- drivers/clocksource/timer-tegra20.c | 369 include/linux/cpuhotplug.h | 1 + 3 files changed, 272 insertions(+), 100 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..6af78534a285 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,7 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM + select TIMER_OF help Enables support for the Tegra driver. diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 4293943f4e2b..96a809341c9b 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -15,21 +15,24 @@ * */ -#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include -#include #include #include -#include -#include +#include +#include +#include + +#include "timer-of.h" +#ifdef CONFIG_ARM #include +#endif #define RTC_SECONDS0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -43,70 +46,147 @@ #define TIMER2_BASE 0x8 #define TIMER3_BASE 0x50 #define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - +#define TIMER10_BASE 0x90 + +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) + +#ifdef CONFIG_ARM +#define TIMER_BASE TIMER3_BASE +#else +#define TIMER_BASE TIMER10_BASE +#endif +#define TIMER10_IRQ_IDX10 +#define TIMER_FOR_CPU(cpu) (TIMER_BASE + (cpu) * 8) +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) + +static u32 usec_config; static void __iomem *timer_reg_base; +#ifdef CONFIG_ARM static void __iomem *rtc_base; - static struct timespec64 persistent_ts; static u64 persistent_ms, last_persistent_ms; - static struct delay_timer tegra_delay_timer; - -#define timer_writel(value, reg) \ - writel_relaxed(value, timer_reg_base + (reg)) -#define timer_readl(reg) \ - readl_relaxed(timer_reg_base + (reg)) +#endif static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - u32 reg; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); - reg = 0x8000 | ((cycles > 1) ? (cycles-1) : 0); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + reg_base + TIMER_PTV); return 0; } -static inline void timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_shutdown(struct clock_event_device *evt) { - timer_writel(0, TIMER3_BASE + TIMER_PTV); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(0, reg_base + TIMER_PTV); + + return 0; } -static int tegra_timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_set_periodic(struct clock_event_device *evt) { - timer_shutdown(evt); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PTV_EN | TIMER_PTV_PER | + ((timer_of_rate(to_timer_of(evt)) / HZ) - 1), + reg_base + TIMER_PTV); + return 0; } -static int tegra_timer_set_periodic(struct clock_event_device *evt) +static irqreturn_t tegra_timer_isr(int irq, void *dev_id) { - u32 reg = 0xC000 | ((100 / HZ) - 1); + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_ARM64 +static DEFINE_PER_CPU(struct timer_of, tegra_to) = { + .flags = T
Re: [PATCH V5 2/7] clocksource: tegra: add Tegra210 timer support
On 2/1/19 8:44 PM, Jon Hunter wrote: On 01/02/2019 03:36, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. It may have been nice to split this into 2 patches to make it easier to see what is going on but not a big deal. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding --- v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 2 +- drivers/clocksource/timer-tegra20.c | 369 include/linux/cpuhotplug.h | 1 + 3 files changed, 272 insertions(+), 100 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..6af78534a285 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,7 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM + select TIMER_OF help Enables support for the Tegra driver. diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 4293943f4e2b..96a809341c9b 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -15,21 +15,24 @@ * */ -#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include -#include #include #include -#include -#include +#include +#include +#include + +#include "timer-of.h" +#ifdef CONFIG_ARM #include +#endif #define RTC_SECONDS0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -43,70 +46,147 @@ #define TIMER2_BASE 0x8 #define TIMER3_BASE 0x50 #define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - +#define TIMER10_BASE 0x90 + +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) + +#ifdef CONFIG_ARM +#define TIMER_BASE TIMER3_BASE +#else +#define TIMER_BASE TIMER10_BASE +#endif +#define TIMER10_IRQ_IDX10 +#define TIMER_FOR_CPU(cpu) (TIMER_BASE + (cpu) * 8) +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) TIMER10_IRQ_IDX and IRQ_IDX_FOR_CPU are only applicable to ARM64 and so we should probably not defined for ARM to avoid any confusion. Okay, will do. Furthermore, a lot of these TIMERx_BASE definitions are unused AFAICT. Would be good to get rid of these. Okay. Maybe we could just have ... +#ifdef CONFIG_ARM +#define TIMER_CPU0 3 +#else +#define TIMER_CPU0 10 +#endif +#define TIMER_BASE_FOR_CPU(cpu) ((TIMER_CPU0 + cpu) * 8) +#define TIMER_FOR_CPU(cpu) (TIMER_CPU0 + cpu) This can't get the timer base address. I think you mean ... +#ifdef CONFIG_ARM +#define TIMER_CPU0 0x50 /* TIMER3 */ +#else +#define TIMER_CPU0 0x90 /* TIMER10 */ +#endif +#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8) This doesn't need. +#define TIMER_FOR_CPU(cpu) (TIMER_CPU0 + cpu) Will fix above accordingly and adding your ack tag. Thanks, Joseph Otherwise looks good to me. Cheers Jon
Re: [PATCH V5 2/7] clocksource: tegra: add Tegra210 timer support
On 2/1/19 11:13 PM, Dmitry Osipenko wrote: 01.02.2019 17:13, Joseph Lo пишет: On 2/1/19 9:54 PM, Jon Hunter wrote: On 01/02/2019 13:11, Dmitry Osipenko wrote: 01.02.2019 16:06, Dmitry Osipenko пишет: 01.02.2019 6:36, Joseph Lo пишет: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding --- snip. +} +TIMER_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer", tegra210_timer_init); +#else /* CONFIG_ARM */ +static int __init tegra20_init_timer(struct device_node *np) +{ What about T132? Isn't it ARM64 which uses tegra20-timer IP? At least T132 DT suggests so and seems this change will break it. [snip] Ah, noticed the "depends on ARM" in Kconfig.. Seems okay then. This is a good point, because even though we had 'depends on ARM', this still means that the Tegra132 DT is incorrect. Joseph, can you take a quick look at Tegra132? Hi Jon and Dmitry, No worry about T132, T132 uses arch timer (v7). The tegra20 timer driver has never been used. We should fix the dtsi file later. Hi Joseph, So is T132 HW actually incompatible with the tegra20-timer? If it's compatible, then I think the driver's code should be made more universal to support T132. From HW point of view, the TIMER1 ~ TIMER4 is compatible with "nvidia,tegra20-timer". But Tegra132 actually has 10 timers which are exactly the same as Tegra30. So it should backward compatible with "nvidia,tegra30-timer", which is tegra_wdt driver now. And Tegra132 should never use this driver. The Tegra timer driver should only be used on Tegra20/30/210, three platforms only. Others use arch timer driver for system timer driver. So we don't really need to take care the usage on other Tegra platforms. Thanks, Joseph
Re: [PATCH V5 2/7] clocksource: tegra: add Tegra210 timer support
On 2/1/19 11:43 PM, Jon Hunter wrote: On 01/02/2019 14:39, Joseph Lo wrote: On 2/1/19 8:44 PM, Jon Hunter wrote: On 01/02/2019 03:36, Joseph Lo wrote: Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. It may have been nice to split this into 2 patches to make it easier to see what is going on but not a big deal. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding --- snip. This can't get the timer base address. I think you mean ... +#ifdef CONFIG_ARM +#define TIMER_CPU0 0x50 /* TIMER3 */ +#else +#define TIMER_CPU0 0x90 /* TIMER10 */ +#endif +#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8) Ah I see. This doesn't need. +#define TIMER_FOR_CPU(cpu) (TIMER_CPU0 + cpu) How come? Don't you still need to know the timer index for a given CPU? Doesn't need. TIMER_BASE_FOR_CPU is enough. Other use cases are well handled by timer-of API. :) Thanks, Joseph
[PATCH V6 2/7] clocksource: tegra: add Tegra210 timer support
Add support for the Tegra210 timer that runs at oscillator clock (TMR10-TMR13). We need these timers to work as clock event device and to replace the ARMv8 architected timer due to it can't survive across the power cycle of the CPU core or CPUPORESET signal. So it can't be a wake-up source when CPU suspends in power down state. Also convert the original driver to use timer-of API. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Joseph Lo Acked-by: Thierry Reding Acked-by: Jon Hunter --- v6: * refine the timer defines * add ack tag from Jon. v5: * add ack tag from Thierry v4: * merge timer-tegra210.c in previous version into timer-tegra20.c v3: * use timer-of API v2: * add error clean-up code --- drivers/clocksource/Kconfig | 2 +- drivers/clocksource/timer-tegra20.c | 371 include/linux/cpuhotplug.h | 1 + 3 files changed, 270 insertions(+), 104 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..6af78534a285 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -131,7 +131,7 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST select CLKSRC_MMIO - depends on ARM + select TIMER_OF help Enables support for the Tegra driver. diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 4293943f4e2b..f66edd63d7f4 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -15,21 +15,24 @@ * */ -#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include -#include #include #include -#include -#include +#include +#include +#include + +#include "timer-of.h" +#ifdef CONFIG_ARM #include +#endif #define RTC_SECONDS0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -39,74 +42,145 @@ #define TIMERUS_USEC_CFG 0x14 #define TIMERUS_CNTR_FREEZE 0x4c -#define TIMER1_BASE 0x0 -#define TIMER2_BASE 0x8 -#define TIMER3_BASE 0x50 -#define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - +#define TIMER_PTV 0x0 +#define TIMER_PTV_EN BIT(31) +#define TIMER_PTV_PER BIT(30) +#define TIMER_PCR 0x4 +#define TIMER_PCR_INTR_CLR BIT(30) + +#ifdef CONFIG_ARM +#define TIMER_CPU0 0x50 /* TIMER3 */ +#else +#define TIMER_CPU0 0x90 /* TIMER10 */ +#define TIMER10_IRQ_IDX10 +#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) +#endif +#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8) + +static u32 usec_config; static void __iomem *timer_reg_base; +#ifdef CONFIG_ARM static void __iomem *rtc_base; - static struct timespec64 persistent_ts; static u64 persistent_ms, last_persistent_ms; - static struct delay_timer tegra_delay_timer; - -#define timer_writel(value, reg) \ - writel_relaxed(value, timer_reg_base + (reg)) -#define timer_readl(reg) \ - readl_relaxed(timer_reg_base + (reg)) +#endif static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - u32 reg; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); - reg = 0x8000 | ((cycles > 1) ? (cycles-1) : 0); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); + writel(TIMER_PTV_EN | + ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */ + reg_base + TIMER_PTV); return 0; } -static inline void timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_shutdown(struct clock_event_device *evt) { - timer_writel(0, TIMER3_BASE + TIMER_PTV); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(0, reg_base + TIMER_PTV); + + return 0; } -static int tegra_timer_shutdown(struct clock_event_device *evt) +static int tegra_timer_set_periodic(struct clock_event_device *evt) { - timer_shutdown(evt); + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PTV_EN | TIMER_PTV_PER | + ((timer_of_rate(to_timer_of(evt)) / HZ) - 1), + reg_base + TIMER_PTV); + return 0; } -static int tegra_timer_set_periodic(struct clock_event_device *evt) +static irqreturn_t tegra_timer_isr(int irq, void *dev_id) { - u32 reg = 0xC000 | ((100 / HZ) - 1); + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + void __iomem *reg_base = timer_of_base(to_timer_of(evt)); + + writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_ARM64 +static DEFINE_PER_CPU(struct timer_of, tegra_to) = { + .flags = TIMER_OF_CLOCK | TIM
[PATCH V6 1/7] dt-bindings: timer: add Tegra210 timer
The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock (TMR10-TMR13). Each TMR can be programmed to generate one-shot periodic, or watchdog interrupts. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: devicet...@vger.kernel.org Signed-off-by: Joseph Lo Reviewed-by: Rob Herring Acked-by: Jon Hunter --- v6: * add ack tag from Jon. v5: * no change v4: * no change v3: * no change v2: * list all the interrupts that are supported by tegra210 timers block * add RB tag from Rob. --- .../bindings/timer/nvidia,tegra210-timer.txt | 36 +++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt new file mode 100644 index ..032cda96fe0d --- /dev/null +++ b/Documentation/devicetree/bindings/timer/nvidia,tegra210-timer.txt @@ -0,0 +1,36 @@ +NVIDIA Tegra210 timer + +The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit +timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived +from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock +(TMR10-TMR13). Each TMR can be programmed to generate one-shot, periodic, +or watchdog interrupts. + +Required properties: +- compatible : "nvidia,tegra210-timer". +- reg : Specifies base physical address and size of the registers. +- interrupts : A list of 14 interrupts; one per each timer channels 0 through + 13. +- clocks : Must contain one entry, for the module clock. + See ../clocks/clock-bindings.txt for details. + +timer@60005000 { + compatible = "nvidia,tegra210-timer"; + reg = <0x0 0x60005000 0x0 0x400>; + interrupts = , +, +, +, +, +, +, +, +, +, +, +, +, +; + clocks = <_car TEGRA210_CLK_TIMER>; + clock-names = "timer"; +}; -- 2.20.1