Re: Performance drop due to alloc_workqueue() misuse and recent change
Hello, again. On Mon, Dec 04, 2023 at 04:03:47PM +, Naohiro Aota wrote: ... > In summary, we misuse max_active, considering it is a global limit. And, > the recent commit introduced a huge performance drop in some cases. We > need to review alloc_workqueue() usage to check if its max_active setting > is proper or not. Can you please test the following branch? https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git unbound-system-wide-max_active Thanks. -- tejun
Re: [PATCH 4/5] clk: sunxi-ng: a64: Add constraints on PLL-VIDEO0's n/m ratio
On 2023-12-19 at 17:54:19 +0100, Jernej Škrabec wrote: > Dne ponedeljek, 18. december 2023 ob 14:35:22 CET je Frank Oltmanns > napisal(a): >> The Allwinner A64 manual lists the following constraint for the >> PLL-VIDEO0 clock: 8 <= N/M <= 25 >> >> Use this constraint. >> >> Signed-off-by: Frank Oltmanns >> --- >> drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 8 ++-- >> 1 file changed, 6 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c >> b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c >> index c034ac027d1c..75d839da446c 100644 >> --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c >> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c >> @@ -68,7 +68,8 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, >> "pll-audio-base", >> BIT(28), /* lock */ >> CLK_SET_RATE_UNGATE); >> >> -static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, >> "pll-video0", >> +static >> SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT_NM_RATIO(pll_video0_clk, >> +"pll-video0", >> "osc24M", 0x010, >> 19200, /* Minimum rate >> */ >> 100800, /* Maximum rate >> */ >> @@ -80,7 +81,10 @@ static >> SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, "pll-vid >> 29700, /* frac rate 1 >> */ >> BIT(31),/* gate */ >> BIT(28),/* lock */ >> -CLK_SET_RATE_UNGATE); >> +CLK_SET_RATE_UNGATE, >> +CCU_FEATURE_FRACTIONAL | >> +CCU_FEATURE_CLOSEST_RATE, > > Above flags are unrelated change, put them in new patch if needed. You might notice that I am using a new macro for initializing the pll_video0_clk struct: New: SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT_NM_RATIO Old: SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST Setting the two CCU_FEATURE flags is part of the old initialization macro. I'll add SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_NM_RATIO_CLOSEST which hopefully resolves the confusion. Thanks, Frank > > Best regards, > Jernej > >> +8, 25); /* min/max nm >> ratio */ >> >> static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", >> "osc24M", 0x018, >> >>
Re: [PATCH 1/5] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate
Hi Jernej! On 2023-12-19 at 17:46:08 +0100, Jernej Škrabec wrote: > Hi Frank! > > Dne ponedeljek, 18. december 2023 ob 14:35:19 CET je Frank Oltmanns > napisal(a): >> The Allwinner A64 manual lists the following constraints for the >> PLL-MIPI clock: >> - M/N >= 3 > > This should be "<=" Yes, good catch! I will fix it in V2. > >> - (PLL_VIDEO0)/M >= 24MHz >> >> The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for >> these constraints. >> >> Signed-off-by: Frank Oltmanns >> --- >> drivers/clk/sunxi-ng/ccu_nkm.c | 23 +++ >> drivers/clk/sunxi-ng/ccu_nkm.h | 8 >> 2 files changed, 31 insertions(+) >> >> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c >> index eed64547ad42..2af5c1ebd527 100644 >> --- a/drivers/clk/sunxi-ng/ccu_nkm.c >> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c >> @@ -16,6 +16,20 @@ struct _ccu_nkm { >> unsigned long m, min_m, max_m; >> }; >> >> +static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long >> parent, >> + unsigned long n, unsigned long m) >> +{ >> +struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common); >> + >> +if (nkm->max_mn_ratio && (m > nkm->max_mn_ratio * n)) >> +return false; >> + >> +if (nkm->parent_wo_nk && (parent < nkm->parent_wo_nk * m)) >> +return false; >> + >> +return true; >> +} >> + >> static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common >> *common, >> struct clk_hw *parent_hw, >> unsigned long *parent, >> unsigned long rate, >> @@ -32,6 +46,9 @@ static unsigned long >> ccu_nkm_find_best_with_parent_adj(struct ccu_common *common >> >> tmp_parent = clk_hw_round_rate(parent_hw, rate >> * _m / (_n * _k)); >> >> +if (!ccu_nkm_is_valid_rate(common, tmp_parent, >> _n, _m)) >> +continue; >> + >> tmp_rate = tmp_parent * _n * _k / _m; >> >> if (ccu_is_better_rate(common, rate, tmp_rate, >> best_rate) || >> @@ -65,6 +82,12 @@ static unsigned long ccu_nkm_find_best(unsigned long >> parent, unsigned long rate, >> for (_k = nkm->min_k; _k <= nkm->max_k; _k++) { >> for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { >> for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { >> +if ((common->reg == 0x040) && (_m > 3 * _n)) >> +break; >> + >> +if ((common->reg == 0x040) && (parent < >> 2400 * _m)) >> +continue; >> + > > You already figured this part. > >> unsigned long tmp_rate; >> >> tmp_rate = parent * _n * _k / _m; >> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h >> index 6601defb3f38..d3d3eaf55faf 100644 >> --- a/drivers/clk/sunxi-ng/ccu_nkm.h >> +++ b/drivers/clk/sunxi-ng/ccu_nkm.h >> @@ -16,6 +16,12 @@ >> * struct ccu_nkm - Definition of an N-K-M clock >> * >> * Clocks based on the formula parent * N * K / M >> + * >> + * @max_mn_ratio: Maximum value for M / N. >> + * @parent_wo_nk: The minimum rate the parent must provide after applying >> the divisor, >> + * but without applying the multipliers, i.e. the >> contstraint >> + * (parent rate)/M >= parent_wo_nk >> + * must be fulfilled. >> */ >> struct ccu_nkm { >> u32 enable; >> @@ -27,6 +33,8 @@ struct ccu_nkm { >> struct ccu_mux_internal mux; >> >> unsigned intfixed_post_div; >> +unsigned long max_mn_ratio; >> +unsigned long parent_wo_nk; > > What about max_m_n_ratio and max_parent_m_ratio, to be consistent? This > should also allow to simplify description. Jernej, thank you so much! This is brilliant! I was racking my brain for a good name but failed. Now, that I see your proposal, I don't know why I hadn't come up with it. It's the obvious choice. I'd say with the new names we should be able to get rid of the comments describing the new struct members (also in ccu_nm.h). What are your thoughts on that? Best regards, Frank > > Best regards, > Jernej > >> >> struct ccu_common common; >> }; >> >>
Re: [PATCH 6/7] accel/qaic: Leverage DRM managed APIs to release resources
On 15.12.2023 19:06, Jeffrey Hugo wrote: > On 12/8/2023 9:34 AM, Jeffrey Hugo wrote: >> From: Pranjal Ramajor Asha Kanojiya >> >> Offload the balancing of init and destroy calls to DRM managed APIs. >> mutex destroy for ->cntl_mutex is not called during device release and >> destroy workqueue is not called in error path of create_qdev(). So, use >> DRM managed APIs to manage the release of resources and avoid such >> problems. >> >> Signed-off-by: Pranjal Ramajor Asha Kanojiya >> Reviewed-by: Jeffrey Hugo >> Signed-off-by: Jeffrey Hugo > > Jacek, I saw a review from you for 1-5, and 7 but not this patch (6). Did I > miss something? Sorry, I was out of office for a couple days and I wasn't able to finish the review. Reviewed-by: Jacek Lawrynowicz
Re: [PATCH 01/27] sparc32: Update defconfig to LEON SMP
Hi Arnd, On Tue, Dec 19, 2023 at 10:23:05PM +, Arnd Bergmann wrote: > On Tue, Dec 19, 2023, at 22:03, Sam Ravnborg via B4 Relay wrote: > > From: Sam Ravnborg > > > > This is a copy of the leon_smp defconfig found in > > gaisler-buildroot-2023.02-1.0. > > > > Signed-off-by: Sam Ravnborg > > Cc: "David S. Miller" > > Cc: Arnd Bergmann > > Cc: Andreas Larsson > > I did not get a cover letter for the series, but I looked at You are listed as a receiver?!? It can be found here: https://lore.kernel.org/sparclinux/20231219-sam-sparc32-sunset-v3-v1-0-64bb44b59...@ravnborg.org/T/#m2fc5b3c23331efd12492a61ba39ac000a563ac52 > all 27 patches and they all look good to me, nice cleanup! > > Acked-by: Arnd Bergmann Thanks! Sam
Re: [PATCH 24/27] sparc32: Drop config SPARC_LEON
On Tue, Dec 19, 2023 at 11:03:29PM +0100, Sam Ravnborg via B4 Relay wrote: > From: Sam Ravnborg > > The only support sparc32 CPU is LEON, so there is no need for a > config option to select it. > > Signed-off-by: Sam Ravnborg > Cc: "David S. Miller" > Cc: Arnd Bergmann > Cc: Andreas Larsson For the USB stuff: Acked-by: Greg Kroah-Hartman
Re: [PATCH v3 2/6] x86/vmware: Introduce vmware_hypercall API
On 12/19/23 4:51 PM, kirill.shute...@linux.intel.com wrote: On Tue, Dec 19, 2023 at 04:17:40PM -0800, Alexey Makhalov wrote: On 12/19/23 3:20 PM, kirill.shute...@linux.intel.com wrote: On Tue, Dec 19, 2023 at 01:57:47PM -0800, Alexey Makhalov wrote: +static inline +unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) ... +static inline +unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2) ... +static inline +unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2, + uint32_t *out3) ... +static inline +unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, uint32_t *out2) ... +static inline +unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1, + unsigned long in3, uint32_t *out2, + uint32_t *out3, uint32_t *out4, + uint32_t *out5) ... +static inline +unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, uint32_t *out1, + uint32_t *out2, uint32_t *out3) Naming is weird. The number in the name doesn't help much as there seems no system on how many of the parameters are ins and outs. There was internal discussion on hypercall API naming. One of proposals was using 2 digits - number of input and number of output arguments. And it definitely looked weird. So, we agreed to have just single number - total number of arguments excluding cmd. Have you considered naming them by number of input parameters? Number of output parameters as demanded by users. So vmware_hypercall4() will become vmware_hypercall1() and current vmware_hypercall1() and vmware_hypercall3() will go away. It is still awful, but /maybe/ better that this, I donno. Deprecating vmware_hypercall1 and vmware_hypercall3 in favor of vmware_hypercall4 will generate less efficient code for the caller of first ones. Using current vmware_hypercall4 instead of vmware_hypercall1 will force the caller to allocate additional variables (register or on stack memory) for hypercall asm inline to put additional output registers on. And specifically to 'usage' of *out3 - compiler will unnecessary 'clobber' useful rdx, when hypervisor will keep it unchanged. Unfortunately VMware hypercall ABI is not as beautiful as KVM one, especially in number of output arguments and their ordering. rbp register usage as an argument is a separate bummer((. So we have to work with what we have. Current set of functions includes only 6 functions (for LB), which is the optimum between readability, maintainability and performance. It covers all current kernel callers and all new callers from yet to be upstreamed patches that we have in Photon OS including 2 patches for x86 and arm64 guest support. Regards, --Alexey
Re: [PATCH v3 6/6] x86/vmware: Add TDX hypercall support
On 12/19/23 5:00 PM, kirill.shute...@linux.intel.com wrote: On Tue, Dec 19, 2023 at 04:27:51PM -0800, Alexey Makhalov wrote: On 12/19/23 3:23 PM, kirill.shute...@linux.intel.com wrote: On Tue, Dec 19, 2023 at 01:57:51PM -0800, Alexey Makhalov wrote: diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 3aa1adaed18f..ef07ab7a07e1 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -428,6 +428,30 @@ static bool __init vmware_legacy_x2apic_available(void) (eax & BIT(VCPU_LEGACY_X2APIC)); } +#ifdef CONFIG_INTEL_TDX_GUEST +unsigned long vmware_tdx_hypercall(unsigned long cmd, + struct tdx_module_args *args) +{ + if (!hypervisor_is_type(X86_HYPER_VMWARE)) + return 0; BTW, don't you want to warn here to? We don't expect vmware hypercalls to be called by non-vmware guest, do we? The answer is below... + + if (cmd & ~VMWARE_CMD_MASK) { + pr_warn("Out of range command %x\n", cmd); + return 0; Is zero success? Shouldn't it be an error? VMware hypercalls do not have a standard way of signalling an error. To generalize expectations from the caller perspective of any existing hypercalls: error (including hypercall is not supported or disabled) is when return value is 0 and out1/2 are unchanged or equal to in1/in2. You are talking about signaling errors over hypercall transport. But if kernel can see that something is wrong why cannot it signal the issue clearly to caller. It is going to be in-kernel convention.These "return 0" blocks were introduced to protect against non-vmware guest or arbitrary modules trying to use __tdx_hypercall via exported vmware_tdx_hypercall function. In this case, it will be NOOP behavior with no or minor side effects. From valid vmware_hypercall callers point of view, there is no such thing as a hypercall not available. Once guest detection code recognizes VMWare hypervisor via cpuid, it will start using hypercalls in accordance to per-call API. Valid VMware guest code will never go into first return, no warning required. Second return can be hit in rare cases for example during development phase, or, hypothetical case, when cmd was dynamically generated. That's why we have a warning warning only for the second condition. While speaking about it, I'm started to lean towards your recommendation. Yes, we can return standard error code such as -EINVAL or just -1 instead of "return 0" in this function. And it will be algorithmically correct. As if Vmware guest caller provide out of range cmd - it is not documented behavior. Speaking of additional in-kernel convention for passing additional parameter if error happens, it does not makes sense for me because: 1. existing caller codes analyze output argument to recognize error error response from the hypervisor. Adding one additional check for in-kernel errors just for TDX path which will be never hit by valid code in production is an unnecessary overhead. 2. It will definitely add an overhead as an error code will require one more output value, or out0 should be moved from return in-register value to return by pointer function argument. Summarizing, overloading vmware_tdx_hypercall return value by arg0 (from the hypervisor) and kernel error (-1 or any other) seems like reasonable change. And to very least, it has to be pr_warn_once(). Good catch! Will change it. Thanks, --Alexey
[PATCH linux-next] drm/panel: Simplify with dev_err_probe()
From: Yang Guang dev_err_probe() can check if the error code is -EPROBE_DEFER and can return the error code, replacing dev_err() with it simplifies the code. Signed-off-by: Chen Haonan --- drivers/gpu/drm/panel/panel-boe-himax8279d.c | 18 ++ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c index 11b64acbe8a9..e225840b0d67 100644 --- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c +++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c @@ -854,26 +854,20 @@ static int panel_add(struct panel_info *pinfo) pinfo->pp18_gpio = devm_gpiod_get(dev, "pp18", GPIOD_OUT_HIGH); if (IS_ERR(pinfo->pp18_gpio)) { - ret = PTR_ERR(pinfo->pp18_gpio); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get pp18 gpio: %d\n", ret); - return ret; + return dev_err_probe(dev, PTR_ERR(pinfo->pp18_gpio), +"failed to get pp18 gpio\n"); } pinfo->pp33_gpio = devm_gpiod_get(dev, "pp33", GPIOD_OUT_HIGH); if (IS_ERR(pinfo->pp33_gpio)) { - ret = PTR_ERR(pinfo->pp33_gpio); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get pp33 gpio: %d\n", ret); - return ret; + return dev_err_probe(dev, PTR_ERR(pinfo->pp33_gpio), +"failed to get pp33 gpio\n"); } pinfo->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); if (IS_ERR(pinfo->enable_gpio)) { - ret = PTR_ERR(pinfo->enable_gpio); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get enable gpio: %d\n", ret); - return ret; + return dev_err_probe(dev, PTR_ERR(pinfo->enable_gpio), +"failed to get enable gpio\n"); } drm_panel_init(>base, dev, _funcs, -- 2.25.1
[PATCH linux-next] drm/amd/display: use kcalloc instead of open coded arithmetic
From: Yang Guang Dynamic size calculations (especially multiplication) should not be performed in memory allocator (or similar) function arguments due to the risk of them overflowing. This could lead to values wrapping around and a smaller allocation being made than the caller was expecting. Using those allocations could lead to linear overflows of heap memory and other misbehaviors. Signed-off-by: Chen Haonan --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d7ac020bd8af..d6d63bd7482e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -9204,7 +9204,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) * Here we create an empty update on each plane. * To fix this, DC should permit updating only stream properties. */ - dummy_updates = kzalloc(sizeof(struct dc_surface_update) * MAX_SURFACES, GFP_ATOMIC); + dummy_updates = kcalloc(MAX_SURFACES, sizeof(struct dc_surface_update), GFP_ATOMIC); for (j = 0; j < status->plane_count; j++) dummy_updates[j].surface = status->plane_states[0]; -- 2.25.1
Re: [RFC PATCH] KVM: Introduce KVM VIRTIO device
On Tue, Dec 19, 2023 at 12:26:45PM +0800, Yan Zhao wrote: > On Mon, Dec 18, 2023 at 07:08:51AM -0800, Sean Christopherson wrote: > > > > Implementation Consideration > > > > === > > > > There is a previous series [1] from google to serve the same purpose to > > > > let KVM be aware of virtio GPU's noncoherent DMA status. That series > > > > requires a new memslot flag, and special memslots in user space. > > > > > > > > We don't choose to use memslot flag to request honoring guest memory > > > > type. > > > > > > memslot flag has the potential to restrict the impact e.g. when using > > > clflush-before-read in migration? > > > > Yep, exactly. E.g. if KVM needs to ensure coherency when freeing memory > > back to > > the host kernel, then the memslot flag will allow for a much more targeted > > operation. > > > > > Of course the implication is to honor guest type only for the selected > > > slot > > > in KVM instead of applying to the entire guest memory as in previous > > > series > > > (which selects this way because vmx_get_mt_mask() is in perf-critical path > > > hence not good to check memslot flag?) > > > > Checking a memslot flag won't impact performance. KVM already has the > > memslot > > when creating SPTEs, e.g. the sole caller of vmx_get_mt_mask(), > > make_spte(), has > > access to the memslot. > > > > That isn't coincidental, KVM _must_ have the memslot to construct the SPTE, > > e.g. > > to retrieve the associated PFN, update write-tracking for shadow pages, etc. > > > Hi Sean, > Do you prefer to introduce a memslot flag KVM_MEM_DMA or KVM_MEM_WC? > For KVM_MEM_DMA, KVM needs to > (a) search VMA for vma->vm_page_prot and convert it to page cache mode (with > pgprot2cachemode()? ), or > (b) look up memtype of the PFN, by calling lookup_memtype(), similar to that > in > pat_pfn_immune_to_uc_mtrr(). > > But pgprot2cachemode() and lookup_memtype() are not exported by x86 code now. > > For KVM_MEM_WC, it requires user to ensure the memory is actually mapped > to WC, right? > > Then, vmx_get_mt_mask() just ignores guest PAT and programs host PAT as EPT > type > for the special memslot only, as below. > Is this understanding correct? > > static u8 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio) > { > if (is_mmio) > > return MTRR_TYPE_UNCACHABLE << VMX_EPT_MT_EPTE_SHIFT; > > > > if (gfn_in_dma_slot(vcpu->kvm, gfn)) { > > u8 type = MTRR_TYPE_WRCOMB; > > //u8 type = pat_pfn_memtype(pfn); > > return (type << VMX_EPT_MT_EPTE_SHIFT) | VMX_EPT_IPAT_BIT; > > } > > > > if (!kvm_arch_has_noncoherent_dma(vcpu->kvm)) > > return (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT) | > VMX_EPT_IPAT_BIT; > > > if (kvm_read_cr0_bits(vcpu, X86_CR0_CD)) { > > if (kvm_check_has_quirk(vcpu->kvm, > KVM_X86_QUIRK_CD_NW_CLEARED)) > return MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT; > > else > > return (MTRR_TYPE_UNCACHABLE << > VMX_EPT_MT_EPTE_SHIFT) | > VMX_EPT_IPAT_BIT; > > } > > > > return kvm_mtrr_get_guest_memory_type(vcpu, gfn) << > VMX_EPT_MT_EPTE_SHIFT; > } > > BTW, since the special memslot must be exposed to guest as virtio GPU BAR in > order to prevent other guest drivers from access, I wonder if it's better to > include some keyword like VIRTIO_GPU_BAR in memslot flag name. Another choice is to add a memslot flag KVM_MEM_HONOR_GUEST_PAT, then user (e.g. QEMU) does special treatment to this kind of memslots (e.g. skipping reading/writing to them in general paths). @@ -7589,26 +7589,29 @@ static u8 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio) if (is_mmio) return MTRR_TYPE_UNCACHABLE << VMX_EPT_MT_EPTE_SHIFT; + if (in_slot_honor_guest_pat(vcpu->kvm, gfn)) + return
Re: [PATCH v3 6/6] x86/vmware: Add TDX hypercall support
On Tue, Dec 19, 2023 at 04:27:51PM -0800, Alexey Makhalov wrote: > > > On 12/19/23 3:23 PM, kirill.shute...@linux.intel.com wrote: > > On Tue, Dec 19, 2023 at 01:57:51PM -0800, Alexey Makhalov wrote: > > > diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c > > > index 3aa1adaed18f..ef07ab7a07e1 100644 > > > --- a/arch/x86/kernel/cpu/vmware.c > > > +++ b/arch/x86/kernel/cpu/vmware.c > > > @@ -428,6 +428,30 @@ static bool __init > > > vmware_legacy_x2apic_available(void) > > > (eax & BIT(VCPU_LEGACY_X2APIC)); > > > } > > > +#ifdef CONFIG_INTEL_TDX_GUEST > > > +unsigned long vmware_tdx_hypercall(unsigned long cmd, > > > +struct tdx_module_args *args) > > > +{ > > > + if (!hypervisor_is_type(X86_HYPER_VMWARE)) > > > + return 0; BTW, don't you want to warn here to? We don't expect vmware hypercalls to be called by non-vmware guest, do we? > > > + > > > + if (cmd & ~VMWARE_CMD_MASK) { > > > + pr_warn("Out of range command %x\n", cmd); > > > + return 0; > > > > Is zero success? Shouldn't it be an error? > > VMware hypercalls do not have a standard way of signalling an error. > To generalize expectations from the caller perspective of any existing > hypercalls: error (including hypercall is not supported or disabled) is when > return value is 0 and out1/2 are unchanged or equal to in1/in2. You are talking about signaling errors over hypercall transport. But if kernel can see that something is wrong why cannot it signal the issue clearly to caller. It is going to be in-kernel convention. And to very least, it has to be pr_warn_once(). -- Kiryl Shutsemau / Kirill A. Shutemov
Re: [PATCH v3 2/6] x86/vmware: Introduce vmware_hypercall API
On Tue, Dec 19, 2023 at 04:17:40PM -0800, Alexey Makhalov wrote: > > > On 12/19/23 3:20 PM, kirill.shute...@linux.intel.com wrote: > > On Tue, Dec 19, 2023 at 01:57:47PM -0800, Alexey Makhalov wrote: > > > +static inline > > > +unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) > > ... > > > +static inline > > > +unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, > > > + uint32_t *out1, uint32_t *out2) > > ... > > > +static inline > > > +unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, > > > + uint32_t *out1, uint32_t *out2, > > > + uint32_t *out3) > > ... > > > +static inline > > > +unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, > > > + unsigned long in3, unsigned long in4, > > > + unsigned long in5, uint32_t *out2) > > ... > > > +static inline > > > +unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1, > > > + unsigned long in3, uint32_t *out2, > > > + uint32_t *out3, uint32_t *out4, > > > + uint32_t *out5) > > ... > > > +static inline > > > +unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1, > > > + unsigned long in3, unsigned long in4, > > > + unsigned long in5, uint32_t *out1, > > > + uint32_t *out2, uint32_t *out3) > > > > Naming is weird. The number in the name doesn't help much as there seems > > no system on how many of the parameters are ins and outs. > > There was internal discussion on hypercall API naming. One of proposals was > using 2 digits - number of input and number of output arguments. > And it definitely looked weird. So, we agreed to have just single number - > total number of arguments excluding cmd. Have you considered naming them by number of input parameters? Number of output parameters as demanded by users. So vmware_hypercall4() will become vmware_hypercall1() and current vmware_hypercall1() and vmware_hypercall3() will go away. It is still awful, but /maybe/ better that this, I donno. -- Kiryl Shutsemau / Kirill A. Shutemov
Re: [PATCH v3 6/6] x86/vmware: Add TDX hypercall support
On 12/19/23 3:23 PM, kirill.shute...@linux.intel.com wrote: On Tue, Dec 19, 2023 at 01:57:51PM -0800, Alexey Makhalov wrote: diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 3aa1adaed18f..ef07ab7a07e1 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -428,6 +428,30 @@ static bool __init vmware_legacy_x2apic_available(void) (eax & BIT(VCPU_LEGACY_X2APIC)); } +#ifdef CONFIG_INTEL_TDX_GUEST +unsigned long vmware_tdx_hypercall(unsigned long cmd, + struct tdx_module_args *args) +{ + if (!hypervisor_is_type(X86_HYPER_VMWARE)) + return 0; + + if (cmd & ~VMWARE_CMD_MASK) { + pr_warn("Out of range command %x\n", cmd); + return 0; Is zero success? Shouldn't it be an error? VMware hypercalls do not have a standard way of signalling an error. To generalize expectations from the caller perspective of any existing hypercalls: error (including hypercall is not supported or disabled) is when return value is 0 and out1/2 are unchanged or equal to in1/in2. All existing vmware_hypercall callers will gracefully handle returned 0. But they should never hit this path, as 0 bail out was introduced as a protection for the case where exported vmware_tdx_hypercall is used by random caller (not following VMware hypercall ABI). + } + + args->r10 = VMWARE_TDX_VENDOR_LEAF; + args->r11 = VMWARE_TDX_HCALL_FUNC; + args->r12 = VMWARE_HYPERVISOR_MAGIC; + args->r13 = cmd; + + __tdx_hypercall(args); + + return args->r12; +} +EXPORT_SYMBOL_GPL(vmware_tdx_hypercall); +#endif + #ifdef CONFIG_AMD_MEM_ENCRYPT static void vmware_sev_es_hcall_prepare(struct ghcb *ghcb, struct pt_regs *regs) -- 2.39.0
[PULL] drm-xe-next v2
Hi Dave and Sima, Here goes a v2 of our first pull request. First PR: https://lore.kernel.org/all/zxzta75g5vhcr...@intel.com/ The lack of committer signature blocked Dave's tools on getting that. I'm sorry for that. As you know we were maintaining this branch with rebases through this past year, so I did the last rebase to fix the tags but ended up not signing off the patches. Fixing this now and hopefully we are getting in and this rebases will stop. Besides that, I also included two more commits in this PR: - One fix that would break the builds without CONFIG_FAULT_INJECTION - One commit that removes the FW loading for blobs that are not in linux-firmware.git yet. Thanks, Rodrigo. The following changes since commit a60501d7c2d3e70b3545b9b96576628e369d8e85: Merge tag 'drm-misc-next-2023-12-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next (2023-12-08 16:27:00 +1000) are available in the Git repository at: https://gitlab.freedesktop.org/drm/xe/kernel.git tags/drm-xe-next-2023-12-19-pr1 for you to fetch changes up to ba43af4e32ca80b2b977281d53636a75a93ca530: drm/xe: Remove ci-only GuC FW definitions (2023-12-19 18:52:21 -0500) Introduce a new DRM driver for Intel GPUs Xe, is a new driver for Intel GPUs that supports both integrated and discrete platforms. The experimental support starts with Tiger Lake. i915 will continue be the main production driver for the platforms up to Meteor Lake and Alchemist. Then the goal is to make this Intel Xe driver the primary driver for Lunar Lake and newer platforms. It uses most, if not all, of the key drm concepts, in special: TTM, drm-scheduler, drm-exec, drm-gpuvm/gpuva and others. Alan Previn (1): drm/xe/guc: Fix h2g_write usage of GUC_CTB_MSG_MAX_LEN Alexander Usyskin (1): drm/xe/gsc: enable pvc support Andrzej Hajda (1): drm/xe: implement driver initiated function-reset Animesh Manna (1): drm/xe/dsb: DSB implementation for xe Anshuman Gupta (7): drm/xe/pm: Disable PM on unbounded pcie parent bridge drm/xe/pm: Add pci d3cold_capable support drm/xe/pm: Refactor xe_pm_runtime_init drm/xe/pm: Add vram_d3cold_threshold Sysfs drm/xe/pm: Toggle d3cold_allowed using vram_usages drm/xe/pm: Init pcode and restore vram on power lost drm/xe/pm: Add vram_d3cold_threshold for d3cold capable device Anusha Srivatsa (10): drm/xe/huc: Support for loading unversiond HuC drm/xe: Load HuC on Alderlake S drm/xe: GuC and HuC loading support for RKL drm/xe: Add Rocketlake device info drm/xe/kunit: Handle fake device creation for all platform/subplatform cases drm/xe: Add missing ADL entries to xe_test_wa drm/xe/rplu: s/ADLP/ALDERLAKE_P drm/xe/rpls: Add RPLS Support drm/xe/rpls: Add Stepping info for RPLS drm/xe: Add missing ADL entries to xe_test_wa Aravind Iddamsetty (5): drm/xe: Get GT clock to nanosecs drm/xe: Use spinlock in forcewake instead of mutex drm/xe/pmu: Enable PMU interface drm/xe/pmu: Drop interrupt pmu event drm/xe: Fix lockdep warning in xe_force_wake calls Ashutosh Dixit (2): drm/xe/uapi: Use common drm_xe_ext_set_property extension drm/xe/pmu: Remove PMU from Xe till uapi is finalized Badal Nilawar (11): drm/xe: Donot apply forcewake while reading actual frequency drm/xe/mtl: Add support to get C6 residency/status of MTL drm/xe/hwmon: Expose power attributes drm/xe/hwmon: Expose card reactive critical power drm/xe/hwmon: Expose input voltage attribute drm/xe/hwmon: Expose hwmon energy attribute drm/xe: Extend rpX values extraction for future platforms drm/xe/hwmon: Add kernel doc and refactor xe hwmon drm/xe/hwmon: Protect hwmon rw attributes with hwmon_lock drm/xe/hwmon: Expose power1_max_interval drm/xe/mtl: Use 16.67 Mhz freq scale factor to get rpX Balasubramani Vivekanandan (9): drm/xe/gt: Enable interrupt while initializing root gt drm/xe: Use max wopcm size when validating the preset GuC wopcm size drm/xe: Stop accepting value in xe_migrate_clear drm/xe: Keep all resize bar related prints inside xe_resize_vram_bar drm/xe/xe2: Add MOCS table drm/xe/lnl: Hook up MOCS table drm/xe: Leverage ComputeCS read L3 caching drm/xe: Add event tracing for CTB drm/xe/trace: Optimize trace definition Bommithi Sakeena (3): drm/xe: Ensure mutex are destroyed drm/xe: Add a missing mutex_destroy to xe_ttm_vram_mgr drm/xe: Encapsulate all the module parameters Bommu Krishnaiah (2): drm/xe/uapi: add exec_queue_id member to drm_xe_wait_user_fence structure drm/xe/uapi: Return correct error code for xe_wait_user_fence_ioctl Brian Welty (12): drm/xe: Fix BUG_ON during bind with prefetch
Re: [PATCH v3 2/6] x86/vmware: Introduce vmware_hypercall API
On 12/19/23 3:20 PM, kirill.shute...@linux.intel.com wrote: On Tue, Dec 19, 2023 at 01:57:47PM -0800, Alexey Makhalov wrote: +static inline +unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) ... +static inline +unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2) ... +static inline +unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2, + uint32_t *out3) ... +static inline +unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, uint32_t *out2) ... +static inline +unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1, + unsigned long in3, uint32_t *out2, + uint32_t *out3, uint32_t *out4, + uint32_t *out5) ... +static inline +unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, uint32_t *out1, + uint32_t *out2, uint32_t *out3) Naming is weird. The number in the name doesn't help much as there seems no system on how many of the parameters are ins and outs. There was internal discussion on hypercall API naming. One of proposals was using 2 digits - number of input and number of output arguments. And it definitely looked weird. So, we agreed to have just single number - total number of arguments excluding cmd. Why these combinations of ins/outs are supported? VMware hypercalls can use up to 6 ins and 6 outs for LB and 7 ins and 7 outs for HB calls. The mapping to x86 registers is below: in0/out0 - rax in1/out1 - rbx in2/out2 - rcx in3/out3 - rdx in4/out4 - rsi in5/out5 - rdi in6/out6 - rbp (only used in high bandwidth hypercalls) args 0, 2 and 6 are remapped to r12, r13 and r14 for TDX. There is a standard on some arguments such as cmd on in2, magic on in0 and output value is on out0. While other arguments are not standardized across hypercall. Theoreticaly max hypercall, in term of number of arguments: vmware_hypercall9(cmd, in1, in3, in4, in5, *out1, *out2, *out3, *out4, *out5) But there is no such called in a linux kernel. Current combination of hypercalls covers all current and future (not yet upstreamed) callers, with round up to next number in some cases. And as an outsider, I'm curious where in2 got lost :P 'lost' arguments: in0 - indirectly initialized inside hypercall function. out0 - return value from the hypercall. [LB hypercalls] in2 <- input cmd [HB hypercalls] in1 <- input cmd Regards, --Alexey
Re: [net-next v1 08/16] memory-provider: dmabuf devmem memory provider
On 12/14/23 20:03, Mina Almasry wrote: On Mon, Dec 11, 2023 at 12:37 PM Pavel Begunkov wrote: ... If you remove the branch, let it fall into ->release and rely on refcounting there, then the callback could also fix up release_cnt or ask pp to do it, like in the patch I linked above Sadly I don't think this is possible due to the reasons I mention in the commit message of that patch. Prematurely releasing ppiov and not having them be candidates for recycling shows me a 4-5x degradation in performance. I don't think I follow. The concept is to only recycle a buffer (i.e. make it available for allocation) when its refs drop to zero, which is IMHO the only way it can work, and IIUC what this patchset is doing. That's also I suggest to do, but through a slightly different path. Let's say at some moment there are 2 refs (e.g. 1 for an skb and 1 for userspace/xarray). Say it first puts the skb: napi_pp_put_page() -> page_pool_return_page() -> mp_ops->release_page() -> need_to_free = put_buf() // not last ref, need_to_free==false, // don't recycle, don't increase release_cnt Then you put the last ref: page_pool_iov_put_many() -> page_pool_return_page() -> mp_ops->release_page() -> need_to_free = put_buf() // last ref, need_to_free==true, // recycle and release_cnt++ And that last put can even be recycled right into the pp / ptr_ring, in which case it doesn't need to touch release_cnt. Does it make sense? I don't see where 4-5x degradation would come from Sorry for the late reply, I have been working on this locally. What you're saying makes sense, and I'm no longer sure why I was seeing a perf degradation without '[net-next v1 10/16] page_pool: don't release iov on elevanted refcount'. However, even though what you're saying is technically correct, AFAIU it's actually semantically wrong. When a page is released by the page_pool, we should call page_pool_clear_pp_info() and completely disconnect the page from the pool. If we call release_page() on a page and then the page pool sees it again in page_pool_return_page(), I think that is considered a bug. You're adding a new feature the semantics of which is already different from what is in there, you can extend it any way as long as it makes sense and agreed on. IMHO, it does. But well, if there is a better solution I'm all for it. In fact I think what you're proposing is as a result of a bug because we don't call a page_pool_clear_pp_info() equivalent on releasing ppiov. I don't get it, what bug? page_pool_clear_pp_info() is not called for ppiov because it doesn't make sense to call it for ppiov, there is no reason to clear ppiov->pp, nor there is any pp_magic. However, I'm reasonably confident I figured out the right thing to do here. The page_pool uses page->pp_frag_count for its refcounting. pp_frag_count is a misnomer, it's being renamed to pp_ref_count in Liang's series[1]). In this series I used a get_page/put_page equivalent for refcounting. Once I transitioned to using pp_[frag|ref]_count for refcounting inside the page_pool, the issue went away, and I no longer need the patch 'page_pool: don't release iov on elevanted refcount'. Lovely, I'll take a look later! (also assuming it's in v5) There is an additional upside, since pages and ppiovs are both being refcounted using pp_[frag|ref]_count, we get some unified handling for ppiov and we reduce the checks around ppiov. This should be fixed properly in the next series. I still need to do some work (~1 week) before I upload the next version as there is a new requirement from MM that we transition to a new type and not re-use page*, but I uploaded my changes github with the refcounting issues resolved in case they're useful to you. Sorry for the churn: https://github.com/mina/linux/commits/tcpdevmem-v1.5/ [1] https://patchwork.kernel.org/project/netdevbpf/list/?series=809049=* -- Pavel Begunkov
Re: [PATCH v3 6/6] x86/vmware: Add TDX hypercall support
On Tue, Dec 19, 2023 at 01:57:51PM -0800, Alexey Makhalov wrote: > diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c > index 3aa1adaed18f..ef07ab7a07e1 100644 > --- a/arch/x86/kernel/cpu/vmware.c > +++ b/arch/x86/kernel/cpu/vmware.c > @@ -428,6 +428,30 @@ static bool __init vmware_legacy_x2apic_available(void) > (eax & BIT(VCPU_LEGACY_X2APIC)); > } > > +#ifdef CONFIG_INTEL_TDX_GUEST > +unsigned long vmware_tdx_hypercall(unsigned long cmd, > +struct tdx_module_args *args) > +{ > + if (!hypervisor_is_type(X86_HYPER_VMWARE)) > + return 0; > + > + if (cmd & ~VMWARE_CMD_MASK) { > + pr_warn("Out of range command %x\n", cmd); > + return 0; Is zero success? Shouldn't it be an error? > + } > + > + args->r10 = VMWARE_TDX_VENDOR_LEAF; > + args->r11 = VMWARE_TDX_HCALL_FUNC; > + args->r12 = VMWARE_HYPERVISOR_MAGIC; > + args->r13 = cmd; > + > + __tdx_hypercall(args); > + > + return args->r12; > +} > +EXPORT_SYMBOL_GPL(vmware_tdx_hypercall); > +#endif > + > #ifdef CONFIG_AMD_MEM_ENCRYPT > static void vmware_sev_es_hcall_prepare(struct ghcb *ghcb, > struct pt_regs *regs) > -- > 2.39.0 > -- Kiryl Shutsemau / Kirill A. Shutemov
Re: [PATCH v3 2/6] x86/vmware: Introduce vmware_hypercall API
On Tue, Dec 19, 2023 at 01:57:47PM -0800, Alexey Makhalov wrote: > +static inline > +unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) ... > +static inline > +unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, > + uint32_t *out1, uint32_t *out2) ... > +static inline > +unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, > + uint32_t *out1, uint32_t *out2, > + uint32_t *out3) ... > +static inline > +unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, > + unsigned long in3, unsigned long in4, > + unsigned long in5, uint32_t *out2) ... > +static inline > +unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1, > + unsigned long in3, uint32_t *out2, > + uint32_t *out3, uint32_t *out4, > + uint32_t *out5) ... > +static inline > +unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1, > + unsigned long in3, unsigned long in4, > + unsigned long in5, uint32_t *out1, > + uint32_t *out2, uint32_t *out3) Naming is weird. The number in the name doesn't help much as there seems no system on how many of the parameters are ins and outs. Why these combinations of ins/outs are supported? And as an outsider, I'm curious where in2 got lost :P -- Kiryl Shutsemau / Kirill A. Shutemov
Re: [PATCH v6] drm/msm/dpu: improve DSC allocation
On Tue, 19 Dec 2023 at 18:18, Kuogee Hsieh wrote: > > Hi Dmitry, > > Anymore comments from you? No, for some reason I missed this patch. Please excuse me. > On 12/14/2023 10:56 AM, Kuogee Hsieh wrote: > > At DSC V1.1 DCE (Display Compression Engine) contains a DSC encoder. > > However, at DSC V1.2 DCE consists of two DSC encoders, one has an odd > > index and another one has an even index. Each encoder can work > > independently. But only two DSC encoders from same DCE can be paired > > to work together to support DSC merge mode at DSC V1.2. For DSC V1.1 > > two consecutive DSC encoders (start with even index) have to be paired > > to support DSC merge mode. In addition, the DSC with even index have > > to be mapped to even PINGPONG index and DSC with odd index have to be > > mapped to odd PINGPONG index at its data path in regardless of DSC > > V1.1 or V1.2. This patch improves DSC allocation mechanism with > > consideration of those factors. > > > > Changes in V6: > > -- rename _dpu_rm_reserve_dsc_single to _dpu_rm_dsc_alloc > > -- rename _dpu_rm_reserve_dsc_pair to _dpu_rm_dsc_alloc_pair > > -- pass global_state to _dpu_rm_pingpong_next_index() > > -- remove pp_max > > -- fix for loop condition check at _dpu_rm_dsc_alloc() > > > > Changes in V5: > > -- delete dsc_id[] > > -- update to global_state->dsc_to_enc_id[] directly > > -- replace ndx with idx > > -- fix indentation at function declaration > > -- only one for loop at _dpu_rm_reserve_dsc_single() > > > > Changes in V4: > > -- rework commit message > > -- use reserved_by_other() > > -- add _dpu_rm_pingpong_next_index() > > -- revise _dpu_rm_pingpong_dsc_check() > > > > Changes in V3: > > -- add dpu_rm_pingpong_dsc_check() > > -- for pair allocation use i += 2 at for loop > > > > Changes in V2: > > -- split _dpu_rm_reserve_dsc() into _dpu_rm_reserve_dsc_single() and > > _dpu_rm_reserve_dsc_pair() > > > > Fixes: f2803ee91a41 ("drm/msm/disp/dpu1: Add DSC support in RM") > > Signed-off-by: Kuogee Hsieh > > --- > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 154 > > + > > 1 file changed, 139 insertions(+), 15 deletions(-) Reviewed-by: Dmitry Baryshkov See below for minor nit. > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c > > index f9215643..0ce2a25 100644 > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c > > @@ -461,29 +461,153 @@ static int _dpu_rm_reserve_ctls( > > return 0; > > } > > > > -static int _dpu_rm_reserve_dsc(struct dpu_rm *rm, > > -struct dpu_global_state *global_state, > > -struct drm_encoder *enc, > > -const struct msm_display_topology *top) > > +static int _dpu_rm_pingpong_next_index(struct dpu_global_state > > *global_state, > > +int start, I'd still prefer to see `enum dpu_pingpong` as a parameter here instead of just an index, but this is just my taste. > > +uint32_t enc_id) > > { > > - int num_dsc = top->num_dsc; > > int i; > > > > - /* check if DSC required are allocated or not */ > > - for (i = 0; i < num_dsc; i++) { > > - if (!rm->dsc_blks[i]) { > > - DPU_ERROR("DSC %d does not exist\n", i); > > - return -EIO; > > + for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) { > > + if (global_state->pingpong_to_enc_id[i] == enc_id) > > + return i; > > + } > > + > > + return -ENAVAIL; > > +} > > + > > +static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx) > > +{ > > + /* > > + * DSC with even index must be used with the PINGPONG with even index > > + * DSC with odd index must be used with the PINGPONG with odd index > > + */ > > + if ((dsc_idx & 0x01) != (pp_idx & 0x01)) > > + return -ENAVAIL; > > + > > + return 0; > > +} > > + > > +static int _dpu_rm_dsc_alloc(struct dpu_rm *rm, > > + struct dpu_global_state *global_state, > > + uint32_t enc_id, > > + const struct msm_display_topology *top) > > +{ > > + int num_dsc = 0; > > + int pp_idx = 0; > > + int dsc_idx; > > + int ret; > > + > > + for (dsc_idx = 0; dsc_idx < ARRAY_SIZE(rm->dsc_blks) && > > + num_dsc < top->num_dsc; dsc_idx++) { > > + if (!rm->dsc_blks[dsc_idx]) > > + continue; > > + > > + if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, > > enc_id)) > > + continue; > > + > > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, > > enc_id); > > + if (pp_idx < 0) > > + return -ENAVAIL; > > + > > + ret = _dpu_rm_pingpong_dsc_check(dsc_idx, pp_idx); > > +
Re: [PATCH 01/27] sparc32: Update defconfig to LEON SMP
On Tue, Dec 19, 2023, at 22:03, Sam Ravnborg via B4 Relay wrote: > From: Sam Ravnborg > > This is a copy of the leon_smp defconfig found in > gaisler-buildroot-2023.02-1.0. > > Signed-off-by: Sam Ravnborg > Cc: "David S. Miller" > Cc: Arnd Bergmann > Cc: Andreas Larsson I did not get a cover letter for the series, but I looked at all 27 patches and they all look good to me, nice cleanup! Acked-by: Arnd Bergmann
[PATCH 07/27] sparc32: Drop run-time patching of ipi trap
From: Sam Ravnborg There is no longer any need for the run-time patching of the ipi trap with the removal of sun4m and sun4d. Remove the patching and drop the ipi implementation for the two machines. The patch includes removal of patching from pcic as this was needed to fix the build. pcic will be removed in a later commit. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/kernel/entry.S | 70 ++- arch/sparc/kernel/kernel.h| 4 --- arch/sparc/kernel/leon_smp.c | 3 -- arch/sparc/kernel/pcic.c | 11 --- arch/sparc/kernel/sun4d_smp.c | 3 -- arch/sparc/kernel/ttable_32.S | 9 +++--- 6 files changed, 7 insertions(+), 93 deletions(-) diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index c6a5cb949381..7cf148a996b9 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -174,32 +174,6 @@ maybe_smp4m_msg_check_resched: maybe_smp4m_msg_out: RESTORE_ALL - .align 4 - .globl linux_trap_ipi15_sun4m -linux_trap_ipi15_sun4m: - SAVE_ALL - sethi %hi(0x8000), %o2 - GET_PROCESSOR4M_ID(o0) - sethi %hi(sun4m_irq_percpu), %l5 - or %l5, %lo(sun4m_irq_percpu), %o5 - sll %o0, 2, %o0 - ld [%o5 + %o0], %o5 - ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending - andcc %o3, %o2, %g0 - be sun4m_nmi_error ! Must be an NMI async memory error -st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x8000 - WRITE_PAUSE - ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending - WRITE_PAUSE - or %l0, PSR_PIL, %l4 - wr %l4, 0x0, %psr - WRITE_PAUSE - wr %l4, PSR_ET, %psr - WRITE_PAUSE - callsmp4m_cross_call_irq -nop - b ret_trap_lockless_ipi -clr%l6 .globl smp4d_ticker /* SMP per-cpu ticker interrupts are handled specially. */ @@ -220,44 +194,6 @@ smp4d_ticker: WRITE_PAUSE RESTORE_ALL - .align 4 - .globl linux_trap_ipi15_sun4d -linux_trap_ipi15_sun4d: - SAVE_ALL - sethi %hi(CC_BASE), %o4 - sethi %hi(MXCC_ERR_ME|MXCC_ERR_PEW|MXCC_ERR_ASE|MXCC_ERR_PEE), %o2 - or %o4, (CC_EREG - CC_BASE), %o0 - ldda[%o0] ASI_M_MXCC, %o0 - andcc %o0, %o2, %g0 - bne 1f -sethi %hi(BB_STAT2), %o2 - lduba [%o2] ASI_M_CTL, %o2 - andcc %o2, BB_STAT2_MASK, %g0 - bne 2f -or %o4, (CC_ICLR - CC_BASE), %o0 - sethi %hi(1 << 15), %o1 - stha%o1, [%o0] ASI_M_MXCC /* Clear PIL 15 in MXCC's ICLR */ - or %l0, PSR_PIL, %l4 - wr %l4, 0x0, %psr - WRITE_PAUSE - wr %l4, PSR_ET, %psr - WRITE_PAUSE - callsmp4d_cross_call_irq -nop - b ret_trap_lockless_ipi -clr%l6 - -1: /* MXCC error */ -2: /* BB error */ - /* Disable PIL 15 */ - set CC_IMSK, %l4 - lduha [%l4] ASI_M_MXCC, %l5 - sethi %hi(1 << 15), %l7 - or %l5, %l7, %l5 - stha%l5, [%l4] ASI_M_MXCC - /* FIXME */ -1: b,a 1b - .globl smpleon_ipi .extern leon_ipi_interrupt /* SMP per-cpu IPI interrupts are handled specially. */ @@ -618,11 +554,11 @@ sun4m_nmi_error: #ifndef CONFIG_SMP .align 4 - .globl linux_trap_ipi15_sun4m -linux_trap_ipi15_sun4m: + .globl linux_trap_ipi15_leon +linux_trap_ipi15_leon: SAVE_ALL - ba sun4m_nmi_error + ba sun4m_nmi_error nop #endif /* CONFIG_SMP */ diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index c8ba3bc7e137..1d3980ac0658 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -134,10 +134,6 @@ void leonsmp_ipi_interrupt(void); void leon_cross_call_irq(void); /* head_32.S */ -extern unsigned int t_nmi[]; -extern unsigned int linux_trap_ipi15_sun4d[]; -extern unsigned int linux_trap_ipi15_sun4m[]; - extern struct tt_entry trapbase; extern struct tt_entry trapbase_cpu1; extern struct tt_entry trapbase_cpu2; diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 991e9ad3d3e8..42820c7422dd 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -463,8 +463,5 @@ static const struct sparc32_ipi_ops leon_ipi_ops = { void __init leon_init_smp(void) { - /* Patch ipi15 trap table */ - t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m); - sparc32_ipi_ops = _ipi_ops; } diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 25fe0a061732..d952bcbbc395 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -354,17 +354,6 @@ int __init pcic_probe(void) prom_getstring(node, "name", namebuf,
[PATCH 12/27] sparc32: Drop mbus support
From: Sam Ravnborg Only used by older SPARC HW, not used by LEON. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/elf_32.h | 2 - arch/sparc/include/asm/mbus.h | 97 - arch/sparc/kernel/cpu.c | 1 - arch/sparc/kernel/setup_32.c| 1 - arch/sparc/mm/iommu.c | 18 ++-- arch/sparc/mm/srmmu.c | 48 6 files changed, 3 insertions(+), 164 deletions(-) diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h index 37a6016c9ccd..b2cca9be55c2 100644 --- a/arch/sparc/include/asm/elf_32.h +++ b/arch/sparc/include/asm/elf_32.h @@ -91,8 +91,6 @@ typedef struct { unsigned intpr_q[64]; } elf_fpregset_t; -#include - /* * This is used to ensure we don't load something for the wrong architecture. */ diff --git a/arch/sparc/include/asm/mbus.h b/arch/sparc/include/asm/mbus.h deleted file mode 100644 index 8b6dbe701b9b.. --- a/arch/sparc/include/asm/mbus.h +++ /dev/null @@ -1,97 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * mbus.h: Various defines for MBUS modules. - * - * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu) - */ - -#ifndef _SPARC_MBUS_H -#define _SPARC_MBUS_H - -#include /* HyperSparc stuff */ -#include /* Ugh, bug city... */ - -enum mbus_module { - HyperSparc= 0, - Swift_ok = 4, - Swift_bad_c = 5, - Swift_lots_o_bugs = 6, - Tsunami = 7, - Viking_12 = 8, - Viking_2x = 9, - Viking_30 = 10, - Viking_35 = 11, - Viking_new= 12, - TurboSparc= 13, - SRMMU_INVAL_MOD = 14, -}; - -extern enum mbus_module srmmu_modtype; -extern unsigned int viking_rev, swift_rev, cypress_rev; - -/* HW Mbus module bugs we have to deal with */ -#define HWBUG_COPYBACK_BROKEN0x0001 -#define HWBUG_ASIFLUSH_BROKEN0x0002 -#define HWBUG_VACFLUSH_BITROT0x0004 -#define HWBUG_KERN_ACCBROKEN 0x0008 -#define HWBUG_KERN_CBITBROKEN0x0010 -#define HWBUG_MODIFIED_BITROT0x0020 -#define HWBUG_PC_BADFAULT_ADDR 0x0040 -#define HWBUG_SUPERSCALAR_BAD0x0080 -#define HWBUG_PACINIT_BITROT 0x0100 - -/* First the module type values. To find out which you have, just load - * the mmu control register from ASI_M_MMUREG alternate address space and - * shift the value right 28 bits. - */ -/* IMPL field means the company which produced the chip. */ -#define MBUS_VIKING0x4 /* bleech, Texas Instruments Module */ -#define MBUS_LSI 0x3 /* LSI Logics */ -#define MBUS_ROSS 0x1 /* Ross is nice */ -#define MBUS_FMI 0x0 /* Fujitsu Microelectronics/Swift */ - -/* Ross Module versions */ -#define ROSS_604_REV_CDE0x0 /* revisions c, d, and e */ -#define ROSS_604_REV_F 0x1 /* revision f */ -#define ROSS_6050xf /* revision a, a.1, and a.2 */ -#define ROSS_605_REV_B 0xe /* revision b */ - -/* TI Viking Module versions */ -#define VIKING_REV_12 0x1 /* Version 1.2 or SPARCclassic's CPU */ -#define VIKING_REV_20x2 /* Version 2.1, 2.2, 2.3, and 2.4 */ -#define VIKING_REV_30 0x3 /* Version 3.0 */ -#define VIKING_REV_35 0x4 /* Version 3.5 */ - -/* LSI Logics. */ -#define LSI_L64815 0x0 - -/* Fujitsu */ -#define FMI_AURORA 0x4 /* MB8690x, a Swift module... */ -#define FMI_TURBO 0x5 /* MB86907, a TurboSparc module... */ - -/* For multiprocessor support we need to be able to obtain the CPU id and - * the MBUS Module id. - */ - -/* The CPU ID is encoded in the trap base register, 20 bits to the left of - * bit zero, with 2 bits being significant. - */ -#define TBR_ID_SHIFT20 - -static inline int get_cpuid(void) -{ - register int retval; - __asm__ __volatile__("rd %%tbr, %0\n\t" -"srl %0, %1, %0\n\t" : -"=r" (retval) : -"i" (TBR_ID_SHIFT)); - return (retval & 3); -} - -static inline int get_modid(void) -{ - return (get_cpuid() | 0x8); -} - - -#endif /* !(_SPARC_MBUS_H) */ diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 79cd6ccfeac0..cca7de051593 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "kernel.h" diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index e3b72a7b46d3..5a497140c52a 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index
[PATCH 20/27] sparc32: Drop unused prom ranges support
From: Sam Ravnborg Drop support for prom ranges - not used anymore. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/oplib_32.h | 11 arch/sparc/prom/Makefile | 1 - arch/sparc/prom/init_32.c | 2 - arch/sparc/prom/ranges.c | 114 -- 4 files changed, 128 deletions(-) diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index d1cf3a27a40d..4ef7f05978d3 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -163,17 +163,6 @@ int prom_setprop(phandle node, const char *prop_name, char *prop_value, phandle prom_inst2pkg(int); -/* Dorking with Bus ranges... */ - -/* Apply promlib probes OBIO ranges to registers. */ -void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs); - -/* Apply ranges of any prom node (and optionally parent node as well) to registers. */ -void prom_apply_generic_ranges(phandle node, phandle parent, - struct linux_prom_registers *sbusregs, int nregs); - -void prom_ranges_init(void); - /* CPU probing helpers. */ int cpu_find_by_instance(int instance, phandle *prom_node, int *mid); int cpu_find_by_mid(int mid, phandle *prom_node); diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile index 397b79af77f7..6d94d8b28bcf 100644 --- a/arch/sparc/prom/Makefile +++ b/arch/sparc/prom/Makefile @@ -10,7 +10,6 @@ lib-y += init_$(BITS).o lib-$(CONFIG_SPARC32) += memory.o lib-y += misc_$(BITS).o lib-$(CONFIG_SPARC32) += mp.o -lib-$(CONFIG_SPARC32) += ranges.o lib-y += console_$(BITS).o lib-y += printf.o lib-y += tree_$(BITS).o diff --git a/arch/sparc/prom/init_32.c b/arch/sparc/prom/init_32.c index d20470166cb1..1681f1f980d4 100644 --- a/arch/sparc/prom/init_32.c +++ b/arch/sparc/prom/init_32.c @@ -67,8 +67,6 @@ void __init prom_init(struct linux_romvec *rp) prom_meminit(); - prom_ranges_init(); - printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n", romvec->pv_romvers, prom_rev); diff --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c deleted file mode 100644 index 20cb828bc5f4.. --- a/arch/sparc/prom/ranges.c +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ranges.c: Handle ranges in newer proms for obio/sbus. - * - * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz) - */ - -#include -#include - -#include -#include -#include - -static struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; -static int num_obio_ranges; - -/* Adjust register values based upon the ranges parameters. */ -static void prom_adjust_regs(struct linux_prom_registers *regp, int nregs, -struct linux_prom_ranges *rangep, int nranges) -{ - int regc, rngc; - - for (regc = 0; regc < nregs; regc++) { - for (rngc = 0; rngc < nranges; rngc++) - if (regp[regc].which_io == rangep[rngc].ot_child_space) - break; /* Fount it */ - if (rngc == nranges) /* oops */ - prom_printf("adjust_regs: Could not find range with matching bus type...\n"); - regp[regc].which_io = rangep[rngc].ot_parent_space; - regp[regc].phys_addr -= rangep[rngc].ot_child_base; - regp[regc].phys_addr += rangep[rngc].ot_parent_base; - } -} - -static void prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1, - struct linux_prom_ranges *ranges2, int nranges2) -{ - int rng1c, rng2c; - - for (rng1c = 0; rng1c < nranges1; rng1c++) { - for (rng2c = 0; rng2c < nranges2; rng2c++) - if (ranges1[rng1c].ot_parent_space == ranges2[rng2c].ot_child_space && - ranges1[rng1c].ot_parent_base >= ranges2[rng2c].ot_child_base && - ranges2[rng2c].ot_child_base + ranges2[rng2c].or_size - ranges1[rng1c].ot_parent_base > 0U) - break; - if (rng2c == nranges2) /* oops */ - prom_printf("adjust_ranges: Could not find matching bus type...\n"); - else if (ranges1[rng1c].ot_parent_base + ranges1[rng1c].or_size > ranges2[rng2c].ot_child_base + ranges2[rng2c].or_size) - ranges1[rng1c].or_size = ranges2[rng2c].ot_child_base + ranges2[rng2c].or_size - ranges1[rng1c].ot_parent_base; - ranges1[rng1c].ot_parent_space = ranges2[rng2c].ot_parent_space; - ranges1[rng1c].ot_parent_base += ranges2[rng2c].ot_parent_base; - } -} - -/* Apply probed obio ranges to registers passed, if no ranges return. */ -void
[PATCH 14/27] sparc32: Drop unused mmu models
From: Sam Ravnborg Drop mmu models not used by LEON, including their header files. This includes removal of unused includes in various files to fix the build. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/mxcc.h | 138 --- arch/sparc/include/asm/ross.h | 192 - arch/sparc/include/asm/swift.h | 107 - arch/sparc/include/asm/tsunami.h| 65 --- arch/sparc/include/asm/turbosparc.h | 126 -- arch/sparc/include/asm/viking.h | 255 arch/sparc/kernel/entry.S | 1 - arch/sparc/mm/Makefile | 1 - arch/sparc/mm/hypersparc.S | 414 --- arch/sparc/mm/io-unit.c | 1 - arch/sparc/mm/iommu.c | 31 +- arch/sparc/mm/mm_32.h | 1 - arch/sparc/mm/srmmu.c | 776 +--- arch/sparc/mm/swift.S | 256 arch/sparc/mm/tsunami.S | 132 -- arch/sparc/mm/viking.S | 284 - 16 files changed, 21 insertions(+), 2759 deletions(-) diff --git a/arch/sparc/include/asm/mxcc.h b/arch/sparc/include/asm/mxcc.h deleted file mode 100644 index 3a2561bea4dd.. --- a/arch/sparc/include/asm/mxcc.h +++ /dev/null @@ -1,138 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * mxcc.h: Definitions of the Viking MXCC registers - * - * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu) - */ - -#ifndef _SPARC_MXCC_H -#define _SPARC_MXCC_H - -/* These registers are accessed through ASI 0x2. */ -#define MXCC_DATSTREAM 0x1C0 /* Data stream register */ -#define MXCC_SRCSTREAM 0x1C00100 /* Source stream register */ -#define MXCC_DESSTREAM 0x1C00200 /* Destination stream register */ -#define MXCC_RMCOUNT 0x1C00300 /* Count of references and misses */ -#define MXCC_STEST 0x1C00804 /* Internal self-test */ -#define MXCC_CREG0x1C00A04 /* Control register */ -#define MXCC_SREG0x1C00B00 /* Status register */ -#define MXCC_RREG0x1C00C04 /* Reset register */ -#define MXCC_EREG0x1C00E00 /* Error code register */ -#define MXCC_PREG0x1C00F04 /* Address port register */ - -/* Some MXCC constants. */ -#define MXCC_STREAM_SIZE 0x20 /* Size in bytes of one stream r/w */ - -/* The MXCC Control Register: - * - * -- - * | | RRC | RSV |PRE|MCE|PARE|ECE|RSV| - * -- - * 31 1098-6 5 43 2 1-0 - * - * RRC: Controls what you read from MXCC_RMCOUNT reg. - * 0=Misses 1=References - * PRE: Prefetch enable - * MCE: Multiple Command Enable - * PARE: Parity enable - * ECE: External cache enable - */ - -#define MXCC_CTL_RRC 0x0200 -#define MXCC_CTL_PRE 0x0020 -#define MXCC_CTL_MCE 0x0010 -#define MXCC_CTL_PARE 0x0008 -#define MXCC_CTL_ECE 0x0004 - -/* The MXCC Error Register: - * - * - * |ME| RSV|CE|PEW|PEE|ASE|EIV| MOPC|ECODE|PRIV|RSV|HPADDR| - * - * 31 30 29 28 27 26 25 24-15 14-7 6 5-3 2-0 - * - * ME: Multiple Errors have occurred - * CE: Cache consistency Error - * PEW: Parity Error during a Write operation - * PEE: Parity Error involving the External cache - * ASE: ASynchronous Error - * EIV: This register is toast - * MOPC: MXCC Operation Code for instance causing error - * ECODE: The Error CODE - * PRIV: A privileged mode error? 0=no 1=yes - * HPADDR: High PhysicalADDRess bits (35-32) - */ - -#define MXCC_ERR_ME 0x8000 -#define MXCC_ERR_CE 0x2000 -#define MXCC_ERR_PEW0x1000 -#define MXCC_ERR_PEE0x0800 -#define MXCC_ERR_ASE0x0400 -#define MXCC_ERR_EIV0x0200 -#define MXCC_ERR_MOPC 0x01FF8000 -#define MXCC_ERR_ECODE 0x7F80 -#define MXCC_ERR_PRIV 0x0040 -#define MXCC_ERR_HPADDR 0x000f - -/* The MXCC Port register: - * - * - - * || MID || - * - - * 3121 20-18 17 0 - * - * MID: The moduleID of the cpu your read this from. - */ - -#ifndef __ASSEMBLY__ - -static inline void mxcc_set_stream_src(unsigned long *paddr) -{ - unsigned long data0 = paddr[0]; - unsigned long data1 = paddr[1]; - - __asm__ __volatile__ ("or %%g0, %0, %%g2\n\t" - "or %%g0, %1, %%g3\n\t" - "stda %%g2, [%2] %3\n\t" : : - "r" (data0), "r" (data1), - "r" (MXCC_SRCSTREAM), -
[PATCH 13/27] sparc32: Drop unused function __get_{phys,iospace}
From: Sam Ravnborg Not used and references stuff that will be dropped later. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/pgtable_32.h | 24 arch/sparc/include/asm/pgtsrmmu.h | 11 --- 2 files changed, 35 deletions(-) diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index 9e85d57ac3f2..92b063531d5c 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h @@ -368,30 +368,6 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte) return __pte(pte_val(pte) & ~SRMMU_SWP_EXCLUSIVE); } -static inline unsigned long -__get_phys (unsigned long addr) -{ - switch (sparc_cpu_model){ - case sun4m: - case sun4d: - return ((srmmu_get_pte (addr) & 0xff00) << 4); - default: - return 0; - } -} - -static inline int -__get_iospace (unsigned long addr) -{ - switch (sparc_cpu_model){ - case sun4m: - case sun4d: - return (srmmu_get_pte (addr) >> 28); - default: - return -1; - } -} - /* * For sparc32&64, the pfn in io_remap_pfn_range() carries in * its high 4 bits. These macros/functions put it there or get it from there. diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h index 18e68d43f036..7cb5cbc83211 100644 --- a/arch/sparc/include/asm/pgtsrmmu.h +++ b/arch/sparc/include/asm/pgtsrmmu.h @@ -125,17 +125,6 @@ static inline void srmmu_flush_whole_tlb(void) } -static inline int -srmmu_get_pte (unsigned long addr) -{ - register unsigned long entry; - - __asm__ __volatile__("\n\tlda [%1] %2,%0\n\t" : - "=r" (entry): - "r" ((addr & 0xf000) | 0x400), "i" (ASI_M_FLUSH_PROBE)); - return entry; -} - #endif /* !(__ASSEMBLY__) */ #endif /* !(_SPARC_PGTSRMMU_H) */ -- 2.34.1
[PATCH 06/27] sparc32: Drop auxio support
From: Sam Ravnborg auxio is not supported by LEON - so drop it. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/auxio_32.h | 73 +--- arch/sparc/kernel/Makefile| 2 +- arch/sparc/kernel/auxio_32.c | 139 -- arch/sparc/kernel/devices.c | 3 - arch/sparc/kernel/kernel.h| 4 -- arch/sparc/kernel/process_32.c| 10 --- arch/sparc/prom/misc_32.c | 2 - 7 files changed, 3 insertions(+), 230 deletions(-) diff --git a/arch/sparc/include/asm/auxio_32.h b/arch/sparc/include/asm/auxio_32.h index 852457c7a265..e2335ddd359d 100644 --- a/arch/sparc/include/asm/auxio_32.h +++ b/arch/sparc/include/asm/auxio_32.h @@ -1,43 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * auxio.h: Definitions and code for the Auxiliary I/O register. + * Dummy definitions for the Auxiliary I/O register. * * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu) */ #ifndef _SPARC_AUXIO_H #define _SPARC_AUXIO_H -#include - -/* This register is an unsigned char in IO space. It does two things. - * First, it is used to control the front panel LED light on machines - * that have it (good for testing entry points to trap handlers and irq's) - * Secondly, it controls various floppy drive parameters. - */ -#define AUXIO_ORMEIN 0xf0/* All writes must set these bits. */ -#define AUXIO_ORMEIN4M0xc0/* sun4m - All writes must set these bits. */ -#define AUXIO_FLPY_DENS 0x20/* Floppy density, high if set. Read only. */ -#define AUXIO_FLPY_DCHG 0x10/* A disk change occurred. Read only. */ -#define AUXIO_EDGE_ON 0x10/* sun4m - On means Jumper block is in. */ -#define AUXIO_FLPY_DSEL 0x08/* Drive select/start-motor. Write only. */ -#define AUXIO_LINK_TEST 0x08/* sun4m - On means TPE Carrier detect. */ - -/* Set the following to one, then zero, after doing a pseudo DMA transfer. */ -#define AUXIO_FLPY_TCNT 0x04/* Floppy terminal count. Write only. */ - -/* Set the following to zero to eject the floppy. */ -#define AUXIO_FLPY_EJCT 0x02/* Eject floppy disk. Write only. */ -#define AUXIO_LED 0x01/* On if set, off if unset. Read/Write */ - -#ifndef __ASSEMBLY__ - -/* - * NOTE: these routines are implementation dependent-- - * understand the hardware you are querying! - */ -void set_auxio(unsigned char bits_on, unsigned char bits_off); -unsigned char get_auxio(void); /* .../asm/floppy.h */ - /* * The following routines are provided for driver-compatibility * with sparc64 (primarily sunlance.c) @@ -46,44 +15,6 @@ unsigned char get_auxio(void); /* .../asm/floppy.h */ #define AUXIO_LTE_ON1 #define AUXIO_LTE_OFF 0 -/* auxio_set_lte - Set Link Test Enable (TPE Link Detect) - * - * on - AUXIO_LTE_ON or AUXIO_LTE_OFF - */ -#define auxio_set_lte(on) \ -do { \ - if(on) { \ - set_auxio(AUXIO_LINK_TEST, 0); \ - } else { \ - set_auxio(0, AUXIO_LINK_TEST); \ - } \ -} while (0) - -#define AUXIO_LED_ON1 -#define AUXIO_LED_OFF 0 - -/* auxio_set_led - Set system front panel LED - * - * on - AUXIO_LED_ON or AUXIO_LED_OFF - */ -#define auxio_set_led(on) \ -do { \ - if(on) { \ - set_auxio(AUXIO_LED, 0); \ - } else { \ - set_auxio(0, AUXIO_LED); \ - } \ -} while (0) - -#endif /* !(__ASSEMBLY__) */ - - -/* AUXIO2 (Power Off Control) */ -extern volatile u8 __iomem *auxio_power_register; - -#defineAUXIO_POWER_DETECT_FAILURE 32 -#defineAUXIO_POWER_CLEAR_FAILURE 2 -#defineAUXIO_POWER_OFF 1 - +#define auxio_set_lte(on) #endif /* !(_SPARC_AUXIO_H) */ diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index ab47823f8b4e..577cb57c588a 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -83,7 +83,7 @@ obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o obj-$(CONFIG_SPARC64_SMP) += hvtramp.o -obj-y += auxio_$(BITS).o +obj-$(CONFIG_SPARC64) += auxio_64.o obj-y += termios.o diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c deleted file mode 100644 index 989860e890c4.. --- a/arch/sparc/kernel/auxio_32.c +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* auxio.c: Probing for the Sparc AUXIO register at boot time. - * - * Copyright (C) 1996 David S. Miller (da...@caip.rutgers.edu) - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include /* memset(), Linux has no bzero() */ -#include - -#include "kernel.h" - -/* Probe and map in the Auxiliary I/O register */ - -/* auxio_register is not static because it is referenced - * in entry.S::floppy_tdone - */ -void __iomem
[PATCH 24/27] sparc32: Drop config SPARC_LEON
From: Sam Ravnborg The only support sparc32 CPU is LEON, so there is no need for a config option to select it. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/Kconfig | 27 +-- arch/sparc/configs/sparc32_defconfig | 1 - drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ehci-hcd.c | 4 ++-- drivers/usb/host/uhci-hcd.c | 2 +- 5 files changed, 13 insertions(+), 23 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 7ae304bab2d8..0fc52c3c7487 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -9,6 +9,10 @@ config 64BIT Say yes to build a 64-bit kernel - formerly known as sparc64 Say no to build a 32-bit kernel - formerly known as sparc + The 32-bit kernel target the synthesizable LEON SPARC processor. + LEON is a part of the GRLIB collection of IP cores that are + distributed under GPL. GRLIB can be downloaded from www.gaisler.com. + You can download a sparc-linux cross-compilation toolchain at www.gaisler.com. config SPARC bool @@ -60,6 +64,10 @@ config SPARC32 select HAVE_UID16 select LOCK_MM_AND_FIND_VMA select OLD_SIGACTION + select USB_EHCI_BIG_ENDIAN_MMIO + select USB_EHCI_BIG_ENDIAN_DESC + select USB_UHCI_BIG_ENDIAN_MMIO + select USB_UHCI_BIG_ENDIAN_DESC select ZONE_DMA config SPARC64 @@ -348,22 +356,6 @@ config SERIAL_CONSOLE If unsure, say N. -config SPARC_LEON - bool "Sparc Leon processor family" - depends on SPARC32 - select USB_EHCI_BIG_ENDIAN_MMIO - select USB_EHCI_BIG_ENDIAN_DESC - select USB_UHCI_BIG_ENDIAN_MMIO - select USB_UHCI_BIG_ENDIAN_DESC - help - If you say Y here if you are running on a SPARC-LEON processor. - The LEON processor is a synthesizable VHDL model of the - SPARC-v8 standard. LEON is part of the GRLIB collection of - IP cores that are distributed under GPL. GRLIB can be downloaded - from www.gaisler.com. You can download a sparc-linux cross-compilation - toolchain at www.gaisler.com. - -if SPARC_LEON menu "U-Boot options" config UBOOT_LOAD_ADDR @@ -394,7 +386,6 @@ config UBOOT_ENTRY_ADDR Kernel. endmenu -endif endmenu @@ -416,7 +407,7 @@ config SUN_LDOMS config LEON_PCI bool - depends on PCI && SPARC_LEON + depends on PCI && SPARC32 default y config SPARC_GRPCI1 diff --git a/arch/sparc/configs/sparc32_defconfig b/arch/sparc/configs/sparc32_defconfig index 71273fc578bf..dfd326f20876 100644 --- a/arch/sparc/configs/sparc32_defconfig +++ b/arch/sparc/configs/sparc32_defconfig @@ -10,7 +10,6 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_ZSTD is not set CONFIG_SMP=y CONFIG_HZ_100=y -CONFIG_SPARC_LEON=y CONFIG_SUN_OPENPROMFS=y CONFIG_SUN_OPENPROMIO=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 4448d0ab06f0..c5f94c70482f 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -595,7 +595,7 @@ config USB_UHCI_HCD config USB_UHCI_SUPPORT_NON_PCI_HC bool - default y if (SPARC_LEON || USB_UHCI_PLATFORM) + default y if (SPARC32 || USB_UHCI_PLATFORM) config USB_UHCI_PLATFORM bool diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 802bfafb1012..5011bc8348bb 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1329,7 +1329,7 @@ MODULE_LICENSE ("GPL"); #include "ehci-xilinx-of.c" #endif -#ifdef CONFIG_SPARC_LEON +#ifdef CONFIG_SPARC32 #include "ehci-grlib.c" #endif @@ -1343,7 +1343,7 @@ static struct platform_driver * const platform_drivers[] = { #ifdef CONFIG_XPS_USB_HCD_XILINX _hcd_xilinx_of_driver, #endif -#ifdef CONFIG_SPARC_LEON +#ifdef CONFIG_SPARC32 _grlib_driver, #endif }; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index fd2408b553cf..7cb820963988 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -846,7 +846,7 @@ static const char hcd_name[] = "uhci_hcd"; #definePCI_DRIVER uhci_pci_driver #endif -#ifdef CONFIG_SPARC_LEON +#ifdef CONFIG_SPARC32 #include "uhci-grlib.c" #define PLATFORM_DRIVERuhci_grlib_driver #endif -- 2.34.1
[PATCH 22/27] sparc32: Drop sun4m irq support
From: Sam Ravnborg Drop all code uses to support sun4m irqs. Update entry.S to call the leon_nmi function. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/kernel/Makefile | 1 - arch/sparc/kernel/entry.S | 29 ++--- arch/sparc/kernel/irq.h | 47 +--- arch/sparc/kernel/irq_32.c | 6 +- arch/sparc/kernel/kernel.h | 4 - arch/sparc/kernel/leon_kernel.c | 10 +- arch/sparc/kernel/sun4m_irq.c | 238 7 files changed, 23 insertions(+), 312 deletions(-) diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 09577e39037c..1961d165b279 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -29,7 +29,6 @@ obj-y += traps_$(BITS).o # IRQ obj-y += irq_$(BITS).o -obj-$(CONFIG_SPARC32) += sun4m_irq.o obj-y += process_$(BITS).o obj-y += process.o diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index eecbe0be7bf6..fb6095aab9c2 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -427,36 +427,21 @@ setcc_trap_handler: jmp %l2 ! advance over trap instruction rett%l2 + 0x4 ! like this... -sun4m_nmi_error: +nmi_error: /* NMI async memory error handling. */ - sethi %hi(0x8000), %l4 - sethi %hi(sun4m_irq_global), %o5 - ld [%o5 + %lo(sun4m_irq_global)], %l5 - st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x8000 - WRITE_PAUSE - ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending - WRITE_PAUSE +#ifndef CONFIG_SMP + .align 4 + .globl linux_trap_ipi15_leon +linux_trap_ipi15_leon: + SAVE_ALL or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE - callsun4m_nmi + callleon_nmi nop - st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x8000 - WRITE_PAUSE - ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending - WRITE_PAUSE RESTORE_ALL - -#ifndef CONFIG_SMP - .align 4 - .globl linux_trap_ipi15_leon -linux_trap_ipi15_leon: - SAVE_ALL - - ba sun4m_nmi_error -nop #endif /* CONFIG_SMP */ .align 4 diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index 8a0b314c8299..9d15dbb9fe6f 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -10,39 +10,14 @@ struct irq_bucket { unsigned int pil; }; -#define SUN4M_HARD_INT(x) (0x1 << (x)) -#define SUN4M_SOFT_INT(x) (0x1 << (x)) - -#define SUN4D_MAX_BOARD 10 -#define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5) +#define MAX_BOARD 10 +#define MAX_IRQ ((MAX_BOARD + 2) << 5) /* Map between the irq identifier used in hw to the * irq_bucket. The map is sufficient large to hold * the sun4d hw identifiers. */ -extern struct irq_bucket *irq_map[SUN4D_MAX_IRQ]; - - -/* sun4m specific type definitions */ - -/* This maps direct to CPU specific interrupt registers */ -struct sun4m_irq_percpu { - u32 pending; - u32 clear; - u32 set; -}; - -/* This maps direct to global interrupt registers */ -struct sun4m_irq_global { - u32 pending; - u32 mask; - u32 mask_clear; - u32 mask_set; - u32 interrupt_target; -}; - -extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; -extern struct sun4m_irq_global __iomem *sun4m_irq_global; +extern struct irq_bucket *irq_map[MAX_IRQ]; unsigned int irq_alloc(unsigned int real_irq, unsigned int pil); void irq_link(unsigned int irq); @@ -51,22 +26,8 @@ void handler_irq(unsigned int pil, struct pt_regs *regs); unsigned long leon_get_irqmask(unsigned int irq); -/* sun4m_irq.c */ -void sun4m_nmi(struct pt_regs *regs); - -/* sun4d_irq.c */ -void sun4d_handler_irq(unsigned int pil, struct pt_regs *regs); - /* leon_kernel.c */ void leon_clear_clock_irq(void); void leon_load_profile_irq(int cpu, unsigned int limit); u32 leon_cycles_offset(void); - -#ifdef CONFIG_SMP - -/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ -#define SUN4D_IPI_IRQ 13 - -void sun4d_ipi_interrupt(void); - -#endif +void leon_nmi(struct pt_regs *regs); diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c index f76f57073323..5bd64828e8a0 100644 --- a/arch/sparc/kernel/irq_32.c +++ b/arch/sparc/kernel/irq_32.c @@ -111,7 +111,7 @@ static struct irq_bucket irq_table[NR_IRQS]; static DEFINE_SPINLOCK(irq_table_lock); /* Map between the irq identifier used in hw to the irq_bucket. */ -struct irq_bucket *irq_map[SUN4D_MAX_IRQ]; +struct irq_bucket *irq_map[MAX_IRQ]; /* Protect access to irq_map */ static DEFINE_SPINLOCK(irq_map_lock);
[PATCH 04/27] sparc32: Drop sun4m specific led driver
From: Sam Ravnborg The led driver is only relevant for the sun4m machines. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/Kconfig | 9 --- arch/sparc/kernel/Makefile | 1 - arch/sparc/kernel/led.c| 146 - 3 files changed, 156 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 54c91431724b..1520f68e944a 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -331,15 +331,6 @@ config SUN_PM Enable power management and CPU standby features on supported SPARC platforms. -config SPARC_LED - tristate "Sun4m LED driver" - depends on SPARC32 - help - This driver toggles the front-panel LED on sun4m systems - in a user-specifiable manner. Its state can be probed - by reading /proc/led and its blinking mode can be changed - via writes to /proc/led - config SERIAL_CONSOLE bool depends on SPARC32 diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 0984bb6f0f17..95687af45d20 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -90,7 +90,6 @@ obj-y += termios.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULES) += sparc_ksyms.o -obj-$(CONFIG_SPARC_LED) += led.o obj-$(CONFIG_KGDB)+= kgdb_$(BITS).o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c deleted file mode 100644 index ab657b359789.. --- a/arch/sparc/kernel/led.c +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define LED_MAX_LENGTH 8 /* maximum chars written to proc file */ - -static inline void led_toggle(void) -{ - unsigned char val = get_auxio(); - unsigned char on, off; - - if (val & AUXIO_LED) { - on = 0; - off = AUXIO_LED; - } else { - on = AUXIO_LED; - off = 0; - } - - set_auxio(on, off); -} - -static struct timer_list led_blink_timer; -static unsigned long led_blink_timer_timeout; - -static void led_blink(struct timer_list *unused) -{ - unsigned long timeout = led_blink_timer_timeout; - - led_toggle(); - - /* reschedule */ - if (!timeout) { /* blink according to load */ - led_blink_timer.expires = jiffies + - ((1 + (avenrun[0] >> FSHIFT)) * HZ); - } else { /* blink at user specified interval */ - led_blink_timer.expires = jiffies + (timeout * HZ); - } - add_timer(_blink_timer); -} - -#ifdef CONFIG_PROC_FS -static int led_proc_show(struct seq_file *m, void *v) -{ - if (get_auxio() & AUXIO_LED) - seq_puts(m, "on\n"); - else - seq_puts(m, "off\n"); - return 0; -} - -static int led_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, led_proc_show, NULL); -} - -static ssize_t led_proc_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) -{ - char *buf = NULL; - - if (count > LED_MAX_LENGTH) - count = LED_MAX_LENGTH; - - buf = memdup_user_nul(buffer, count); - if (IS_ERR(buf)) - return PTR_ERR(buf); - - /* work around \n when echo'ing into proc */ - if (buf[count - 1] == '\n') - buf[count - 1] = '\0'; - - /* before we change anything we want to stop any running timers, -* otherwise calls such as on will have no persistent effect -*/ - del_timer_sync(_blink_timer); - - if (!strcmp(buf, "on")) { - auxio_set_led(AUXIO_LED_ON); - } else if (!strcmp(buf, "toggle")) { - led_toggle(); - } else if ((*buf > '0') && (*buf <= '9')) { - led_blink_timer_timeout = simple_strtoul(buf, NULL, 10); - led_blink(_blink_timer); - } else if (!strcmp(buf, "load")) { - led_blink_timer_timeout = 0; - led_blink(_blink_timer); - } else { - auxio_set_led(AUXIO_LED_OFF); - } - - kfree(buf); - - return count; -} - -static const struct proc_ops led_proc_ops = { - .proc_open = led_proc_open, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release, - .proc_write = led_proc_write, -}; -#endif - -#define LED_VERSION"0.1" - -static int __init led_init(void) -{ - timer_setup(_blink_timer, led_blink, 0); - -#ifdef CONFIG_PROC_FS - if (!proc_create("led", 0, NULL, _proc_ops)) - return -ENOMEM; -#endif - printk(KERN_INFO - "led: version %s, Lars Kotthoff
[PATCH 03/27] sparc32: Drop floppy support
From: Sam Ravnborg LEON do not have floppy support so we can drop it Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/Kconfig | 2 +- arch/sparc/include/asm/floppy.h| 2 - arch/sparc/include/asm/floppy_32.h | 393 - arch/sparc/kernel/entry.S | 137 - arch/sparc/kernel/irq.h| 3 - arch/sparc/kernel/irq_32.c | 93 - arch/sparc/kernel/kernel.h | 2 - 7 files changed, 1 insertion(+), 631 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 49849790e66d..54c91431724b 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -195,7 +195,7 @@ config GENERIC_CALIBRATE_DELAY config ARCH_MAY_HAVE_PC_FDC bool - default y + default y if SPARC64 config EMULATED_CMPXCHG bool diff --git a/arch/sparc/include/asm/floppy.h b/arch/sparc/include/asm/floppy.h index 4b315802e635..c89f719a18e9 100644 --- a/arch/sparc/include/asm/floppy.h +++ b/arch/sparc/include/asm/floppy.h @@ -3,7 +3,5 @@ #define ___ASM_SPARC_FLOPPY_H #if defined(__sparc__) && defined(__arch64__) #include -#else -#include #endif #endif diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h deleted file mode 100644 index 836f6575aa1d.. --- a/arch/sparc/include/asm/floppy_32.h +++ /dev/null @@ -1,393 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* asm/floppy.h: Sparc specific parts of the Floppy driver. - * - * Copyright (C) 1995 David S. Miller (da...@davemloft.net) - */ - -#ifndef __ASM_SPARC_FLOPPY_H -#define __ASM_SPARC_FLOPPY_H - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* We don't need no stinkin' I/O port allocation crap. */ -#undef release_region -#undef request_region -#define release_region(X, Y) do { } while(0) -#define request_region(X, Y, Z)(1) - -/* References: - * 1) Netbsd Sun floppy driver. - * 2) NCR 82077 controller manual - * 3) Intel 82077 controller manual - */ -struct sun_flpy_controller { - volatile unsigned char status_82072; /* Main Status reg. */ -#define dcr_82072 status_82072 /* Digital Control reg. */ -#define status1_82077 status_82072 /* Auxiliary Status reg. 1 */ - - volatile unsigned char data_82072;/* Data fifo. */ -#define status2_82077 data_82072 /* Auxiliary Status reg. 2 */ - - volatile unsigned char dor_82077; /* Digital Output reg. */ - volatile unsigned char tapectl_82077; /* What the? Tape control reg? */ - - volatile unsigned char status_82077; /* Main Status Register. */ -#define drs_82077 status_82077 /* Digital Rate Select reg. */ - - volatile unsigned char data_82077;/* Data fifo. */ - volatile unsigned char ___unused; - volatile unsigned char dir_82077; /* Digital Input reg. */ -#define dcr_82077 dir_82077 /* Config Control reg. */ -}; - -/* You'll only ever find one controller on a SparcStation anyways. */ -static struct sun_flpy_controller *sun_fdc = NULL; - -struct sun_floppy_ops { - unsigned char (*fd_inb)(int port); - void (*fd_outb)(unsigned char value, int port); -}; - -static struct sun_floppy_ops sun_fdops; - -#define fd_inb(base, reg) sun_fdops.fd_inb(reg) -#define fd_outb(value, base, reg) sun_fdops.fd_outb(value, reg) -#define fd_enable_dma() sun_fd_enable_dma() -#define fd_disable_dma() sun_fd_disable_dma() -#define fd_request_dma() (0) /* nothing... */ -#define fd_free_dma() /* nothing... */ -#define fd_clear_dma_ff() /* nothing... */ -#define fd_set_dma_mode(mode) sun_fd_set_dma_mode(mode) -#define fd_set_dma_addr(addr) sun_fd_set_dma_addr(addr) -#define fd_set_dma_count(count) sun_fd_set_dma_count(count) -#define fd_enable_irq() /* nothing... */ -#define fd_disable_irq() /* nothing... */ -#define fd_request_irq() sun_fd_request_irq() -#define fd_free_irq() /* nothing... */ -#if 0 /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */ -#define fd_dma_mem_alloc(size)((unsigned long) vmalloc(size)) -#define fd_dma_mem_free(addr,size) (vfree((void *)(addr))) -#endif - -/* XXX This isn't really correct. XXX */ -#define get_dma_residue(x)(0) - -#define FLOPPY0_TYPE 4 -#define FLOPPY1_TYPE 0 - -/* Super paranoid... */ -#undef HAVE_DISABLE_HLT - -/* Here is where we catch the floppy driver trying to initialize, - * therefore this is where we call the PROM device tree probing - * routine etc. on the Sparc. - */ -#define FDC1 sun_floppy_init() - -#define N_FDC1 -#define N_DRIVE 8 - -/* No 64k boundary crossing problems on the Sparc. */ -#define CROSS_64KB(a,s) (0) - -/* Routines unique to each controller type on a Sun. */ -static void
[PATCH 01/27] sparc32: Update defconfig to LEON SMP
From: Sam Ravnborg This is a copy of the leon_smp defconfig found in gaisler-buildroot-2023.02-1.0. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/configs/sparc32_defconfig | 171 +++ 1 file changed, 91 insertions(+), 80 deletions(-) diff --git a/arch/sparc/configs/sparc32_defconfig b/arch/sparc/configs/sparc32_defconfig index 5010164de3e4..71273fc578bf 100644 --- a/arch/sparc/configs/sparc32_defconfig +++ b/arch/sparc/configs/sparc32_defconfig @@ -1,97 +1,108 @@ +CONFIG_DEFAULT_HOSTNAME="leon" CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_PCI=y -CONFIG_SUN_OPENPROMFS=m -CONFIG_BINFMT_MISC=m +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_RD_ZSTD is not set +CONFIG_SMP=y +CONFIG_HZ_100=y +CONFIG_SPARC_LEON=y +CONFIG_SUN_OPENPROMFS=y +CONFIG_SUN_OPENPROMIO=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_MISC=y +# CONFIG_COMPACTION is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y -CONFIG_XFRM_USER=m -CONFIG_NET_KEY=m CONFIG_INET=y CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NET_PKTGEN=m -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_BLK_DEV_RAM=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_DEV_SR=m -CONFIG_CHR_DEV_SG=m -CONFIG_SCSI_QLOGICPTI=m -CONFIG_SCSI_SUNESP=y +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y CONFIG_NETDEVICES=y -CONFIG_DUMMY=m -CONFIG_NET_ETHERNET=y -CONFIG_MII=m -CONFIG_SUNLANCE=y -CONFIG_HAPPYMEAL=m -CONFIG_SUNBMAC=m -CONFIG_SUNQE=m +CONFIG_GRETH=y +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_BROADCOM_PHY=y +CONFIG_CICADA_PHY=y +CONFIG_DAVICOM_PHY=y +CONFIG_ICPLUS_PHY=y +CONFIG_LXT_PHY=y +CONFIG_LSI_ET1011C_PHY=y +CONFIG_MARVELL_PHY=y +CONFIG_MICREL_PHY=y +CONFIG_NATIONAL_PHY=y +CONFIG_QSEMI_PHY=y +CONFIG_REALTEK_PHY=y +CONFIG_SMSC_PHY=y +CONFIG_STE10XP=y +CONFIG_VITESSE_PHY=y # CONFIG_WLAN is not set -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_EVBUG=m -CONFIG_KEYBOARD_ATKBD=m -CONFIG_KEYBOARD_SUNKBD=m -CONFIG_MOUSE_PS2=m -CONFIG_MOUSE_SERIAL=m -CONFIG_SERIO=m +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set # CONFIG_SERIO_I8042 is not set CONFIG_SERIAL_SUNZILOG=y CONFIG_SERIAL_SUNZILOG_CONSOLE=y -CONFIG_SERIAL_SUNSU=y -CONFIG_SERIAL_SUNSU_CONSOLE=y -CONFIG_SPI=y -CONFIG_SPI_XILINX=m -CONFIG_SPI_XILINX_PLTFM=m -CONFIG_SUN_OPENPROMIO=m -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_AUTOFS_FS=m -CONFIG_ISO9660_FS=m +CONFIG_SERIAL_GRLIB_GAISLER_APBUART=y +CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_HID_GENERIC is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_RTC_HCTOSYS is not set +# CONFIG_RTC_INTF_SYSFS is not set +# CONFIG_RTC_INTF_PROC is not set +# CONFIG_RTC_INTF_DEV is not set +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_FSCACHE=y CONFIG_PROC_KCORE=y -CONFIG_ROMFS_FS=m +CONFIG_TMPFS=y +# CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y +CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y -CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_NFS_FSCACHE=y CONFIG_NLS=y
[PATCH 11/27] sparc32: Drop pcic support
From: Sam Ravnborg pcic is only used by MicroSPARC-IIep and not relevant for LEON. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/Kconfig| 5 - arch/sparc/include/asm/pcic.h | 130 --- arch/sparc/kernel/Makefile| 1 - arch/sparc/kernel/entry.S | 48 --- arch/sparc/kernel/irq_32.c| 1 - arch/sparc/kernel/kernel.h| 4 - arch/sparc/kernel/pcic.c | 829 -- arch/sparc/kernel/time_32.c | 6 +- 8 files changed, 1 insertion(+), 1023 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 55a9e67c482e..7ae304bab2d8 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -414,11 +414,6 @@ config SUN_LDOMS Say Y here is you want to support virtual devices via Logical Domains. -config PCIC_PCI - bool - depends on PCI && SPARC32 && !SPARC_LEON - default y - config LEON_PCI bool depends on PCI && SPARC_LEON diff --git a/arch/sparc/include/asm/pcic.h b/arch/sparc/include/asm/pcic.h deleted file mode 100644 index 238376b1ffcc.. --- a/arch/sparc/include/asm/pcic.h +++ /dev/null @@ -1,130 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * pcic.h: JavaEngine 1 specific PCI definitions. - * - * Copyright (C) 1998 V. Roganov and G. Raiko - */ - -#ifndef __SPARC_PCIC_H -#define __SPARC_PCIC_H - -#ifndef __ASSEMBLY__ - -#include -#include -#include -#include -#include - -struct linux_pcic { -void __iomem*pcic_regs; -unsigned long pcic_io; -void __iomem*pcic_config_space_addr; -void __iomem*pcic_config_space_data; - struct resource pcic_res_regs; - struct resource pcic_res_io; - struct resource pcic_res_cfg_addr; - struct resource pcic_res_cfg_data; -struct linux_pbm_info pbm; - struct pcic_ca2irq *pcic_imap; - int pcic_imdim; -}; - -#ifdef CONFIG_PCIC_PCI -int pcic_present(void); -int pcic_probe(void); -void pci_time_init(void); -void sun4m_pci_init_IRQ(void); -#else -static inline int pcic_present(void) { return 0; } -static inline int pcic_probe(void) { return 0; } -static inline void pci_time_init(void) {} -static inline void sun4m_pci_init_IRQ(void) {} -#endif -#endif - -/* Size of PCI I/O space which we relocate. */ -#define PCI_SPACE_SIZE 0x100 /* 16 MB */ - -/* PCIC Register Set. */ -#define PCI_DIAGNOSTIC_00x40/* 32 bits */ -#define PCI_SIZE_0 0x44/* 32 bits */ -#define PCI_SIZE_1 0x48/* 32 bits */ -#define PCI_SIZE_2 0x4c/* 32 bits */ -#define PCI_SIZE_3 0x50/* 32 bits */ -#define PCI_SIZE_4 0x54/* 32 bits */ -#define PCI_SIZE_5 0x58/* 32 bits */ -#define PCI_PIO_CONTROL 0x60/* 8 bits */ -#define PCI_DVMA_CONTROL0x62/* 8 bits */ -#define PCI_DVMA_CONTROL_INACTIVITY_REQ(1<<0) -#define PCI_DVMA_CONTROL_IOTLB_ENABLE (1<<0) -#define PCI_DVMA_CONTROL_IOTLB_DISABLE 0 -#define PCI_DVMA_CONTROL_INACTIVITY_ACK(1<<4) -#define PCI_INTERRUPT_CONTROL 0x63/* 8 bits */ -#define PCI_CPU_INTERRUPT_PENDING 0x64/* 32 bits */ -#define PCI_DIAGNOSTIC_10x68/* 16 bits */ -#define PCI_SOFTWARE_INT_CLEAR 0x6a/* 16 bits */ -#define PCI_SOFTWARE_INT_SET0x6e/* 16 bits */ -#define PCI_SYS_INT_PENDING 0x70/* 32 bits */ -#define PCI_SYS_INT_PENDING_PIO 0x4000 -#define PCI_SYS_INT_PENDING_DMA 0x2000 -#define PCI_SYS_INT_PENDING_PCI 0x1000 -#define PCI_SYS_INT_PENDING_APSR 0x0800 -#define PCI_SYS_INT_TARGET_MASK 0x74/* 32 bits */ -#define PCI_SYS_INT_TARGET_MASK_CLEAR 0x78/* 32 bits */ -#define PCI_SYS_INT_TARGET_MASK_SET 0x7c/* 32 bits */ -#define PCI_SYS_INT_PENDING_CLEAR 0x83/* 8 bits */ -#define PCI_SYS_INT_PENDING_CLEAR_ALL 0x80 -#define PCI_SYS_INT_PENDING_CLEAR_PIO 0x40 -#define PCI_SYS_INT_PENDING_CLEAR_DMA 0x20 -#define PCI_SYS_INT_PENDING_CLEAR_PCI 0x10 -#define PCI_IOTLB_CONTROL 0x84/* 8 bits */ -#define PCI_INT_SELECT_LO 0x88/* 16 bits */ -#define PCI_ARBITRATION_SELECT 0x8a/* 16 bits */ -#define PCI_INT_SELECT_HI 0x8c/* 16 bits */ -#define PCI_HW_INT_OUTPUT 0x8e/* 16 bits */ -#define PCI_IOTLB_RAM_INPUT 0x90/* 32 bits */ -#define PCI_IOTLB_CAM_INPUT 0x94/* 32 bits */ -#define PCI_IOTLB_RAM_OUTPUT0x98/* 32 bits */ -#define PCI_IOTLB_CAM_OUTPUT0x9c/* 32 bits */
[PATCH 09/27] sparc32: Drop sun4m/sun4d specific irq handling
From: Sam Ravnborg Some of the sun4m irq infrastructure is used by LEON too, so keep that and drop the rest. The patch include a few extra fixes fix the build after the removal of the irq support. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/irq_32.h | 2 - arch/sparc/kernel/Makefile | 2 +- arch/sparc/kernel/irq_32.c | 30 +-- arch/sparc/kernel/kernel.h | 13 -- arch/sparc/kernel/sun4d_irq.c | 494 arch/sparc/kernel/sun4d_smp.c | 4 - arch/sparc/kernel/sun4m_irq.c | 240 --- arch/sparc/mm/io-unit.c | 2 - 8 files changed, 2 insertions(+), 785 deletions(-) diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h index 6ee48321cbc2..c402c81b85a7 100644 --- a/arch/sparc/include/asm/irq_32.h +++ b/arch/sparc/include/asm/irq_32.h @@ -17,8 +17,6 @@ #define irq_canonicalize(irq) (irq) -void __init sun4d_init_sbi_irq(void); - #define NO_IRQ 0x #endif diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 577cb57c588a..e79ef2049ea2 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -29,7 +29,7 @@ obj-y += traps_$(BITS).o # IRQ obj-y += irq_$(BITS).o -obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4d_irq.o +obj-$(CONFIG_SPARC32) += sun4m_irq.o obj-y += process_$(BITS).o obj-y += process.o diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c index 510184c3aa17..135170f362c1 100644 --- a/arch/sparc/kernel/irq_32.c +++ b/arch/sparc/kernel/irq_32.c @@ -235,36 +235,8 @@ void handler_irq(unsigned int pil, struct pt_regs *regs) set_irq_regs(old_regs); } -/* djhr - * This could probably be made indirect too and assigned in the CPU - * bits of the code. That would be much nicer I think and would also - * fit in with the idea of being able to tune your kernel for your machine - * by removing unrequired machine and device support. - * - */ - void __init init_IRQ(void) { - switch (sparc_cpu_model) { - case sun4m: - pcic_probe(); - if (pcic_present()) - sun4m_pci_init_IRQ(); - else - sun4m_init_IRQ(); - break; - - case sun4d: - sun4d_init_IRQ(); - break; - - case sparc_leon: - leon_init_IRQ(); - break; - - default: - prom_printf("Cannot initialize IRQs on this Sun machine..."); - break; - } + leon_init_IRQ(); } diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 85a3c3d1195e..f090d34a2f56 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -93,7 +93,6 @@ extern spinlock_t irq_action_lock; void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); /* sun4m_irq.c */ -void sun4m_init_IRQ(void); void sun4m_unmask_profile_irq(void); void sun4m_clear_profile_irq(int cpu); @@ -106,18 +105,6 @@ void __init smp4m_smp_done(void); void smp4m_cross_call_irq(void); void smp4m_percpu_timer_interrupt(struct pt_regs *regs); -/* sun4d_irq.c */ -extern spinlock_t sun4d_imsk_lock; - -void sun4d_init_IRQ(void); -int sun4d_request_irq(unsigned int irq, - irq_handler_t handler, - unsigned long irqflags, - const char *devname, void *dev_id); -int show_sun4d_interrupts(struct seq_file *, void *); -void sun4d_distribute_irqs(void); -void sun4d_free_irq(unsigned int irq, void *dev_id); - /* sun4d_smp.c */ void sun4d_cpu_pre_starting(void *arg); void sun4d_cpu_pre_online(void *arg); diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c deleted file mode 100644 index 7140cff04b54.. --- a/arch/sparc/kernel/sun4d_irq.c +++ /dev/null @@ -1,494 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * SS1000/SC2000 interrupt handling. - * - * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz) - * Heavily based on arch/sparc/kernel/irq.c. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "kernel.h" -#include "irq.h" - -/* Sun4d interrupts fall roughly into two categories. SBUS and - * cpu local. CPU local interrupts cover the timer interrupts - * and whatnot, and we encode those as normal PILs between - * 0 and 15. - * SBUS interrupts are encodes as a combination of board, level and slot. - */ - -struct sun4d_handler_data { - unsigned int cpuid;/* target cpu */ - unsigned int real_irq; /* interrupt level */ -}; - - -static unsigned int sun4d_encode_irq(int board, int lvl, int slot) -{ - return (board + 1) << 5 | (lvl << 2) | slot; -} - -struct sun4d_timer_regs { - u32
[PATCH 10/27] sparc32: Drop sun4d/sun4m smp support
From: Sam Ravnborg Drop the sun4m and sun4d smp support code. The sparc32 kernel will not boot unless this is a LEON system, so drop checks for other systems as they will not trigger. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/kernel/Makefile| 2 +- arch/sparc/kernel/kernel.h| 18 -- arch/sparc/kernel/smp_32.c| 102 +-- arch/sparc/kernel/sun4d_smp.c | 408 -- arch/sparc/kernel/sun4m_smp.c | 275 arch/sparc/mm/srmmu.c | 10 +- 6 files changed, 8 insertions(+), 807 deletions(-) diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index e79ef2049ea2..386bbb30fff2 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -80,7 +80,7 @@ obj-$(CONFIG_SPARC_GRPCI2)+= leon_pci_grpci2.o obj-$(CONFIG_SPARC_GRPCI1)+= leon_pci_grpci1.o obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o -obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o +obj-$(CONFIG_SPARC32_SMP) += leon_smp.o obj-$(CONFIG_SPARC64_SMP) += hvtramp.o obj-$(CONFIG_SPARC64) += auxio_64.o diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index f090d34a2f56..ff8f412e3153 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -96,24 +96,6 @@ void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); void sun4m_unmask_profile_irq(void); void sun4m_clear_profile_irq(int cpu); -/* sun4m_smp.c */ -void sun4m_cpu_pre_starting(void *arg); -void sun4m_cpu_pre_online(void *arg); -void __init smp4m_boot_cpus(void); -int smp4m_boot_one_cpu(int i, struct task_struct *idle); -void __init smp4m_smp_done(void); -void smp4m_cross_call_irq(void); -void smp4m_percpu_timer_interrupt(struct pt_regs *regs); - -/* sun4d_smp.c */ -void sun4d_cpu_pre_starting(void *arg); -void sun4d_cpu_pre_online(void *arg); -void __init smp4d_boot_cpus(void); -int smp4d_boot_one_cpu(int i, struct task_struct *idle); -void __init smp4d_smp_done(void); -void smp4d_cross_call_irq(void); -void smp4d_percpu_timer_interrupt(struct pt_regs *regs); - /* leon_smp.c */ void leon_cpu_pre_starting(void *arg); void leon_cpu_pre_online(void *arg); diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 87eaa7719fa2..42fb90577a82 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -87,29 +87,7 @@ void __init smp_cpus_done(unsigned int max_cpus) num, bogosum/(50/HZ), (bogosum/(5000/HZ))%100); - switch(sparc_cpu_model) { - case sun4m: - smp4m_smp_done(); - break; - case sun4d: - smp4d_smp_done(); - break; - case sparc_leon: - leon_smp_done(); - break; - case sun4e: - printk("SUN4E\n"); - BUG(); - break; - case sun4u: - printk("SUN4U\n"); - BUG(); - break; - default: - printk("UNKNOWN!\n"); - BUG(); - break; - } + leon_smp_done(); } void cpu_panic(void) @@ -191,29 +169,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) smp_store_cpu_info(boot_cpu_id); - switch(sparc_cpu_model) { - case sun4m: - smp4m_boot_cpus(); - break; - case sun4d: - smp4d_boot_cpus(); - break; - case sparc_leon: - leon_boot_cpus(); - break; - case sun4e: - printk("SUN4E\n"); - BUG(); - break; - case sun4u: - printk("SUN4U\n"); - BUG(); - break; - default: - printk("UNKNOWN!\n"); - BUG(); - break; - } + leon_boot_cpus(); } /* Set this up early so that things like the scheduler can init @@ -252,31 +208,7 @@ void __init smp_prepare_boot_cpu(void) int __cpu_up(unsigned int cpu, struct task_struct *tidle) { - int ret=0; - - switch(sparc_cpu_model) { - case sun4m: - ret = smp4m_boot_one_cpu(cpu, tidle); - break; - case sun4d: - ret = smp4d_boot_one_cpu(cpu, tidle); - break; - case sparc_leon: - ret = leon_boot_one_cpu(cpu, tidle); - break; - case sun4e: - printk("SUN4E\n"); - BUG(); - break; - case sun4u: - printk("SUN4U\n"); - BUG(); - break; - default: - printk("UNKNOWN!\n"); - BUG(); - break; - } + int ret = leon_boot_one_cpu(cpu, tidle); if (!ret) { cpumask_set_cpu(cpu, _commenced_mask); @@ -291,19 +223,7 @@ static void
[PATCH 23/27] sparc32: Drop unused trampoline code
From: Sam Ravnborg Drop the sun4m and sun4d code from trampoline_32 Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/kernel/kernel.h| 3 +- arch/sparc/kernel/trampoline_32.S | 127 +- 2 files changed, 3 insertions(+), 127 deletions(-) diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 30adbec894f7..aea96b6b881c 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -112,8 +112,7 @@ extern unsigned int real_irq_entry[]; extern unsigned int smp4d_ticker[]; /* trampoline_32.S */ -extern unsigned long sun4m_cpu_startup; -extern unsigned long sun4d_cpu_startup; +void leon_smp_cpu_startup(int boot_cpu); /* signal_32.c */ asmlinkage void do_sigreturn(struct pt_regs *regs); diff --git a/arch/sparc/kernel/trampoline_32.S b/arch/sparc/kernel/trampoline_32.S index 82fafeeb3a62..685b20923f6b 100644 --- a/arch/sparc/kernel/trampoline_32.S +++ b/arch/sparc/kernel/trampoline_32.S @@ -15,136 +15,12 @@ #include #include - .globl sun4m_cpu_startup - .globl sun4d_cpu_startup - - .align 4 - /* When we start up a cpu for the first time it enters this routine. * This initializes the chip from whatever state the prom left it * in and sets PIL in %psr to 15, no irqs. */ - -sun4m_cpu_startup: -cpu1_startup: - sethi %hi(trapbase_cpu1), %g3 - b 1f -or %g3, %lo(trapbase_cpu1), %g3 - -cpu2_startup: - sethi %hi(trapbase_cpu2), %g3 - b 1f -or %g3, %lo(trapbase_cpu2), %g3 - -cpu3_startup: - sethi %hi(trapbase_cpu3), %g3 - b 1f -or %g3, %lo(trapbase_cpu3), %g3 - -1: - /* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */ - set (PSR_PIL | PSR_S | PSR_PS), %g1 - wr %g1, 0x0, %psr ! traps off though - WRITE_PAUSE - - /* Our %wim is one behind CWP */ - mov 2, %g1 - wr %g1, 0x0, %wim - WRITE_PAUSE - - /* This identifies "this cpu". */ - wr %g3, 0x0, %tbr - WRITE_PAUSE - - /* Give ourselves a stack and curptr. */ - set current_set, %g5 - srl %g3, 10, %g4 - and %g4, 0xc, %g4 - ld [%g5 + %g4], %g6 - - sethi %hi(THREAD_SIZE - STACKFRAME_SZ), %sp - or %sp, %lo(THREAD_SIZE - STACKFRAME_SZ), %sp - add %g6, %sp, %sp - - /* Turn on traps (PSR_ET). */ - rd %psr, %g1 - wr %g1, PSR_ET, %psr ! traps on - WRITE_PAUSE - - /* Init our caches, etc. */ - set poke_srmmu, %g5 - ld [%g5], %g5 - call%g5 -nop - - /* Start this processor. */ - callsmp_callin -nop - - b,a smp_panic - .text .align 4 - -smp_panic: - callcpu_panic -nop - -/* CPUID in bootbus can be found at PA 0xff014 */ -#define SUN4D_BOOTBUS_CPUID0xf014 - - .align 4 - -sun4d_cpu_startup: - /* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */ - set (PSR_PIL | PSR_S | PSR_PS), %g1 - wr %g1, 0x0, %psr ! traps off though - WRITE_PAUSE - - /* Our %wim is one behind CWP */ - mov 2, %g1 - wr %g1, 0x0, %wim - WRITE_PAUSE - - /* Set tbr - we use just one trap table. */ - set trapbase, %g1 - wr %g1, 0x0, %tbr - WRITE_PAUSE - - /* Get our CPU id out of bootbus */ - set SUN4D_BOOTBUS_CPUID, %g3 - lduba [%g3] ASI_M_CTL, %g3 - and %g3, 0xf8, %g3 - srl %g3, 3, %g1 - sta %g1, [%g0] ASI_M_VIKING_TMP1 - - /* Give ourselves a stack and curptr. */ - set current_set, %g5 - srl %g3, 1, %g4 - ld [%g5 + %g4], %g6 - - sethi %hi(THREAD_SIZE - STACKFRAME_SZ), %sp - or %sp, %lo(THREAD_SIZE - STACKFRAME_SZ), %sp - add %g6, %sp, %sp - - /* Turn on traps (PSR_ET). */ - rd %psr, %g1 - wr %g1, PSR_ET, %psr ! traps on - WRITE_PAUSE - - /* Init our caches, etc. */ - set poke_srmmu, %g5 - ld [%g5], %g5 - call%g5 -nop - - /* Start this processor. */ - callsmp_callin -nop - - b,a smp_panic - - .align 4 .global leon_smp_cpu_startup, smp_penguin_ctable leon_smp_cpu_startup: @@ -198,4 +74,5 @@ leon_smp_cpu_startup: callsmp_callin nop - b,a smp_panic + b,a cpu_panic +nop -- 2.34.1
[PATCH 27/27] fbdev/p9100: Drop now unused driver p9100
From: Sam Ravnborg The p9100 driver is only relevant for the Sparcbook 3 machine, and with sun4m support removed this driver is no longer relevant. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson Cc: Helge Deller --- drivers/video/fbdev/Kconfig | 8 - drivers/video/fbdev/Makefile | 1 - drivers/video/fbdev/p9100.c | 372 --- 3 files changed, 381 deletions(-) diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 94f6dca5856f..ebcc3815c7a5 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -576,14 +576,6 @@ config FB_CG14 This is the frame buffer device driver for the CGfourteen frame buffer on Desktop SPARCsystems with the SX graphics option. -config FB_P9100 - bool "P9100 (Sparcbook 3 only) support" - depends on FB_SBUS - select FB_SBUS_HELPERS - help - This is the frame buffer device driver for the P9100 card - supported on Sparcbook 3 machines. - config FB_LEO bool "Leo (ZX) support" depends on FB_SBUS diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index 8e15220152bd..bc9b24648347 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -51,7 +51,6 @@ obj-$(CONFIG_FB_CG6) += cg6.o obj-$(CONFIG_FB_CG3) += cg3.o obj-$(CONFIG_FB_BW2) += bw2.o obj-$(CONFIG_FB_CG14) += cg14.o -obj-$(CONFIG_FB_P9100)+= p9100.o obj-$(CONFIG_FB_TCX) += tcx.o obj-$(CONFIG_FB_LEO) += leo.o obj-$(CONFIG_FB_ACORN)+= acornfb.o diff --git a/drivers/video/fbdev/p9100.c b/drivers/video/fbdev/p9100.c deleted file mode 100644 index e1356f8a866e.. --- a/drivers/video/fbdev/p9100.c +++ /dev/null @@ -1,372 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* p9100.c: P9100 frame buffer driver - * - * Copyright (C) 2003, 2006 David S. Miller (da...@davemloft.net) - * Copyright 1999 Derrick J Brashear (sha...@dementia.org) - * - * Driver layout based loosely on tgafb.c, see that file for credits. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "sbuslib.h" - -/* - * Local functions. - */ - -static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned, - unsigned, struct fb_info *); -static int p9100_blank(int, struct fb_info *); - -static int p9100_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma); -static int p9100_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); - -/* - * Frame buffer operations - */ - -static const struct fb_ops p9100_ops = { - .owner = THIS_MODULE, - FB_DEFAULT_SBUS_OPS(p9100), - .fb_setcolreg = p9100_setcolreg, - .fb_blank = p9100_blank, -}; - -/* P9100 control registers */ -#define P9100_SYSCTL_OFF 0x0UL -#define P9100_VIDEOCTL_OFF 0x100UL -#define P9100_VRAMCTL_OFF 0x180UL -#define P9100_RAMDAC_OFF 0x200UL -#define P9100_VIDEOCOPROC_OFF 0x400UL - -/* P9100 command registers */ -#define P9100_CMD_OFF 0x0UL - -/* P9100 framebuffer memory */ -#define P9100_FB_OFF 0x0UL - -/* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */ -#define SYS_CONFIG_PIXELSIZE_SHIFT 26 - -#define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */ - -struct p9100_regs { - /* Registers for the system control */ - u32 sys_base; - u32 sys_config; - u32 sys_intr; - u32 sys_int_ena; - u32 sys_alt_rd; - u32 sys_alt_wr; - u32 sys_xxx[58]; - - /* Registers for the video control */ - u32 vid_base; - u32 vid_hcnt; - u32 vid_htotal; - u32 vid_hsync_rise; - u32 vid_hblank_rise; - u32 vid_hblank_fall; - u32 vid_hcnt_preload; - u32 vid_vcnt; - u32 vid_vlen; - u32 vid_vsync_rise; - u32 vid_vblank_rise; - u32 vid_vblank_fall; - u32 vid_vcnt_preload; - u32 vid_screenpaint_addr; - u32 vid_screenpaint_timectl1; - u32 vid_screenpaint_qsfcnt; - u32 vid_screenpaint_timectl2; - u32 vid_xxx[15]; - - /* Registers for the video control */ - u32 vram_base; - u32 vram_memcfg; - u32 vram_refresh_pd; - u32 vram_refresh_cnt; - u32 vram_raslo_max; - u32 vram_raslo_cur; - u32 pwrup_cfg; - u32 vram_xxx[25]; - - /* Registers for IBM RGB528 Palette */ - u32 ramdac_cmap_wridx; - u32 ramdac_palette_data; - u32 ramdac_pixel_mask; - u32 ramdac_palette_rdaddr; - u32 ramdac_idx_lo; - u32 ramdac_idx_hi; - u32 ramdac_idx_data; - u32 ramdac_idx_ctl; - u32 ramdac_xxx[1784]; -}; - -struct p9100_cmd_parameng { - u32 parameng_status; - u32 parameng_bltcmd; - u32
[PATCH 17/27] sparc32: Drop run-time patching of ASI instructions
From: Sam Ravnborg With only LEON supported there is no need to run-time patch the instructions to match ASI. Move a few functions back to C with inline asm, now that run-time patching is not needed. Deleted a few functions that turns out not to be used rather than re-implement them in C. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/asmmacro.h | 22 --- arch/sparc/include/asm/pgtsrmmu.h | 29 +++--- arch/sparc/include/asm/sections.h | 3 -- arch/sparc/include/asm/winmacro.h | 11 +- arch/sparc/kernel/entry.S | 7 +--- arch/sparc/kernel/etrap_32.S | 15 +++ arch/sparc/kernel/rtrap_32.S | 18 +++-- arch/sparc/kernel/setup_32.c | 37 - arch/sparc/kernel/vmlinux.lds.S | 5 --- arch/sparc/kernel/wof.S | 18 +++-- arch/sparc/kernel/wuf.S | 21 -- arch/sparc/mm/Makefile| 1 - arch/sparc/mm/srmmu_access.S | 83 --- 13 files changed, 43 insertions(+), 227 deletions(-) diff --git a/arch/sparc/include/asm/asmmacro.h b/arch/sparc/include/asm/asmmacro.h index 49aaf6f3bc55..d5782dbc7810 100644 --- a/arch/sparc/include/asm/asmmacro.h +++ b/arch/sparc/include/asm/asmmacro.h @@ -21,26 +21,4 @@ /* All traps low-level code here must end with this macro. */ #define RESTORE_ALL b ret_trap_entry; clr %l6; -/* Support for run-time patching of single instructions. - * This is used to handle the differences in the ASI for - * MMUREGS for LEON and SUN. - * - * Sample: - * LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %o0 - * SUN_PI_(lda [%g0] ASI_M_MMUREGS, %o0 - * PI == Patch Instruction - * - * For LEON we will use the first variant, - * and for all other we will use the SUN variant. - * The order is important. - */ -#define LEON_PI(...) \ -662: __VA_ARGS__ - -#define SUN_PI_(...) \ - .section .leon_1insn_patch, "ax"; \ - .word 662b; \ - __VA_ARGS__;\ - .previous - #endif /* !(_SPARC_ASMMACRO_H) */ diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h index 664d4bba1bcb..69c28ff3c4c4 100644 --- a/arch/sparc/include/asm/pgtsrmmu.h +++ b/arch/sparc/include/asm/pgtsrmmu.h @@ -107,23 +107,24 @@ extern void *srmmu_nocache_pool; #define __nocache_va(PADDR) (__va((unsigned long)PADDR) - (unsigned long)srmmu_nocache_pool + SRMMU_NOCACHE_VADDR) #define __nocache_fix(VADDR) ((__typeof__(VADDR))__va(__nocache_pa(VADDR))) -/* Accessing the MMU control register. */ -unsigned int srmmu_get_mmureg(void); -void srmmu_set_mmureg(unsigned long regval); -void srmmu_set_ctable_ptr(unsigned long paddr); -void srmmu_set_context(int context); -int srmmu_get_context(void); -unsigned int srmmu_get_fstatus(void); -unsigned int srmmu_get_faddr(void); - -/* This is guaranteed on all SRMMU's. */ -static inline void srmmu_flush_whole_tlb(void) +static inline void srmmu_set_ctable_ptr(unsigned long paddr) { - __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : -"r" (0x400),/* Flush entire TLB!! */ -"i" (ASI_M_FLUSH_PROBE) : "memory"); + paddr = ((paddr >> 4) & SRMMU_CTX_PMASK); + asm volatile("sta %0, [%1] %2\n\t" : : "r" (paddr), "r" (SRMMU_CTXTBL_PTR), "i" (ASI_LEON_MMUREGS) : "memory"); +} + +static inline void srmmu_set_context(int context) +{ + asm volatile("sta %0, [%1] %2\n\t" : : "r" (context), "r" (SRMMU_CTX_REG), "i" (ASI_LEON_MMUREGS) : "memory"); +} +static inline int srmmu_get_context(void) +{ + register int retval; + asm volatile("lda [%1] %2, %0\n\t" : "=r" (retval) : "r" (SRMMU_CTX_REG), "i" (ASI_LEON_MMUREGS)); + return retval; } + #endif /* !(__ASSEMBLY__) */ #endif /* !(_SPARC_PGTSRMMU_H) */ diff --git a/arch/sparc/include/asm/sections.h b/arch/sparc/include/asm/sections.h index 08f833453ab3..e9d28148850b 100644 --- a/arch/sparc/include/asm/sections.h +++ b/arch/sparc/include/asm/sections.h @@ -8,7 +8,4 @@ /* sparc entry point */ extern char _start[]; -extern char __leon_1insn_patch[]; -extern char __leon_1insn_patch_end[]; - #endif diff --git a/arch/sparc/include/asm/winmacro.h b/arch/sparc/include/asm/winmacro.h index b6e911f5d93c..c496b04cdfaf 100644 --- a/arch/sparc/include/asm/winmacro.h +++ b/arch/sparc/include/asm/winmacro.h @@ -108,18 +108,11 @@ 661: rd %tbr, %idreg; \ srl %idreg, 10, %idreg; \ and %idreg, 0xc, %idreg;\ - .section.cpuid_patch, "ax"; \ - /* Instruction location. */ \ - .word 661b; \ - /* SUN4D implementation. */ \ - lda [%g0] ASI_M_VIKING_TMP1, %idreg; \ - sll
[PATCH 00/27] sparc32: sunset sun4m and sun4d
/winmacro.h | 11 +- arch/sparc/kernel/Makefile| 8 +- arch/sparc/kernel/apc.c | 196 arch/sparc/kernel/auxio_32.c | 139 -- arch/sparc/kernel/cpu.c | 1 - arch/sparc/kernel/devices.c | 10 +- arch/sparc/kernel/entry.S | 413 + arch/sparc/kernel/etrap_32.S | 50 +- arch/sparc/kernel/head_32.S | 255 +-- arch/sparc/kernel/ioport.c| 55 +-- arch/sparc/kernel/irq.h | 85 +--- arch/sparc/kernel/irq_32.c| 133 +- arch/sparc/kernel/kernel.h| 53 +-- arch/sparc/kernel/led.c | 146 -- arch/sparc/kernel/leon_kernel.c | 53 +-- arch/sparc/kernel/leon_pmc.c | 16 +- arch/sparc/kernel/leon_smp.c | 3 - arch/sparc/kernel/of_device_32.c | 18 +- arch/sparc/kernel/pcic.c | 840 -- arch/sparc/kernel/pmc.c | 100 arch/sparc/kernel/process_32.c| 10 - arch/sparc/kernel/rtrap_32.S | 73 ++- arch/sparc/kernel/setup_32.c | 115 - arch/sparc/kernel/smp_32.c| 102 + arch/sparc/kernel/sun4d_irq.c | 519 - arch/sparc/kernel/sun4d_smp.c | 415 - arch/sparc/kernel/sun4m_irq.c | 478 --- arch/sparc/kernel/sun4m_smp.c | 275 --- arch/sparc/kernel/time_32.c | 68 +-- arch/sparc/kernel/trampoline_32.S | 127 + arch/sparc/kernel/ttable_32.S | 9 +- arch/sparc/kernel/vmlinux.lds.S | 5 - arch/sparc/kernel/wof.S | 61 +-- arch/sparc/kernel/wuf.S | 41 +- arch/sparc/mm/Makefile| 4 +- arch/sparc/mm/hypersparc.S| 414 - arch/sparc/mm/io-unit.c | 286 arch/sparc/mm/iommu.c | 455 -- arch/sparc/mm/mm_32.h | 4 - arch/sparc/mm/srmmu.c | 836 + arch/sparc/mm/srmmu_access.S | 83 arch/sparc/mm/swift.S | 256 --- arch/sparc/mm/tsunami.S | 132 -- arch/sparc/mm/viking.S| 284 arch/sparc/prom/Makefile | 1 - arch/sparc/prom/init_32.c | 2 - arch/sparc/prom/misc_32.c | 2 - arch/sparc/prom/ranges.c | 114 - drivers/sbus/char/Kconfig | 8 - drivers/sbus/char/Makefile| 1 - drivers/sbus/char/uctrl.c | 435 -- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ehci-hcd.c | 4 +- drivers/usb/host/uhci-hcd.c | 2 +- drivers/video/fbdev/Kconfig | 10 +- drivers/video/fbdev/Makefile | 1 - drivers/video/fbdev/p9100.c | 372 --- sound/sparc/Kconfig | 1 + 88 files changed, 318 insertions(+), 10809 deletions(-) --- base-commit: bee0e7762ad2c6025b9f5245c040fcc36ef2bde8 change-id: 20231219-sam-sparc32-sunset-v3-4751ea89da2d Best regards, -- Sam Ravnborg
[PATCH 21/27] sparc32: Drop unused iommu support
From: Sam Ravnborg LEON do not have any iommu support - drop it. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/iommu.h| 2 - arch/sparc/include/asm/iommu_32.h | 122 --- arch/sparc/kernel/ioport.c| 1 - arch/sparc/mm/Makefile| 2 +- arch/sparc/mm/iommu.c | 420 -- arch/sparc/mm/mm_32.h | 3 - arch/sparc/mm/srmmu.c | 3 - 7 files changed, 1 insertion(+), 552 deletions(-) diff --git a/arch/sparc/include/asm/iommu.h b/arch/sparc/include/asm/iommu.h index 37935cb34865..ea07526ff476 100644 --- a/arch/sparc/include/asm/iommu.h +++ b/arch/sparc/include/asm/iommu.h @@ -3,7 +3,5 @@ #define ___ASM_SPARC_IOMMU_H #if defined(__sparc__) && defined(__arch64__) #include -#else -#include #endif #endif diff --git a/arch/sparc/include/asm/iommu_32.h b/arch/sparc/include/asm/iommu_32.h deleted file mode 100644 index af51cd5ea3c1.. --- a/arch/sparc/include/asm/iommu_32.h +++ /dev/null @@ -1,122 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* iommu.h: Definitions for the sun4m IOMMU. - * - * Copyright (C) 1996 David S. Miller (da...@caip.rutgers.edu) - */ -#ifndef _SPARC_IOMMU_H -#define _SPARC_IOMMU_H - -#include -#include - -/* The iommu handles all virtual to physical address translations - * that occur between the SBUS and physical memory. Access by - * the cpu to IO registers and similar go over the mbus so are - * translated by the on chip SRMMU. The iommu and the srmmu do - * not need to have the same translations at all, in fact most - * of the time the translations they handle are a disjunct set. - * Basically the iommu handles all dvma sbus activity. - */ - -/* The IOMMU registers occupy three pages in IO space. */ -struct iommu_regs { - /* First page */ - volatile unsigned long control;/* IOMMU control */ - volatile unsigned long base; /* Physical base of iopte page table */ - volatile unsigned long _unused1[3]; - volatile unsigned long tlbflush; /* write only */ - volatile unsigned long pageflush; /* write only */ - volatile unsigned long _unused2[1017]; - /* Second page */ - volatile unsigned long afsr; /* Async-fault status register */ - volatile unsigned long afar; /* Async-fault physical address */ - volatile unsigned long _unused3[2]; - volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */ - volatile unsigned long sbuscfg1; - volatile unsigned long sbuscfg2; - volatile unsigned long sbuscfg3; - volatile unsigned long mfsr; /* Memory-fault status register */ - volatile unsigned long mfar; /* Memory-fault physical address */ - volatile unsigned long _unused4[1014]; - /* Third page */ - volatile unsigned long mid;/* IOMMU module-id */ -}; - -#define IOMMU_CTRL_IMPL 0xf000 /* Implementation */ -#define IOMMU_CTRL_VERS 0x0f00 /* Version */ -#define IOMMU_CTRL_RNGE 0x001c /* Mapping RANGE */ -#define IOMMU_RNGE_16MB 0x /* 0xff00 -> 0x */ -#define IOMMU_RNGE_32MB 0x0004 /* 0xfe00 -> 0x */ -#define IOMMU_RNGE_64MB 0x0008 /* 0xfc00 -> 0x */ -#define IOMMU_RNGE_128MB0x000c /* 0xf800 -> 0x */ -#define IOMMU_RNGE_256MB0x0010 /* 0xf000 -> 0x */ -#define IOMMU_RNGE_512MB0x0014 /* 0xe000 -> 0x */ -#define IOMMU_RNGE_1GB 0x0018 /* 0xc000 -> 0x */ -#define IOMMU_RNGE_2GB 0x001c /* 0x8000 -> 0x */ -#define IOMMU_CTRL_ENAB 0x0001 /* IOMMU Enable */ - -#define IOMMU_AFSR_ERR 0x8000 /* LE, TO, or BE asserted */ -#define IOMMU_AFSR_LE 0x4000 /* SBUS reports error after transaction */ -#define IOMMU_AFSR_TO 0x2000 /* Write access took more than 12.8 us. */ -#define IOMMU_AFSR_BE 0x1000 /* Write access received error acknowledge */ -#define IOMMU_AFSR_SIZE 0x0e00 /* Size of transaction causing error */ -#define IOMMU_AFSR_S0x0100 /* Sparc was in supervisor mode */ -#define IOMMU_AFSR_RESV 0x00f0 /* Reserver, forced to 0x8 by hardware */ -#define IOMMU_AFSR_ME 0x0008 /* Multiple errors occurred */ -#define IOMMU_AFSR_RD 0x0004 /* A read operation was in progress */ -#define IOMMU_AFSR_FAV 0x0002 /* IOMMU afar has valid contents */ - -#define IOMMU_SBCFG_SAB30 0x0001 /* Phys-address bit 30 when bypass enabled */ -#define IOMMU_SBCFG_BA160x0004 /* Slave supports 16 byte bursts */ -#define IOMMU_SBCFG_BA8 0x0002 /* Slave supports 8 byte bursts */ -#define IOMMU_SBCFG_BYPASS 0x0001 /* Bypass IOMMU, treat all addresses - produced by this device as pure -
[PATCH 15/27] sparc32: Drop check for sparc_model
From: Sam Ravnborg sparc32 is always LEON, so no need to check for the model. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/cpu_type.h | 18 - arch/sparc/include/asm/io_32.h| 4 +- arch/sparc/include/asm/pgtsrmmu.h | 1 - arch/sparc/kernel/devices.c | 7 +--- arch/sparc/kernel/ioport.c| 4 +- arch/sparc/kernel/leon_pmc.c | 16 arch/sparc/kernel/setup_32.c | 79 +-- 7 files changed, 12 insertions(+), 117 deletions(-) diff --git a/arch/sparc/include/asm/cpu_type.h b/arch/sparc/include/asm/cpu_type.h index 2b59799859d1..3e0154c3f41d 100644 --- a/arch/sparc/include/asm/cpu_type.h +++ b/arch/sparc/include/asm/cpu_type.h @@ -2,28 +2,10 @@ #ifndef __ASM_CPU_TYPE_H #define __ASM_CPU_TYPE_H -/* - * Sparc (general) CPU types - */ -enum sparc_cpu { - sun4m = 0x00, - sun4d = 0x01, - sun4e = 0x02, - sun4u = 0x03, /* V8 ploos ploos */ - sun_unknown = 0x04, - ap1000 = 0x05, /* almost a sun4m */ - sparc_leon = 0x06, /* Leon SoC */ -}; - #ifdef CONFIG_SPARC32 -extern enum sparc_cpu sparc_cpu_model; #define SUN4M_NCPUS4 /* Architectural limit of sun4m. */ -#else - -#define sparc_cpu_model sun4u - #endif #endif /* __ASM_CPU_TYPE_H */ diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h index 549f0a72280d..83abe709d120 100644 --- a/arch/sparc/include/asm/io_32.h +++ b/arch/sparc/include/asm/io_32.h @@ -138,11 +138,11 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *); static inline int sbus_can_dma_64bit(void) { - return 0; /* actually, sparc_cpu_model==sun4d */ + return 0; } static inline int sbus_can_burst64(void) { - return 0; /* actually, sparc_cpu_model==sun4d */ + return 0; } struct device; void sbus_set_sbus64(struct device *, int); diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h index 7cb5cbc83211..664d4bba1bcb 100644 --- a/arch/sparc/include/asm/pgtsrmmu.h +++ b/arch/sparc/include/asm/pgtsrmmu.h @@ -124,7 +124,6 @@ static inline void srmmu_flush_whole_tlb(void) "i" (ASI_M_FLUSH_PROBE) : "memory"); } - #endif /* !(__ASSEMBLY__) */ #endif /* !(_SPARC_PGTSRMMU_H) */ diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index b3c2d51b22c4..2963e89611a3 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c @@ -26,8 +26,6 @@ static char *cpu_mid_prop(void) { - if (sparc_cpu_model == sun4d) - return "cpu-id"; return "mid"; } @@ -40,8 +38,6 @@ static int check_cpu_node(phandle nd, int *cur_inst, *prom_node = nd; if (mid) { *mid = prom_getintdefault(nd, cpu_mid_prop(), 0); - if (sparc_cpu_model == sun4m) - *mid &= 3; } return 0; } @@ -92,8 +88,7 @@ static int cpu_mid_compare(phandle nd, int instance, void *_arg) int this_mid; this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0); - if (this_mid == desired_mid - || (sparc_cpu_model == sun4m && (this_mid & 3) == desired_mid)) + if (this_mid == desired_mid) return 0; return -ENODEV; } diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 5ebca5c7af1e..cf0ace29704a 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -309,9 +309,7 @@ arch_initcall(sparc_register_ioport); void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, enum dma_data_direction dir) { - if (dir != DMA_TO_DEVICE && - sparc_cpu_model == sparc_leon && - !sparc_leon3_snooping_enabled()) + if (dir != DMA_TO_DEVICE && !sparc_leon3_snooping_enabled()) leon_flush_dcache_all(); } diff --git a/arch/sparc/kernel/leon_pmc.c b/arch/sparc/kernel/leon_pmc.c index 6c00cbad7fb5..d4a2d49f941c 100644 --- a/arch/sparc/kernel/leon_pmc.c +++ b/arch/sparc/kernel/leon_pmc.c @@ -79,15 +79,13 @@ static void pmc_leon_idle(void) /* Install LEON Power Down function */ static int __init leon_pmc_install(void) { - if (sparc_cpu_model == sparc_leon) { - /* Assign power management IDLE handler */ - if (pmc_leon_need_fixup()) - sparc_idle = pmc_leon_idle_fixup; - else - sparc_idle = pmc_leon_idle; - - printk(KERN_INFO "leon: power management initialized\n"); - } + /* Assign power management IDLE handler */ + if (pmc_leon_need_fixup()) + sparc_idle = pmc_leon_idle_fixup; + else + sparc_idle = pmc_leon_idle; + + printk(KERN_INFO "leon: power management initialized\n"); return 0; } diff --git
[PATCH 18/27] sparc32: Drop support for 7 register windows
From: Sam Ravnborg Some older SPARC CPUs had support for only 7 register windows. To support this run-time patching was used. LEON demand 8 register windows for use with Linux so there is no need to support the 7 window configuration. The complexity of the assembler code is reduced when dropping the run-time patching, thus increasing the maintainability. Signed-off-by: Sam Ravnborg Cc: Sam Ravnborg Cc: "David S. Miller" Cc: Andreas Larsson --- arch/sparc/include/asm/switch_to_32.h | 1 - arch/sparc/kernel/entry.S | 28 --- arch/sparc/kernel/etrap_32.S | 35 +-- arch/sparc/kernel/head_32.S | 65 --- arch/sparc/kernel/rtrap_32.S | 55 + arch/sparc/kernel/wof.S | 43 --- arch/sparc/kernel/wuf.S | 20 +++ 7 files changed, 57 insertions(+), 190 deletions(-) diff --git a/arch/sparc/include/asm/switch_to_32.h b/arch/sparc/include/asm/switch_to_32.h index 42eeafcb8a41..7aaaf31c09b4 100644 --- a/arch/sparc/include/asm/switch_to_32.h +++ b/arch/sparc/include/asm/switch_to_32.h @@ -37,7 +37,6 @@ extern struct thread_info *current_set[NR_CPUS]; #define prepare_arch_switch(next) do { \ __asm__ __volatile__( \ - ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \ "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \ "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \ "save %sp, -0x40, %sp\n\t" \ diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 9cf8f87e8c42..078a8f7f8383 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -384,11 +384,8 @@ do_flush_windows: RESTORE_ALL - .globl flush_patch_one - /* We get these for debugging routines using __builtin_return_address() */ dfw_kernel: -flush_patch_one: FLUSH_ALL_KERNEL_WINDOWS /* Advance over the trap instruction. */ @@ -558,10 +555,9 @@ sys_rt_sigreturn: * XXX code just like on sparc64... -DaveM */ .align 4 - .globl sys_fork, flush_patch_two + .globl sys_fork sys_fork: mov %o7, %l5 -flush_patch_two: FLUSH_ALL_KERNEL_WINDOWS; ld [%curptr + TI_TASK], %o4 rd %psr, %g4 @@ -574,10 +570,9 @@ flush_patch_two: mov%l5, %o7 /* Whee, kernel threads! */ - .globl sys_clone, flush_patch_three + .globl sys_clone sys_clone: mov %o7, %l5 -flush_patch_three: FLUSH_ALL_KERNEL_WINDOWS; ld [%curptr + TI_TASK], %o4 rd %psr, %g4 @@ -590,9 +585,8 @@ flush_patch_three: mov%l5, %o7 /* Whee, real vfork! */ - .globl sys_vfork, flush_patch_four + .globl sys_vfork sys_vfork: -flush_patch_four: FLUSH_ALL_KERNEL_WINDOWS; ld [%curptr + TI_TASK], %o4 rd %psr, %g4 @@ -909,17 +903,7 @@ breakpoint_trap: #endif .align 4 - .globl flush_patch_exception -flush_patch_exception: - FLUSH_ALL_KERNEL_WINDOWS; - ldd [%o0], %o6 - jmpl%o7 + 0xc, %g0 ! see asm-sparc/processor.h -mov1, %g1 ! signal EFAULT condition - - .align 4 - .globl kill_user_windows, kuw_patch1_7win - .globl kuw_patch1 -kuw_patch1_7win: sll %o3, 6, %o3 + .globl kill_user_windows /* No matter how much overhead this routine has in the worst * case scenario, it is several times better than taking the @@ -939,11 +923,11 @@ kill_user_windows: be 4f ! yep, we are done rd %wim, %o3 ! get current wim srl %o3, 1, %o4 ! simulate a save -kuw_patch1: +kuw_next: sll %o3, 7, %o3 ! compute next wim or %o4, %o3, %o3 ! result andncc %o0, %o3, %o0 ! clean this bit in umask - bne kuw_patch1 ! not done yet + bne kuw_next! not done yet srl%o3, 1, %o4 ! begin another save simulation wr %o3, 0x0, %wim ! set the new wim st %g0, [%g6 + TI_UWINMASK]! clear uwinmask diff --git a/arch/sparc/kernel/etrap_32.S b/arch/sparc/kernel/etrap_32.S index bb222459f097..95dfdea1f36c 100644 --- a/arch/sparc/kernel/etrap_32.S +++ b/arch/sparc/kernel/etrap_32.S @@ -30,18 +30,6 @@ .text .align 4 - /* SEVEN WINDOW PATCH INSTRUCTIONS */ - .globl tsetup_7win_patch1, tsetup_7win_patch2 - .globl tsetup_7win_patch3, tsetup_7win_patch4 - .globl tsetup_7win_patch5, tsetup_7win_patch6 -tsetup_7win_patch1:sll %t_wim, 0x6, %t_wim -tsetup_7win_patch2:
[PATCH 05/27] sparc32: Drop sun specific power management drivers
From: Sam Ravnborg Drop the two sun specific apc and pmc drivers. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/Kconfig | 7 -- arch/sparc/kernel/Makefile | 1 - arch/sparc/kernel/apc.c| 196 - arch/sparc/kernel/pmc.c| 100 --- 4 files changed, 304 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 1520f68e944a..55a9e67c482e 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -324,13 +324,6 @@ config CMDLINE NOTE: This option WILL override the PROM bootargs setting! -config SUN_PM - bool - default y if SPARC32 - help - Enable power management and CPU standby features on supported - SPARC platforms. - config SERIAL_CONSOLE bool depends on SPARC32 diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 95687af45d20..ab47823f8b4e 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -84,7 +84,6 @@ obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o obj-$(CONFIG_SPARC64_SMP) += hvtramp.o obj-y += auxio_$(BITS).o -obj-$(CONFIG_SUN_PM) += apc.o pmc.o obj-y += termios.o diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c deleted file mode 100644 index d44725d37e30.. --- a/arch/sparc/kernel/apc.c +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* apc - Driver implementation for power management functions - * of Aurora Personality Chip (APC) on SPARCstation-4/5 and - * derivatives. - * - * Copyright (c) 2002 Eric Brower (ebro...@usa.net) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* Debugging - * - * #define APC_DEBUG_LED - */ - -#define APC_MINOR MISC_DYNAMIC_MINOR -#define APC_OBPNAME"power-management" -#define APC_DEVNAME "apc" - -static u8 __iomem *regs; -static int apc_no_idle = 0; - -#define apc_readb(offs)(sbus_readb(regs+offs)) -#define apc_writeb(val, offs) (sbus_writeb(val, regs+offs)) - -/* Specify "apc=noidle" on the kernel command line to - * disable APC CPU standby support. Certain prototype - * systems (SPARCstation-Fox) do not play well with APC - * CPU idle, so disable this if your system has APC and - * crashes randomly. - */ -static int __init apc_setup(char *str) -{ - if(!strncmp(str, "noidle", strlen("noidle"))) { - apc_no_idle = 1; - return 1; - } - return 0; -} -__setup("apc=", apc_setup); - -/* - * CPU idle callback function - * See .../arch/sparc/kernel/process.c - */ -static void apc_swift_idle(void) -{ -#ifdef APC_DEBUG_LED - set_auxio(0x00, AUXIO_LED); -#endif - - apc_writeb(apc_readb(APC_IDLE_REG) | APC_IDLE_ON, APC_IDLE_REG); - -#ifdef APC_DEBUG_LED - set_auxio(AUXIO_LED, 0x00); -#endif -} - -static inline void apc_free(struct platform_device *op) -{ - of_iounmap(>resource[0], regs, resource_size(>resource[0])); -} - -static int apc_open(struct inode *inode, struct file *f) -{ - return 0; -} - -static int apc_release(struct inode *inode, struct file *f) -{ - return 0; -} - -static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg) -{ - __u8 inarg, __user *arg = (__u8 __user *) __arg; - - switch (cmd) { - case APCIOCGFANCTL: - if (put_user(apc_readb(APC_FANCTL_REG) & APC_REGMASK, arg)) - return -EFAULT; - break; - - case APCIOCGCPWR: - if (put_user(apc_readb(APC_CPOWER_REG) & APC_REGMASK, arg)) - return -EFAULT; - break; - - case APCIOCGBPORT: - if (put_user(apc_readb(APC_BPORT_REG) & APC_BPMASK, arg)) - return -EFAULT; - break; - - case APCIOCSFANCTL: - if (get_user(inarg, arg)) - return -EFAULT; - apc_writeb(inarg & APC_REGMASK, APC_FANCTL_REG); - break; - - case APCIOCSCPWR: - if (get_user(inarg, arg)) - return -EFAULT; - apc_writeb(inarg & APC_REGMASK, APC_CPOWER_REG); - break; - - case APCIOCSBPORT: - if (get_user(inarg, arg)) - return -EFAULT; - apc_writeb(inarg & APC_BPMASK, APC_BPORT_REG); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static const struct file_operations apc_fops = { - .unlocked_ioctl = apc_ioctl, - .open = apc_open, - .release = apc_release, - .llseek = noop_llseek, -}; - -static struct miscdevice
[PATCH 25/27] sparc32: Drop sbus support
From: Sam Ravnborg LEON do not have an sbus - so drop support for that for sparc32. Fix a few Kconfig expressions to use CONFIG_SBUS rather than SPARC as only SPARC64 has an sbus now. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/Kconfig | 4 +- arch/sparc/include/asm/fb.h | 8 ++-- arch/sparc/include/asm/io_32.h | 83 arch/sparc/kernel/ioport.c | 49 arch/sparc/kernel/of_device_32.c | 14 --- drivers/video/fbdev/Kconfig | 2 +- sound/sparc/Kconfig | 1 + 7 files changed, 9 insertions(+), 152 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 0fc52c3c7487..1b9cf7f3c500 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -392,11 +392,11 @@ endmenu menu "Bus options (PCI etc.)" config SBUS bool - default y + default y if SPARC64 config SBUSCHAR bool - default y + default y if SPARC64 config SUN_LDOMS bool "Sun Logical Domains support" diff --git a/arch/sparc/include/asm/fb.h b/arch/sparc/include/asm/fb.h index 24440c0fda49..15b007875457 100644 --- a/arch/sparc/include/asm/fb.h +++ b/arch/sparc/include/asm/fb.h @@ -8,6 +8,9 @@ struct fb_info; +int fb_is_primary_device(struct fb_info *info); +#define fb_is_primary_device fb_is_primary_device + #ifdef CONFIG_SPARC32 static inline pgprot_t pgprot_framebuffer(pgprot_t prot, unsigned long vm_start, unsigned long vm_end, @@ -18,9 +21,7 @@ static inline pgprot_t pgprot_framebuffer(pgprot_t prot, #define pgprot_framebuffer pgprot_framebuffer #endif -int fb_is_primary_device(struct fb_info *info); -#define fb_is_primary_device fb_is_primary_device - +#ifdef CONFIG_SPARC64 static inline void fb_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n) { sbus_memcpy_fromio(to, from, n); @@ -38,6 +39,7 @@ static inline void fb_memset_io(volatile void __iomem *addr, int c, size_t n) sbus_memset_io(addr, c, n); } #define fb_memset fb_memset_io +#endif #include diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h index 83abe709d120..b9f280ee1b11 100644 --- a/arch/sparc/include/asm/io_32.h +++ b/arch/sparc/include/asm/io_32.h @@ -56,78 +56,6 @@ static inline void _memcpy_toio(volatile void __iomem *dst, const void *src, } } -/* - * SBus accessors. - * - * SBus has only one, memory mapped, I/O space. - * We do not need to flip bytes for SBus of course. - */ -static inline u8 sbus_readb(const volatile void __iomem *addr) -{ - return *(__force volatile u8 *)addr; -} - -static inline u16 sbus_readw(const volatile void __iomem *addr) -{ - return *(__force volatile u16 *)addr; -} - -static inline u32 sbus_readl(const volatile void __iomem *addr) -{ - return *(__force volatile u32 *)addr; -} - -static inline void sbus_writeb(u8 b, volatile void __iomem *addr) -{ - *(__force volatile u8 *)addr = b; -} - -static inline void sbus_writew(u16 w, volatile void __iomem *addr) -{ - *(__force volatile u16 *)addr = w; -} - -static inline void sbus_writel(u32 l, volatile void __iomem *addr) -{ - *(__force volatile u32 *)addr = l; -} - -static inline void sbus_memset_io(volatile void __iomem *__dst, int c, - __kernel_size_t n) -{ - while(n--) { - sbus_writeb(c, __dst); - __dst++; - } -} - -static inline void sbus_memcpy_fromio(void *dst, - const volatile void __iomem *src, - __kernel_size_t n) -{ - char *d = dst; - - while (n--) { - char tmp = sbus_readb(src); - *d++ = tmp; - src++; - } -} - -static inline void sbus_memcpy_toio(volatile void __iomem *dst, -const void *src, -__kernel_size_t n) -{ - const char *s = src; - volatile void __iomem *d = dst; - - while (n--) { - char tmp = *s++; - sbus_writeb(tmp, d); - d++; - } -} - /* Create a virtual mapping cookie for an IO port range */ void __iomem *ioport_map(unsigned long port, unsigned int nr); void ioport_unmap(void __iomem *); @@ -136,17 +64,6 @@ void ioport_unmap(void __iomem *); struct pci_dev; void pci_iounmap(struct pci_dev *dev, void __iomem *); -static inline int sbus_can_dma_64bit(void) -{ - return 0; -} -static inline int sbus_can_burst64(void) -{ - return 0; -} -struct device; -void sbus_set_sbus64(struct device *, int); - #define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1 diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 9c4c72775274..97b836f3be25 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c
[PATCH 26/27] sbus: char: Drop now unused uctrl driver
From: Sam Ravnborg The uctrl driver is only relevant for the Sparcbook 3 machine, and with sun4m support removed this driver is no logner relevant. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- drivers/sbus/char/Kconfig | 8 - drivers/sbus/char/Makefile | 1 - drivers/sbus/char/uctrl.c | 435 - 3 files changed, 444 deletions(-) diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig index 7c0a308e4959..8b80abc554ed 100644 --- a/drivers/sbus/char/Kconfig +++ b/drivers/sbus/char/Kconfig @@ -21,14 +21,6 @@ config OBP_FLASH The OpenBoot PROM on Ultra systems is flashable. If you want to be able to upgrade the OBP firmware, say Y here. -config TADPOLE_TS102_UCTRL - tristate "Tadpole TS102 Microcontroller support" - help - Say Y here to directly support the TS102 Microcontroller interface - on the Tadpole Sparcbook 3. This device handles power-management - events, and can also notice the attachment/detachment of external - monitors and mice. - config BBC_I2C tristate "UltraSPARC-III bootbus i2c controller driver" depends on PCI && SPARC64 diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile index 44347c918f6b..9db2faabfae8 100644 --- a/drivers/sbus/char/Makefile +++ b/drivers/sbus/char/Makefile @@ -14,6 +14,5 @@ obj-$(CONFIG_ENVCTRL) += envctrl.o obj-$(CONFIG_DISPLAY7SEG) += display7seg.o obj-$(CONFIG_OBP_FLASH)+= flash.o obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o -obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o obj-$(CONFIG_BBC_I2C) += bbc.o obj-$(CONFIG_ORACLE_DAX) += oradax.o diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c deleted file mode 100644 index 0660425e3a5a.. --- a/drivers/sbus/char/uctrl.c +++ /dev/null @@ -1,435 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 - * - * Copyright 1999 Derrick J Brashear (sha...@dementia.org) - * Copyright 2008 David S. Miller (da...@davemloft.net) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define DEBUG 1 -#ifdef DEBUG -#define dprintk(x) printk x -#else -#define dprintk(x) -#endif - -struct uctrl_regs { - u32 uctrl_intr; - u32 uctrl_data; - u32 uctrl_stat; - u32 uctrl_xxx[5]; -}; - -struct ts102_regs { - u32 card_a_intr; - u32 card_a_stat; - u32 card_a_ctrl; - u32 card_a_xxx; - u32 card_b_intr; - u32 card_b_stat; - u32 card_b_ctrl; - u32 card_b_xxx; - u32 uctrl_intr; - u32 uctrl_data; - u32 uctrl_stat; - u32 uctrl_xxx; - u32 ts102_xxx[4]; -}; - -/* Bits for uctrl_intr register */ -#define UCTRL_INTR_TXE_REQ 0x01/* transmit FIFO empty int req */ -#define UCTRL_INTR_TXNF_REQ0x02/* transmit FIFO not full int req */ -#define UCTRL_INTR_RXNE_REQ0x04/* receive FIFO not empty int req */ -#define UCTRL_INTR_RXO_REQ 0x08/* receive FIFO overflow int req */ -#define UCTRL_INTR_TXE_MSK 0x10/* transmit FIFO empty mask */ -#define UCTRL_INTR_TXNF_MSK0x20/* transmit FIFO not full mask */ -#define UCTRL_INTR_RXNE_MSK0x40/* receive FIFO not empty mask */ -#define UCTRL_INTR_RXO_MSK 0x80/* receive FIFO overflow mask */ - -/* Bits for uctrl_stat register */ -#define UCTRL_STAT_TXE_STA 0x01/* transmit FIFO empty status */ -#define UCTRL_STAT_TXNF_STA0x02/* transmit FIFO not full status */ -#define UCTRL_STAT_RXNE_STA0x04/* receive FIFO not empty status */ -#define UCTRL_STAT_RXO_STA 0x08/* receive FIFO overflow status */ - -static DEFINE_MUTEX(uctrl_mutex); -static const char *uctrl_extstatus[16] = { -"main power available", -"internal battery attached", -"external battery attached", -"external VGA attached", -"external keyboard attached", -"external mouse attached", -"lid down", -"internal battery currently charging", -"external battery currently charging", -"internal battery currently discharging", -"external battery currently discharging", -}; - -/* Everything required for one transaction with the uctrl */ -struct uctrl_txn { - u8 opcode; - u8 inbits; - u8 outbits; - u8 *inbuf; - u8 *outbuf; -}; - -struct uctrl_status { - u8 current_temp; /* 0x07 */ - u8 reset_status; /* 0x0b */ - u16 event_status; /* 0x0c */ - u16 error_status; /* 0x10 */ - u16 external_status; /* 0x11, 0x1b */ - u8 internal_charge; /* 0x18 */ - u8 external_charge; /* 0x19 */
[PATCH 19/27] sparc32: Drop additional sun4d bits
From: Sam Ravnborg Drop sun4d specific support. Not used by LEON. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/io-unit.h | 59 arch/sparc/include/asm/obio.h| 226 --- arch/sparc/include/asm/sbi.h | 116 arch/sparc/kernel/entry.S| 1 - arch/sparc/kernel/ioport.c | 1 - arch/sparc/mm/Makefile | 2 +- arch/sparc/mm/io-unit.c | 283 --- arch/sparc/mm/srmmu.c| 1 - 8 files changed, 1 insertion(+), 688 deletions(-) diff --git a/arch/sparc/include/asm/io-unit.h b/arch/sparc/include/asm/io-unit.h deleted file mode 100644 index 8c38f5b9f927.. --- a/arch/sparc/include/asm/io-unit.h +++ /dev/null @@ -1,59 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* io-unit.h: Definitions for the sun4d IO-UNIT. - * - * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz) - */ -#ifndef _SPARC_IO_UNIT_H -#define _SPARC_IO_UNIT_H - -#include -#include -#include - -/* The io-unit handles all virtual to physical address translations - * that occur between the SBUS and physical memory. Access by - * the cpu to IO registers and similar go over the xdbus so are - * translated by the on chip SRMMU. The io-unit and the srmmu do - * not need to have the same translations at all, in fact most - * of the time the translations they handle are a disjunct set. - * Basically the io-unit handles all dvma sbus activity. - */ - -/* AIEEE, unlike the nice sun4m, these monsters have - fixed DMA range 64M */ - -#define IOUNIT_DMA_BASE0xfc00 /* TOP - 64M */ -#define IOUNIT_DMA_SIZE0x0400 /* 64M */ -/* We use last 1M for sparc_dvma_malloc */ -#define IOUNIT_DVMA_SIZE0x0010 /* 1M */ - -/* The format of an iopte in the external page tables */ -#define IOUPTE_PAGE 0xff00 /* Physical page number (PA[35:12]) */ -#define IOUPTE_CACHE 0x0080 /* Cached (in Viking/MXCC) */ -/* XXX Jakub, find out how to program SBUS streaming cache on XDBUS/sun4d. - * XXX Actually, all you should need to do is find out where the registers - * XXX are and copy over the sparc64 implementation I wrote. There may be - * XXX some horrible hwbugs though, so be careful. -DaveM - */ -#define IOUPTE_STREAM0x0040 /* Translation can use streaming cache */ -#define IOUPTE_INTRA0x0008 /* SBUS direct slot->slot transfer */ -#define IOUPTE_WRITE 0x0004 /* Writeable */ -#define IOUPTE_VALID 0x0002 /* IOPTE is valid */ -#define IOUPTE_PARITY0x0001 /* Parity is checked during DVMA */ - -struct iounit_struct { - unsigned long bmap[(IOUNIT_DMA_SIZE >> (PAGE_SHIFT + 3)) / sizeof(unsigned long)]; - spinlock_t lock; - iopte_t __iomem *page_table; - unsigned long rotor[3]; - unsigned long limit[4]; -}; - -#define IOUNIT_BMAP1_START 0x -#define IOUNIT_BMAP1_END (IOUNIT_DMA_SIZE >> (PAGE_SHIFT + 1)) -#define IOUNIT_BMAP2_START IOUNIT_BMAP1_END -#define IOUNIT_BMAP2_END IOUNIT_BMAP2_START + (IOUNIT_DMA_SIZE >> (PAGE_SHIFT + 2)) -#define IOUNIT_BMAPM_START IOUNIT_BMAP2_END -#define IOUNIT_BMAPM_END ((IOUNIT_DMA_SIZE - IOUNIT_DVMA_SIZE) >> PAGE_SHIFT) - -#endif /* !(_SPARC_IO_UNIT_H) */ diff --git a/arch/sparc/include/asm/obio.h b/arch/sparc/include/asm/obio.h deleted file mode 100644 index 1b151f738b00.. --- a/arch/sparc/include/asm/obio.h +++ /dev/null @@ -1,226 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * obio.h: Some useful locations in 0xF PA obio space on sun4d. - * - * Copyright (C) 1997 Jakub Jelinek - */ - -#ifndef _SPARC_OBIO_H -#define _SPARC_OBIO_H - -#include - -/* This weird monster likes to use the very upper parts of - 36bit PA for these things :) */ - -/* CSR space (for each XDBUS) - * - * | 0xFE | DEVID|| XDBUS ID | | - * - * 35 28 2720 1910 98 7 0 - */ - -#define CSR_BASE_ADDR 0xe000 -#define CSR_CPU_SHIFT (32 - 4 - 5) -#define CSR_XDBUS_SHIFT8 - -#define CSR_BASE(cpu) (((CSR_BASE_ADDR >> CSR_CPU_SHIFT) + cpu) << CSR_CPU_SHIFT) - -/* ECSR space (not for each XDBUS) - * - * | 0xF | DEVID[7:1] | | - * - * 35 32 3125 240 - */ - -#define
[PATCH 16/27] sparc32: Drop use of sparc_config
From: Sam Ravnborg sparc_config were used to handle the differences between the machines. With only LEON supported sparc_config is no longer required. Refactor the time code a litte as some parts are obsolete and other parts are only used when SMP is not enabled. Signed-off-by: Sam Ravnborg Cc: Sam Ravnborg Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/include/asm/timer_32.h | 1 + arch/sparc/kernel/irq.h | 37 +++--- arch/sparc/kernel/irq_32.c| 3 -- arch/sparc/kernel/leon_kernel.c | 27 +++-- arch/sparc/kernel/of_device_32.c | 4 +-- arch/sparc/kernel/time_32.c | 64 +-- 6 files changed, 33 insertions(+), 103 deletions(-) diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index eecd2696922d..1cd89a99966f 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -17,6 +17,7 @@ #include /* For SUN4M_NCPUS */ #define SBUS_CLOCK_RATE 200 /* 2MHz */ +#define LEON_CLOCK_RATE 100 #define TIMER_VALUE_SHIFT 9 #define TIMER_VALUE_MASK 0x3f #define TIMER_LIMIT_BIT (1 << 31) /* Bit 31 in Counter-Timer register */ diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index 0d9b740725b4..8a0b314c8299 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -44,38 +44,6 @@ struct sun4m_irq_global { extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; extern struct sun4m_irq_global __iomem *sun4m_irq_global; -/* The following definitions describe the individual platform features: */ -#define FEAT_L10_CLOCKSOURCE (1 << 0) /* L10 timer is used as a clocksource */ -#define FEAT_L10_CLOCKEVENT (1 << 1) /* L10 timer is used as a clockevent */ -#define FEAT_L14_ONESHOT (1 << 2) /* L14 timer clockevent can oneshot */ - -/* - * Platform specific configuration - * The individual platforms assign their platform - * specifics in their init functions. - */ -struct sparc_config { - void (*init_timers)(void); - unsigned int (*build_device_irq)(struct platform_device *op, -unsigned int real_irq); - - /* generic clockevent features - see FEAT_* above */ - int features; - - /* clock rate used for clock event timer */ - int clock_rate; - - /* one period for clock source timer */ - unsigned int cs_period; - - /* function to obtain offsett for cs period */ - unsigned int (*get_cycles_offset)(void); - - void (*clear_clock_irq)(void); - void (*load_profile_irq)(int cpu, unsigned int limit); -}; -extern struct sparc_config sparc_config; - unsigned int irq_alloc(unsigned int real_irq, unsigned int pil); void irq_link(unsigned int irq); void irq_unlink(unsigned int irq); @@ -89,6 +57,11 @@ void sun4m_nmi(struct pt_regs *regs); /* sun4d_irq.c */ void sun4d_handler_irq(unsigned int pil, struct pt_regs *regs); +/* leon_kernel.c */ +void leon_clear_clock_irq(void); +void leon_load_profile_irq(int cpu, unsigned int limit); +u32 leon_cycles_offset(void); + #ifdef CONFIG_SMP /* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c index a6af08fce796..f76f57073323 100644 --- a/arch/sparc/kernel/irq_32.c +++ b/arch/sparc/kernel/irq_32.c @@ -24,9 +24,6 @@ #include "kernel.h" #include "irq.h" -/* platform specific irq setup */ -struct sparc_config sparc_config; - unsigned long arch_local_irq_save(void) { unsigned long retval; diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index ea04bad6a118..fa9cdaffdc6b 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -237,12 +237,6 @@ unsigned int leon_build_device_irq(unsigned int real_irq, return irq; } -static unsigned int _leon_build_device_irq(struct platform_device *op, - unsigned int real_irq) -{ - return leon_build_device_irq(real_irq, handle_simple_irq, "edge", 0); -} - void leon_update_virq_handling(unsigned int virq, irq_flow_handler_t flow_handler, const char *name, int do_ack) @@ -258,7 +252,7 @@ void leon_update_virq_handling(unsigned int virq, irq_set_chip_data(virq, (void *)mask); } -static u32 leon_cycles_offset(void) +u32 leon_cycles_offset(void) { u32 rld, val, ctrl, off; @@ -312,14 +306,6 @@ void __init leon_init_timers(void) u32 config; u32 ctrl; - sparc_config.get_cycles_offset = leon_cycles_offset; - sparc_config.cs_period = 100 / HZ; - sparc_config.features |= FEAT_L10_CLOCKSOURCE; - -#ifndef CONFIG_SMP - sparc_config.features |= FEAT_L10_CLOCKEVENT; -#endif - leondebug_irq_disable = 0; leon_debug_irqout = 0; master_l10_counter = (u32 __iomem
[PATCH 08/27] sparc32: Drop patching of interrupt vector
From: Sam Ravnborg Drop the sun4m specific handling and the patching that takes place in sun4d and LEON. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/kernel/entry.S | 98 - arch/sparc/kernel/kernel.h | 1 - arch/sparc/kernel/leon_kernel.c | 16 --- arch/sparc/kernel/sun4d_irq.c | 25 --- 4 files changed, 140 deletions(-) diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 7cf148a996b9..9bd3813b872d 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -79,15 +79,6 @@ bad_trap_handler: real_irq_entry: SAVE_ALL -#ifdef CONFIG_SMP - .globl patchme_maybe_smp_msg - - cmp %l7, 11 -patchme_maybe_smp_msg: - bgu maybe_smp4m_msg -nop -#endif - real_irq_continue: or %l0, PSR_PIL, %g2 wr %g2, 0x0, %psr @@ -105,95 +96,6 @@ patch_handler_irq: RESTORE_ALL #ifdef CONFIG_SMP - /* SMP per-cpu ticker interrupts are handled specially. */ -smp4m_ticker: - bne real_irq_continue+4 -or %l0, PSR_PIL, %g2 - wr %g2, 0x0, %psr - WRITE_PAUSE - wr %g2, PSR_ET, %psr - WRITE_PAUSE - callsmp4m_percpu_timer_interrupt -add%sp, STACKFRAME_SZ, %o0 - wr %l0, PSR_ET, %psr - WRITE_PAUSE - RESTORE_ALL - -#define GET_PROCESSOR4M_ID(reg)\ - rd %tbr, %reg; \ - srl %reg, 12, %reg; \ - and %reg, 3, %reg; - - /* Here is where we check for possible SMP IPI passed to us -* on some level other than 15 which is the NMI and only used -* for cross calls. That has a separate entry point below. -* -* IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*. -*/ -maybe_smp4m_msg: - GET_PROCESSOR4M_ID(o3) - sethi %hi(sun4m_irq_percpu), %l5 - sll %o3, 2, %o3 - or %l5, %lo(sun4m_irq_percpu), %o5 - sethi %hi(0x7000), %o2! Check all soft-IRQs - ld [%o5 + %o3], %o1 - ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending - andcc %o3, %o2, %g0 - be,asmp4m_ticker -cmp%l7, 14 - /* Soft-IRQ IPI */ - st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x7000 - WRITE_PAUSE - ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending - WRITE_PAUSE - or %l0, PSR_PIL, %l4 - wr %l4, 0x0, %psr - WRITE_PAUSE - wr %l4, PSR_ET, %psr - WRITE_PAUSE - srl %o3, 28, %o2! shift for simpler checks below -maybe_smp4m_msg_check_single: - andcc %o2, 0x1, %g0 - beq,a maybe_smp4m_msg_check_mask -andcc %o2, 0x2, %g0 - callsmp_call_function_single_interrupt -nop - andcc %o2, 0x2, %g0 -maybe_smp4m_msg_check_mask: - beq,a maybe_smp4m_msg_check_resched -andcc %o2, 0x4, %g0 - callsmp_call_function_interrupt -nop - andcc %o2, 0x4, %g0 -maybe_smp4m_msg_check_resched: - /* rescheduling is done in RESTORE_ALL regardless, but incr stats */ - beq,a maybe_smp4m_msg_out -nop - callsmp_resched_interrupt -nop -maybe_smp4m_msg_out: - RESTORE_ALL - - - .globl smp4d_ticker - /* SMP per-cpu ticker interrupts are handled specially. */ -smp4d_ticker: - SAVE_ALL - or %l0, PSR_PIL, %g2 - sethi %hi(CC_ICLR), %o0 - sethi %hi(1 << 14), %o1 - or %o0, %lo(CC_ICLR), %o0 - stha%o1, [%o0] ASI_M_MXCC /* Clear PIL 14 in MXCC's ICLR */ - wr %g2, 0x0, %psr - WRITE_PAUSE - wr %g2, PSR_ET, %psr - WRITE_PAUSE - callsmp4d_percpu_timer_interrupt -add%sp, STACKFRAME_SZ, %o0 - wr %l0, PSR_ET, %psr - WRITE_PAUSE - RESTORE_ALL - .globl smpleon_ipi .extern leon_ipi_interrupt /* SMP per-cpu IPI interrupts are handled specially. */ diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 1d3980ac0658..85a3c3d1195e 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -145,7 +145,6 @@ extern char cputypval[]; extern unsigned long lvl14_save[4]; extern unsigned int real_irq_entry[]; extern unsigned int smp4d_ticker[]; -extern unsigned int patchme_maybe_smp_msg[]; /* trampoline_32.S */ extern unsigned long sun4m_cpu_startup; diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 4c61da491fee..ea04bad6a118 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -421,22 +421,6 @@ void __init leon_init_timers(void) if (eirq != 0) leon_eirq_setup(eirq); -#ifdef CONFIG_SMP - { - unsigned long flags; - - /* -
[PATCH 02/27] sparc32: Drop sun4m/sun4d support from head_32.S
From: Sam Ravnborg Remove the most obvious parts of sun4* support from head_32.S. Use a single print if a sun4* machine is detected thus restricting boots to LEON machines. Signed-off-by: Sam Ravnborg Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Andreas Larsson --- arch/sparc/kernel/head_32.S | 190 +++- 1 file changed, 9 insertions(+), 181 deletions(-) diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S index 964c61b5cd03..03dc232dd235 100644 --- a/arch/sparc/kernel/head_32.S +++ b/arch/sparc/kernel/head_32.S @@ -45,11 +45,7 @@ cputypvar: .align 4 notsup: - .asciz "Sparc-Linux sun4/sun4c or MMU-less not supported\n\n" - .align 4 - -sun4e_notsup: -.asciz "Sparc-Linux sun4e support does not exist\n\n" + .asciz "This kernel only supports LEON SPARC V8\n\n" .align 4 /* The trap-table - located in the __HEAD section */ @@ -215,114 +211,10 @@ not_a_sun4: be leon_remap /* It is a LEON - jump */ nop - /* Sanity-check, is MMU enabled */ - lda [%g0] ASI_M_MMUREGS, %g1 - andcc %g1, 1, %g0 - be halt_notsup -nop - - /* Check for a viking (TI) module. */ - cmp %g3, PSR_IMPL_TI - bne srmmu_not_viking -nop - - /* Figure out what kind of viking we are on. -* We need to know if we have to play with the -* AC bit and disable traps or not. -*/ - - /* I've only seen MicroSparc's on SparcClassics with this -* bit set. -*/ - set 0x800, %g2 - lda [%g0] ASI_M_MMUREGS, %g3! peek in the control reg - and %g2, %g3, %g3 - subcc %g3, 0x0, %g0 - bnz srmmu_not_viking! is in mbus mode -nop - - rd %psr, %g3 ! DO NOT TOUCH %g3 - andn%g3, PSR_ET, %g2 - wr %g2, 0x0, %psr - WRITE_PAUSE - - /* Get context table pointer, then convert to -* a physical address, which is 36 bits. -*/ - set AC_M_CTPR, %g4 - lda [%g4] ASI_M_MMUREGS, %g4 - sll %g4, 0x4, %g4 ! We use this below - ! DO NOT TOUCH %g4 - - /* Set the AC bit in the Viking's MMU control reg. */ - lda [%g0] ASI_M_MMUREGS, %g5! DO NOT TOUCH %g5 - set 0x8000, %g6 ! AC bit mask - or %g5, %g6, %g6 ! Or it in... - sta %g6, [%g0] ASI_M_MMUREGS! Close your eyes... - - /* Grrr, why does it seem like every other load/store -* on the sun4m is in some ASI space... -* Fine with me, let's get the pointer to the level 1 -* page table directory and fetch its entry. -*/ - lda [%g4] ASI_M_BYPASS, %o1 ! This is a level 1 ptr - srl %o1, 0x4, %o1 ! Clear low 4 bits - sll %o1, 0x8, %o1 ! Make physical - - /* Ok, pull in the PTD. */ - lda [%o1] ASI_M_BYPASS, %o2 ! This is the 0x0 16MB pgd - - /* Calculate to KERNBASE entry. */ - add %o1, KERNBASE >> (PGDIR_SHIFT - 2), %o3 - - /* Poke the entry into the calculated address. */ - sta %o2, [%o3] ASI_M_BYPASS - - /* I don't get it Sun, if you engineered all these -* boot loaders and the PROM (thank you for the debugging -* features btw) why did you not have them load kernel -* images up in high address space, since this is necessary -* for ABI compliance anyways? Does this low-mapping provide -* enhanced interoperability? -* -* "The PROM is the computer." -*/ - - /* Ok, restore the MMU control register we saved in %g5 */ - sta %g5, [%g0] ASI_M_MMUREGS! POW... ouch - - /* Turn traps back on. We saved it in %g3 earlier. */ - wr %g3, 0x0, %psr ! tick tock, tick tock - - /* Now we burn precious CPU cycles due to bad engineering. */ - WRITE_PAUSE - - /* Wow, all that just to move a 32-bit value from one -* place to another... Jump to high memory. -*/ - b go_to_highmem + /* Not LEON - halt */ +
[PATCH v3 4/6] input/vmmouse: Use vmware_hypercall API
From: Alexey Makhalov Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. No functional changes intended. Signed-off-by: Alexey Makhalov Reviewed-by: Nadav Amit Reviewed-by: Zack Rusin Acked-by: Dmitry Torokhov --- drivers/input/mouse/vmmouse.c | 76 ++- 1 file changed, 22 insertions(+), 54 deletions(-) diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c index ea9eff7c8099..fb1d986a6895 100644 --- a/drivers/input/mouse/vmmouse.c +++ b/drivers/input/mouse/vmmouse.c @@ -21,19 +21,16 @@ #include "psmouse.h" #include "vmmouse.h" -#define VMMOUSE_PROTO_MAGIC0x564D5868U - /* * Main commands supported by the vmmouse hypervisor port. */ -#define VMMOUSE_PROTO_CMD_GETVERSION 10 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA 39 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS40 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND 41 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT 86 +#define VMWARE_CMD_ABSPOINTER_DATA 39 +#define VMWARE_CMD_ABSPOINTER_STATUS 40 +#define VMWARE_CMD_ABSPOINTER_COMMAND 41 +#define VMWARE_CMD_ABSPOINTER_RESTRICT 86 /* - * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND + * Subcommands for VMWARE_CMD_ABSPOINTER_COMMAND */ #define VMMOUSE_CMD_ENABLE 0x45414552U #define VMMOUSE_CMD_DISABLE0x00f5U @@ -76,28 +73,6 @@ struct vmmouse_data { char dev_name[128]; }; -/* - * Hypervisor-specific bi-directional communication channel - * implementing the vmmouse protocol. Should never execute on - * bare metal hardware. - */ -#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \ -({ \ - unsigned long __dummy1, __dummy2; \ - __asm__ __volatile__ (VMWARE_HYPERCALL :\ - "=a"(out1), \ - "=b"(out2), \ - "=c"(out3), \ - "=d"(out4), \ - "=S"(__dummy1), \ - "=D"(__dummy2) :\ - "a"(VMMOUSE_PROTO_MAGIC), \ - "b"(in1), \ - "c"(VMMOUSE_PROTO_CMD_##cmd), \ - "d"(0) :\ - "memory"); \ -}) - /** * vmmouse_report_button - report button state on the correct input device * @@ -145,14 +120,12 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) struct input_dev *abs_dev = priv->abs_dev; struct input_dev *pref_dev; u32 status, x, y, z; - u32 dummy1, dummy2, dummy3; unsigned int queue_length; unsigned int count = 255; while (count--) { /* See if we have motion data. */ - VMMOUSE_CMD(ABSPOINTER_STATUS, 0, - status, dummy1, dummy2, dummy3); + status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0); if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) { psmouse_err(psmouse, "failed to fetch status data\n"); /* @@ -172,7 +145,8 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) } /* Now get it */ - VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z); + status = vmware_hypercall4(VMWARE_CMD_ABSPOINTER_DATA, 4, + , , ); /* * And report what we've got. Prefer to report button @@ -247,14 +221,10 @@ static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse) static void vmmouse_disable(struct psmouse *psmouse) { u32 status; - u32 dummy1, dummy2, dummy3, dummy4; - - VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE, - dummy1, dummy2, dummy3, dummy4); - VMMOUSE_CMD(ABSPOINTER_STATUS, 0, - status, dummy1, dummy2, dummy3); + vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE); + status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0); if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR) psmouse_warn(psmouse, "failed to disable vmmouse device\n"); } @@ -271,26 +241,24 @@ static void vmmouse_disable(struct psmouse *psmouse) static int vmmouse_enable(struct psmouse *psmouse) { u32 status, version; - u32 dummy1, dummy2, dummy3, dummy4; /* * Try enabling the device. If successful, we should be able to * read valid version ID back from it. */ - VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE, - dummy1, dummy2, dummy3, dummy4); +
[PATCH v3 6/6] x86/vmware: Add TDX hypercall support
From: Alexey Makhalov VMware hypercalls use I/O port, VMCALL or VMMCALL instructions. Add __tdx_hypercall path to support TDX guests. No change in high bandwidth hypercalls, as only low bandwidth ones are supported for TDX guests. Co-developed-by: Tim Merrifield Signed-off-by: Tim Merrifield Signed-off-by: Alexey Makhalov Reviewed-by: Nadav Amit --- arch/x86/include/asm/vmware.h | 83 +++ arch/x86/kernel/cpu/vmware.c | 24 ++ 2 files changed, 107 insertions(+) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index 719e41260ece..cad6f5b371a8 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -34,12 +34,65 @@ #define VMWARE_CMD_GETHZ 45 #define VMWARE_CMD_GETVCPU_INFO68 #define VMWARE_CMD_STEALCLOCK 91 +/* + * Hypercall command mask: + * bits[6:0] command, range [0, 127] + * bits[19:16] sub-command, range [0, 15] + */ +#define VMWARE_CMD_MASK0xf007fU #define CPUID_VMWARE_FEATURES_ECX_VMMCALL BIT(0) #define CPUID_VMWARE_FEATURES_ECX_VMCALL BIT(1) extern u8 vmware_hypercall_mode; +#define VMWARE_TDX_VENDOR_LEAF 0x1af7e4909ULL +#define VMWARE_TDX_HCALL_FUNC 1 + +extern unsigned long vmware_tdx_hypercall(unsigned long cmd, + struct tdx_module_args *args); + +/* + * TDCALL[TDG.VP.VMCALL] uses rax (arg0) and rcx (arg2), while the use of + * rbp (arg6) is discouraged by the TDX specification. Therefore, we + * remap those registers to r12, r13 and r14, respectively. + */ +static inline +unsigned long vmware_tdx_hypercall_args(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, unsigned long in6, + uint32_t *out1, uint32_t *out2, + uint32_t *out3, uint32_t *out4, + uint32_t *out5, uint32_t *out6) +{ + unsigned long ret; + + struct tdx_module_args args = { + .rbx = in1, + .rdx = in3, + .rsi = in4, + .rdi = in5, + .r14 = in6, + }; + + ret = vmware_tdx_hypercall(cmd, ); + + if (out1) + *out1 = args.rbx; + if (out2) + *out2 = args.r13; + if (out3) + *out3 = args.rdx; + if (out4) + *out4 = args.rsi; + if (out5) + *out5 = args.rdi; + if (out6) + *out6 = args.r14; + + return ret; +} + /* * The low bandwidth call. The low word of edx is presumed to have OUT bit * set. The high word of edx may contain input data from the caller. @@ -67,6 +120,11 @@ unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall_args(cmd, in1, 0, 0, 0, 0, +NULL, NULL, NULL, +NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -85,6 +143,11 @@ unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall_args(cmd, in1, 0, 0, 0, 0, +out1, out2, NULL, +NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=b" (*out1), "=c" (*out2) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -104,6 +167,11 @@ unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall_args(cmd, in1, 0, 0, 0, 0, +out1, out2, out3, +NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3) : [port] "i" (VMWARE_HYPERVISOR_PORT), @@ -123,6 +191,11 @@ unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, { unsigned long out0; + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return vmware_tdx_hypercall_args(cmd, in1, in3, in4, in5, 0, +NULL, out2, NULL, +NULL, NULL, NULL); + asm_inline volatile (VMWARE_HYPERCALL : "=a" (out0), "=c" (*out2) : [port] "i"
[PATCH v3 2/6] x86/vmware: Introduce vmware_hypercall API
From: Alexey Makhalov Introduce vmware_hypercall family of functions. It is a common implementation to be used by the VMware guest code and virtual device drivers in architecture independent manner. The API consists of vmware_hypercallX and vmware_hypercall_hb_{out,in} set of functions by analogy with KVM hypercall API. Architecture specific implementation is hidden inside. It will simplify future enhancements in VMware hypercalls such as SEV-ES and TDX related changes without needs to modify a caller in device drivers code. Current implementation extends an idea from commit bac7b4e84323 ("x86/vmware: Update platform detection code for VMCALL/VMMCALL hypercalls") to have a slow, but safe path in VMWARE_HYPERCALL earlier during the boot when alternatives are not yet applied. This logic was inherited from VMWARE_CMD from the commit mentioned above. Default alternative code was optimized by size to reduce excessive nop alignment once alternatives are applied. Total default code size is 26 bytes, in worse case (3 bytes alternative) remaining 23 bytes will be aligned by only 3 long NOP instructions. Signed-off-by: Alexey Makhalov Reviewed-by: Nadav Amit Reviewed-by: Jeff Sipek --- arch/x86/include/asm/vmware.h | 262 ++ arch/x86/kernel/cpu/vmware.c | 35 ++--- 2 files changed, 220 insertions(+), 77 deletions(-) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index 3636faa8b4fe..719e41260ece 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -40,69 +40,219 @@ extern u8 vmware_hypercall_mode; -/* The low bandwidth call. The low word of edx is presumed clear. */ -#define VMWARE_HYPERCALL \ - ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT) ", %%dx; " \ - "inl (%%dx), %%eax", \ - "vmcall", X86_FEATURE_VMCALL, \ - "vmmcall", X86_FEATURE_VMW_VMMCALL) - /* - * The high bandwidth out call. The low word of edx is presumed to have the - * HB and OUT bits set. + * The low bandwidth call. The low word of edx is presumed to have OUT bit + * set. The high word of edx may contain input data from the caller. */ -#define VMWARE_HYPERCALL_HB_OUT \ - ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \ - "rep outsb", \ +#define VMWARE_HYPERCALL \ + ALTERNATIVE_3("cmpb $" \ + __stringify(CPUID_VMWARE_FEATURES_ECX_VMMCALL) \ + ", %[mode]\n\t" \ + "jg 2f\n\t" \ + "je 1f\n\t" \ + "movw %[port], %%dx\n\t" \ + "inl (%%dx), %%eax\n\t" \ + "jmp 3f\n\t" \ + "1: vmmcall\n\t" \ + "jmp 3f\n\t" \ + "2: vmcall\n\t" \ + "3:\n\t", \ + "movw %[port], %%dx\n\t" \ + "inl (%%dx), %%eax", X86_FEATURE_HYPERVISOR, \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) +static inline +unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (0) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0), "=b" (*out1), "=c" (*out2) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (0) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, +
[PATCH v3 3/6] ptp/vmware: Use vmware_hypercall API
From: Alexey Makhalov Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. No functional changes intended. Signed-off-by: Alexey Makhalov Reviewed-by: Nadav Amit Reviewed-by: Jeff Sipek --- drivers/ptp/ptp_vmw.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/ptp/ptp_vmw.c b/drivers/ptp/ptp_vmw.c index 27c5547aa8a9..e5bb521b9b82 100644 --- a/drivers/ptp/ptp_vmw.c +++ b/drivers/ptp/ptp_vmw.c @@ -14,7 +14,6 @@ #include #include -#define VMWARE_MAGIC 0x564D5868 #define VMWARE_CMD_PCLK(nr) ((nr << 16) | 97) #define VMWARE_CMD_PCLK_GETTIME VMWARE_CMD_PCLK(0) @@ -24,15 +23,10 @@ static struct ptp_clock *ptp_vmw_clock; static int ptp_vmw_pclk_read(u64 *ns) { - u32 ret, nsec_hi, nsec_lo, unused1, unused2, unused3; - - asm volatile (VMWARE_HYPERCALL : - "=a"(ret), "=b"(nsec_hi), "=c"(nsec_lo), "=d"(unused1), - "=S"(unused2), "=D"(unused3) : - "a"(VMWARE_MAGIC), "b"(0), - "c"(VMWARE_CMD_PCLK_GETTIME), "d"(0) : - "memory"); + u32 ret, nsec_hi, nsec_lo; + ret = vmware_hypercall3(VMWARE_CMD_PCLK_GETTIME, 0, + _hi, _lo); if (ret == 0) *ns = ((u64)nsec_hi << 32) | nsec_lo; return ret; -- 2.39.0
[PATCH v3 5/6] drm/vmwgfx: Use vmware_hypercall API
From: Alexey Makhalov Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h: implement arm64 variant of vmware_hypercall. And keep it here until introduction of ARM64 VMWare hypervisor interface. Signed-off-by: Alexey Makhalov Reviewed-by: Nadav Amit Reviewed-by: Zack Rusin --- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 173 +++ drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h | 197 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h | 185 3 files changed, 197 insertions(+), 358 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c index 2651fe0ef518..1f15990d3934 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c @@ -48,8 +48,6 @@ #define RETRIES 3 -#define VMW_HYPERVISOR_MAGIC0x564D5868 - #define VMW_PORT_CMD_MSG30 #define VMW_PORT_CMD_HB_MSG 0 #define VMW_PORT_CMD_OPEN_CHANNEL (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG) @@ -104,20 +102,18 @@ static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] = */ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) { - unsigned long eax, ebx, ecx, edx, si = 0, di = 0; + u32 ecx, edx, esi, edi; - VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL, - (protocol | GUESTMSG_FLAG_COOKIE), si, di, - 0, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall6(VMW_PORT_CMD_OPEN_CHANNEL, + (protocol | GUESTMSG_FLAG_COOKIE), 0, + , , , ); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) return -EINVAL; channel->channel_id = HIGH_WORD(edx); - channel->cookie_high = si; - channel->cookie_low = di; + channel->cookie_high = esi; + channel->cookie_low = edi; return 0; } @@ -133,17 +129,13 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) */ static int vmw_close_channel(struct rpc_channel *channel) { - unsigned long eax, ebx, ecx, edx, si, di; - - /* Set up additional parameters */ - si = channel->cookie_high; - di = channel->cookie_low; + u32 ecx; - VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL, - 0, si, di, - channel->channel_id << 16, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall5(VMW_PORT_CMD_CLOSE_CHANNEL, + 0, channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, + ); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) return -EINVAL; @@ -163,24 +155,18 @@ static int vmw_close_channel(struct rpc_channel *channel) static unsigned long vmw_port_hb_out(struct rpc_channel *channel, const char *msg, bool hb) { - unsigned long si, di, eax, ebx, ecx, edx; + u32 ebx, ecx; unsigned long msg_len = strlen(msg); /* HB port can't access encrypted memory. */ if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) { - unsigned long bp = channel->cookie_high; - u32 channel_id = (channel->channel_id << 16); - - si = (uintptr_t) msg; - di = channel->cookie_low; - - VMW_PORT_HB_OUT( + vmware_hypercall_hb_out( (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, - msg_len, si, di, - VMWARE_HYPERVISOR_HB | channel_id | - VMWARE_HYPERVISOR_OUT, - VMW_HYPERVISOR_MAGIC, bp, - eax, ebx, ecx, edx, si, di); + msg_len, + channel->channel_id << 16, + (uintptr_t) msg, channel->cookie_low, + channel->cookie_high, + ); return ebx; } @@ -194,14 +180,13 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel, memcpy(, msg, bytes); msg_len -= bytes; msg += bytes; - si = channel->cookie_high; - di = channel->cookie_low; - - VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16), -word, si, di, -channel->channel_id << 16, -VMW_HYPERVISOR_MAGIC, -eax, ebx, ecx, edx, si, di); + + vmware_hypercall5(VMW_PORT_CMD_MSG | + (MSG_TYPE_SENDPAYLOAD << 16), + word, channel->channel_id << 16, +
[PATCH v3 1/6] x86/vmware: Move common macros to vmware.h
From: Alexey Makhalov Move VMware hypercall macros to vmware.h. This is a prerequisite for the introduction of vmware_hypercall API. No functional changes besides exporting vmware_hypercall_mode symbol. Signed-off-by: Alexey Makhalov Reviewed-by: Nadav Amit --- arch/x86/include/asm/vmware.h | 69 ++- arch/x86/kernel/cpu/vmware.c | 57 +++-- 2 files changed, 66 insertions(+), 60 deletions(-) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index ac9fc51e2b18..3636faa8b4fe 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -8,25 +8,37 @@ /* * The hypercall definitions differ in the low word of the %edx argument - * in the following way: the old port base interface uses the port - * number to distinguish between high- and low bandwidth versions. + * in the following way: the old I/O port based interface uses the port + * number to distinguish between high- and low bandwidth versions, and + * uses IN/OUT instructions to define transfer direction. * * The new vmcall interface instead uses a set of flags to select * bandwidth mode and transfer direction. The flags should be loaded * into %dx by any user and are automatically replaced by the port - * number if the VMWARE_HYPERVISOR_PORT method is used. + * number if the I/O port method is used. * * In short, new driver code should strictly use the new definition of * %dx content. */ -/* Old port-based version */ -#define VMWARE_HYPERVISOR_PORT0x5658 -#define VMWARE_HYPERVISOR_PORT_HB 0x5659 +#define VMWARE_HYPERVISOR_HB BIT(0) +#define VMWARE_HYPERVISOR_OUT BIT(1) -/* Current vmcall / vmmcall version */ -#define VMWARE_HYPERVISOR_HB BIT(0) -#define VMWARE_HYPERVISOR_OUT BIT(1) +#define VMWARE_HYPERVISOR_PORT 0x5658 +#define VMWARE_HYPERVISOR_PORT_HB (VMWARE_HYPERVISOR_PORT | \ +VMWARE_HYPERVISOR_HB) + +#define VMWARE_HYPERVISOR_MAGIC0x564d5868U + +#define VMWARE_CMD_GETVERSION 10 +#define VMWARE_CMD_GETHZ 45 +#define VMWARE_CMD_GETVCPU_INFO68 +#define VMWARE_CMD_STEALCLOCK 91 + +#define CPUID_VMWARE_FEATURES_ECX_VMMCALL BIT(0) +#define CPUID_VMWARE_FEATURES_ECX_VMCALL BIT(1) + +extern u8 vmware_hypercall_mode; /* The low bandwidth call. The low word of edx is presumed clear. */ #define VMWARE_HYPERCALL \ @@ -54,4 +66,43 @@ "rep insb", \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) + +#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \ + __asm__("inl (%%dx), %%eax" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :\ + "a"(VMWARE_HYPERVISOR_MAGIC), \ + "c"(VMWARE_CMD_##cmd), \ + "d"(VMWARE_HYPERVISOR_PORT), "b"(UINT_MAX) :\ + "memory") + +#define VMWARE_VMCALL(cmd, eax, ebx, ecx, edx) \ + __asm__("vmcall" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :\ + "a"(VMWARE_HYPERVISOR_MAGIC), \ + "c"(VMWARE_CMD_##cmd), \ + "d"(0), "b"(UINT_MAX) : \ + "memory") + +#define VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx) \ + __asm__("vmmcall" : \ + "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :\ + "a"(VMWARE_HYPERVISOR_MAGIC), \ + "c"(VMWARE_CMD_##cmd), \ + "d"(0), "b"(UINT_MAX) : \ + "memory") + +#define VMWARE_CMD(cmd, eax, ebx, ecx, edx) do { \ + switch (vmware_hypercall_mode) {\ + case CPUID_VMWARE_FEATURES_ECX_VMCALL: \ + VMWARE_VMCALL(cmd, eax, ebx, ecx, edx); \ + break; \ + case CPUID_VMWARE_FEATURES_ECX_VMMCALL: \ + VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx);\ + break; \ + default:\ + VMWARE_PORT(cmd, eax, ebx, ecx, edx); \ + break; \ + } \ + } while
[PATCH v3 0/6] VMware hypercalls enhancements
VMware hypercalls invocations were all spread out across the kernel implementing same ABI as in-place asm-inline. With encrypted memory and confidential computing it became harder to maintain every changes in these hypercall implementations. Intention of this patchset is to introduce arch independent VMware hypercall API layer other subsystems such as device drivers can call to, while hiding architecture specific implementation behind. Second patch introduces the vmware_hypercall low and high bandwidth families of functions, with little enhancements there. Sixth patch adds tdx hypercall support arm64 implementation of vmware_hypercalls is in drivers/gpu/drm/ vmwgfx/vmwgfx_msg_arm64.h and going to be moved to arch/arm64 with a separate patchset with the introduction of VMware Linux guest support for arm64. No functional changes in drivers/input/mouse/vmmouse.c and drivers/ptp/ptp_vmw.c v2->v3 changes: (no functional changes in patches 1-5) - Improved commit message in patches 1, 2 and 5 as was suggested by Borislav Petkov. - To address Dave Hansen's concern, patch 6 was reorganized to avoid exporting bare __tdx_hypercall and to make exported vmware_tdx_hypercall VMWare guest specific. v1->v2 changes (no functional changes): - Improved commit message in patches 2 and 5. - Added Reviewed-by for all patches. - Added Ack from Dmitry Torokhov in patch 4. No fixes regarding reported by Simon Horman gcc error in this patch. Alexey Makhalov (6): x86/vmware: Move common macros to vmware.h x86/vmware: Introduce vmware_hypercall API ptp/vmware: Use vmware_hypercall API input/vmmouse: Use vmware_hypercall API drm/vmwgfx: Use vmware_hypercall API x86/vmware: Add TDX hypercall support arch/x86/include/asm/vmware.h | 338 -- arch/x86/kernel/cpu/vmware.c | 116 +++- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 173 --- drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h | 197 + drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h | 185 drivers/input/mouse/vmmouse.c | 76 ++--- drivers/ptp/ptp_vmw.c | 12 +- 7 files changed, 577 insertions(+), 520 deletions(-) -- 2.39.0
Re: [PATCH] drivers: video: logo: use %u format specifier for unsigned int values
On 12/19/23 07:14, Colin Ian King wrote: > Currently the %d format specifier is being used for unsigned int values. > Fix this by using the correct %u format specifier. Cleans up cppcheck > warnings: > > warning: %d in format string (no. 1) requires 'int' but the argument > type is 'unsigned int'. [invalidPrintfArgType_sint] > > Signed-off-by: Colin Ian King Reviewed-by: Randy Dunlap Thanks. > --- > drivers/video/logo/pnmtologo.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/drivers/video/logo/pnmtologo.c b/drivers/video/logo/pnmtologo.c > index ada5ef6e51b7..2434a25afb64 100644 > --- a/drivers/video/logo/pnmtologo.c > +++ b/drivers/video/logo/pnmtologo.c > @@ -249,10 +249,10 @@ static void write_footer(void) > fputs("\n};\n\n", out); > fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname); > fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]); > - fprintf(out, "\t.width\t\t= %d,\n", logo_width); > - fprintf(out, "\t.height\t\t= %d,\n", logo_height); > + fprintf(out, "\t.width\t\t= %u,\n", logo_width); > + fprintf(out, "\t.height\t\t= %u,\n", logo_height); > if (logo_type == LINUX_LOGO_CLUT224) { > - fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize); > + fprintf(out, "\t.clutsize\t= %u,\n", logo_clutsize); > fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname); > } > fprintf(out, "\t.data\t\t= %s_data\n", logoname); -- #Randy https://people.kernel.org/tglx/notes-about-netiquette https://subspace.kernel.org/etiquette.html
[PATCH v3 4/4] drm/ssd130x: Add support for the SSD133x OLED controller family
The Solomon SSD133x controllers (such as the SSD1331) are used by RGB dot matrix OLED panels, add a modesetting pipeline to support the chip family. The SSD133x controllers support 256 (8-bit) and 65k (16-bit) color depths but only the former is implemented for now. This is because the 256 color depth format matches a fourcc code already present in DRM (RGB8), but the 65k pixel format does not match the existing RG16 fourcc code format. Instead of a R:G:B 5:6:5, the controller expects the 16-bit pixels to be R:G:B 6:5:6, and so a new fourcc needs to be added to support this format. Signed-off-by: Javier Martinez Canillas --- (no changes since v1) drivers/gpu/drm/solomon/ssd130x-i2c.c | 5 + drivers/gpu/drm/solomon/ssd130x-spi.c | 7 + drivers/gpu/drm/solomon/ssd130x.c | 370 ++ drivers/gpu/drm/solomon/ssd130x.h | 5 +- 4 files changed, 386 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/solomon/ssd130x-i2c.c b/drivers/gpu/drm/solomon/ssd130x-i2c.c index f2ccab9c06d9..a047dbec4e48 100644 --- a/drivers/gpu/drm/solomon/ssd130x-i2c.c +++ b/drivers/gpu/drm/solomon/ssd130x-i2c.c @@ -105,6 +105,11 @@ static const struct of_device_id ssd130x_of_match[] = { .compatible = "solomon,ssd1327", .data = _variants[SSD1327_ID], }, + /* ssd133x family */ + { + .compatible = "solomon,ssd1331", + .data = _variants[SSD1331_ID], + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, ssd130x_of_match); diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c b/drivers/gpu/drm/solomon/ssd130x-spi.c index 84e035a7ab3f..84bfde31d172 100644 --- a/drivers/gpu/drm/solomon/ssd130x-spi.c +++ b/drivers/gpu/drm/solomon/ssd130x-spi.c @@ -142,6 +142,11 @@ static const struct of_device_id ssd130x_of_match[] = { .compatible = "solomon,ssd1327", .data = _variants[SSD1327_ID], }, + /* ssd133x family */ + { + .compatible = "solomon,ssd1331", + .data = _variants[SSD1331_ID], + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, ssd130x_of_match); @@ -166,6 +171,8 @@ static const struct spi_device_id ssd130x_spi_table[] = { { "ssd1322", SSD1322_ID }, { "ssd1325", SSD1325_ID }, { "ssd1327", SSD1327_ID }, + /* ssd133x family */ + { "ssd1331", SSD1331_ID }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(spi, ssd130x_spi_table); diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index bef293922b98..447d0c7c88c6 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -119,6 +119,26 @@ #define SSD130X_SET_VCOMH_VOLTAGE 0xbe #define SSD132X_SET_FUNCTION_SELECT_B 0xd5 +/* ssd133x commands */ +#define SSD133X_SET_COL_RANGE 0x15 +#define SSD133X_SET_ROW_RANGE 0x75 +#define SSD133X_CONTRAST_A 0x81 +#define SSD133X_CONTRAST_B 0x82 +#define SSD133X_CONTRAST_C 0x83 +#define SSD133X_SET_MASTER_CURRENT 0x87 +#define SSD132X_SET_PRECHARGE_A0x8a +#define SSD132X_SET_PRECHARGE_B0x8b +#define SSD132X_SET_PRECHARGE_C0x8c +#define SSD133X_SET_DISPLAY_START 0xa1 +#define SSD133X_SET_DISPLAY_OFFSET 0xa2 +#define SSD133X_SET_DISPLAY_NORMAL 0xa4 +#define SSD133X_SET_MASTER_CONFIG 0xad +#define SSD133X_POWER_SAVE_MODE0xb0 +#define SSD133X_PHASES_PERIOD 0xb1 +#define SSD133X_SET_CLOCK_FREQ 0xb3 +#define SSD133X_SET_PRECHARGE_VOLTAGE 0xbb +#define SSD133X_SET_VCOMH_VOLTAGE 0xbe + #define MAX_CONTRAST 255 const struct ssd130x_deviceinfo ssd130x_variants[] = { @@ -180,6 +200,12 @@ const struct ssd130x_deviceinfo ssd130x_variants[] = { .default_width = 128, .default_height = 128, .family_id = SSD132X_FAMILY, + }, + /* ssd133x family */ + [SSD1331_ID] = { + .default_width = 96, + .default_height = 64, + .family_id = SSD133X_FAMILY, } }; EXPORT_SYMBOL_NS_GPL(ssd130x_variants, DRM_SSD130X); @@ -589,6 +615,117 @@ static int ssd132x_init(struct ssd130x_device *ssd130x) return 0; } +static int ssd133x_init(struct ssd130x_device *ssd130x) +{ + int ret; + + /* Set color A contrast */ + ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_A, 0x91); + if (ret < 0) + return ret; + + /* Set color B contrast */ + ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_B, 0x50); + if (ret < 0) + return ret; + + /* Set color C contrast */ + ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_C, 0x7d); + if (ret <
[PATCH v3 3/4] dt-bindings: display: Add SSD133x OLED controllers
Add a Device Tree binding schema for the OLED panels based on the Solomon SSD133x family of controllers. Signed-off-by: Javier Martinez Canillas --- Changes in v3: - Move solomon,ssd-common.yaml ref before the properties section and width/height constraints after the other properties (Conor Dooley). Changes in v2: - Unconditionally set the width and height constraints (Conor Dooley). - Fix indentation in the DTS examples (Krzysztof Kozlowski). .../bindings/display/solomon,ssd133x.yaml | 57 +++ 1 file changed, 57 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/solomon,ssd133x.yaml diff --git a/Documentation/devicetree/bindings/display/solomon,ssd133x.yaml b/Documentation/devicetree/bindings/display/solomon,ssd133x.yaml new file mode 100644 index ..e93879b3da5d --- /dev/null +++ b/Documentation/devicetree/bindings/display/solomon,ssd133x.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/solomon,ssd133x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Solomon SSD133x OLED Display Controllers + +maintainers: + - Javier Martinez Canillas + +allOf: + - $ref: solomon,ssd-common.yaml# + +properties: + compatible: +enum: + - solomon,ssd1331 + + solomon,width: +default: 96 + + solomon,height: +default: 64 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | +i2c { +#address-cells = <1>; +#size-cells = <0>; + +oled@3c { +compatible = "solomon,ssd1331"; +reg = <0x3c>; +reset-gpios = < 7>; +}; + +}; + - | +spi { +#address-cells = <1>; +#size-cells = <0>; + +oled@0 { +compatible = "solomon,ssd1331"; +reg = <0x0>; +reset-gpios = < 7>; +dc-gpios = < 8>; +spi-max-frequency = <1000>; +}; +}; -- 2.43.0
[PATCH v3 2/4] dt-bindings: display: ssd132x: Add vendor prefix to width and height
Commit 2d23e7d6bacb ("dt-bindings: display: Add SSD132x OLED controllers") used the wrong properties for width and height, instead of the correct "solomon,width" and "solomon,height" properties. Fix this by adding the vendor prefix to the width and height properties. Fixes: 2d23e7d6bacb ("dt-bindings: display: Add SSD132x OLED controllers") Reported-by: Conor Dooley Closes: https://lore.kernel.org/dri-devel/20231218-example-envision-b41ca8efa251@spud/ Signed-off-by: Javier Martinez Canillas --- (no changes since v1) .../devicetree/bindings/display/solomon,ssd132x.yaml | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/display/solomon,ssd132x.yaml b/Documentation/devicetree/bindings/display/solomon,ssd132x.yaml index 37975ee61c5a..dd7939989cf4 100644 --- a/Documentation/devicetree/bindings/display/solomon,ssd132x.yaml +++ b/Documentation/devicetree/bindings/display/solomon,ssd132x.yaml @@ -30,9 +30,9 @@ allOf: const: solomon,ssd1322 then: properties: -width: +solomon,width: default: 480 -height: +solomon,height: default: 128 - if: @@ -42,9 +42,9 @@ allOf: const: solomon,ssd1325 then: properties: -width: +solomon,width: default: 128 -height: +solomon,height: default: 80 - if: @@ -54,9 +54,9 @@ allOf: const: solomon,ssd1327 then: properties: -width: +solomon,width: default: 128 -height: +solomon,height: default: 128 unevaluatedProperties: false -- 2.43.0
[PATCH v3 1/4] dt-bindings: display: ssd1307fb: Add vendor prefix to width and height
The commit 591825fba8a2 ("dt-bindings: display: ssd1307fb: Remove default width and height values") used the wrong properties for width and height, instead of the correct "solomon,width" and "solomon,height" properties. Fix this by adding the vendor prefix to the width and height properties. Fixes: 591825fba8a2 ("dt-bindings: display: ssd1307fb: Remove default width and height values") Reported-by: Conor Dooley Closes: https://lore.kernel.org/dri-devel/20231218-example-envision-b41ca8efa251@spud/ Signed-off-by: Javier Martinez Canillas --- (no changes since v1) .../bindings/display/solomon,ssd1307fb.yaml | 20 +-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml index 3afbb52d1b7f..153ff86fb405 100644 --- a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml +++ b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml @@ -131,9 +131,9 @@ allOf: const: sinowealth,sh1106 then: properties: -width: +solomon,width: default: 132 -height: +solomon,height: default: 64 solomon,dclk-div: default: 1 @@ -149,9 +149,9 @@ allOf: - solomon,ssd1305 then: properties: -width: +solomon,width: default: 132 -height: +solomon,height: default: 64 solomon,dclk-div: default: 1 @@ -167,9 +167,9 @@ allOf: - solomon,ssd1306 then: properties: -width: +solomon,width: default: 128 -height: +solomon,height: default: 64 solomon,dclk-div: default: 1 @@ -185,9 +185,9 @@ allOf: - solomon,ssd1307 then: properties: -width: +solomon,width: default: 128 -height: +solomon,height: default: 39 solomon,dclk-div: default: 2 @@ -205,9 +205,9 @@ allOf: - solomon,ssd1309 then: properties: -width: +solomon,width: default: 128 -height: +solomon,height: default: 64 solomon,dclk-div: default: 1 -- 2.43.0
[PATCH v3 0/4] drm/solomon: Add support for the SSD133x controller family
Hello, This patch-set adds support for the family of SSD133x Solomon controllers, such as the SSD1331. These are used for RGB Dot Matrix OLED/PLED panels. This is a v3 that addresses issues pointed out in v2: https://lore.kernel.org/dri-devel/20231218132045.2066576-1-javi...@redhat.com/ The patches were tested on a Waveshare SSD1331 display using glmark2-drm, fbcon, fbtests and the retroarch emulator. The binding schema were tested using the `make W=1 dt_binding_check` target. Patch #1 and #2 are fixes for the DT binding schema of the existing SSD130x and SSD132x families. Patch #3 adds a DT binding schema for the SSD133x controllers and patch #4 extends the ssd130x DRM driver to support the SSD133x controller family. Best regards, Javier Changes in v3: - Move solomon,ssd-common.yaml ref before the properties section and width/height constraints after the other properties (Conor Dooley). Changes in v2: - Unconditionally set the width and height constraints (Conor Dooley). - Fix indentation in the DTS examples (Krzysztof Kozlowski). Javier Martinez Canillas (4): dt-bindings: display: ssd1307fb: Add vendor prefix to width and height dt-bindings: display: ssd132x: Add vendor prefix to width and height dt-bindings: display: Add SSD133x OLED controllers drm/ssd130x: Add support for the SSD133x OLED controller family .../bindings/display/solomon,ssd1307fb.yaml | 20 +- .../bindings/display/solomon,ssd132x.yaml | 12 +- .../bindings/display/solomon,ssd133x.yaml | 57 +++ drivers/gpu/drm/solomon/ssd130x-i2c.c | 5 + drivers/gpu/drm/solomon/ssd130x-spi.c | 7 + drivers/gpu/drm/solomon/ssd130x.c | 370 ++ drivers/gpu/drm/solomon/ssd130x.h | 5 +- 7 files changed, 459 insertions(+), 17 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/solomon,ssd133x.yaml -- 2.43.0
[PATCH] drm/i915/guc: Avoid circular locking issue on busyness flush
From: John Harrison Avoid the following lockdep complaint: <4> [298.856498] == <4> [298.856500] WARNING: possible circular locking dependency detected <4> [298.856503] 6.7.0-rc5-CI_DRM_14017-g58ac4ffc75b6+ #1 Tainted: G N <4> [298.856505] -- <4> [298.856507] kworker/4:1H/190 is trying to acquire lock: <4> [298.856509] 8881103e9978 (>reset.backoff_srcu){}-{0:0}, at: _intel_gt_reset_lock+0x35/0x380 [i915] <4> [298.856661] but task is already holding lock: <4> [298.856663] c900013f7e58 ((work_completion)(&(>timestamp.work)->work)){+.+.}-{0:0}, at: process_scheduled_works+0x264/0x530 <4> [298.856671] which lock already depends on the new lock. The complaint is not actually valid. The busyness worker thread does indeed hold the worker lock and then attempt to acquire the reset lock (which may have happened in reverse order elsewhere). However, it does so with a trylock that exits if the reset lock is not available (specifically to prevent this and other similar deadlocks). Unfortunately, lockdep does not understand the trylock semantics (the lock is an i915 specific custom implementation for resets). Not doing a synchronous flush of the worker thread when a reset is in progress resolves the lockdep splat by never even attempting to grab the lock in this particular scenario. There are situatons where a synchronous cancel is required, however. So, always do the synchronous cancel if not in reset. And add an extra synchronous cancel to the end of the reset flow to account for when a reset is occurring at driver shutdown and the cancel is no longer synchronous but could lead to unallocated memory accesses if the worker is not stopped. Signed-off-by: Zhanjun Dong Signed-off-by: John Harrison Cc: Andi Shyti Cc: Daniel Vetter --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 48 ++- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 2 +- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index a259f1118c5ab..0228a77d456ed 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1362,7 +1362,45 @@ static void guc_enable_busyness_worker(struct intel_guc *guc) static void guc_cancel_busyness_worker(struct intel_guc *guc) { - cancel_delayed_work_sync(>timestamp.work); + /* +* There are many different call stacks that can get here. Some of them +* hold the reset mutex. The busyness worker also attempts to acquire the +* reset mutex. Synchronously flushing a worker thread requires acquiring +* the worker mutex. Lockdep sees this as a conflict. It thinks that the +* flush can deadlock because it holds the worker mutex while waiting for +* the reset mutex, but another thread is holding the reset mutex and might +* attempt to use other worker functions. +* +* In practice, this scenario does not exist because the busyness worker +* does not block waiting for the reset mutex. It does a try-lock on it and +* immediately exits if the lock is already held. Unfortunately, the mutex +* in question (I915_RESET_BACKOFF) is an i915 implementation which has lockdep +* annotation but not to the extent of explaining the 'might lock' is also a +* 'does not need to lock'. So one option would be to add more complex lockdep +* annotations to ignore the issue (if at all possible). A simpler option is to +* just not flush synchronously when a rest in progress. Given that the worker +* will just early exit and re-schedule itself anyway, there is no advantage +* to running it immediately. +* +* If a reset is not in progress, then the synchronous flush may be required. +* As noted many call stacks lead here, some during suspend and driver unload +* which do require a synchronous flush to make sure the worker is stopped +* before memory is freed. +* +* Trying to pass a 'need_sync' or 'in_reset' flag all the way down through +* every possible call stack is unfeasible. It would be too intrusive to many +* areas that really don't care about the GuC backend. However, there is the +* 'reset_in_progress' flag available, so just use that. +* +* And note that in the case of a reset occurring during driver unload +* (wedge_on_fini), skipping the cancel in _prepare (when the reset flag is set +* is fine because there is another cancel in _finish (when the reset flag is +* not). +*/ + if (guc_to_gt(guc)->uc.reset_in_progress) + cancel_delayed_work(>timestamp.work); + else +
Re: [RFC PATCH v3 04/23] drm/vkms: Add kunit tests for VKMS LUT handling
On 2023-12-07 09:30, Pekka Paalanen wrote: > On Wed, 8 Nov 2023 11:36:23 -0500 > Harry Wentland wrote: > >> Debugging LUT math is much easier when we can unit test >> it. Add kunit functionality to VKMS and add tests for >> - get_lut_index >> - lerp_u16 >> >> v3: >> - Use include way of testing static functions (Arthur) >> >> Signed-off-by: Harry Wentland >> Cc: Arthur Grillo >> --- >> drivers/gpu/drm/vkms/Kconfig | 5 ++ >> drivers/gpu/drm/vkms/tests/.kunitconfig | 4 ++ >> drivers/gpu/drm/vkms/tests/vkms_color_tests.c | 62 +++ >> drivers/gpu/drm/vkms/vkms_composer.c | 8 ++- >> 4 files changed, 77 insertions(+), 2 deletions(-) >> create mode 100644 drivers/gpu/drm/vkms/tests/.kunitconfig >> create mode 100644 drivers/gpu/drm/vkms/tests/vkms_color_tests.c >> >> diff --git a/drivers/gpu/drm/vkms/Kconfig b/drivers/gpu/drm/vkms/Kconfig >> index b9ecdebecb0b..c1f8b343ff0e 100644 >> --- a/drivers/gpu/drm/vkms/Kconfig >> +++ b/drivers/gpu/drm/vkms/Kconfig >> @@ -13,3 +13,8 @@ config DRM_VKMS >>a VKMS. >> >>If M is selected the module will be called vkms. >> + >> +config DRM_VKMS_KUNIT_TESTS >> +tristate "Tests for VKMS" if !KUNIT_ALL_TESTS >> +depends on DRM_VKMS && KUNIT >> +default KUNIT_ALL_TESTS >> diff --git a/drivers/gpu/drm/vkms/tests/.kunitconfig >> b/drivers/gpu/drm/vkms/tests/.kunitconfig >> new file mode 100644 >> index ..70e378228cbd >> --- /dev/null >> +++ b/drivers/gpu/drm/vkms/tests/.kunitconfig >> @@ -0,0 +1,4 @@ >> +CONFIG_KUNIT=y >> +CONFIG_DRM=y >> +CONFIG_DRM_VKMS=y >> +CONFIG_DRM_VKMS_KUNIT_TESTS=y >> diff --git a/drivers/gpu/drm/vkms/tests/vkms_color_tests.c >> b/drivers/gpu/drm/vkms/tests/vkms_color_tests.c >> new file mode 100644 >> index ..b995114cf6b8 >> --- /dev/null >> +++ b/drivers/gpu/drm/vkms/tests/vkms_color_tests.c >> @@ -0,0 +1,62 @@ >> +/* SPDX-License-Identifier: GPL-2.0+ */ >> + >> +#include >> + >> +#include >> + >> +#define TEST_LUT_SIZE 16 >> + >> +static struct drm_color_lut test_linear_array[TEST_LUT_SIZE] = { >> +{ 0x0, 0x0, 0x0, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +{ 0x, 0x, 0x, 0 }, >> +}; >> + >> +const struct vkms_color_lut test_linear_lut = { >> +.base = test_linear_array, >> +.lut_length = TEST_LUT_SIZE, >> +.channel_value2index_ratio = 0xf000fll >> +}; >> + >> + >> +static void vkms_color_test_get_lut_index(struct kunit *test) >> +{ >> +int i; >> + >> +KUNIT_EXPECT_EQ(test, drm_fixp2int(get_lut_index(_linear_lut, >> test_linear_array[0].red)), 0); >> + >> +for (i = 0; i < TEST_LUT_SIZE; i++) >> +KUNIT_EXPECT_EQ(test, >> drm_fixp2int_ceil(get_lut_index(_linear_lut, >> test_linear_array[i].red)), i); > > Hi, > > what about testing with values not directly hitting a LUT element? > >> +} >> + >> +static void vkms_color_test_lerp(struct kunit *test) >> +{ >> +KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, 0x8000), 0x8); > > It would raise much more confidence in lerp_u16() if there were more cases: > - odd a > - odd b > - odd b-a > - b = a > - b = a + 1 > > For each of the above: > - t = 0.0 > - t = 1.0 > - t = 0.0 + 1 > - t = 1.0 - 1 > - t chosen so that result must round/truncate > - t chosen to verify the flipping point of result a (or b) to a+1 (or b-1) > > I think those are the fragile points in a lerp implementation. > Good point. Adding the "t = 1.0 - 1" test actually showed a problem with the lerp_u16 function. I have a fix for it. Harry > > Thanks, > pq > >> +} >> + >> +static struct kunit_case vkms_color_test_cases[] = { >> +KUNIT_CASE(vkms_color_test_get_lut_index), >> +KUNIT_CASE(vkms_color_test_lerp), >> +{} >> +}; >> + >> +static struct kunit_suite vkms_color_test_suite = { >> +.name = "vkms-color", >> +.test_cases = vkms_color_test_cases, >> +}; >> +kunit_test_suite(vkms_color_test_suite); >> + >> +MODULE_LICENSE("GPL"); >> \ No newline at end of file >> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c >> b/drivers/gpu/drm/vkms/vkms_composer.c >> index 3c99fb8b54e2..6f942896036e 100644 >> --- a/drivers/gpu/drm/vkms/vkms_composer.c >> +++ b/drivers/gpu/drm/vkms/vkms_composer.c >> @@ -91,7 +91,7 @@ static void fill_background(const struct pixel_argb_u16 >> *background_color, >> } >> >> // lerp(a, b, t) = a + (b - a) * t >> -static u16 lerp_u16(u16 a, u16 b, s64 t) >> +u16 lerp_u16(u16 a, u16 b, s64 t) >> { >> s64 a_fp =
Re: [PATCH] drm/amd/display: remove redundant initialization of variable remainder
Applied. Thanks! On Tue, Dec 19, 2023 at 12:40 PM Colin Ian King wrote: > > Variable remainder is being initialized with a value that is never read, > the assignment is redundant and can be removed. Also add a newline > after the declaration to clean up the coding style. > > Signed-off-by: Colin Ian King > --- > drivers/gpu/drm/amd/display/dc/basics/conversion.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c > b/drivers/gpu/drm/amd/display/dc/basics/conversion.c > index e295a839ab47..1090d235086a 100644 > --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c > +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c > @@ -103,7 +103,8 @@ void convert_float_matrix( > > static uint32_t find_gcd(uint32_t a, uint32_t b) > { > - uint32_t remainder = 0; > + uint32_t remainder; > + > while (b != 0) { > remainder = a % b; > a = b; > -- > 2.39.2 >
[PATCH v5 8/8] Documentation: iio: Document high-speed DMABUF based API
Document the new DMABUF based API. Signed-off-by: Paul Cercueil --- v2: - Explicitly state that the new interface is optional and is not implemented by all drivers. - The IOCTLs can now only be called on the buffer FD returned by IIO_BUFFER_GET_FD_IOCTL. - Move the page up a bit in the index since it is core stuff and not driver-specific. v3: Update the documentation to reflect the new API. v5: Use description lists for the documentation of the three new IOCTLs instead of abusing subsections. --- Documentation/iio/dmabuf_api.rst | 54 Documentation/iio/index.rst | 2 ++ 2 files changed, 56 insertions(+) create mode 100644 Documentation/iio/dmabuf_api.rst diff --git a/Documentation/iio/dmabuf_api.rst b/Documentation/iio/dmabuf_api.rst new file mode 100644 index ..1cd6cd51a582 --- /dev/null +++ b/Documentation/iio/dmabuf_api.rst @@ -0,0 +1,54 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=== +High-speed DMABUF interface for IIO +=== + +1. Overview +=== + +The Industrial I/O subsystem supports access to buffers through a +file-based interface, with read() and write() access calls through the +IIO device's dev node. + +It additionally supports a DMABUF based interface, where the userspace +can attach DMABUF objects (externally created) to a IIO buffer, and +subsequently use them for data transfers. + +A userspace application can then use this interface to share DMABUF +objects between several interfaces, allowing it to transfer data in a +zero-copy fashion, for instance between IIO and the USB stack. + +The userspace application can also memory-map the DMABUF objects, and +access the sample data directly. The advantage of doing this vs. the +read() interface is that it avoids an extra copy of the data between the +kernel and userspace. This is particularly useful for high-speed devices +which produce several megabytes or even gigabytes of data per second. +It does however increase the userspace-kernelspace synchronization +overhead, as the DMA_BUF_SYNC_START and DMA_BUF_SYNC_END IOCTLs have to +be used for data integrity. + +2. User API +=== + +As part of this interface, three new IOCTLs have been added. These three +IOCTLs have to be performed on the IIO buffer's file descriptor, +obtained using the IIO_BUFFER_GET_FD_IOCTL() ioctl. + + ``IIO_BUFFER_DMABUF_ATTACH_IOCTL(int)`` +Attach the DMABUF object, identified by its file descriptor, to the +IIO buffer. Returns zero on success, and a negative errno value on +error. + + ``IIO_BUFFER_DMABUF_DETACH_IOCTL(int)`` +Detach the given DMABUF object, identified by its file descriptor, +from the IIO buffer. Returns zero on success, and a negative errno +value on error. + +Note that closing the IIO buffer's file descriptor will +automatically detach all previously attached DMABUF objects. + + ``IIO_BUFFER_DMABUF_ENQUEUE_IOCTL(struct iio_dmabuf *iio_dmabuf)`` +Enqueue a previously attached DMABUF object to the buffer queue. +Enqueued DMABUFs will be read from (if output buffer) or written to +(if input buffer) as long as the buffer is enabled. diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst index 1b7292c58cd0..3eae8fcb1938 100644 --- a/Documentation/iio/index.rst +++ b/Documentation/iio/index.rst @@ -9,6 +9,8 @@ Industrial I/O iio_configfs + dmabuf_api + ep93xx_adc bno055 -- 2.43.0
[PATCH v5 7/8] iio: buffer-dmaengine: Support new DMABUF based userspace API
Use the functions provided by the buffer-dma core to implement the DMABUF userspace API in the buffer-dmaengine IIO buffer implementation. Since we want to be able to transfer an arbitrary number of bytes and not necesarily the full DMABUF, the associated scatterlist is converted to an array of DMA addresses + lengths, which is then passed to dmaengine_prep_slave_dma_array(). Signed-off-by: Paul Cercueil --- v3: Use the new dmaengine_prep_slave_dma_array(), and adapt the code to work with the new functions introduced in industrialio-buffer-dma.c. v5: - Use the new dmaengine_prep_slave_dma_vec(). - Restrict to input buffers, since output buffers are not yet supported by IIO buffers. --- .../buffer/industrialio-buffer-dmaengine.c| 52 --- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index 5f85ba38e6f6..825d76a24a67 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -64,15 +64,51 @@ static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue, struct dmaengine_buffer *dmaengine_buffer = iio_buffer_to_dmaengine_buffer(>buffer); struct dma_async_tx_descriptor *desc; + unsigned int i, nents; + struct scatterlist *sgl; + struct dma_vec *vecs; + size_t max_size; dma_cookie_t cookie; + size_t len_total; - block->bytes_used = min(block->size, dmaengine_buffer->max_size); - block->bytes_used = round_down(block->bytes_used, - dmaengine_buffer->align); + if (queue->buffer.direction != IIO_BUFFER_DIRECTION_IN) { + /* We do not yet support output buffers. */ + return -EINVAL; + } - desc = dmaengine_prep_slave_single(dmaengine_buffer->chan, - block->phys_addr, block->bytes_used, DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT); + if (block->sg_table) { + sgl = block->sg_table->sgl; + nents = sg_nents_for_len(sgl, block->bytes_used); + + vecs = kmalloc_array(nents, sizeof(*vecs), GFP_KERNEL); + if (!vecs) + return -ENOMEM; + + len_total = block->bytes_used; + + for (i = 0; i < nents; i++) { + vecs[i].addr = sg_dma_address(sgl); + vecs[i].len = min(sg_dma_len(sgl), len_total); + len_total -= vecs[i].len; + + sgl = sg_next(sgl); + } + + desc = dmaengine_prep_slave_dma_vec(dmaengine_buffer->chan, + vecs, nents, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT); + kfree(vecs); + } else { + max_size = min(block->size, dmaengine_buffer->max_size); + max_size = round_down(max_size, dmaengine_buffer->align); + block->bytes_used = max_size; + + desc = dmaengine_prep_slave_single(dmaengine_buffer->chan, + block->phys_addr, + block->bytes_used, + DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT); + } if (!desc) return -ENOMEM; @@ -120,6 +156,10 @@ static const struct iio_buffer_access_funcs iio_dmaengine_buffer_ops = { .data_available = iio_dma_buffer_data_available, .release = iio_dmaengine_buffer_release, + .enqueue_dmabuf = iio_dma_buffer_enqueue_dmabuf, + .attach_dmabuf = iio_dma_buffer_attach_dmabuf, + .detach_dmabuf = iio_dma_buffer_detach_dmabuf, + .modes = INDIO_BUFFER_HARDWARE, .flags = INDIO_BUFFER_FLAG_FIXED_WATERMARK, }; -- 2.43.0
[PATCH v5 6/8] iio: buffer-dma: Enable support for DMABUFs
Implement iio_dma_buffer_attach_dmabuf(), iio_dma_buffer_detach_dmabuf() and iio_dma_buffer_transfer_dmabuf(), which can then be used by the IIO DMA buffer implementations. Signed-off-by: Paul Cercueil --- v3: Update code to provide the functions that will be used as callbacks for the new IOCTLs. --- drivers/iio/buffer/industrialio-buffer-dma.c | 157 +-- include/linux/iio/buffer-dma.h | 26 +++ 2 files changed, 170 insertions(+), 13 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c index 5610ba67925e..adb64f975064 100644 --- a/drivers/iio/buffer/industrialio-buffer-dma.c +++ b/drivers/iio/buffer/industrialio-buffer-dma.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -94,14 +95,24 @@ static void iio_buffer_block_release(struct kref *kref) { struct iio_dma_buffer_block *block = container_of(kref, struct iio_dma_buffer_block, kref); + struct iio_dma_buffer_queue *queue = block->queue; - WARN_ON(block->state != IIO_BLOCK_STATE_DEAD); + WARN_ON(block->fileio && block->state != IIO_BLOCK_STATE_DEAD); - dma_free_coherent(block->queue->dev, PAGE_ALIGN(block->size), - block->vaddr, block->phys_addr); + mutex_lock(>lock); - iio_buffer_put(>queue->buffer); + if (block->fileio) { + dma_free_coherent(queue->dev, PAGE_ALIGN(block->size), + block->vaddr, block->phys_addr); + queue->num_fileio_blocks--; + } + + queue->num_blocks--; kfree(block); + + mutex_unlock(>lock); + + iio_buffer_put(>buffer); } static void iio_buffer_block_get(struct iio_dma_buffer_block *block) @@ -163,7 +174,7 @@ static struct iio_dma_buffer_queue *iio_buffer_to_queue(struct iio_buffer *buf) } static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block( - struct iio_dma_buffer_queue *queue, size_t size) + struct iio_dma_buffer_queue *queue, size_t size, bool fileio) { struct iio_dma_buffer_block *block; @@ -171,13 +182,16 @@ static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block( if (!block) return NULL; - block->vaddr = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size), - >phys_addr, GFP_KERNEL); - if (!block->vaddr) { - kfree(block); - return NULL; + if (fileio) { + block->vaddr = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size), + >phys_addr, GFP_KERNEL); + if (!block->vaddr) { + kfree(block); + return NULL; + } } + block->fileio = fileio; block->size = size; block->state = IIO_BLOCK_STATE_DONE; block->queue = queue; @@ -186,6 +200,9 @@ static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block( iio_buffer_get(>buffer); + queue->num_blocks++; + queue->num_fileio_blocks += fileio; + return block; } @@ -211,6 +228,9 @@ void iio_dma_buffer_block_done(struct iio_dma_buffer_block *block) _iio_dma_buffer_block_done(block); spin_unlock_irqrestore(>list_lock, flags); + if (!block->fileio) + iio_buffer_signal_dmabuf_done(block->attach, 0); + iio_buffer_block_put_atomic(block); wake_up_interruptible_poll(>buffer.pollq, EPOLLIN | EPOLLRDNORM); } @@ -237,10 +257,14 @@ void iio_dma_buffer_block_list_abort(struct iio_dma_buffer_queue *queue, list_del(>head); block->bytes_used = 0; _iio_dma_buffer_block_done(block); + + if (!block->fileio) + iio_buffer_signal_dmabuf_done(block->attach, -EINTR); iio_buffer_block_put_atomic(block); } spin_unlock_irqrestore(>list_lock, flags); + queue->fileio.enabled = false; wake_up_interruptible_poll(>buffer.pollq, EPOLLIN | EPOLLRDNORM); } EXPORT_SYMBOL_GPL(iio_dma_buffer_block_list_abort); @@ -261,6 +285,12 @@ static bool iio_dma_block_reusable(struct iio_dma_buffer_block *block) } } +static bool iio_dma_buffer_fileio_mode(struct iio_dma_buffer_queue *queue) +{ + return queue->fileio.enabled || + queue->num_blocks == queue->num_fileio_blocks; +} + /** * iio_dma_buffer_request_update() - DMA buffer request_update callback * @buffer: The buffer which to request an update @@ -287,6 +317,12 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer) mutex_lock(>lock); + queue->fileio.enabled = iio_dma_buffer_fileio_mode(queue); + + /* If DMABUFs were created, disable fileio interface */ + if (!queue->fileio.enabled) + goto out_unlock; + /* Allocations are page
[PATCH v5 5/8] iio: core: Add new DMABUF interface infrastructure
Add the necessary infrastructure to the IIO core to support a new optional DMABUF based interface. With this new interface, DMABUF objects (externally created) can be attached to a IIO buffer, and subsequently used for data transfer. A userspace application can then use this interface to share DMABUF objects between several interfaces, allowing it to transfer data in a zero-copy fashion, for instance between IIO and the USB stack. The userspace application can also memory-map the DMABUF objects, and access the sample data directly. The advantage of doing this vs. the read() interface is that it avoids an extra copy of the data between the kernel and userspace. This is particularly userful for high-speed devices which produce several megabytes or even gigabytes of data per second. As part of the interface, 3 new IOCTLs have been added: IIO_BUFFER_DMABUF_ATTACH_IOCTL(int fd): Attach the DMABUF object identified by the given file descriptor to the buffer. IIO_BUFFER_DMABUF_DETACH_IOCTL(int fd): Detach the DMABUF object identified by the given file descriptor from the buffer. Note that closing the IIO buffer's file descriptor will automatically detach all previously attached DMABUF objects. IIO_BUFFER_DMABUF_ENQUEUE_IOCTL(struct iio_dmabuf *): Request a data transfer to/from the given DMABUF object. Its file descriptor, as well as the transfer size and flags are provided in the "iio_dmabuf" structure. These three IOCTLs have to be performed on the IIO buffer's file descriptor, obtained using the IIO_BUFFER_GET_FD_IOCTL() ioctl. Signed-off-by: Paul Cercueil --- v2: Only allow the new IOCTLs on the buffer FD created with IIO_BUFFER_GET_FD_IOCTL(). v3: - Get rid of the old IOCTLs. The IIO subsystem does not create or manage DMABUFs anymore, and only attaches/detaches externally created DMABUFs. - Add IIO_BUFFER_DMABUF_CYCLIC to the supported flags. v5: - Use dev_err() instead of pr_err() - Inline to_iio_dma_fence() - Add comment to explain why we unref twice when detaching dmabuf - Remove TODO comment. It is actually safe to free the file's private data even when transfers are still pending because it won't be accessed. - Fix documentation of new fields in struct iio_buffer_access_funcs - iio_dma_resv_lock() does not need to be exported, make it static --- drivers/iio/industrialio-buffer.c | 402 ++ include/linux/iio/buffer_impl.h | 26 ++ include/uapi/linux/iio/buffer.h | 22 ++ 3 files changed, 450 insertions(+) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 09c41e9ccf87..24c040e073a7 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -13,10 +13,14 @@ #include #include #include +#include +#include +#include #include #include #include #include +#include #include #include @@ -28,6 +32,31 @@ #include #include +#define DMABUF_ENQUEUE_TIMEOUT_MS 5000 + +struct iio_dma_fence; + +struct iio_dmabuf_priv { + struct list_head entry; + struct kref ref; + + struct iio_buffer *buffer; + struct iio_dma_buffer_block *block; + + u64 context; + spinlock_t lock; + + struct dma_buf_attachment *attach; + struct iio_dma_fence *fence; +}; + +struct iio_dma_fence { + struct dma_fence base; + struct iio_dmabuf_priv *priv; + struct sg_table *sgt; + enum dma_data_direction dir; +}; + static const char * const iio_endian_prefix[] = { [IIO_BE] = "be", [IIO_LE] = "le", @@ -332,6 +361,7 @@ void iio_buffer_init(struct iio_buffer *buffer) { INIT_LIST_HEAD(>demux_list); INIT_LIST_HEAD(>buffer_list); + INIT_LIST_HEAD(>dmabufs); init_waitqueue_head(>pollq); kref_init(>ref); if (!buffer->watermark) @@ -1519,14 +1549,54 @@ static void iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev) kfree(iio_dev_opaque->legacy_scan_el_group.attrs); } +static void iio_buffer_dmabuf_release(struct kref *ref) +{ + struct iio_dmabuf_priv *priv = container_of(ref, struct iio_dmabuf_priv, ref); + struct dma_buf_attachment *attach = priv->attach; + struct iio_buffer *buffer = priv->buffer; + struct dma_buf *dmabuf = attach->dmabuf; + + buffer->access->detach_dmabuf(buffer, priv->block); + + dma_buf_detach(attach->dmabuf, attach); + dma_buf_put(dmabuf); + kfree(priv); +} + +void iio_buffer_dmabuf_get(struct dma_buf_attachment *attach) +{ + struct iio_dmabuf_priv *priv = attach->importer_priv; + + kref_get(>ref); +} +EXPORT_SYMBOL_GPL(iio_buffer_dmabuf_get); + +void iio_buffer_dmabuf_put(struct dma_buf_attachment *attach) +{ + struct iio_dmabuf_priv *priv = attach->importer_priv; + + kref_put(>ref, iio_buffer_dmabuf_release); +} +EXPORT_SYMBOL_GPL(iio_buffer_dmabuf_put); + static int iio_buffer_chrdev_release(struct
[PATCH v5 4/8] dmaengine: dma-axi-dmac: Implement device_prep_slave_dma_vec
Add implementation of the .device_prep_slave_dma_vec() callback. Signed-off-by: Paul Cercueil --- v3: New patch v5: Implement .device_prep_slave_dma_vec() instead of v3's .device_prep_slave_dma_array(). --- drivers/dma/dma-axi-dmac.c | 40 ++ 1 file changed, 40 insertions(+) diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 2457a420c13d..363808088cc5 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -535,6 +535,45 @@ static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan, return sg; } +static struct dma_async_tx_descriptor * +axi_dmac_prep_slave_dma_vec(struct dma_chan *c, const struct dma_vec *vecs, + size_t nb, enum dma_transfer_direction direction, + unsigned long flags) +{ + struct axi_dmac_chan *chan = to_axi_dmac_chan(c); + struct axi_dmac_desc *desc; + unsigned int num_sgs = 0; + struct axi_dmac_sg *dsg; + size_t i; + + if (direction != chan->direction) + return NULL; + + for (i = 0; i < nb; i++) + num_sgs += DIV_ROUND_UP(vecs[i].len, chan->max_length); + + desc = axi_dmac_alloc_desc(num_sgs); + if (!desc) + return NULL; + + dsg = desc->sg; + + for (i = 0; i < nb; i++) { + if (!axi_dmac_check_addr(chan, vecs[i].addr) || + !axi_dmac_check_len(chan, vecs[i].len)) { + kfree(desc); + return NULL; + } + + dsg = axi_dmac_fill_linear_sg(chan, direction, vecs[i].addr, 1, + vecs[i].len, dsg); + } + + desc->cyclic = false; + + return vchan_tx_prep(>vchan, >vdesc, flags); +} + static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg( struct dma_chan *c, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, @@ -957,6 +996,7 @@ static int axi_dmac_probe(struct platform_device *pdev) dma_dev->device_tx_status = dma_cookie_status; dma_dev->device_issue_pending = axi_dmac_issue_pending; dma_dev->device_prep_slave_sg = axi_dmac_prep_slave_sg; + dma_dev->device_prep_slave_dma_vec = axi_dmac_prep_slave_dma_vec; dma_dev->device_prep_dma_cyclic = axi_dmac_prep_dma_cyclic; dma_dev->device_prep_interleaved_dma = axi_dmac_prep_interleaved; dma_dev->device_terminate_all = axi_dmac_terminate_all; -- 2.43.0
[PATCH v5 3/8] dmaengine: Add API function dmaengine_prep_slave_dma_vec()
This function can be used to initiate a scatter-gather DMA transfer, where the address and size of each segment is located in one entry of the dma_vec array. The major difference with dmaengine_prep_slave_sg() is that it supports specifying the lengths of each DMA transfer; as trying to override the length of the transfer with dmaengine_prep_slave_sg() is a very tedious process. The introduction of a new API function is also justified by the fact that scatterlists are on their way out. Note that dmaengine_prep_interleaved_dma() is not helpful either in that case, as it assumes that the address of each segment will be higher than the one of the previous segment, which we just cannot guarantee in case of a scatter-gather transfer. Signed-off-by: Paul Cercueil --- v3: New patch v5: Replace with function dmaengine_prep_slave_dma_vec(), and struct 'dma_vec'. Note that at some point we will need to support cyclic transfers using dmaengine_prep_slave_dma_vec(). Maybe with a new "flags" parameter to the function? --- include/linux/dmaengine.h | 25 + 1 file changed, 25 insertions(+) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 3df70d6131c8..ee5931ddb42f 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -160,6 +160,16 @@ struct dma_interleaved_template { struct data_chunk sgl[]; }; +/** + * struct dma_vec - DMA vector + * @addr: Bus address of the start of the vector + * @len: Length in bytes of the DMA vector + */ +struct dma_vec { + dma_addr_t addr; + size_t len; +}; + /** * enum dma_ctrl_flags - DMA flags to augment operation preparation, * control completion, and communicate status. @@ -910,6 +920,10 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)( struct dma_chan *chan, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_slave_dma_vec)( + struct dma_chan *chan, const struct dma_vec *vecs, + size_t nents, enum dma_transfer_direction direction, + unsigned long flags); struct dma_async_tx_descriptor *(*device_prep_slave_sg)( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, @@ -972,6 +986,17 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( dir, flags, NULL); } +static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_dma_vec( + struct dma_chan *chan, const struct dma_vec *vecs, size_t nents, + enum dma_transfer_direction dir, unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_slave_dma_vec) + return NULL; + + return chan->device->device_prep_slave_dma_vec(chan, vecs, nents, + dir, flags); +} + static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction dir, unsigned long flags) -- 2.43.0
[PATCH v5 2/8] iio: buffer-dma: split iio_dma_buffer_fileio_free() function
From: Alexandru Ardelean This change splits the logic into a separate function, which will be re-used later. Signed-off-by: Alexandru Ardelean Cc: Alexandru Ardelean Signed-off-by: Paul Cercueil --- drivers/iio/buffer/industrialio-buffer-dma.c | 43 +++- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c index 1fc91467d1aa..5610ba67925e 100644 --- a/drivers/iio/buffer/industrialio-buffer-dma.c +++ b/drivers/iio/buffer/industrialio-buffer-dma.c @@ -346,6 +346,29 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer) } EXPORT_SYMBOL_GPL(iio_dma_buffer_request_update); +static void iio_dma_buffer_fileio_free(struct iio_dma_buffer_queue *queue) +{ + unsigned int i; + + spin_lock_irq(>list_lock); + for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) { + if (!queue->fileio.blocks[i]) + continue; + queue->fileio.blocks[i]->state = IIO_BLOCK_STATE_DEAD; + } + spin_unlock_irq(>list_lock); + + INIT_LIST_HEAD(>incoming); + + for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) { + if (!queue->fileio.blocks[i]) + continue; + iio_buffer_block_put(queue->fileio.blocks[i]); + queue->fileio.blocks[i] = NULL; + } + queue->fileio.active_block = NULL; +} + static void iio_dma_buffer_submit_block(struct iio_dma_buffer_queue *queue, struct iio_dma_buffer_block *block) { @@ -638,27 +661,9 @@ EXPORT_SYMBOL_GPL(iio_dma_buffer_init); */ void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue) { - unsigned int i; - mutex_lock(>lock); - spin_lock_irq(>list_lock); - for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) { - if (!queue->fileio.blocks[i]) - continue; - queue->fileio.blocks[i]->state = IIO_BLOCK_STATE_DEAD; - } - spin_unlock_irq(>list_lock); - - INIT_LIST_HEAD(>incoming); - - for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) { - if (!queue->fileio.blocks[i]) - continue; - iio_buffer_block_put(queue->fileio.blocks[i]); - queue->fileio.blocks[i] = NULL; - } - queue->fileio.active_block = NULL; + iio_dma_buffer_fileio_free(queue); queue->ops = NULL; mutex_unlock(>lock); -- 2.43.0
[PATCH v5 1/8] iio: buffer-dma: Get rid of outgoing queue
The buffer-dma code was using two queues, incoming and outgoing, to manage the state of the blocks in use. While this totally works, it adds some complexity to the code, especially since the code only manages 2 blocks. It is much easier to just check each block's state manually, and keep a counter for the next block to dequeue. Since the new DMABUF based API wouldn't use the outgoing queue anyway, getting rid of it now makes the upcoming changes simpler. With this change, the IIO_BLOCK_STATE_DEQUEUED is now useless, and can be removed. Signed-off-by: Paul Cercueil --- v2: - Only remove the outgoing queue, and keep the incoming queue, as we want the buffer to start streaming data as soon as it is enabled. - Remove IIO_BLOCK_STATE_DEQUEUED, since it is now functionally the same as IIO_BLOCK_STATE_DONE. --- drivers/iio/buffer/industrialio-buffer-dma.c | 44 ++-- include/linux/iio/buffer-dma.h | 7 ++-- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c index d348af8b9705..1fc91467d1aa 100644 --- a/drivers/iio/buffer/industrialio-buffer-dma.c +++ b/drivers/iio/buffer/industrialio-buffer-dma.c @@ -179,7 +179,7 @@ static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block( } block->size = size; - block->state = IIO_BLOCK_STATE_DEQUEUED; + block->state = IIO_BLOCK_STATE_DONE; block->queue = queue; INIT_LIST_HEAD(>head); kref_init(>kref); @@ -191,16 +191,8 @@ static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block( static void _iio_dma_buffer_block_done(struct iio_dma_buffer_block *block) { - struct iio_dma_buffer_queue *queue = block->queue; - - /* -* The buffer has already been freed by the application, just drop the -* reference. -*/ - if (block->state != IIO_BLOCK_STATE_DEAD) { + if (block->state != IIO_BLOCK_STATE_DEAD) block->state = IIO_BLOCK_STATE_DONE; - list_add_tail(>head, >outgoing); - } } /** @@ -261,7 +253,6 @@ static bool iio_dma_block_reusable(struct iio_dma_buffer_block *block) * not support abort and has not given back the block yet. */ switch (block->state) { - case IIO_BLOCK_STATE_DEQUEUED: case IIO_BLOCK_STATE_QUEUED: case IIO_BLOCK_STATE_DONE: return true; @@ -317,7 +308,6 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer) * dead. This means we can reset the lists without having to fear * corrution. */ - INIT_LIST_HEAD(>outgoing); spin_unlock_irq(>list_lock); INIT_LIST_HEAD(>incoming); @@ -456,14 +446,20 @@ static struct iio_dma_buffer_block *iio_dma_buffer_dequeue( struct iio_dma_buffer_queue *queue) { struct iio_dma_buffer_block *block; + unsigned int idx; spin_lock_irq(>list_lock); - block = list_first_entry_or_null(>outgoing, struct - iio_dma_buffer_block, head); - if (block != NULL) { - list_del(>head); - block->state = IIO_BLOCK_STATE_DEQUEUED; + + idx = queue->fileio.next_dequeue; + block = queue->fileio.blocks[idx]; + + if (block->state == IIO_BLOCK_STATE_DONE) { + idx = (idx + 1) % ARRAY_SIZE(queue->fileio.blocks); + queue->fileio.next_dequeue = idx; + } else { + block = NULL; } + spin_unlock_irq(>list_lock); return block; @@ -539,6 +535,7 @@ size_t iio_dma_buffer_data_available(struct iio_buffer *buf) struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buf); struct iio_dma_buffer_block *block; size_t data_available = 0; + unsigned int i; /* * For counting the available bytes we'll use the size of the block not @@ -552,8 +549,15 @@ size_t iio_dma_buffer_data_available(struct iio_buffer *buf) data_available += queue->fileio.active_block->size; spin_lock_irq(>list_lock); - list_for_each_entry(block, >outgoing, head) - data_available += block->size; + + for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) { + block = queue->fileio.blocks[i]; + + if (block != queue->fileio.active_block + && block->state == IIO_BLOCK_STATE_DONE) + data_available += block->size; + } + spin_unlock_irq(>list_lock); mutex_unlock(>lock); @@ -617,7 +621,6 @@ int iio_dma_buffer_init(struct iio_dma_buffer_queue *queue, queue->ops = ops; INIT_LIST_HEAD(>incoming); - INIT_LIST_HEAD(>outgoing); mutex_init(>lock); spin_lock_init(>list_lock); @@ -645,7 +648,6 @@ void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue) continue;
[PATCH v5 0/8] iio: new DMABUF based API, v5
[V4 was: "iio: Add buffer write() support"][1] Hi Jonathan, This is a respin of the V3 of my patchset that introduced a new interface based on DMABUF objects [2]. The V4 was a split of the patchset, to attempt to upstream buffer write() support first. But since there is no current user upstream, it was not merged. This V5 is about doing the opposite, and contains the new DMABUF interface, without adding the buffer write() support. It can already be used with the upstream adi-axi-adc driver. In user-space, Libiio uses it to transfer back and forth blocks of samples between the hardware and the applications, without having to copy the data. On a ZCU102 with a FMComms3 daughter board, running Libiio from the pcercuei/dev-new-dmabuf-api branch [3], compiled with WITH_LOCAL_DMABUF_API=OFF (so that it uses fileio): sudo utils/iio_rwdev -b 4096 -B cf-ad9361-lpc Throughput: 116 MiB/s Same hardware, with the DMABUF API (WITH_LOCAL_DMABUF_API=ON): sudo utils/iio_rwdev -b 4096 -B cf-ad9361-lpc Throughput: 475 MiB/s This benchmark only measures the speed at which the data can be fetched to iio_rwdev's internal buffers, and does not actually try to read the data (e.g. to pipe it to stdout). It shows that fetching the data is more than 4x faster using the new interface. When actually reading the data, the performance difference isn't that impressive (maybe because in case of DMABUF the data is not in cache): WITH_LOCAL_DMABUF_API=OFF (so that it uses fileio): sudo utils/iio_rwdev -b 4096 cf-ad9361-lpc | dd of=/dev/zero status=progress 2446422528 bytes (2.4 GB, 2.3 GiB) copied, 22 s, 111 MB/s WITH_LOCAL_DMABUF_API=ON: sudo utils/iio_rwdev -b 4096 cf-ad9361-lpc | dd of=/dev/zero status=progress 2334388736 bytes (2.3 GB, 2.2 GiB) copied, 21 s, 114 MB/s One interesting thing to note is that fileio is (currently) actually faster than the DMABUF interface if you increase a lot the buffer size. My explanation is that the cache invalidation routine takes more and more time the bigger the DMABUF gets. This is because the DMABUF is backed by small-size pages, so a (e.g.) 64 MiB DMABUF is backed by up to 16 thousands pages, that have to be invalidated one by one. This can be addressed by using huge pages, but the udmabuf driver does not (yet) support creating DMABUFs backed by huge pages. Anyway, the real benefits happen when the DMABUFs are either shared between IIO devices, or between the IIO subsystem and another filesystem. In that case, the DMABUFs are simply passed around drivers, without the data being copied at any moment. We use that feature to transfer samples from our transceivers to USB, using a DMABUF interface to FunctionFS [4]. This drastically increases the throughput, to about 274 MiB/s over a USB3 link, vs. 127 MiB/s using IIO's fileio interface + write() to the FunctionFS endpoints, for a lower CPU usage (0.85 vs. 0.65 load avg.). Based on linux-next/next-20231219. Cheers, -Paul [1] https://lore.kernel.org/all/20230807112113.47157-1-p...@crapouillou.net/ [2] https://lore.kernel.org/all/20230403154800.215924-1-p...@crapouillou.net/ [3] https://github.com/analogdevicesinc/libiio/tree/pcercuei/dev-new-dmabuf-api [4] https://lore.kernel.org/all/20230322092118.9213-1-p...@crapouillou.net/ --- Changelog: - [3/8]: Replace V3's dmaengine_prep_slave_dma_array() with a new dmaengine_prep_slave_dma_vec(), which uses a new 'dma_vec' struct. Note that at some point we will need to support cyclic transfers using dmaengine_prep_slave_dma_vec(). Maybe with a new "flags" parameter to the function? - [4/8]: Implement .device_prep_slave_dma_vec() instead of V3's .device_prep_slave_dma_array(). @Vinod: this patch will cause a small conflict with my other patchset adding scatter-gather support to the axi-dmac driver. This patch adds a call to axi_dmac_alloc_desc(num_sgs), but the prototype of this function changed in my other patchset - it would have to be passed the "chan" variable. I don't know how you prefer it to be resolved. Worst case scenario (and if @Jonathan is okay with that) this one patch can be re-sent later, but it would make this patchset less "atomic". - [5/8]: - Use dev_err() instead of pr_err() - Inline to_iio_dma_fence() - Add comment to explain why we unref twice when detaching dmabuf - Remove TODO comment. It is actually safe to free the file's private data even when transfers are still pending because it won't be accessed. - Fix documentation of new fields in struct iio_buffer_access_funcs - iio_dma_resv_lock() does not need to be exported, make it static - [7/8]: - Use the new dmaengine_prep_slave_dma_vec(). - Restrict to input buffers, since output buffers are not yet supported by IIO buffers. - [8/8]: Use description lists for the documentation of the three new IOCTLs instead of abusing subsections. --- Alexandru Ardelean (1): iio: buffer-dma: split iio_dma_buffer_
Re: [PATCH RFC 01/10] dt-bindings: gpu: Add PowerVR Series5 SGX GPUs
On 12/18/23 4:54 AM, H. Nikolaus Schaller wrote: Am 18.12.2023 um 11:14 schrieb Maxime Ripard : On Mon, Dec 18, 2023 at 10:28:09AM +0100, H. Nikolaus Schaller wrote: Hi Maxime, Am 15.12.2023 um 14:33 schrieb Maxime Ripard : It's for a separate architecture, with a separate driver, maintained out of tree by a separate community, with a separate set of requirements as evidenced by the other thread. And that's all fine in itself, but there's very little reason to put these two bindings in the same file. We could also turn this around, why is it important that it's in the same file? Same vendor. And enough similarity in architectures, even a logical sequence of development of versions (SGX = Version 5, Rogue = Version 6+) behind. (SGX and Rogue seem to be just trade names for their architecture development). Again, none of that matters for *where* the binding is stored. So what then speaks against extending the existing bindings file as proposed here? I mean, apart from everything you quoted, then sure, nothing speaks against it. AFAIK bindings should describe hardware and not communities or drivers or who is currently maintaining it. The latter can change, the first not. Bindings are supposed to describe hardware indeed. Nothing was ever said about where those bindings are supposed to be located. There's hundreds of other YAML bindings describing devices of the same vendors and different devices from the same generation. Usually SoC seem to be split over multiple files by subsystem. Not by versions or generations. If the subsystems are similar enough they share the same bindings doc instead of having one for each generation duplicating a lot of code. Here is a comparable example that combines multiple vendors and generations: Documentation/devicetree/bindings/usb/generic-ehci.yaml EHCI is a single interface for USB2.0 controllers. It's a standard API, and is made of a single driver that requires minor modifications to deal with multiple devices. We're very far from the same situation here. How far are we really? And, it is the purpose of the driver to handle different cases. That there are currently two drivers is just a matter of history and not a necessity. If anything it'll make it easier for you. I'm really not sure why it is controversial and you're fighting this so hard. Well, you made it controversial by proposing to split what IMHO belongs together. No, reviews aren't controversial. The controversy started when you chose to oppose it while you could have just rolled with it. Well, you asked "I think it would be best to have a separate file for this, img,sgx.yaml maybe?" and "Because it's more convenient?" I understood that as an invitation for discussing the pros and cons and working out the most convenient solution. And that involves playing the devil's advocate which of course is controversial by principle. Now, IMHO all the pros and cons are on the table and the question is who makes a decision how to go. As much as I would land on the side of same file for both, the answer to this question is simple: the maintainer makes the decision :) So I'll respin with separate binding files. The hidden unaddressed issue here is that by making these bindings separate it implies they are not on equal footing (i.e. pre-series6 GPUs are not true "powervr" and so do not belong in img,powervr.yaml). So if no one objects I'd also like to do the rename of that file as suggested before and have: img,powervr-sgx.yaml img,powervr-rogue.yaml I feel that the original patch is good enough for its purpose and follows some design pattern that can be deduced from other binding docs. [citation needed] Joke: Documentation/devicetree/bindings/* - I am not aware of a formal analysis of course. But see my example for ehci. It follows the pattern I mean. If clocks, regs, interrupts, resets, and more properties are (almost) the same, then group them and just differentiate by different compatible strings. If necessary use some - if: clauses. It is the task of drivers to handle the details. As my other (maybe more important) comment to this patch did indicate we IMHO can easily live with something like + - items: + - enum: + - ti,am62-gpu # IMG AXE GPU model/revision is fully discoverable + - ti,omap3430-gpu # sgx530 Rev 121 + - ti,omap3630-gpu # sgx530 Rev 125 + - ingenic,jz4780-gpu # sgx540 Rev 130 + - ti,omap4430-gpu # sgx540 Rev 120 + - allwinner,sun6i-a31-gpu # sgx544 MP2 Rev 115 + - ti,omap4470-gpu # sgx544 MP1 Rev 112 + - ti,omap5432-gpu # sgx544 MP2 Rev 105 + - ti,am5728-gpu # sgx544 MP2 Rev 116 + - ti,am6548-gpu # sgx544 MP1 Rev 117 While we could live with this, the "compatible" groupings makes life just a bit easier. This is true really for any DT compatible string and is not based on any
Re: [PATCH 5/5] drm/panel: st7703: Drive XBD599 panel at higher clock rate
Dne ponedeljek, 18. december 2023 ob 14:35:23 CET je Frank Oltmanns napisal(a): > This panel is used in the pinephone that runs on a Allwinner A64 SOC. > Acoording to it's datasheet, the SOC requires PLL-MIPI to run at more > than 500 MHz. > > Therefore, change [hv]sync_(start|end) so that we reach a clock rate > that is high enough to drive PLL-MIPI within its limits. > > Signed-off-by: Frank Oltmanns I'm not too sure about this patch. I see that PLL_MIPI doesn't have set minimum frequency limit in clock driver. If you add it, clock framework should find rate that is high enough and divisible with target rate. Best regards, Jernej > --- > drivers/gpu/drm/panel/panel-sitronix-st7703.c | 14 +++--- > 1 file changed, 7 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c > b/drivers/gpu/drm/panel/panel-sitronix-st7703.c > index b55bafd1a8be..6886fd7f765e 100644 > --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c > +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c > @@ -320,14 +320,14 @@ static int xbd599_init_sequence(struct st7703 *ctx) > > static const struct drm_display_mode xbd599_mode = { > .hdisplay= 720, > - .hsync_start = 720 + 40, > - .hsync_end = 720 + 40 + 40, > - .htotal = 720 + 40 + 40 + 40, > + .hsync_start = 720 + 65, > + .hsync_end = 720 + 65 + 65, > + .htotal = 720 + 65 + 65 + 65, > .vdisplay= 1440, > - .vsync_start = 1440 + 18, > - .vsync_end = 1440 + 18 + 10, > - .vtotal = 1440 + 18 + 10 + 17, > - .clock = 69000, > + .vsync_start = 1440 + 30, > + .vsync_end = 1440 + 30 + 22, > + .vtotal = 1440 + 30 + 22 + 29, > + .clock = (720 + 65 + 65 + 65) * (1440 + 30 + 22 + 29) * 60 / 1000, > .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, > .width_mm= 68, > .height_mm = 136, > >
[PATCH v3 28/29] ARM: dts: rockchip: Add HDMI node for RK3128
RK3128 has Innosilicon based HDMI TX controller similar to the one found in RK3036. Add it and the respective port nodes to the SoC device tree. Signed-off-by: Alex Bee --- changes in v2: - no changes changes in v3: - no changes arch/arm/boot/dts/rockchip/rk3128.dtsi | 33 ++ 1 file changed, 33 insertions(+) diff --git a/arch/arm/boot/dts/rockchip/rk3128.dtsi b/arch/arm/boot/dts/rockchip/rk3128.dtsi index 1a3bc8b2bc6e..fb98873fd94e 100644 --- a/arch/arm/boot/dts/rockchip/rk3128.dtsi +++ b/arch/arm/boot/dts/rockchip/rk3128.dtsi @@ -270,6 +270,11 @@ vop: vop@1010e000 { vop_out: port { #address-cells = <1>; #size-cells = <0>; + + vop_out_hdmi: endpoint@0 { + reg = <0>; + remote-endpoint = <_in_vop>; + }; }; }; @@ -463,6 +468,34 @@ usb2phy_otg: otg-port { }; }; + hdmi: hdmi@20034000 { + compatible = "rockchip,rk3128-inno-hdmi"; + reg = <0x20034000 0x4000>; + interrupts = ; + clocks = < PCLK_HDMI>, < DCLK_VOP>; + clock-names = "pclk", "ref"; + pinctrl-names = "default"; + pinctrl-0 = <_xfer _hpd _cec>; + power-domains = < RK3128_PD_VIO>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + hdmi_in: port@0 { + reg = <0>; + hdmi_in_vop: endpoint { + remote-endpoint = <_out_hdmi>; + }; + }; + + hdmi_out: port@1 { + reg = <1>; + }; + }; + }; + timer0: timer@20044000 { compatible = "rockchip,rk3128-timer", "rockchip,rk3288-timer"; reg = <0x20044000 0x20>; -- 2.43.0
[PATCH v3 27/29] ARM: dts: rockchip: Add display subsystem for RK3128
Add vop and display-subsystem nodes to RK3128's device tree. Signed-off-by: Alex Bee --- changes in v2: - no changes changes in v3: - no changes arch/arm/boot/dts/rockchip/rk3128.dtsi | 27 ++ 1 file changed, 27 insertions(+) diff --git a/arch/arm/boot/dts/rockchip/rk3128.dtsi b/arch/arm/boot/dts/rockchip/rk3128.dtsi index e2264c40b924..1a3bc8b2bc6e 100644 --- a/arch/arm/boot/dts/rockchip/rk3128.dtsi +++ b/arch/arm/boot/dts/rockchip/rk3128.dtsi @@ -115,6 +115,12 @@ opp-12 { }; }; + display_subsystem: display-subsystem { + compatible = "rockchip,display-subsystem"; + ports = <_out>; + status = "disabled"; + }; + gpu_opp_table: opp-table-1 { compatible = "operating-points-v2"; @@ -246,6 +252,27 @@ power-domain@RK3128_PD_GPU { }; }; + vop: vop@1010e000 { + compatible = "rockchip,rk3126-vop"; + reg = <0x1010e000 0x300>; + interrupts = ; + clocks = < ACLK_LCDC0>, < DCLK_VOP>, +< HCLK_LCDC0>; + clock-names = "aclk_vop", "dclk_vop", + "hclk_vop"; + resets = < SRST_VOP_A>, < SRST_VOP_H>, +< SRST_VOP_D>; + reset-names = "axi", "ahb", + "dclk"; + power-domains = < RK3128_PD_VIO>; + status = "disabled"; + + vop_out: port { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + qos_gpu: qos@1012d000 { compatible = "rockchip,rk3128-qos", "syscon"; reg = <0x1012d000 0x20>; -- 2.43.0
[PATCH v3 24/29] drm/rockchip: inno_hdmi: Add RK3128 support
This variant requires the phy reference clock to be enabled before the DDC block can work and the (initial) DDC bus frequency is calculated based on the rate of this clock. Besides the only difference is phy configuration required to make the driver working for this variant as well. Signed-off-by: Alex Bee --- changes in v2: - no changes changes in v3: - no changes drivers/gpu/drm/rockchip/inno_hdmi.c | 46 +--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index df979bab9abd..8a1a2320749a 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -51,6 +51,7 @@ struct inno_hdmi { struct device *dev; struct clk *pclk; + struct clk *refclk; void __iomem *regs; struct drm_connectorconnector; @@ -132,6 +133,12 @@ static struct inno_hdmi_phy_config rk3036_hdmi_phy_configs[] = { { ~0UL, 0x00, 0x00 } }; +static struct inno_hdmi_phy_config rk3128_hdmi_phy_configs[] = { + { 7425, 0x3f, 0xaa }, + { 16500, 0x5f, 0xaa }, + { ~0UL, 0x00, 0x00 } +}; + static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi, unsigned long pixelclk) { @@ -905,6 +912,20 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, return ret; } + hdmi->refclk = devm_clk_get_optional(hdmi->dev, "ref"); + if (IS_ERR(hdmi->refclk)) { + DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI reference clock\n"); + ret = PTR_ERR(hdmi->refclk); + goto err_disable_pclk; + } + + ret = clk_prepare_enable(hdmi->refclk); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, + "Cannot enable HDMI reference clock: %d\n", ret); + goto err_disable_pclk; + } + irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; @@ -921,12 +942,16 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, } /* -* When IP controller haven't configured to an accurate video -* timing, then the TMDS clock source would be switched to -* PCLK_HDMI, so we need to init the TMDS rate to PCLK rate, -* and reconfigure the DDC clock. +* When the controller isn't configured to an accurate +* video timing and there is no reference clock available, +* then the TMDS clock source would be switched to PCLK_HDMI, +* so we need to init the TMDS rate to PCLK rate, and +* reconfigure the DDC clock. */ - inno_hdmi_i2c_init(hdmi, clk_get_rate(hdmi->pclk)); + if (hdmi->refclk) + inno_hdmi_i2c_init(hdmi, clk_get_rate(hdmi->refclk)); + else + inno_hdmi_i2c_init(hdmi, clk_get_rate(hdmi->pclk)); ret = inno_hdmi_register(drm, hdmi); if (ret) @@ -950,6 +975,8 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, err_put_adapter: i2c_put_adapter(hdmi->ddc); err_disable_clk: + clk_disable_unprepare(hdmi->refclk); +err_disable_pclk: clk_disable_unprepare(hdmi->pclk); return ret; } @@ -963,6 +990,7 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, hdmi->encoder.encoder.funcs->destroy(>encoder.encoder); i2c_put_adapter(hdmi->ddc); + clk_disable_unprepare(hdmi->refclk); clk_disable_unprepare(hdmi->pclk); } @@ -986,10 +1014,18 @@ static const struct inno_hdmi_variant rk3036_inno_hdmi_variant = { .default_phy_config = _hdmi_phy_configs[1], }; +static const struct inno_hdmi_variant rk3128_inno_hdmi_variant = { + .phy_configs = rk3128_hdmi_phy_configs, + .default_phy_config = _hdmi_phy_configs[1], +}; + static const struct of_device_id inno_hdmi_dt_ids[] = { { .compatible = "rockchip,rk3036-inno-hdmi", .data = _inno_hdmi_variant, }, + { .compatible = "rockchip,rk3128-inno-hdmi", + .data = _inno_hdmi_variant, + }, {}, }; MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids); -- 2.43.0
[PATCH v3 16/29] drm/rockchip: inno_hdmi: Remove unused drm device pointer
From: Maxime Ripard The drm_dev field in the inno_hdmi struct stores a pointer to the DRM device but is never used anywhere in the driver. Let's remove it. Signed-off-by: Maxime Ripard Tested-by: Alex Bee Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - added my SoB drivers/gpu/drm/rockchip/inno_hdmi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 49367ca24125..51c1a69dfcc0 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -44,7 +44,6 @@ struct inno_hdmi_i2c { struct inno_hdmi { struct device *dev; - struct drm_device *drm_dev; int irq; struct clk *pclk; @@ -757,7 +756,6 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, return -ENOMEM; hdmi->dev = dev; - hdmi->drm_dev = drm; hdmi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hdmi->regs)) -- 2.43.0
[PATCH v3 14/29] drm/rockchip: inno_hdmi: Move infoframe disable to separate function
From: Maxime Ripard The code to upload infoframes to the controller uses a weird construct which, based on the previous function call return code, will either disable or enable that infoframe. In order to get rid of that argument, let's split the function to disable the infoframe into a separate function and make it obvious what we are doing in the error path. Signed-off-by: Maxime Ripard Tested-by: Alex Bee Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - added my SoB drivers/gpu/drm/rockchip/inno_hdmi.c | 46 ++-- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 5c9f1325441f..10466c2aa520 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -205,34 +205,44 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi) inno_hdmi_set_pwr_mode(hdmi, NORMAL); } -static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc, - union hdmi_infoframe *frame, u32 frame_index) +static void inno_hdmi_disable_frame(struct inno_hdmi *hdmi, u32 frame_index) { struct drm_connector *connector = >connector; if (frame_index != INFOFRAME_AVI) { drm_err(connector->dev, "Unsupported infoframe type: %u\n", frame_index); - return 0; + return; } hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index); +} - if (setup_rc >= 0) { - u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE]; - ssize_t rc, i; - - rc = hdmi_infoframe_pack(frame, packed_frame, -sizeof(packed_frame)); - if (rc < 0) - return rc; +static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, + union hdmi_infoframe *frame, u32 frame_index) +{ + struct drm_connector *connector = >connector; + u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE]; + ssize_t rc, i; - for (i = 0; i < rc; i++) - hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, - packed_frame[i]); + if (frame_index != INFOFRAME_AVI) { + drm_err(connector->dev, + "Unsupported infoframe type: %u\n", frame_index); + return 0; } - return setup_rc; + inno_hdmi_disable_frame(hdmi, frame_index); + + rc = hdmi_infoframe_pack(frame, packed_frame, +sizeof(packed_frame)); + if (rc < 0) + return rc; + + for (i = 0; i < rc; i++) + hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, + packed_frame[i]); + + return 0; } static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, @@ -244,6 +254,10 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, rc = drm_hdmi_avi_infoframe_from_display_mode(, >connector, mode); + if (rc) { + inno_hdmi_disable_frame(hdmi, INFOFRAME_AVI); + return rc; + } if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444) frame.avi.colorspace = HDMI_COLORSPACE_YUV444; @@ -252,7 +266,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, else frame.avi.colorspace = HDMI_COLORSPACE_RGB; - return inno_hdmi_upload_frame(hdmi, rc, , INFOFRAME_AVI); + return inno_hdmi_upload_frame(hdmi, , INFOFRAME_AVI); } static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) -- 2.43.0
[PATCH v3 21/29] drm/rockchip: inno_hdmi: Don't power up the phy after resetting
inno_hdmi_reset is only ever called when initializing the controller. At this point it’s completely uneccessary to power up the PHY, since all what has to work at this point is the DDC bus. The phy will be powered up correctly when a mode is set in inno_hdmi_encoder_enable and disabled in inno_hdmi_encoder_disable. Set it to LOWER_PWR after resetting the controller. Signed-off-by: Alex Bee --- changes in v3: - new patch drivers/gpu/drm/rockchip/inno_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index e6d37772500c..9fea464b6234 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -202,7 +202,7 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi) val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH; hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val); - inno_hdmi_set_pwr_mode(hdmi, NORMAL); + inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR); } static void inno_hdmi_disable_frame(struct inno_hdmi *hdmi, -- 2.43.0
[PATCH v3 26/29] drm/rockchip: inno_hdmi: Drop custom fill_modes hook
Now that we have proper pixelclock-based mode validation we can drop the custom fill_modes hook. CRTC size validation for the display controller has been added with Commit 8e140cb60270 ("drm/rockchip: vop: limit maximum resolution to hardware capabilities") Signed-off-by: Alex Bee Reviewed-by: Maxime Ripard --- changes in v2: - no changes changes in v3: - collect RB drivers/gpu/drm/rockchip/inno_hdmi.c | 9 + 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index a2a9e54b76c0..29a2c1b87294 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -631,13 +631,6 @@ inno_hdmi_connector_mode_valid(struct drm_connector *connector, return inno_hdmi_display_mode_valid(hdmi, mode); } -static int -inno_hdmi_probe_single_connector_modes(struct drm_connector *connector, - uint32_t maxX, uint32_t maxY) -{ - return drm_helper_probe_single_connector_modes(connector, 1920, 1080); -} - static void inno_hdmi_connector_destroy(struct drm_connector *connector) { drm_connector_unregister(connector); @@ -691,7 +684,7 @@ inno_hdmi_atomic_destroy_state(struct drm_connector *connector, } static const struct drm_connector_funcs inno_hdmi_connector_funcs = { - .fill_modes = inno_hdmi_probe_single_connector_modes, + .fill_modes = drm_helper_probe_single_connector_modes, .detect = inno_hdmi_connector_detect, .destroy = inno_hdmi_connector_destroy, .reset = inno_hdmi_connector_reset, -- 2.43.0
[PATCH v3 07/29] drm/rockchip: inno_hdmi: Get rid of mode_set
From: Maxime Ripard We're not doing anything special in atomic_mode_set so we can simply merge it into atomic_enable. Signed-off-by: Maxime Ripard Tested-by: Alex Bee Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - added my SoB drivers/gpu/drm/rockchip/inno_hdmi.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 48c4f010b260..299770e481b7 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -490,21 +490,22 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, return 0; } -static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - struct drm_display_mode *adj_mode = _state->adjusted_mode; - struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); - - inno_hdmi_setup(hdmi, adj_mode); -} - static void inno_hdmi_encoder_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + + conn_state = drm_atomic_get_new_connector_state(state, >connector); + if (WARN_ON(!conn_state)) + return; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + return; + inno_hdmi_setup(hdmi, _state->adjusted_mode); inno_hdmi_set_pwr_mode(hdmi, NORMAL); } @@ -533,7 +534,6 @@ static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = { .atomic_check = inno_hdmi_encoder_atomic_check, .atomic_enable = inno_hdmi_encoder_enable, .atomic_disable = inno_hdmi_encoder_disable, - .atomic_mode_set= inno_hdmi_encoder_mode_set, }; static enum drm_connector_status -- 2.43.0
[PATCH v3 29/29] ARM: dts: rockchip: Enable HDMI output for XPI-3128
Add an hdmi-connector node and enable the hdmi, display-subsystem and vop nodes. Signed-off-by: Alex Bee --- changes in v2: - no changes changes in v3: - no changes .../arm/boot/dts/rockchip/rk3128-xpi-3128.dts | 29 +++ 1 file changed, 29 insertions(+) diff --git a/arch/arm/boot/dts/rockchip/rk3128-xpi-3128.dts b/arch/arm/boot/dts/rockchip/rk3128-xpi-3128.dts index 03a97881519a..21c1678f4e91 100644 --- a/arch/arm/boot/dts/rockchip/rk3128-xpi-3128.dts +++ b/arch/arm/boot/dts/rockchip/rk3128-xpi-3128.dts @@ -47,6 +47,17 @@ dc_5v: dc-5v-regulator { regulator-boot-on; }; + hdmi-connnector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <_connector_out>; + }; + }; + }; + /* * This is a vbus-supply, which also supplies the GL852G usb hub, * thus has to be always-on @@ -239,6 +250,10 @@ { cpu-supply = <_arm>; }; +_subsystem { + status = "okay"; +}; + { bus-width = <8>; vmmc-supply = <_io>; @@ -328,6 +343,16 @@ { status = "okay"; }; + { + status = "okay"; +}; + +_out { + hdmi_connector_out: endpoint { + remote-endpoint = <_connector_in>; + }; +}; + { phy0: ethernet-phy@1 { compatible = "ethernet-phy-ieee802.3-c22"; @@ -423,3 +448,7 @@ _host { _otg { status = "okay"; }; + + { + status = "okay"; +}; -- 2.43.0
[PATCH v3 10/29] drm/rockchip: inno_hdmi: Remove useless input format
From: Maxime Ripard The driver has a lot of logic to deal with multiple input formats, but hardcodes it to RGB. This means that most of that code has been dead code, so let's get rid of it. Signed-off-by: Maxime Ripard Tested-by: Alex Bee [made checkpatch happy] Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - none drivers/gpu/drm/rockchip/inno_hdmi.c | 41 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 58aff7a9c09a..7c75feedacad 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -28,7 +28,6 @@ #include "inno_hdmi.h" struct hdmi_data_info { - unsigned int enc_in_format; unsigned int enc_out_format; unsigned int colorimetry; }; @@ -328,47 +327,30 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) v_VIDEO_INPUT_CSP(0); hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value); - if (data->enc_in_format == data->enc_out_format) { - if ((data->enc_in_format == HDMI_COLORSPACE_RGB) || - (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) { - value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1); - hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value); - - hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, - m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP, - v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) | - v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE)); - return 0; - } + if (data->enc_out_format == HDMI_COLORSPACE_RGB) { + value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1); + hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value); + + hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, + m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP, + v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) | + v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE)); + return 0; } if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) { - if ((data->enc_in_format == HDMI_COLORSPACE_RGB) && - (data->enc_out_format == HDMI_COLORSPACE_YUV444)) { + if (data->enc_out_format == HDMI_COLORSPACE_YUV444) { csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; csc_enable = v_CSC_ENABLE; - } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) && - (data->enc_out_format == HDMI_COLORSPACE_RGB)) { - csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT; - auto_csc = AUTO_CSC_ENABLE; - c0_c2_change = C0_C2_CHANGE_DISABLE; - csc_enable = v_CSC_DISABLE; } } else { - if ((data->enc_in_format == HDMI_COLORSPACE_RGB) && - (data->enc_out_format == HDMI_COLORSPACE_YUV444)) { + if (data->enc_out_format == HDMI_COLORSPACE_YUV444) { csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; csc_enable = v_CSC_ENABLE; - } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) && - (data->enc_out_format == HDMI_COLORSPACE_RGB)) { - csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT; - auto_csc = AUTO_CSC_ENABLE; - c0_c2_change = C0_C2_CHANGE_DISABLE; - csc_enable = v_CSC_DISABLE; } } @@ -443,7 +425,6 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, struct drm_display_info *display = >connector.display_info; u8 vic = drm_match_cea_mode(mode); - hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB; hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB; if (vic == 6 || vic == 7 || -- 2.43.0
[PATCH v3 19/29] drm/rockchip: inno_hdmi: Subclass connector state
The data which is currently hold in hdmi_data should not be part of device itself but of the connector state. Introduce a connector state subclass and move the data from hdmi_data in there. Suggested-by: Maxime Ripard Signed-off-by: Alex Bee --- changes in v2: - new patch changes in v3: - added missing customizations of reset and atomic_destroy_state connector hooks - moved inno_conn_state member assignments to atomic_check drivers/gpu/drm/rockchip/inno_hdmi.c | 111 --- 1 file changed, 84 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index c306db90832a..7ce5836fc80d 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -26,11 +26,6 @@ #include "inno_hdmi.h" -struct hdmi_data_info { - unsigned int enc_out_format; - unsigned int colorimetry; -}; - struct inno_hdmi_i2c { struct i2c_adapter adap; @@ -52,8 +47,12 @@ struct inno_hdmi { struct inno_hdmi_i2c *i2c; struct i2c_adapter *ddc; +}; - struct hdmi_data_info hdmi_data; +struct inno_hdmi_connector_state { + struct drm_connector_state base; + unsigned intenc_out_format; + unsigned intcolorimetry; }; static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder) @@ -68,6 +67,9 @@ static struct inno_hdmi *connector_to_inno_hdmi(struct drm_connector *connector) return container_of(connector, struct inno_hdmi, connector); } +#define to_inno_hdmi_conn_state(conn_state) \ + container_of_const(conn_state, struct inno_hdmi_connector_state, base) + enum { CSC_RGB_0_255_TO_ITU601_16_235_8BIT, CSC_RGB_0_255_TO_ITU709_16_235_8BIT, @@ -246,6 +248,10 @@ static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, struct drm_display_mode *mode) { + struct drm_connector *connector = >connector; + struct drm_connector_state *conn_state = connector->state; + struct inno_hdmi_connector_state *inno_conn_state = + to_inno_hdmi_conn_state(conn_state); union hdmi_infoframe frame; int rc; @@ -257,9 +263,9 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, return rc; } - if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444) + if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) frame.avi.colorspace = HDMI_COLORSPACE_YUV444; - else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422) + else if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV422) frame.avi.colorspace = HDMI_COLORSPACE_YUV422; else frame.avi.colorspace = HDMI_COLORSPACE_RGB; @@ -269,7 +275,10 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) { - struct hdmi_data_info *data = >hdmi_data; + struct drm_connector *connector = >connector; + struct drm_connector_state *conn_state = connector->state; + struct inno_hdmi_connector_state *inno_conn_state = + to_inno_hdmi_conn_state(conn_state); int c0_c2_change = 0; int csc_enable = 0; int csc_mode = 0; @@ -287,7 +296,7 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) v_VIDEO_INPUT_CSP(0); hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value); - if (data->enc_out_format == HDMI_COLORSPACE_RGB) { + if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) { value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1); hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value); @@ -298,15 +307,15 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) return 0; } - if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) { - if (data->enc_out_format == HDMI_COLORSPACE_YUV444) { + if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) { + if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; csc_enable = v_CSC_ENABLE; } } else { - if (data->enc_out_format == HDMI_COLORSPACE_YUV444) { + if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; @@ -383,17 +392,6 @@ static int
[PATCH v3 05/29] drm/rockchip: inno_hdmi: Remove useless copy of drm_display_mode
From: Maxime Ripard The driver maintains a copy of the adjusted mode but doesn't use it anywhere. Remove it. Signed-off-by: Maxime Ripard Tested-by: Alex Bee Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - added my SoB drivers/gpu/drm/rockchip/inno_hdmi.c | 4 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 0b1740b38c7b..14d2ba92a606 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -62,7 +62,6 @@ struct inno_hdmi { unsigned int tmds_rate; struct hdmi_data_info hdmi_data; - struct drm_display_mode previous_mode; }; static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder) @@ -498,9 +497,6 @@ static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder, struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); inno_hdmi_setup(hdmi, adj_mode); - - /* Store the display mode for plugin/DPMS poweron events */ - drm_mode_copy(>previous_mode, adj_mode); } static void inno_hdmi_encoder_enable(struct drm_encoder *encoder) -- 2.43.0
[PATCH v3 20/29] drm/rockchip: inno_hdmi: Correctly setup HDMI quantization range
The display controller will always give full range RGB regardless of the mode set, but HDMI requires certain modes to be transmitted in limited range RGB. This is especially required for HDMI sinks which do not support non-standard quantization ranges. This enables color space conversion for those modes and sets the quantization range accordingly in the AVI infoframe. Signed-off-by: Alex Bee --- changes in v2: - made rgb_limited_range part of the new custom connector state changes in v3: - moved assignment of rgb_limited_range to atomic check drivers/gpu/drm/rockchip/inno_hdmi.c | 60 +++- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 7ce5836fc80d..e6d37772500c 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -53,6 +53,7 @@ struct inno_hdmi_connector_state { struct drm_connector_state base; unsigned intenc_out_format; unsigned intcolorimetry; + boolrgb_limited_range; }; static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder) @@ -270,6 +271,18 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, else frame.avi.colorspace = HDMI_COLORSPACE_RGB; + if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) { + drm_hdmi_avi_infoframe_quant_range(, + connector, mode, + inno_conn_state->rgb_limited_range ? + HDMI_QUANTIZATION_RANGE_LIMITED : + HDMI_QUANTIZATION_RANGE_FULL); + } else { + frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT; + frame.avi.ycc_quantization_range = + HDMI_YCC_QUANTIZATION_RANGE_LIMITED; + } + return inno_hdmi_upload_frame(hdmi, , HDMI_INFOFRAME_TYPE_AVI); } @@ -297,29 +310,37 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value); if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) { - value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1); - hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value); - - hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, - m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP, - v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) | - v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE)); - return 0; - } - - if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) { - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { - csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT; + if (inno_conn_state->rgb_limited_range) { + csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; csc_enable = v_CSC_ENABLE; + + } else { + value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1); + hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value); + + hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, + m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP, + v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) | + v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE)); + return 0; } } else { - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { - csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT; - auto_csc = AUTO_CSC_DISABLE; - c0_c2_change = C0_C2_CHANGE_DISABLE; - csc_enable = v_CSC_ENABLE; + if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) { + if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { + csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT; + auto_csc = AUTO_CSC_DISABLE; + c0_c2_change = C0_C2_CHANGE_DISABLE; + csc_enable = v_CSC_ENABLE; + } + } else { + if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { + csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT; + auto_csc = AUTO_CSC_DISABLE; + c0_c2_change = C0_C2_CHANGE_DISABLE; + csc_enable = v_CSC_ENABLE; +
[PATCH v3 25/29] drm/rockchip: inno_hdmi: Add basic mode validation
As per TRM this controller supports pixelclocks starting from 25 MHz. The maximum supported pixelclocks are defined by the phy configurations we have. Also it can't support modes that require doubled clocks. If the variant has a phy reference clock we can additionally validate against VESA DMT'srecommendations. Signed-off-by: Alex Bee Reviewed-by: Maxime Ripard --- changes in v2: - rename inno_mode_valid -> inno_hdmi_display_mode_valid - fixed max_tolerance calculation - use abs_diff() instead of abs() - call in inno_hdmi_display_mode_valid in atomic_check changes in v3: - collect RB drivers/gpu/drm/rockchip/inno_hdmi.c | 42 ++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 8a1a2320749a..a2a9e54b76c0 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -26,6 +26,8 @@ #include "inno_hdmi.h" +#define INNO_HDMI_MIN_TMDS_CLOCK 2500U + struct inno_hdmi_phy_config { unsigned long pixelclock; u8 pre_emphasis; @@ -497,6 +499,38 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, return 0; } +static enum drm_mode_status inno_hdmi_display_mode_valid(struct inno_hdmi *hdmi, +struct drm_display_mode *mode) +{ + unsigned long mpixelclk, max_tolerance; + long rounded_refclk; + + /* No support for double-clock modes */ + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + return MODE_BAD; + + mpixelclk = mode->clock * 1000; + + if (mpixelclk < INNO_HDMI_MIN_TMDS_CLOCK) + return MODE_CLOCK_LOW; + + if (inno_hdmi_find_phy_config(hdmi, mpixelclk) < 0) + return MODE_CLOCK_HIGH; + + if (hdmi->refclk) { + rounded_refclk = clk_round_rate(hdmi->refclk, mpixelclk); + if (rounded_refclk < 0) + return MODE_BAD; + + /* Vesa DMT standard mentions +/- 0.5% max tolerance */ + max_tolerance = mpixelclk / 200; + if (abs_diff((unsigned long)rounded_refclk, mpixelclk) > max_tolerance) + return MODE_NOCLOCK; + } + + return MODE_OK; +} + static void inno_hdmi_encoder_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { @@ -529,6 +563,7 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); + struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); struct drm_display_mode *mode = _state->adjusted_mode; u8 vic = drm_match_cea_mode(mode); struct inno_hdmi_connector_state *inno_conn_state = @@ -549,7 +584,8 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, inno_conn_state->rgb_limited_range = drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED; - return 0; + return inno_hdmi_display_mode_valid(hdmi, + _state->adjusted_mode) == MODE_OK ? 0 : -EINVAL; } static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = { @@ -590,7 +626,9 @@ static enum drm_mode_status inno_hdmi_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - return MODE_OK; + struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); + + return inno_hdmi_display_mode_valid(hdmi, mode); } static int -- 2.43.0
[PATCH v3 17/29] drm/rockchip: inno_hdmi: Drop irq struct member
The struct member irq isn't used anywhere. Drop it. Signed-off-by: Alex Bee Reviewed-by: Maxime Ripard --- changes in v2: - new patch changes in v3: - collect RB drivers/gpu/drm/rockchip/inno_hdmi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 51c1a69dfcc0..138cd4287dea 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -45,7 +45,6 @@ struct inno_hdmi_i2c { struct inno_hdmi { struct device *dev; - int irq; struct clk *pclk; void __iomem *regs; -- 2.43.0
[PATCH v3 04/29] drm/rockchip: inno_hdmi: Remove useless mode_fixup
From: Maxime Ripard The mode_fixup implementation doesn't do anything, so we can simply remove it. Signed-off-by: Maxime Ripard Tested-by: Alex Bee Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - added my SoB drivers/gpu/drm/rockchip/inno_hdmi.c | 8 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 345253e033c5..0b1740b38c7b 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -517,13 +517,6 @@ static void inno_hdmi_encoder_disable(struct drm_encoder *encoder) inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR); } -static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder, -const struct drm_display_mode *mode, -struct drm_display_mode *adj_mode) -{ - return true; -} - static int inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, @@ -540,7 +533,6 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = { .enable = inno_hdmi_encoder_enable, .disable= inno_hdmi_encoder_disable, - .mode_fixup = inno_hdmi_encoder_mode_fixup, .mode_set = inno_hdmi_encoder_mode_set, .atomic_check = inno_hdmi_encoder_atomic_check, }; -- 2.43.0
[PATCH v3 18/29] drm/rockchip: inno_hdmi: Remove useless include
The inclusion syscon.h isn't used anywhere. Remove it. Signed-off-by: Alex Bee Reviewed-by: Maxime Ripard --- changes in v2: - new patch changes in v3: - collect RB drivers/gpu/drm/rockchip/inno_hdmi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 138cd4287dea..c306db90832a 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include -- 2.43.0
[PATCH v3 08/29] drm/rockchip: inno_hdmi: no need to store vic
From: Maxime Ripard The mode's VIC is only ever used in the inno_hdmi_setup() function so there's no need to store it in the main structure. Signed-off-by: Maxime Ripard Tested-by: Alex Bee [made checkpatch happy] Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - none drivers/gpu/drm/rockchip/inno_hdmi.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 299770e481b7..d99896f1a73a 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -28,7 +28,6 @@ #include "inno_hdmi.h" struct hdmi_data_info { - int vic; bool sink_has_audio; unsigned int enc_in_format; unsigned int enc_out_format; @@ -443,16 +442,15 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, struct drm_display_mode *mode) { struct drm_display_info *display = >connector.display_info; - - hdmi->hdmi_data.vic = drm_match_cea_mode(mode); + u8 vic = drm_match_cea_mode(mode); hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB; hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB; - if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) || - (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) || - (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) || - (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18)) + if (vic == 6 || vic == 7 || + vic == 21 || vic == 22 || + vic == 2 || vic == 3 || + vic == 17 || vic == 18) hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601; else hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; -- 2.43.0
[PATCH v3 22/29] drm/rockchip: inno_hdmi: Split power mode setting
This splits setting the power mode of the controller / phy in two functions. It's done in preparation of setting up the phy based on the pixelclock. No functional changes intended. Signed-off-by: Alex Bee --- changes in v3: - new patch drivers/gpu/drm/rockchip/inno_hdmi.c | 54 +--- drivers/gpu/drm/rockchip/inno_hdmi.h | 5 --- 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 9fea464b6234..e21f6d7aeee6 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -154,38 +154,31 @@ static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable) hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF); } -static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode) +static void inno_hdmi_standby(struct inno_hdmi *hdmi) { - switch (mode) { - case NORMAL: - inno_hdmi_sys_power(hdmi, false); + inno_hdmi_sys_power(hdmi, false); - hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f); - hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb); - - hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); - hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14); - hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10); - hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f); - hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00); - hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01); - - inno_hdmi_sys_power(hdmi, true); - break; + hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00); + hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00); + hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00); + hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); +}; - case LOWER_PWR: - inno_hdmi_sys_power(hdmi, false); - hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00); - hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00); - hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00); - hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); +static void inno_hdmi_power_up(struct inno_hdmi *hdmi) +{ + inno_hdmi_sys_power(hdmi, false); - break; + hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f); + hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb); + hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); + hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14); + hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10); + hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f); + hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00); + hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01); - default: - DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode); - } -} + inno_hdmi_sys_power(hdmi, true); +}; static void inno_hdmi_reset(struct inno_hdmi *hdmi) { @@ -202,7 +195,7 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi) val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH; hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val); - inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR); + inno_hdmi_standby(hdmi); } static void inno_hdmi_disable_frame(struct inno_hdmi *hdmi, @@ -441,6 +434,8 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); + inno_hdmi_power_up(hdmi); + return 0; } @@ -460,7 +455,6 @@ static void inno_hdmi_encoder_enable(struct drm_encoder *encoder, return; inno_hdmi_setup(hdmi, _state->adjusted_mode); - inno_hdmi_set_pwr_mode(hdmi, NORMAL); } static void inno_hdmi_encoder_disable(struct drm_encoder *encoder, @@ -468,7 +462,7 @@ static void inno_hdmi_encoder_disable(struct drm_encoder *encoder, { struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); - inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR); + inno_hdmi_standby(hdmi); } static int diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.h b/drivers/gpu/drm/rockchip/inno_hdmi.h index 93245b55f967..a7edf3559e60 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.h +++ b/drivers/gpu/drm/rockchip/inno_hdmi.h @@ -10,11 +10,6 @@ #define DDC_SEGMENT_ADDR 0x30 -enum PWR_MODE { - NORMAL, - LOWER_PWR, -}; - #define HDMI_SCL_RATE (100*1000) #define DDC_BUS_FREQ_L 0x4b #define DDC_BUS_FREQ_H 0x4c -- 2.43.0
[PATCH v3 23/29] drm/rockchip: inno_hdmi: Add variant support
In preparation to support RK3128's integration of the controller, this patch adds a simple variant implementation. They mainly differ in the phy configuration required, so those are part of the match_data. The values have been taken from downstream. The pixelclocks in there are meant to be max-inclusive. Signed-off-by: Alex Bee --- changes in v2: - no changes changes in v3: - adapt to the newly introduced inno_hdmi_power_up / inno_hdmi_standby functions drivers/gpu/drm/rockchip/inno_hdmi.c | 74 ++-- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index e21f6d7aeee6..df979bab9abd 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -26,6 +26,17 @@ #include "inno_hdmi.h" +struct inno_hdmi_phy_config { + unsigned long pixelclock; + u8 pre_emphasis; + u8 voltage_level_control; +}; + +struct inno_hdmi_variant { + struct inno_hdmi_phy_config *phy_configs; + struct inno_hdmi_phy_config *default_phy_config; +}; + struct inno_hdmi_i2c { struct i2c_adapter adap; @@ -47,6 +58,8 @@ struct inno_hdmi { struct inno_hdmi_i2c *i2c; struct i2c_adapter *ddc; + + const struct inno_hdmi_variant *variant; }; struct inno_hdmi_connector_state { @@ -113,6 +126,30 @@ static const char coeff_csc[][24] = { }, }; +static struct inno_hdmi_phy_config rk3036_hdmi_phy_configs[] = { + { 7425, 0x3f, 0xbb }, + { 16500, 0x6f, 0xbb }, + { ~0UL, 0x00, 0x00 } +}; + +static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi, +unsigned long pixelclk) +{ + const struct inno_hdmi_phy_config *phy_configs = + hdmi->variant->phy_configs; + int i; + + for (i = 0; phy_configs[i].pixelclock != ~0UL; i++) { + if (pixelclk <= phy_configs[i].pixelclock) + return i; + } + + DRM_DEV_DEBUG(hdmi->dev, "No phy configuration for pixelclock %lu\n", + pixelclk); + + return -EINVAL; +} + static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset) { return readl_relaxed(hdmi->regs + (offset) * 0x04); @@ -164,12 +201,25 @@ static void inno_hdmi_standby(struct inno_hdmi *hdmi) hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); }; -static void inno_hdmi_power_up(struct inno_hdmi *hdmi) +static void inno_hdmi_power_up(struct inno_hdmi *hdmi, + unsigned long mpixelclock) { + struct inno_hdmi_phy_config *phy_config; + int ret = inno_hdmi_find_phy_config(hdmi, mpixelclock); + + if (ret < 0) { + phy_config = hdmi->variant->default_phy_config; + DRM_DEV_ERROR(hdmi->dev, + "Using default phy configuration for TMDS rate %lu", + mpixelclock); + } else { + phy_config = >variant->phy_configs[ret]; + } + inno_hdmi_sys_power(hdmi, false); - hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f); - hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb); + hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, phy_config->pre_emphasis); + hdmi_writeb(hdmi, HDMI_PHY_DRIVER, phy_config->voltage_level_control); hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14); hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10); @@ -406,6 +456,7 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, struct drm_display_mode *mode) { struct drm_display_info *display = >connector.display_info; + unsigned long mpixelclock = mode->clock * 1000; /* Mute video and audio output */ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, @@ -428,13 +479,13 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, * DCLK_LCDC, so we need to init the TMDS rate to mode pixel * clock rate, and reconfigure the DDC clock. */ - inno_hdmi_i2c_init(hdmi, mode->clock * 1000); + inno_hdmi_i2c_init(hdmi, mpixelclock); /* Unmute video and audio output */ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); - inno_hdmi_power_up(hdmi); + inno_hdmi_power_up(hdmi, mpixelclock); return 0; } @@ -821,6 +872,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = data; struct inno_hdmi *hdmi; + const struct inno_hdmi_variant *variant; int irq; int ret; @@ -830,6 +882,12 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, hdmi->dev = dev; + variant =
[PATCH v3 13/29] drm/rockchip: inno_hdmi: Drop HDMI Vendor Infoframe support
From: Maxime Ripard The HDMI vendor infoframe is only meant to be sent with 4k60 modes and higher, but the controller doesn't support them. Let's drop them from the kernel. Suggested-by: Johan Jonker Signed-off-by: Maxime Ripard Tested-by: Alex Bee Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - added my SoB drivers/gpu/drm/rockchip/inno_hdmi.c | 35 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 102195837206..5c9f1325441f 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -206,11 +206,15 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi) } static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc, - union hdmi_infoframe *frame, u32 frame_index, - u32 mask, u32 disable, u32 enable) + union hdmi_infoframe *frame, u32 frame_index) { - if (mask) - hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable); + struct drm_connector *connector = >connector; + + if (frame_index != INFOFRAME_AVI) { + drm_err(connector->dev, + "Unsupported infoframe type: %u\n", frame_index); + return 0; + } hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index); @@ -226,28 +230,11 @@ static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc, for (i = 0; i < rc; i++) hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, packed_frame[i]); - - if (mask) - hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable); } return setup_rc; } -static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi, - struct drm_display_mode *mode) -{ - union hdmi_infoframe frame; - int rc; - - rc = drm_hdmi_vendor_infoframe_from_display_mode(, ->connector, -mode); - - return inno_hdmi_upload_frame(hdmi, rc, , INFOFRAME_VSI, - m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1)); -} - static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, struct drm_display_mode *mode) { @@ -265,7 +252,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, else frame.avi.colorspace = HDMI_COLORSPACE_RGB; - return inno_hdmi_upload_frame(hdmi, rc, , INFOFRAME_AVI, 0, 0, 0); + return inno_hdmi_upload_frame(hdmi, rc, , INFOFRAME_AVI); } static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) @@ -408,10 +395,8 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, inno_hdmi_config_video_csc(hdmi); - if (display->is_hdmi) { + if (display->is_hdmi) inno_hdmi_config_video_avi(hdmi, mode); - inno_hdmi_config_video_vsi(hdmi, mode); - } /* * When IP controller have configured to an accurate video -- 2.43.0
[PATCH v3 09/29] drm/rockchip: inno_hdmi: Remove unneeded has audio flag
From: Maxime Ripard The sink_has_audio flag is not used anywhere in the driver so let's get rid of it. It's redundant with drm_display_info.has_audio anyway. Signed-off-by: Maxime Ripard Tested-by: Alex Bee Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - added my SoB drivers/gpu/drm/rockchip/inno_hdmi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index d99896f1a73a..58aff7a9c09a 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -28,7 +28,6 @@ #include "inno_hdmi.h" struct hdmi_data_info { - bool sink_has_audio; unsigned int enc_in_format; unsigned int enc_out_format; unsigned int colorimetry; @@ -554,7 +553,6 @@ static int inno_hdmi_connector_get_modes(struct drm_connector *connector) edid = drm_get_edid(connector, hdmi->ddc); if (edid) { - hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid); drm_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); kfree(edid); -- 2.43.0
[PATCH v3 11/29] drm/rockchip: inno_hdmi: Remove YUV-based csc coefficents
Now that the unneeded support for YUV based input formats is gone, the csc coefficients for those formats can be dropped as well. Signed-off-by: Alex Bee --- changes in v2: - new patch changes in v3: - none drivers/gpu/drm/rockchip/inno_hdmi.c | 37 1 file changed, 37 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 7c75feedacad..04344ee1265d 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -74,49 +74,12 @@ static struct inno_hdmi *connector_to_inno_hdmi(struct drm_connector *connector) } enum { - CSC_ITU601_16_235_TO_RGB_0_255_8BIT, - CSC_ITU601_0_255_TO_RGB_0_255_8BIT, - CSC_ITU709_16_235_TO_RGB_0_255_8BIT, CSC_RGB_0_255_TO_ITU601_16_235_8BIT, CSC_RGB_0_255_TO_ITU709_16_235_8BIT, CSC_RGB_0_255_TO_RGB_16_235_8BIT, }; static const char coeff_csc[][24] = { - /* -* YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]): -* R = 1.164*Y + 1.596*V - 204 -* G = 1.164*Y - 0.391*U - 0.813*V + 154 -* B = 1.164*Y + 2.018*U - 258 -*/ - { - 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc, - 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a, - 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02 - }, - /* -* YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]): -* R = Y + 1.402*V - 248 -* G = Y - 0.344*U - 0.714*V + 135 -* B = Y + 1.772*U - 227 -*/ - { - 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8, - 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87, - 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3 - }, - /* -* YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]): -* R = 1.164*Y + 1.793*V - 248 -* G = 1.164*Y - 0.213*U - 0.534*V + 77 -* B = 1.164*Y + 2.115*U - 289 -*/ - { - 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8, - 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d, - 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21 - }, - /* * RGB2YUV:601 SD mode: * Cb = -0.291G - 0.148R + 0.439B + 128 -- 2.43.0
[PATCH v3 06/29] drm/rockchip: inno_hdmi: Switch encoder hooks to atomic
From: Maxime Ripard The inno_hdmi encoder still uses the !atomic variants of enable, disable and modeset. Convert to their atomic equivalents. Signed-off-by: Maxime Ripard Tested-by: Alex Bee Signed-off-by: Alex Bee --- changes in v2: - imported patch changes in v3: - added my SoB drivers/gpu/drm/rockchip/inno_hdmi.c | 19 +++ 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 14d2ba92a606..48c4f010b260 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -491,22 +491,25 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, } static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { + struct drm_display_mode *adj_mode = _state->adjusted_mode; struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); inno_hdmi_setup(hdmi, adj_mode); } -static void inno_hdmi_encoder_enable(struct drm_encoder *encoder) +static void inno_hdmi_encoder_enable(struct drm_encoder *encoder, +struct drm_atomic_state *state) { struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); inno_hdmi_set_pwr_mode(hdmi, NORMAL); } -static void inno_hdmi_encoder_disable(struct drm_encoder *encoder) +static void inno_hdmi_encoder_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); @@ -527,10 +530,10 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, } static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = { - .enable = inno_hdmi_encoder_enable, - .disable= inno_hdmi_encoder_disable, - .mode_set = inno_hdmi_encoder_mode_set, - .atomic_check = inno_hdmi_encoder_atomic_check, + .atomic_check = inno_hdmi_encoder_atomic_check, + .atomic_enable = inno_hdmi_encoder_enable, + .atomic_disable = inno_hdmi_encoder_disable, + .atomic_mode_set= inno_hdmi_encoder_mode_set, }; static enum drm_connector_status -- 2.43.0