* Re: Detecting AArch32 support from a AArch64 process in user space
From: Dave Martin @ 2019-08-08 9:35 UTC (permalink / raw)
To: Stefan Agner
Cc: Marc Zyngier, ynorov, will.deacon, linux-arm-kernel,
suzuki.poulose
In-Reply-To: <ffbb92107af81971c03ec832cf25116c@agner.ch>
On Thu, Aug 08, 2019 at 09:36:42AM +0200, Stefan Agner wrote:
> [resend this time with the correct mailing list address]
>
> Hello,
>
> I am trying to detect whether an ARMv8 system running in AArch64 state
> supports AArch32 state from a user space process. The arm64_features[]
> in
Why? Is this just for diagnostic purposes, or some programmatic reason?
In the latter case, just try to do what ever it is you want to do that
depends on AArch32: if it fails, you don't have AArch32.
> arch/arm64/kernel/cpufeature.c lists a CPU feature "32-bit EL0 Support".
> However, afaik this CPU feature is not directly exposed to user-space.
> The features do get printed in the kernel log, but that requires
> privileges and only works directly after boot. There is
Please don't scrape dmesg :)
However, detecting AArch32 support is a bit annoying due to the fact
that there's no hwcap or similar.
> system_supports_32bit_el0() which is used in various places in the arm64
> architecture code. One of the instances where I can make sense of from
> user space is through the personality system call. One idea is to call
> personality(PER_LINUX32). It would then return error code 22 in case
> 32-bit is not supported in user space. However, if successful this
> changes the personality of the current process which might have side
> effects which I do not want...?
>
> I started to ask myself what PER_LINUX32 actually changes. From what I
> can tell it only changes the behavior of /proc/cpuinfo? The personality
> seems not to be applied automatically to 32-bit processes, so this is a
> opt-in backward compatibility feature?
Basically yes. Nonetheless, this is probably a reasonable way to test
for AArch32 userspace support.
> To be on the safe side, I was thinking about executing the system call
> in a separate process. However, at that point I could also just execute
> a statically linked AArch32 binary and see whether I get a "exec format
> error". I guess this could then be either due to missing AArch32 CPU
> support or the kernel not being compiled with 32-bit compatibility.
personality() returns the old personality, so you providing you don't
have multiple threads you can probably try to set it to PER_LINUX32
and then restore it.
Otherwise, you would need to fork and try personality() from the child.
Or as you suggest, try to exec a 32-bit binary.
> At last I was considering reading directly from the CPU. But from what I
> understand the register used in the kernel to determine 32-bit
> compatibility (ID_AA64PFR0_EL1) is not accessible by user space (due to
> the suffix _EL1).
>
> Any advice/thoughts on this topic?
This register is emulated for userspace, so you can read it. However,
the relevant field gets masked out, so this is probably not much use to
you.
We could expose the field, but a test that relies on it wouldn't be
backwards compatible.
If you just want to do this test from a script for diagnostic purposes
and the filesystem has util-linux, then something like
linux32 /bin/true
might also work (this is effectively a scripted version of the
personality(PER_LINUX32) test).
Cheers
---Dave
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 47/59] KVM: arm64: nv: Propagate CNTVOFF_EL2 to the virtual EL1 timer
From: Alexandru Elisei @ 2019-08-08 9:34 UTC (permalink / raw)
To: Marc Zyngier, linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara, Dave Martin
In-Reply-To: <20190621093843.220980-48-marc.zyngier@arm.com>
On 6/21/19 10:38 AM, Marc Zyngier wrote:
> We need to allow a guest hypervisor to virtualize the virtual timer.
> FOr that, let's propagate CNTVOFF_EL2 to the guest's view of that
> timer.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm64/include/asm/kvm_host.h | 1 -
> arch/arm64/kvm/sys_regs.c | 8 ++++++--
> include/kvm/arm_arch_timer.h | 1 +
> virt/kvm/arm/arch_timer.c | 12 ++++++++++++
> 4 files changed, 19 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index b7c44adcdbf3..e0fe9acb46bf 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -252,7 +252,6 @@ enum vcpu_sysreg {
> RMR_EL2, /* Reset Management Register */
> CONTEXTIDR_EL2, /* Context ID Register (EL2) */
> TPIDR_EL2, /* EL2 Software Thread ID Register */
> - CNTVOFF_EL2, /* Counter-timer Virtual Offset register */
> CNTHCTL_EL2, /* Counter-timer Hypervisor Control register */
> SP_EL2, /* EL2 Stack Pointer */
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 1b8016330a19..2031a59fcf49 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -150,7 +150,6 @@ struct el2_sysreg_map {
> PURE_EL2_SYSREG( RVBAR_EL2 ),
> PURE_EL2_SYSREG( RMR_EL2 ),
> PURE_EL2_SYSREG( TPIDR_EL2 ),
> - PURE_EL2_SYSREG( CNTVOFF_EL2 ),
> PURE_EL2_SYSREG( CNTHCTL_EL2 ),
> PURE_EL2_SYSREG( HPFAR_EL2 ),
> EL2_SYSREG( SCTLR_EL2, SCTLR_EL1, translate_sctlr ),
> @@ -1351,6 +1350,11 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
> tmr = TIMER_PTIMER;
> treg = TIMER_REG_CVAL;
> break;
> + case SYS_CNTVOFF_EL2:
> + tmr = TIMER_VTIMER;
> + treg = TIMER_REG_VOFF;
> + break;
> +
> default:
> BUG();
> }
> @@ -2122,7 +2126,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
> { SYS_DESC(SYS_CONTEXTIDR_EL2), access_rw, reset_val, CONTEXTIDR_EL2, 0 },
> { SYS_DESC(SYS_TPIDR_EL2), access_rw, reset_val, TPIDR_EL2, 0 },
>
> - { SYS_DESC(SYS_CNTVOFF_EL2), access_rw, reset_val, CNTVOFF_EL2, 0 },
> + { SYS_DESC(SYS_CNTVOFF_EL2), access_arch_timer },
> { SYS_DESC(SYS_CNTHCTL_EL2), access_rw, reset_val, CNTHCTL_EL2, 0 },
>
> { SYS_DESC(SYS_CNTHP_TVAL_EL2), access_arch_timer },
> diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
> index 3a5d9255120e..3389606f3029 100644
> --- a/include/kvm/arm_arch_timer.h
> +++ b/include/kvm/arm_arch_timer.h
> @@ -23,6 +23,7 @@ enum kvm_arch_timer_regs {
> TIMER_REG_CVAL,
> TIMER_REG_TVAL,
> TIMER_REG_CTL,
> + TIMER_REG_VOFF,
> };
>
> struct arch_timer_context {
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index 3d84c240071d..1d53352c7d97 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -913,6 +913,10 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,
> val = kvm_phys_timer_read() - timer->cntvoff;
> break;
>
> + case TIMER_REG_VOFF:
> + val = timer->cntvoff;
> + break;
> +
> default:
> BUG();
> }
> @@ -955,6 +959,10 @@ static void kvm_arm_timer_write(struct kvm_vcpu *vcpu,
> timer->cnt_cval = val;
> break;
>
> + case TIMER_REG_VOFF:
> + timer->cntvoff = val;
> + break;
> +
> default:
> BUG();
> }
> @@ -1166,6 +1174,10 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
> return -EINVAL;
> }
>
> + /* Nested virtualization requires zero offset for virtual EL2 */
> + if (nested_virt_in_use(vcpu))
> + vcpu_vtimer(vcpu)->cntvoff = 0;
I think this is related to the fact that the virtual offset is treated as 0 when
reading CNTVCT_EL0 from EL2, or from from EL2 and EL0 if E2H, TGE are set
(please correct me if I'm wrong).
However, when the guest runs in virtual EL2, the direct_vtimer is the hvtimer,
so the value that ends up in CNTVOFF_EL2 is vcpu_hvtimer(vcpu)->cntvoff.
Thanks,
Alex
> +
> get_timer_map(vcpu, &map);
>
> ret = kvm_vgic_map_phys_irq(vcpu,
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v7 0/2] arm64 tagged address ABI
From: Szabolcs Nagy @ 2019-08-08 9:32 UTC (permalink / raw)
To: Catalin Marinas, linux-arm-kernel@lists.infradead.org
Cc: linux-arch@vger.kernel.org, Vincenzo Frascino,
linux-doc@vger.kernel.org, Andrey Konovalov, Kevin Brodsky,
Will Deacon, Dave Hansen, nd
In-Reply-To: <20190807155321.9648-1-catalin.marinas@arm.com>
On 07/08/2019 16:53, Catalin Marinas wrote:
> Hi,
>
> Thanks for the feedback so far. This is an updated series documenting
> the AArch64 Tagged Address ABI as implemented by these patches:
>
> http://lkml.kernel.org/r/cover.1563904656.git.andreyknvl@google.com
>
> Version 6 of the documentation series is available here:
>
> http://lkml.kernel.org/r/20190725135044.24381-1-vincenzo.frascino@arm.com
>
> Changes in v7:
>
> - Dropped the MAP_PRIVATE requirements for tagged pointers for both
> anonymous and file mappings. One reason is that we can't enforce such
> restriction anyway. The other reason is that a future series
> implementing support for the hardware MTE will detect
> incompatibilities of the new PROT_MTE flag with various mmap()
> options.
OK.
> - As a consequence of the above, I removed Szabolcs ack as I'm not sure
> he's ok with the change.
>
> - Clarified the sysctl and prctl() interaction and reordered the
> descriptions.
>
> - Reworded the prctl(PR_SET_MM) restrictions.
>
> - Removed the description of the tag preservation from the first patch
> as it didn't really make sense (the syscall ABI has always preserved
> all registers other than x0 on return to user).
preservation is more interesting when a user pointer
is passed to the kernel and later it is passed back
to user space (e.g. set/get_robust_list, or sigaction
where old handler pointer is returned), then the
kernel may want to drop the tag to do something with
the pointer, but user space may want it to be preserved.
in principle segfault si_addr is a similar case when
memory access via tagged pointer faults: currently
the kernel does not preserve the tag.
so i think it's interesting to know when exactly the
kernel preserves the tags, but it may not be easy to
document in a generic way.
>
> - s/ARM64/AArch64/ for consistency with the tagged-pointers.rst
> document.
>
> - Other minor rewordings.
>
> Vincenzo Frascino (2):
> arm64: Define Documentation/arm64/tagged-address-abi.rst
> arm64: Relax Documentation/arm64/tagged-pointers.rst
>
> Documentation/arm64/tagged-address-abi.rst | 151 +++++++++++++++++++++
> Documentation/arm64/tagged-pointers.rst | 23 +++-
> 2 files changed, 167 insertions(+), 7 deletions(-)
> create mode 100644 Documentation/arm64/tagged-address-abi.rst
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v7 1/2] arm64: Define Documentation/arm64/tagged-address-abi.rst
From: Szabolcs Nagy @ 2019-08-08 9:25 UTC (permalink / raw)
To: Dave Hansen, Catalin Marinas,
linux-arm-kernel@lists.infradead.org
Cc: linux-arch@vger.kernel.org, Vincenzo Frascino,
linux-doc@vger.kernel.org, Andrey Konovalov, Kevin Brodsky,
Will Deacon, nd
In-Reply-To: <826a9ace-feac-c019-843e-07e23c9fd46c@intel.com>
On 07/08/2019 21:38, Dave Hansen wrote:
> On 8/7/19 8:53 AM, Catalin Marinas wrote:
>> +- The syscall behaviour is undefined for non valid tagged pointers.
>
> Do you really mean "undefined"? I mean, a bad pointer is a bad pointer.
> Why should it matter if it's a tagged bad pointer or an untagged bad
> pointer?
bad pointers are invalid, but some non-bad pointers are
also invalid if they are tagged (e.g. tagged pointer to
device memory?) those may be valid to dereference in
userspace but don't work across the syscall abi (device
driver does not handle the tag?).
>> +- mmap() addr parameter.
>> +
>> +- mremap() new_address parameter.
>
> Is munmap() missing? Or was there a reason for leaving it out?
the new address in mmap and mremap may not be currently
mapped, other m* functions operate on existing mappings
(munmap, madvise, mprotect, mlock,...)
although by this logic brk (and related PR_SET_MM_*)
should be excluded here too.
>> +- prctl(PR_SET_MM, ``*``, ...) other than arg2 PR_SET_MM_MAP and
>> + PR_SET_MM_MAP_SIZE.
>> +
>> +- prctl(PR_SET_MM, PR_SET_MM_MAP{,_SIZE}, ...) struct prctl_mm_map fields.
>> +
>> +Any attempt to use non-zero tagged pointers will lead to undefined
>> +behaviour.
>
> I wonder if you want to generalize this a bit. I think you're saying
> that parts of the ABI that modify the *layout* of the address space
> never accept tagged pointers.
something like that, but i think this is hard to specify
in a generic way.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [V1, 2/2] media: i2c: Add more sensor mode for ov8856 camera sensor
From: dongchun.zhu @ 2019-08-08 9:22 UTC (permalink / raw)
To: mchehab, robh+dt, mark.rutland, sakari.ailus, drinkcat, tfiga,
matthias.bgg, bingbu.cao
Cc: devicetree, srv_heupstream, shengnan.wang, sj.huang,
linux-mediatek, dongchun.zhu, louis.kuo, linux-arm-kernel,
linux-media
In-Reply-To: <20190808092215.5608-1-dongchun.zhu@mediatek.com>
From: Dongchun Zhu <dongchun.zhu@mediatek.com>
This patch mainly adds two more sensor modes for OV8856 image sensor.
The OV8856 driver currently supports output format: 10-bit Raw,
the resolution of 1632*1224 and 3264*2448, and the bayer order of BGGR.
The hardware version also differs in some OTP regiser,
as well as PLL register setting.
Signed-off-by: Dongchun Zhu <dongchun.zhu@mediatek.com>
---
drivers/media/i2c/ov8856.c | 624 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 621 insertions(+), 3 deletions(-)
diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c
index cd347d6..e0610b6 100644
--- a/drivers/media/i2c/ov8856.c
+++ b/drivers/media/i2c/ov8856.c
@@ -1,12 +1,15 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Intel Corporation.
+#include <linux/clk.h>
#include <asm/unaligned.h>
#include <linux/acpi.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
@@ -19,6 +22,7 @@
#define OV8856_LINK_FREQ_180MHZ 180000000ULL
#define OV8856_SCLK 144000000ULL
#define OV8856_MCLK 19200000
+#define OV8856_XVCLK_FREQ 24000000
#define OV8856_DATA_LANES 4
#define OV8856_RGB_DEPTH 10
@@ -29,6 +33,18 @@
#define OV8856_MODE_STANDBY 0x00
#define OV8856_MODE_STREAMING 0x01
+/* define 1B module */
+#define OV8856_1B_MODULE 0x02
+
+/* otp sram register */
+#define OV8856_OTP_REG 0x700f
+#define OV8856_OTP_REG_ONE 0x3d84
+#define OV8856_OTP_REG_TWO 0x3d81
+
+/* clock register */
+#define OV8856_CLK_REG 0x3614
+#define OV8856_CLK_REG_1B_VAL 0x20
+
/* vertical-timings from sensor */
#define OV8856_REG_VTS 0x380e
#define OV8856_VTS_MAX 0x7fff
@@ -64,6 +80,14 @@
#define to_ov8856(_sd) container_of(_sd, struct ov8856, sd)
+static const char * const ov8856_supply_names[] = {
+ "dovdd", /* Digital I/O power */
+ "avdd", /* Analog power */
+ "dvdd", /* Digital core power */
+};
+
+#define OV8856_NUM_SUPPLIES ARRAY_SIZE(ov8856_supply_names)
+
enum {
OV8856_LINK_FREQ_720MBPS,
OV8856_LINK_FREQ_360MBPS,
@@ -316,6 +340,208 @@ static const struct ov8856_reg mode_3280x2464_regs[] = {
{0x5e00, 0x00}
};
+static const struct ov8856_reg mode_3264x2448_regs[] = {
+ {0x0103, 0x01},
+ {0x0302, 0x3c},
+ {0x0303, 0x01},
+ {0x031e, 0x0c},
+ {0x3000, 0x00},
+ {0x300e, 0x00},
+ {0x3010, 0x00},
+ {0x3015, 0x84},
+ {0x3018, 0x72},
+ {0x3021, 0x23},
+ {0x3033, 0x24},
+ {0x3500, 0x00},
+ {0x3501, 0x9a},
+ {0x3502, 0x20},
+ {0x3503, 0x08},
+ {0x3505, 0x83},
+ {0x3508, 0x01},
+ {0x3509, 0x80},
+ {0x350c, 0x00},
+ {0x350d, 0x80},
+ {0x350e, 0x04},
+ {0x350f, 0x00},
+ {0x3510, 0x00},
+ {0x3511, 0x02},
+ {0x3512, 0x00},
+ {0x3600, 0x72},
+ {0x3601, 0x40},
+ {0x3602, 0x30},
+ {0x3610, 0xc5},
+ {0x3611, 0x58},
+ {0x3612, 0x5c},
+ {0x3613, 0xca},
+ {0x3614, 0x60},
+ {0x3628, 0xff},
+ {0x3629, 0xff},
+ {0x362a, 0xff},
+ {0x3633, 0x10},
+ {0x3634, 0x10},
+ {0x3635, 0x10},
+ {0x3636, 0x10},
+ {0x3663, 0x08},
+ {0x3669, 0x34},
+ {0x366d, 0x00},
+ {0x366e, 0x10},
+ {0x3706, 0x86},
+ {0x370b, 0x7e},
+ {0x3714, 0x23},
+ {0x3730, 0x12},
+ {0x3733, 0x10},
+ {0x3764, 0x00},
+ {0x3765, 0x00},
+ {0x3769, 0x62},
+ {0x376a, 0x2a},
+ {0x376b, 0x30},
+ {0x3780, 0x00},
+ {0x3781, 0x24},
+ {0x3782, 0x00},
+ {0x3783, 0x23},
+ {0x3798, 0x2f},
+ {0x37a1, 0x60},
+ {0x37a8, 0x6a},
+ {0x37ab, 0x3f},
+ {0x37c2, 0x04},
+ {0x37c3, 0xf1},
+ {0x37c9, 0x80},
+ {0x37cb, 0x16},
+ {0x37cc, 0x16},
+ {0x37cd, 0x16},
+ {0x37ce, 0x16},
+ {0x3800, 0x00},
+ {0x3801, 0x00},
+ {0x3802, 0x00},
+ {0x3803, 0x0c},
+ {0x3804, 0x0c},
+ {0x3805, 0xdf},
+ {0x3806, 0x09},
+ {0x3807, 0xa3},
+ {0x3808, 0x0c},
+ {0x3809, 0xc0},
+ {0x380a, 0x09},
+ {0x380b, 0x90},
+ {0x380c, 0x07},
+ {0x380d, 0x8c},
+ {0x380e, 0x09},
+ {0x380f, 0xb2},
+ {0x3810, 0x00},
+ {0x3811, 0x04},
+ {0x3812, 0x00},
+ {0x3813, 0x02},
+ {0x3814, 0x01},
+ {0x3815, 0x01},
+ {0x3816, 0x00},
+ {0x3817, 0x00},
+ {0x3818, 0x00},
+ {0x3819, 0x00},
+ {0x3820, 0x80},
+ {0x3821, 0x46},
+ {0x382a, 0x01},
+ {0x382b, 0x01},
+ {0x3830, 0x06},
+ {0x3836, 0x02},
+ {0x3862, 0x04},
+ {0x3863, 0x08},
+ {0x3cc0, 0x33},
+ {0x3d85, 0x17},
+ {0x3d8c, 0x73},
+ {0x3d8d, 0xde},
+ {0x4001, 0xe0},
+ {0x4003, 0x40},
+ {0x4008, 0x00},
+ {0x4009, 0x0b},
+ {0x400a, 0x00},
+ {0x400b, 0x84},
+ {0x400f, 0x80},
+ {0x4010, 0xf0},
+ {0x4011, 0xff},
+ {0x4012, 0x02},
+ {0x4013, 0x01},
+ {0x4014, 0x01},
+ {0x4015, 0x01},
+ {0x4042, 0x00},
+ {0x4043, 0x80},
+ {0x4044, 0x00},
+ {0x4045, 0x80},
+ {0x4046, 0x00},
+ {0x4047, 0x80},
+ {0x4048, 0x00},
+ {0x4049, 0x80},
+ {0x4041, 0x03},
+ {0x404c, 0x20},
+ {0x404d, 0x00},
+ {0x404e, 0x20},
+ {0x4203, 0x80},
+ {0x4307, 0x30},
+ {0x4317, 0x00},
+ {0x4502, 0x50},
+ {0x4503, 0x08},
+ {0x4601, 0x80},
+ {0x4800, 0x44},
+ {0x4816, 0x53},
+ {0x481b, 0x50},
+ {0x481f, 0x27},
+ {0x4823, 0x3c},
+ {0x482b, 0x00},
+ {0x4831, 0x66},
+ {0x4837, 0x16},
+ {0x483c, 0x0f},
+ {0x484b, 0x05},
+ {0x5000, 0x77},
+ {0x5001, 0x0a},
+ {0x5003, 0xc8},
+ {0x5004, 0x04},
+ {0x5006, 0x00},
+ {0x5007, 0x00},
+ {0x502e, 0x03},
+ {0x5030, 0x41},
+ {0x5780, 0x14},
+ {0x5781, 0x0f},
+ {0x5782, 0x44},
+ {0x5783, 0x02},
+ {0x5784, 0x01},
+ {0x5785, 0x01},
+ {0x5786, 0x00},
+ {0x5787, 0x04},
+ {0x5788, 0x02},
+ {0x5789, 0x0f},
+ {0x578a, 0xfd},
+ {0x578b, 0xf5},
+ {0x578c, 0xf5},
+ {0x578d, 0x03},
+ {0x578e, 0x08},
+ {0x578f, 0x0c},
+ {0x5790, 0x08},
+ {0x5791, 0x04},
+ {0x5792, 0x00},
+ {0x5793, 0x52},
+ {0x5794, 0xa3},
+ {0x5795, 0x02},
+ {0x5796, 0x20},
+ {0x5797, 0x20},
+ {0x5798, 0xd5},
+ {0x5799, 0xd5},
+ {0x579a, 0x00},
+ {0x579b, 0x50},
+ {0x579c, 0x00},
+ {0x579d, 0x2c},
+ {0x579e, 0x0c},
+ {0x579f, 0x40},
+ {0x57a0, 0x09},
+ {0x57a1, 0x40},
+ {0x59f8, 0x3d},
+ {0x5a08, 0x02},
+ {0x5b00, 0x02},
+ {0x5b01, 0x10},
+ {0x5b02, 0x03},
+ {0x5b03, 0xcf},
+ {0x5b05, 0x6c},
+ {0x5e00, 0x00},
+ {0x5e10, 0xfc}
+};
+
static const struct ov8856_reg mode_1640x1232_regs[] = {
{0x3000, 0x20},
{0x3003, 0x08},
@@ -506,6 +732,208 @@ static const struct ov8856_reg mode_1640x1232_regs[] = {
{0x5e00, 0x00}
};
+static const struct ov8856_reg mode_1632x1224_regs[] = {
+ {0x0103, 0x01},
+ {0x0302, 0x3c},
+ {0x0303, 0x01},
+ {0x031e, 0x0c},
+ {0x3000, 0x00},
+ {0x300e, 0x00},
+ {0x3010, 0x00},
+ {0x3015, 0x84},
+ {0x3018, 0x72},
+ {0x3021, 0x23},
+ {0x3033, 0x24},
+ {0x3500, 0x00},
+ {0x3501, 0x4c},
+ {0x3502, 0xe0},
+ {0x3503, 0x08},
+ {0x3505, 0x83},
+ {0x3508, 0x01},
+ {0x3509, 0x80},
+ {0x350c, 0x00},
+ {0x350d, 0x80},
+ {0x350e, 0x04},
+ {0x350f, 0x00},
+ {0x3510, 0x00},
+ {0x3511, 0x02},
+ {0x3512, 0x00},
+ {0x3600, 0x72},
+ {0x3601, 0x40},
+ {0x3602, 0x30},
+ {0x3610, 0xc5},
+ {0x3611, 0x58},
+ {0x3612, 0x5c},
+ {0x3613, 0xca},
+ {0x3614, 0x60},
+ {0x3628, 0xff},
+ {0x3629, 0xff},
+ {0x362a, 0xff},
+ {0x3633, 0x10},
+ {0x3634, 0x10},
+ {0x3635, 0x10},
+ {0x3636, 0x10},
+ {0x3663, 0x08},
+ {0x3669, 0x34},
+ {0x366d, 0x00},
+ {0x366e, 0x08},
+ {0x3706, 0x86},
+ {0x370b, 0x7e},
+ {0x3714, 0x27},
+ {0x3730, 0x12},
+ {0x3733, 0x10},
+ {0x3764, 0x00},
+ {0x3765, 0x00},
+ {0x3769, 0x62},
+ {0x376a, 0x2a},
+ {0x376b, 0x30},
+ {0x3780, 0x00},
+ {0x3781, 0x24},
+ {0x3782, 0x00},
+ {0x3783, 0x23},
+ {0x3798, 0x2f},
+ {0x37a1, 0x60},
+ {0x37a8, 0x6a},
+ {0x37ab, 0x3f},
+ {0x37c2, 0x14},
+ {0x37c3, 0xf1},
+ {0x37c9, 0x80},
+ {0x37cb, 0x16},
+ {0x37cc, 0x16},
+ {0x37cd, 0x16},
+ {0x37ce, 0x16},
+ {0x3800, 0x00},
+ {0x3801, 0x00},
+ {0x3802, 0x00},
+ {0x3803, 0x0c},
+ {0x3804, 0x0c},
+ {0x3805, 0xdf},
+ {0x3806, 0x09},
+ {0x3807, 0xa3},
+ {0x3808, 0x06},
+ {0x3809, 0x60},
+ {0x380a, 0x04},
+ {0x380b, 0xc8},
+ {0x380c, 0x07},
+ {0x380d, 0x8c},
+ {0x380e, 0x09},
+ {0x380f, 0xb2},
+ {0x3810, 0x00},
+ {0x3811, 0x02},
+ {0x3812, 0x00},
+ {0x3813, 0x02},
+ {0x3814, 0x03},
+ {0x3815, 0x01},
+ {0x3816, 0x00},
+ {0x3817, 0x00},
+ {0x3818, 0x00},
+ {0x3819, 0x00},
+ {0x3820, 0x80},
+ {0x3821, 0x47},
+ {0x382a, 0x03},
+ {0x382b, 0x01},
+ {0x3830, 0x06},
+ {0x3836, 0x02},
+ {0x3862, 0x04},
+ {0x3863, 0x08},
+ {0x3cc0, 0x33},
+ {0x3d85, 0x17},
+ {0x3d8c, 0x73},
+ {0x3d8d, 0xde},
+ {0x4001, 0xe0},
+ {0x4003, 0x40},
+ {0x4008, 0x00},
+ {0x4009, 0x05},
+ {0x400a, 0x00},
+ {0x400b, 0x84},
+ {0x400f, 0x80},
+ {0x4010, 0xf0},
+ {0x4011, 0xff},
+ {0x4012, 0x02},
+ {0x4013, 0x01},
+ {0x4014, 0x01},
+ {0x4015, 0x01},
+ {0x4042, 0x00},
+ {0x4043, 0x80},
+ {0x4044, 0x00},
+ {0x4045, 0x80},
+ {0x4046, 0x00},
+ {0x4047, 0x80},
+ {0x4048, 0x00},
+ {0x4049, 0x80},
+ {0x4041, 0x03},
+ {0x404c, 0x20},
+ {0x404d, 0x00},
+ {0x404e, 0x20},
+ {0x4203, 0x80},
+ {0x4307, 0x30},
+ {0x4317, 0x00},
+ {0x4502, 0x50},
+ {0x4503, 0x08},
+ {0x4601, 0x80},
+ {0x4800, 0x44},
+ {0x4816, 0x53},
+ {0x481b, 0x50},
+ {0x481f, 0x27},
+ {0x4823, 0x3c},
+ {0x482b, 0x00},
+ {0x4831, 0x66},
+ {0x4837, 0x16},
+ {0x483c, 0x0f},
+ {0x484b, 0x05},
+ {0x5000, 0x77},
+ {0x5001, 0x0a},
+ {0x5003, 0xc8},
+ {0x5004, 0x04},
+ {0x5006, 0x00},
+ {0x5007, 0x00},
+ {0x502e, 0x03},
+ {0x5030, 0x41},
+ {0x5795, 0x00},
+ {0x5796, 0x10},
+ {0x5797, 0x10},
+ {0x5798, 0x73},
+ {0x5799, 0x73},
+ {0x579a, 0x00},
+ {0x579b, 0x28},
+ {0x579c, 0x00},
+ {0x579d, 0x16},
+ {0x579e, 0x06},
+ {0x579f, 0x20},
+ {0x57a0, 0x04},
+ {0x57a1, 0xa0},
+ {0x5780, 0x14},
+ {0x5781, 0x0f},
+ {0x5782, 0x44},
+ {0x5783, 0x02},
+ {0x5784, 0x01},
+ {0x5785, 0x01},
+ {0x5786, 0x00},
+ {0x5787, 0x04},
+ {0x5788, 0x02},
+ {0x5789, 0x0f},
+ {0x578a, 0xfd},
+ {0x578b, 0xf5},
+ {0x578c, 0xf5},
+ {0x578d, 0x03},
+ {0x578e, 0x08},
+ {0x578f, 0x0c},
+ {0x5790, 0x08},
+ {0x5791, 0x04},
+ {0x5792, 0x00},
+ {0x5793, 0x52},
+ {0x5794, 0xa3},
+ {0x59f8, 0x3d},
+ {0x5a08, 0x02},
+ {0x5b00, 0x02},
+ {0x5b01, 0x10},
+ {0x5b02, 0x03},
+ {0x5b03, 0xcf},
+ {0x5b05, 0x6c},
+ {0x5e00, 0x00},
+ {0x5e10, 0xfc}
+};
+
static const char * const ov8856_test_pattern_menu[] = {
"Disabled",
"Standard Color Bar",
@@ -548,6 +976,18 @@ static const struct ov8856_mode supported_modes[] = {
.link_freq_index = OV8856_LINK_FREQ_720MBPS,
},
{
+ .width = 3264,
+ .height = 2448,
+ .hts = 1932,
+ .vts_def = 2482,
+ .vts_min = 2482,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_3264x2448_regs),
+ .regs = mode_3264x2448_regs,
+ },
+ .link_freq_index = OV8856_LINK_FREQ_720MBPS,
+ },
+ {
.width = 1640,
.height = 1232,
.hts = 3820,
@@ -558,6 +998,18 @@ static const struct ov8856_mode supported_modes[] = {
.regs = mode_1640x1232_regs,
},
.link_freq_index = OV8856_LINK_FREQ_360MBPS,
+ },
+ {
+ .width = 1632,
+ .height = 1224,
+ .hts = 1932,
+ .vts_def = 2482,
+ .vts_min = 2482,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1632x1224_regs),
+ .regs = mode_1632x1224_regs,
+ },
+ .link_freq_index = OV8856_LINK_FREQ_360MBPS,
}
};
@@ -566,6 +1018,10 @@ struct ov8856 {
struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
+ struct clk *xvclk;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[OV8856_NUM_SUPPLIES];
+
/* V4L2 Controls */
struct v4l2_ctrl *link_freq;
struct v4l2_ctrl *pixel_rate;
@@ -576,6 +1032,9 @@ struct ov8856 {
/* Current mode */
const struct ov8856_mode *cur_mode;
+ /* module hardware version */
+ bool is_1B_module;
+
/* To serialize asynchronus callbacks */
struct mutex mutex;
@@ -696,6 +1155,24 @@ static int ov8856_test_pattern(struct ov8856 *ov8856, u32 pattern)
OV8856_REG_VALUE_08BIT, pattern);
}
+static int ov8856_update_otp_reg(struct ov8856 *ov8856)
+{
+ int ret;
+
+ ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
+ OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING);
+ if (ret)
+ return ret;
+
+ ret = ov8856_write_reg(ov8856, OV8856_OTP_REG_ONE,
+ OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY);
+ if (ret)
+ return ret;
+
+ return ov8856_write_reg(ov8856, OV8856_OTP_REG_TWO,
+ OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING);
+}
+
static int ov8856_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct ov8856 *ov8856 = container_of(ctrl->handler,
@@ -825,7 +1302,13 @@ static void ov8856_update_pad_format(const struct ov8856_mode *mode,
{
fmt->width = mode->width;
fmt->height = mode->height;
- fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+
+ /* Bayer Order is determined by image resolution */
+ if (fmt->width == 3264 || fmt->width == 1632)
+ fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ else
+ fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+
fmt->field = V4L2_FIELD_NONE;
}
@@ -850,6 +1333,17 @@ static int ov8856_start_streaming(struct ov8856 *ov8856)
return ret;
}
+ /* update R3614 for 1B module */
+ if (ov8856->is_1B_module) {
+ ret = ov8856_write_reg(ov8856, OV8856_CLK_REG,
+ OV8856_REG_VALUE_08BIT,
+ OV8856_CLK_REG_1B_VAL);
+ if (ret) {
+ dev_err(&client->dev, "failed to set R3614");
+ return ret;
+ }
+ }
+
ret = __v4l2_ctrl_handler_setup(ov8856->sd.ctrl_handler);
if (ret)
return ret;
@@ -882,6 +1376,8 @@ static int ov8856_set_stream(struct v4l2_subdev *sd, int enable)
if (ov8856->streaming == enable)
return 0;
+ dev_dbg(&client->dev, "hardware version: (%d)\n", ov8856->is_1B_module);
+
mutex_lock(&ov8856->mutex);
if (enable) {
ret = pm_runtime_get_sync(&client->dev);
@@ -908,6 +1404,54 @@ static int ov8856_set_stream(struct v4l2_subdev *sd, int enable)
return ret;
}
+/* Calculate the delay in us by clock rate and clock cycles */
+static inline u32 ov8856_cal_delay(u32 cycles)
+{
+ return DIV_ROUND_UP(cycles, OV8856_XVCLK_FREQ / 1000 / 1000);
+}
+
+static int __ov8856_power_on(struct ov8856 *ov8856)
+{
+ int ret;
+ u32 delay_us;
+ struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd);
+
+ ret = clk_prepare_enable(ov8856->xvclk);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to enable xvclk\n");
+ return ret;
+ }
+
+ gpiod_set_value_cansleep(ov8856->reset_gpio, 1);
+
+ ret = regulator_bulk_enable(OV8856_NUM_SUPPLIES, ov8856->supplies);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to enable regulators\n");
+ goto disable_clk;
+ }
+
+ gpiod_set_value_cansleep(ov8856->reset_gpio, 0);
+
+ /* 8192 cycles prior to first SCCB transaction */
+ delay_us = ov8856_cal_delay(8192);
+ usleep_range(delay_us * 2, delay_us * 4);
+
+ return 0;
+
+disable_clk:
+ clk_disable_unprepare(ov8856->xvclk);
+
+ return ret;
+}
+
+static void __ov8856_power_off(struct ov8856 *ov8856)
+{
+ clk_disable_unprepare(ov8856->xvclk);
+ gpiod_set_value_cansleep(ov8856->reset_gpio, 1);
+
+ regulator_bulk_disable(OV8856_NUM_SUPPLIES, ov8856->supplies);
+}
+
static int __maybe_unused ov8856_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -915,8 +1459,8 @@ static int __maybe_unused ov8856_suspend(struct device *dev)
struct ov8856 *ov8856 = to_ov8856(sd);
mutex_lock(&ov8856->mutex);
- if (ov8856->streaming)
- ov8856_stop_streaming(ov8856);
+
+ __ov8856_power_off(ov8856);
mutex_unlock(&ov8856->mutex);
@@ -1089,6 +1633,20 @@ static int ov8856_identify_module(struct ov8856 *ov8856)
return -ENXIO;
}
+ /* set R3614 to distinguish harward versions */
+ ret = ov8856_update_otp_reg(ov8856);
+ if (ret) {
+ dev_err(&client->dev, "failed to set otp register");
+ return ret;
+ }
+
+ ret = ov8856_read_reg(ov8856, OV8856_OTP_REG,
+ OV8856_REG_VALUE_08BIT, &val);
+ if (ret)
+ return ret;
+
+ ov8856->is_1B_module = (val == OV8856_1B_MODULE) ? 1 : 0;
+
return 0;
}
@@ -1164,11 +1722,27 @@ static int ov8856_remove(struct i2c_client *client)
media_entity_cleanup(&sd->entity);
v4l2_ctrl_handler_free(sd->ctrl_handler);
pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev))
+ __ov8856_power_off(ov8856);
+ pm_runtime_set_suspended(&client->dev);
mutex_destroy(&ov8856->mutex);
return 0;
}
+static int ov8856_configure_regulators(struct ov8856 *ov8856)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd);
+ int i;
+
+ for (i = 0; i < OV8856_NUM_SUPPLIES; i++)
+ ov8856->supplies[i].supply = ov8856_supply_names[i];
+
+ return devm_regulator_bulk_get(&client->dev,
+ OV8856_NUM_SUPPLIES,
+ ov8856->supplies);
+}
+
static int ov8856_probe(struct i2c_client *client)
{
struct ov8856 *ov8856;
@@ -1186,6 +1760,40 @@ static int ov8856_probe(struct i2c_client *client)
return -ENOMEM;
v4l2_i2c_subdev_init(&ov8856->sd, client, &ov8856_subdev_ops);
+
+ ov8856->xvclk = devm_clk_get(&client->dev, "xvclk");
+ if (IS_ERR(ov8856->xvclk)) {
+ dev_err(&client->dev, "Failed to get xvclk\n");
+ return -EINVAL;
+ }
+
+ ret = clk_set_rate(ov8856->xvclk, OV8856_XVCLK_FREQ);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to set xvclk rate (24MHz)\n");
+ return ret;
+ }
+ if (clk_get_rate(ov8856->xvclk) != OV8856_XVCLK_FREQ)
+ dev_warn(&client->dev,
+ "xvclk mismatched, modes are based on 24MHz\n");
+
+ ov8856->reset_gpio = devm_gpiod_get(&client->dev,
+ "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ov8856->reset_gpio)) {
+ dev_err(&client->dev, "Failed to get reset-gpios\n");
+ return -EINVAL;
+ }
+
+ ret = ov8856_configure_regulators(ov8856);
+ if (ret) {
+ dev_err(&client->dev, "Failed to get power regulators\n");
+ return ret;
+ }
+
+ ret = __ov8856_power_on(ov8856);
+ if (ret)
+ goto probe_error_v4l2_ctrl_handler_free;
+
ret = ov8856_identify_module(ov8856);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
@@ -1251,11 +1859,21 @@ static const struct acpi_device_id ov8856_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, ov8856_acpi_ids);
#endif
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id ov8856_of_match[] = {
+ { .compatible = "ovti,ov8856" },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, ov8856_of_match);
+#endif
+
static struct i2c_driver ov8856_i2c_driver = {
.driver = {
.name = "ov8856",
.pm = &ov8856_pm_ops,
.acpi_match_table = ACPI_PTR(ov8856_acpi_ids),
+ .of_match_table = of_match_ptr(ov8856_of_match),
},
.probe_new = ov8856_probe,
.remove = ov8856_remove,
--
2.9.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [V1, 1/2] media: dt-bindings: media: i2c: Add bindings for ov8856
From: dongchun.zhu @ 2019-08-08 9:22 UTC (permalink / raw)
To: mchehab, robh+dt, mark.rutland, sakari.ailus, drinkcat, tfiga,
matthias.bgg, bingbu.cao
Cc: devicetree, srv_heupstream, shengnan.wang, sj.huang,
linux-mediatek, dongchun.zhu, louis.kuo, linux-arm-kernel,
linux-media
In-Reply-To: <20190808092215.5608-1-dongchun.zhu@mediatek.com>
From: Dongchun Zhu <dongchun.zhu@mediatek.com>
Add device tree binding documentation for the ov8856 camera sensor.
Signed-off-by: Dongchun Zhu <dongchun.zhu@mediatek.com>
---
.../devicetree/bindings/media/i2c/ov8856.txt | 41 ++++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 42 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/ov8856.txt
diff --git a/Documentation/devicetree/bindings/media/i2c/ov8856.txt b/Documentation/devicetree/bindings/media/i2c/ov8856.txt
new file mode 100644
index 0000000..96b10e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ov8856.txt
@@ -0,0 +1,41 @@
+* Omnivision OV8856 MIPI CSI-2 sensor
+
+Required Properties:
+- compatible: shall be "ovti,ov8856"
+- clocks: reference to the xvclk input clock
+- clock-names: shall be "xvclk"
+- avdd-supply: Analog voltage supply, 2.8 volts
+- dovdd-supply: Digital I/O voltage supply, 1.8 volts
+- dvdd-supply: Digital core voltage supply, 1.2 volts
+- reset-gpios: Low active reset gpio
+
+The device node shall contain one 'port' child node with an
+'endpoint' subnode for its digital output video port,
+in accordance with the video interface bindings defined in
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+The endpoint optional property 'data-lanes' shall be "<0 1 3 4>".
+
+Example:
+&i2c7 {
+ ov8856: camera-sensor@10 {
+ compatible = "ovti,ov8856";
+ reg = <0x10>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&clk_24m_cam>;
+
+ clocks = <&cru SCLK_TESTCLKOUT1>;
+ clock-names = "xvclk";
+
+ avdd-supply = <&mt6358_vcama2_reg>;
+ dvdd-supply = <&mt6358_vcamd_reg>;
+ dovdd-supply = <&mt6358_vcamio_reg>;
+ reset-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+
+ port {
+ wcam_out: endpoint {
+ remote-endpoint = <&mipi_in_wcam>;
+ data-lanes = <0 1 3 4>;
+ };
+ };
+ };
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 783569e..7746c6b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11889,6 +11889,7 @@ L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/i2c/ov8856.c
+F: Documentation/devicetree/bindings/media/i2c/ov8856.txt
OMNIVISION OV9650 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
--
2.9.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [V1, 0/2] media: ov8856: DT bindings and sensor mode improvements
From: dongchun.zhu @ 2019-08-08 9:22 UTC (permalink / raw)
To: mchehab, robh+dt, mark.rutland, sakari.ailus, drinkcat, tfiga,
matthias.bgg, bingbu.cao
Cc: devicetree, srv_heupstream, shengnan.wang, sj.huang,
linux-mediatek, dongchun.zhu, louis.kuo, linux-arm-kernel,
linux-media
From: Dongchun Zhu <dongchun.zhu@mediatek.com>
Hello,
This series adds DT bindings and some more sensor modes for users to use.
From the latest ov8856 datasheet, it is proposed to adopt the resolution of 1632*1224 and 3264*2448,
together with Bayer Order of BGGR. Thus here we provide two more scenarios.
In addition, the hardware version of ov8856 is also distinguished from one OTP SRAM register R700F.
PLL register R3614 requires to be correspondingly updated.
For instance, 0x20 is suggested for 1B camera module.
It is emphasized that I2C still actives while device is to runtime suspended.
This makes ov8856_suspend function need to remove the operation of stoping streaming.
Finally, ARM and device tree matching were added as an alternative.
Dongchun Zhu (2):
media: dt-bindings: media: i2c: Add bindings for OV8856
media: i2c: Add more sensor mode for OV8856 camera sensor
.../devicetree/bindings/media/i2c/ov8856.txt | 41 ++
MAINTAINERS | 1 +
drivers/media/i2c/ov8856.c | 624 ++++++++++++++++++++-
3 files changed, 663 insertions(+), 3 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/i2c/ov8856.txt
--
2.9.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] arm64: Clarify when cpu_enable() is called
From: Suzuki K Poulose @ 2019-08-08 9:20 UTC (permalink / raw)
To: will, broonie; +Cc: catalin.marinas, linux-arm-kernel
In-Reply-To: <20190807160107.fpanxo4iimhg743c@willie-the-truck>
On 07/08/2019 17:01, Will Deacon wrote:
> [+Suzuki]
>
> On Tue, Aug 06, 2019 at 06:00:43PM +0100, Mark Brown wrote:
>> Strengthen the wording in the documentation for cpu_enable() to make it
>> more obvious to readers not already familiar with the code when the core
>> will call this callback and that this is intentional.
>>
>> Signed-off-by: Mark Brown <broonie@kernel.org>
>> ---
>> arch/arm64/include/asm/cpufeature.h | 6 +++---
>> 1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index cf65a47ee6b4..3d8afcf687d9 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -289,9 +289,9 @@ struct arm64_cpu_capabilities {
>> u16 type;
>> bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
>> /*
>> - * Take the appropriate actions to enable this capability for this CPU.
>> - * For each successfully booted CPU, this method is called for each
>> - * globally detected capability.
>> + * Take the appropriate actions to configure this capability for this
>> + * CPU. This will be called on all CPUs in the system if the
>> + * capability is detected anywhere in the system.
>> */
>> void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
>> union {
>
> That's not quite right though either, is it? We need to take into account
> the scope of the capability/erratum as well,
Exactly. Each capability is detected based on the "SCOPE" of the capability.
So, the above statement is clearly misleading (i.e, mentioning the case for the
LOCAL_CPU scope capabilities) and is wrong for SYSTEM scope. For that matter,
one should not talk about the "where" it is detected, as long as he understands
the "scope" of the capability.
since we don't /always/ call
> this function for everybody.
>
> Suzuki, are there any cases where ->cpu_enable() may be called on a CPU
> without the feature outside of ARM64_CPUCAP_LOCAL_CPU_ERRATUM or
> ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE?
The callback can be issued for any "capability" with LOCAL_CPU scope, provided
the capability is detected before the system finalizes the list. So, it applies
for both the above and the ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE.
Cheers
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v6 11/14] mips: Adjust brk randomization offset to fit generic version
From: Sergei Shtylyov @ 2019-08-08 9:19 UTC (permalink / raw)
To: Alexandre Ghiti, Andrew Morton
Cc: Albert Ou, Kees Cook, linux-mm, Catalin Marinas, Palmer Dabbelt,
Will Deacon, Russell King, Ralf Baechle, linux-kernel,
linux-fsdevel, Luis Chamberlain, Paul Burton, Paul Walmsley,
James Hogan, linux-riscv, linux-mips, Christoph Hellwig,
linux-arm-kernel, Alexander Viro
In-Reply-To: <20190808061756.19712-12-alex@ghiti.fr>
Hello!
On 08.08.2019 9:17, Alexandre Ghiti wrote:
> This commit simply bumps up to 32MB and 1GB the random offset
> of brk, compared to 8MB and 256MB, for 32bit and 64bit respectively.
>
> Suggested-by: Kees Cook <keescook@chromium.org>
> Signed-off-by: Alexandre Ghiti <alex@ghiti.fr>
> Acked-by: Paul Burton <paul.burton@mips.com>
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
> ---
> arch/mips/mm/mmap.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
> index a7e84b2e71d7..ff6ab87e9c56 100644
> --- a/arch/mips/mm/mmap.c
> +++ b/arch/mips/mm/mmap.c
[...]
> @@ -189,11 +190,11 @@ static inline unsigned long brk_rnd(void)
> unsigned long rnd = get_random_long();
>
> rnd = rnd << PAGE_SHIFT;
> - /* 8MB for 32bit, 256MB for 64bit */
> + /* 32MB for 32bit, 1GB for 64bit */
> if (TASK_IS_32BIT_ADDR)
> - rnd = rnd & 0x7ffffful;
> + rnd = rnd & (SZ_32M - 1);
> else
> - rnd = rnd & 0xffffffful;
> + rnd = rnd & (SZ_1G - 1);
Why not make these 'rnd &= SZ_* - 1', while at it anyways?
[...]
MBR, Sergei
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 2/2] ARM: zynq: Use memcpy_toio instead of memcpy on smp bring-up
From: Michal Simek @ 2019-08-08 9:19 UTC (permalink / raw)
To: Luis Araneda, Michal Simek; +Cc: Russell King, linux-arm-kernel, linux-kernel
In-Reply-To: <CAHbBuxpM8YKxADGJv2PAPbyS-2FZ6xiwohJwGJ1DMPuGnDV-Jg@mail.gmail.com>
[-- Attachment #1.1.1: Type: text/plain, Size: 1491 bytes --]
On 06. 08. 19 14:49, Luis Araneda wrote:
> Hi Michal,
>
> On Tue, Aug 6, 2019 at 2:42 AM Michal Simek <michal.simek@xilinx.com> wrote:
>> On 06. 08. 19 5:07, Luis Araneda wrote:
>>> This fixes a kernel panic (read overflow) on memcpy when
>>> FORTIFY_SOURCE is enabled.
>>>
>>> The computed size of memcpy args are:
>>> - p_size (dst): 4294967295 = (size_t) -1
>>> - q_size (src): 1
>>> - size (len): 8
>>>
>>> Additionally, the memory is marked as __iomem, so one of
>>> the memcpy_* functions should be used for read/write
>>>
>>> Signed-off-by: Luis Araneda <luaraneda@gmail.com>
> [...]
>> I would consider this one as stable material. Please also add there link
>> to the patch which this patch fixes.
>
> I'm dropping stable CC (for now), as I'm not sure I completely
> understood the process for inclusion in stable trees.
> Do I have to wait for the patch to be on Linus' tree before CCing stable?
just put Cc: to commit message and they will pick it up.
>
> As for the link which this patch fixes, you mean
> aa7eb2bb4e4a22e41bbe4612ff46e5885b13c33e (arm: zynq: Add smp support)?
> where you added SMP support for zynq.
yes but make sha1 only 12char long.
M
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/2] ARM: zynq: support smp in thumb mode
From: Michal Simek @ 2019-08-08 9:18 UTC (permalink / raw)
To: Luis Araneda, Michal Simek; +Cc: Russell King, linux-arm-kernel, linux-kernel
In-Reply-To: <CAHbBuxosAnWdpee8jS7feR06+KF_PjOiTF2+PsiMnMAjwfUFKw@mail.gmail.com>
[-- Attachment #1.1.1: Type: text/plain, Size: 1311 bytes --]
On 06. 08. 19 14:40, Luis Araneda wrote:
> Hi,
>
> On Tue, Aug 6, 2019 at 2:39 AM Michal Simek <michal.simek@xilinx.com> wrote:
>>
>> On 06. 08. 19 5:07, Luis Araneda wrote:
>>> Add .arm directive to headsmp.S to ensure that the
>>> CPU starts in 32-bit ARM mode and the correct code
>>> size is copied on smp bring-up
>>>
>>> Additionally, start secondary CPUs on secondary_startup_arm
>>> to automatically switch from ARM to thumb on a thumb kernel
> [...]
>>
>> It is really a question if this should go to stable tree. It is pretty
>> much new feature.
>> Will be good to also add link to similar patch for example this one
>> 5616f36713ea77f57ae908bf2fef641364403c9f.
>
> Ok, I'm dropping stable from CC. From the previous comments, I thought
> that the two patches were part of the same fix, but now I realized
> this is a feature rather than a fix.
>
> Michal, do you want a new version with the link to the similar patch
> or would you take it in its current form?
new version please.
M
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 0/9] ARM: davinci: da850-evm: remove more legacy GPIO calls
From: Sekhar Nori @ 2019-08-08 9:16 UTC (permalink / raw)
To: Bartosz Golaszewski, Kevin Hilman, Bartlomiej Zolnierkiewicz,
David Lechner, Linus Walleij
Cc: Bartosz Golaszewski, linux-fbdev, Linux Kernel Mailing List,
Linux ARM
In-Reply-To: <CAMRc=Me51RgQu8VK70dy=1OhmHeKo40HLxfsvp2nD5UC+Mzb=w@mail.gmail.com>
On 05/08/19 2:00 PM, Bartosz Golaszewski wrote:
> pon., 22 lip 2019 o 15:44 Bartosz Golaszewski <brgl@bgdev.pl> napisał(a):
>>
>> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>>
>> This is another small step on the path to liberating davinci from legacy
>> GPIO API calls and shrinking the davinci GPIO driver by not having to
>> support the base GPIO number anymore.
>>
>> This time we're removing the legacy calls used indirectly by the LCDC
>> fbdev driver.
>>
>> First two patches enable the GPIO backlight driver in
>> davinci_all_defconfig.
>>
>> Patch 3/12 models the backlight GPIO as an actual GPIO backlight device.
>>
>> Patches 4-6 extend the fbdev driver with regulator support and convert
>> the da850-evm board file to using it.
>>
>> Last three patches are improvements to the da8xx fbdev driver since
>> we're already touching it in this series.
>>
>> v1 -> v2:
>> - dopped the gpio-backlight patches from this series as since v5.3-rc1 we
>> can probe the module with neither the OF node nor platform data
>> - collected review and ack tags
>> - rebased on top of v5.3-rc1
>>
>> Bartosz Golaszewski (9):
>> ARM: davinci: refresh davinci_all_defconfig
>> ARM: davinci_all_defconfig: enable GPIO backlight
>> ARM: davinci: da850-evm: model the backlight GPIO as an actual device
>> fbdev: da8xx: add support for a regulator
>> ARM: davinci: da850-evm: switch to using a fixed regulator for lcdc
>> fbdev: da8xx: remove panel_power_ctrl() callback from platform data
>> fbdev: da8xx-fb: use devm_platform_ioremap_resource()
>> fbdev: da8xx-fb: drop a redundant if
>> fbdev: da8xx: use resource management for dma
>>
>> arch/arm/configs/davinci_all_defconfig | 27 ++----
>> arch/arm/mach-davinci/board-da850-evm.c | 90 +++++++++++++-----
>> drivers/video/fbdev/da8xx-fb.c | 118 +++++++++++++-----------
>> include/video/da8xx-fb.h | 1 -
>> 4 files changed, 141 insertions(+), 95 deletions(-)
>>
>> --
>> 2.21.0
>>
>
> Hi Sekhar,
>
> the fbdev patches have been acked by Bartlomiej. I think the entire
> series can go through the ARM-SoC tree.
Applied for v5.4. Will queue through ARM-SoC.
Thanks,
Sekhar
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v6 09/14] mips: Properly account for stack randomization and stack guard gap
From: Sergei Shtylyov @ 2019-08-08 9:16 UTC (permalink / raw)
To: Alexandre Ghiti, Andrew Morton
Cc: Albert Ou, Kees Cook, linux-mm, Catalin Marinas, Palmer Dabbelt,
Will Deacon, Russell King, Ralf Baechle, linux-kernel,
linux-fsdevel, Luis Chamberlain, Paul Burton, Paul Walmsley,
James Hogan, linux-riscv, linux-mips, Christoph Hellwig,
linux-arm-kernel, Alexander Viro
In-Reply-To: <20190808061756.19712-10-alex@ghiti.fr>
Hello!
On 08.08.2019 9:17, Alexandre Ghiti wrote:
> This commit takes care of stack randomization and stack guard gap when
> computing mmap base address and checks if the task asked for randomization.
>
> This fixes the problem uncovered and not fixed for arm here:
> https://lkml.kernel.org/r/20170622200033.25714-1-riel@redhat.com
>
> Signed-off-by: Alexandre Ghiti <alex@ghiti.fr>
> Acked-by: Kees Cook <keescook@chromium.org>
> Acked-by: Paul Burton <paul.burton@mips.com>
> Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
> ---
> arch/mips/mm/mmap.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
> index d79f2b432318..f5c778113384 100644
> --- a/arch/mips/mm/mmap.c
> +++ b/arch/mips/mm/mmap.c
> @@ -21,8 +21,9 @@ unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
> EXPORT_SYMBOL(shm_align_mask);
>
> /* gap between mmap and stack */
> -#define MIN_GAP (128*1024*1024UL)
> -#define MAX_GAP ((TASK_SIZE)/6*5)
> +#define MIN_GAP (128*1024*1024UL)
> +#define MAX_GAP ((TASK_SIZE)/6*5)
Could add spaces around *, while touching this anyway? And parens
around TASK_SIZE shouldn't be needed...
> +#define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12))
>
> static int mmap_is_legacy(struct rlimit *rlim_stack)
> {
> @@ -38,6 +39,15 @@ static int mmap_is_legacy(struct rlimit *rlim_stack)
> static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack)
> {
> unsigned long gap = rlim_stack->rlim_cur;
> + unsigned long pad = stack_guard_gap;
> +
> + /* Account for stack randomization if necessary */
> + if (current->flags & PF_RANDOMIZE)
> + pad += (STACK_RND_MASK << PAGE_SHIFT);
Parens not needed here.
> +
> + /* Values close to RLIM_INFINITY can overflow. */
> + if (gap + pad > gap)
> + gap += pad;
>
> if (gap < MIN_GAP)
> gap = MIN_GAP;
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v8 05/14] media: rkisp1: add Rockchip ISP1 subdev driver
From: Sakari Ailus @ 2019-08-08 9:14 UTC (permalink / raw)
To: Helen Koike
Cc: devicetree, eddie.cai.linux, kernel, heiko, jacob2.chen,
jeffy.chen, zyc, linux-kernel, tfiga, linux-rockchip, Allon Huang,
Jacob Chen, hans.verkuil, laurent.pinchart, zhengsq, mchehab,
ezequiel, linux-arm-kernel, linux-media
In-Reply-To: <20190730184256.30338-6-helen.koike@collabora.com>
Hi Helen,
On Tue, Jul 30, 2019 at 03:42:47PM -0300, Helen Koike wrote:
> From: Jacob Chen <jacob2.chen@rock-chips.com>
>
> Add the subdev driver for rockchip isp1.
>
> Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
> Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
> Signed-off-by: Yichong Zhong <zyc@rock-chips.com>
> Signed-off-by: Jacob Chen <cc@rock-chips.com>
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
> Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
> Signed-off-by: Tomasz Figa <tfiga@chromium.org>
> [fixed unknown entity type / switched to PIXEL_RATE]
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> [update for upstream]
> Signed-off-by: Helen Koike <helen.koike@collabora.com>
>
> ---
>
> Changes in v8: None
> Changes in v7:
> - fixed warning because of unknown entity type
> - fixed v4l2-compliance errors regarding rkisp1 formats, try formats
> and default values
> - fix typo riksp1/rkisp1
> - redesign: remove mipi/csi subdevice, sensors connect directly to the
> isp subdevice in the media topology now. As a consequence, remove the
> hack in mipidphy_g_mbus_config() where information from the sensor was
> being propagated through the topology.
> - From the old dphy:
> * cache get_remote_sensor() in s_stream
> * use V4L2_CID_PIXEL_RATE instead of V4L2_CID_LINK_FREQ
> - Replace stream state with a boolean
> - code styling and checkpatch fixes
> - fix stop_stream (return after calling stop, do not reenable the stream)
> - fix rkisp1_isp_sd_get_selection when V4L2_SUBDEV_FORMAT_TRY is set
> - fix get format in output (isp_sd->out_fmt.mbus_code was being ignored)
> - s/intput/input
> - remove #define sd_to_isp_sd(_sd), add a static inline as it will be
> reused by the capture
>
> drivers/media/platform/rockchip/isp1/rkisp1.c | 1286 +++++++++++++++++
> drivers/media/platform/rockchip/isp1/rkisp1.h | 111 ++
> 2 files changed, 1397 insertions(+)
> create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.c
> create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.h
>
> diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.c b/drivers/media/platform/rockchip/isp1/rkisp1.c
> new file mode 100644
> index 000000000000..6d0c0ffb5e03
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/rkisp1.c
> @@ -0,0 +1,1286 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#include <linux/iopoll.h>
> +#include <linux/phy/phy.h>
> +#include <linux/phy/phy-mipi-dphy.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/videodev2.h>
> +#include <linux/vmalloc.h>
> +#include <media/v4l2-event.h>
> +
> +#include "common.h"
> +#include "regs.h"
> +
> +#define CIF_ISP_INPUT_W_MAX 4032
> +#define CIF_ISP_INPUT_H_MAX 3024
> +#define CIF_ISP_INPUT_W_MIN 32
> +#define CIF_ISP_INPUT_H_MIN 32
> +#define CIF_ISP_OUTPUT_W_MAX CIF_ISP_INPUT_W_MAX
> +#define CIF_ISP_OUTPUT_H_MAX CIF_ISP_INPUT_H_MAX
> +#define CIF_ISP_OUTPUT_W_MIN CIF_ISP_INPUT_W_MIN
> +#define CIF_ISP_OUTPUT_H_MIN CIF_ISP_INPUT_H_MIN
> +
> +/*
> + * NOTE: MIPI controller and input MUX are also configured in this file,
> + * because ISP Subdev is not only describe ISP submodule(input size,format,
> + * output size, format), but also a virtual route device.
> + */
> +
> +/*
> + * There are many variables named with format/frame in below code,
> + * please see here for their meaning.
> + *
> + * Cropping regions of ISP
> + *
> + * +---------------------------------------------------------+
> + * | Sensor image |
> + * | +---------------------------------------------------+ |
> + * | | ISP_ACQ (for black level) | |
> + * | | in_frm | |
> + * | | +--------------------------------------------+ | |
> + * | | | ISP_OUT | | |
> + * | | | in_crop | | |
> + * | | | +---------------------------------+ | | |
> + * | | | | ISP_IS | | | |
> + * | | | | rkisp1_isp_subdev: out_crop | | | |
> + * | | | +---------------------------------+ | | |
> + * | | +--------------------------------------------+ | |
> + * | +---------------------------------------------------+ |
> + * +---------------------------------------------------------+
> + */
> +
> +static inline struct rkisp1_device *sd_to_isp_dev(struct v4l2_subdev *sd)
> +{
> + return container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev);
> +}
> +
> +/* Get sensor by enabled media link */
> +static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
> +{
> + struct media_pad *local, *remote;
> + struct media_entity *sensor_me;
> +
> + local = &sd->entity.pads[RKISP1_ISP_PAD_SINK];
> + remote = media_entity_remote_pad(local);
> + if (!remote) {
> + v4l2_warn(sd, "No link between isp and sensor\n");
> + return NULL;
> + }
> +
> + sensor_me = media_entity_remote_pad(local)->entity;
> + return media_entity_to_v4l2_subdev(sensor_me);
> +}
> +
> +static struct rkisp1_sensor *sd_to_sensor(struct rkisp1_device *dev,
> + struct v4l2_subdev *sd)
Indentation.
> +{
> + struct rkisp1_sensor *sensor;
> +
> + list_for_each_entry(sensor, &dev->sensors, list)
> + if (sensor->sd == sd)
> + return sensor;
> +
> + return NULL;
> +}
> +
> +/**************** register operations ****************/
> +
> +/*
> + * Image Stabilization.
> + * This should only be called when configuring CIF
> + * or at the frame end interrupt
> + */
> +static void rkisp1_config_ism(struct rkisp1_device *dev)
> +{
> + void __iomem *base = dev->base_addr;
> + struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop;
> + u32 val;
> +
> + writel(0, base + CIF_ISP_IS_RECENTER);
> + writel(0, base + CIF_ISP_IS_MAX_DX);
> + writel(0, base + CIF_ISP_IS_MAX_DY);
> + writel(0, base + CIF_ISP_IS_DISPLACE);
> + writel(out_crop->left, base + CIF_ISP_IS_H_OFFS);
> + writel(out_crop->top, base + CIF_ISP_IS_V_OFFS);
> + writel(out_crop->width, base + CIF_ISP_IS_H_SIZE);
> + writel(out_crop->height, base + CIF_ISP_IS_V_SIZE);
> +
> + /* IS(Image Stabilization) is always on, working as output crop */
> + writel(1, base + CIF_ISP_IS_CTRL);
> + val = readl(base + CIF_ISP_CTRL);
> + val |= CIF_ISP_CTRL_ISP_CFG_UPD;
> + writel(val, base + CIF_ISP_CTRL);
> +}
> +
> +/*
> + * configure isp blocks with input format, size......
> + */
> +static int rkisp1_config_isp(struct rkisp1_device *dev)
> +{
> + u32 isp_ctrl = 0, irq_mask = 0, acq_mult = 0, signal = 0;
> + struct v4l2_rect *out_crop, *in_crop;
> + void __iomem *base = dev->base_addr;
> + struct v4l2_mbus_framefmt *in_frm;
> + struct ispsd_out_fmt *out_fmt;
> + struct rkisp1_sensor *sensor;
> + struct ispsd_in_fmt *in_fmt;
> +
> + sensor = dev->active_sensor;
> + in_frm = &dev->isp_sdev.in_frm;
> + in_fmt = &dev->isp_sdev.in_fmt;
> + out_fmt = &dev->isp_sdev.out_fmt;
> + out_crop = &dev->isp_sdev.out_crop;
> + in_crop = &dev->isp_sdev.in_crop;
> +
> + if (in_fmt->fmt_type == FMT_BAYER) {
> + acq_mult = 1;
> + if (out_fmt->fmt_type == FMT_BAYER) {
> + if (sensor->mbus.type == V4L2_MBUS_BT656)
> + isp_ctrl =
> + CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656;
> + else
> + isp_ctrl =
> + CIF_ISP_CTRL_ISP_MODE_RAW_PICT;
> + } else {
> + writel(CIF_ISP_DEMOSAIC_TH(0xc),
> + base + CIF_ISP_DEMOSAIC);
> +
> + if (sensor->mbus.type == V4L2_MBUS_BT656)
> + isp_ctrl = CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656;
> + else
> + isp_ctrl = CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601;
> + }
> + } else if (in_fmt->fmt_type == FMT_YUV) {
> + acq_mult = 2;
> + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
> + isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU601;
> + } else {
> + if (sensor->mbus.type == V4L2_MBUS_BT656)
> + isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU656;
> + else
> + isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU601;
> +
> + }
> +
> + irq_mask |= CIF_ISP_DATA_LOSS;
> + }
> +
> + /* Set up input acquisition properties */
> + if (sensor->mbus.type == V4L2_MBUS_BT656 ||
> + sensor->mbus.type == V4L2_MBUS_PARALLEL) {
> + if (sensor->mbus.flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
> + signal = CIF_ISP_ACQ_PROP_POS_EDGE;
> + }
> +
> + if (sensor->mbus.type == V4L2_MBUS_PARALLEL) {
> + if (sensor->mbus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
> + signal |= CIF_ISP_ACQ_PROP_VSYNC_LOW;
> +
> + if (sensor->mbus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
> + signal |= CIF_ISP_ACQ_PROP_HSYNC_LOW;
> + }
> +
> + writel(isp_ctrl, base + CIF_ISP_CTRL);
> + writel(signal | in_fmt->yuv_seq |
> + CIF_ISP_ACQ_PROP_BAYER_PAT(in_fmt->bayer_pat) |
> + CIF_ISP_ACQ_PROP_FIELD_SEL_ALL, base + CIF_ISP_ACQ_PROP);
> + writel(0, base + CIF_ISP_ACQ_NR_FRAMES);
> +
> + /* Acquisition Size */
> + writel(0, base + CIF_ISP_ACQ_H_OFFS);
> + writel(0, base + CIF_ISP_ACQ_V_OFFS);
> + writel(acq_mult * in_frm->width, base + CIF_ISP_ACQ_H_SIZE);
> + writel(in_frm->height, base + CIF_ISP_ACQ_V_SIZE);
> +
> + /* ISP Out Area */
> + writel(in_crop->left, base + CIF_ISP_OUT_H_OFFS);
> + writel(in_crop->top, base + CIF_ISP_OUT_V_OFFS);
> + writel(in_crop->width, base + CIF_ISP_OUT_H_SIZE);
> + writel(in_crop->height, base + CIF_ISP_OUT_V_SIZE);
> +
> + /* interrupt mask */
> + irq_mask |= CIF_ISP_FRAME | CIF_ISP_V_START | CIF_ISP_PIC_SIZE_ERROR |
> + CIF_ISP_FRAME_IN;
> + writel(irq_mask, base + CIF_ISP_IMSC);
> +
> + if (out_fmt->fmt_type == FMT_BAYER)
> + rkisp1_params_disable_isp(&dev->params_vdev);
> + else
> + rkisp1_params_configure_isp(&dev->params_vdev, in_fmt,
> + dev->isp_sdev.quantization);
> +
> + return 0;
> +}
> +
> +static int rkisp1_config_dvp(struct rkisp1_device *dev)
> +{
> + struct ispsd_in_fmt *in_fmt = &dev->isp_sdev.in_fmt;
> + void __iomem *base = dev->base_addr;
> + u32 val, input_sel;
> +
> + switch (in_fmt->bus_width) {
> + case 8:
> + input_sel = CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO;
> + break;
> + case 10:
> + input_sel = CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO;
> + break;
> + case 12:
> + input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
> + break;
> + default:
> + v4l2_err(&dev->v4l2_dev, "Invalid bus width\n");
> + return -EINVAL;
> + }
> +
> + val = readl(base + CIF_ISP_ACQ_PROP);
> + writel(val | input_sel, base + CIF_ISP_ACQ_PROP);
> +
> + return 0;
> +}
> +
> +static int rkisp1_config_mipi(struct rkisp1_device *dev)
> +{
> + struct ispsd_in_fmt *in_fmt = &dev->isp_sdev.in_fmt;
> + struct rkisp1_sensor *sensor = dev->active_sensor;
> + void __iomem *base = dev->base_addr;
> + unsigned int lanes;
> + u32 mipi_ctrl;
> +
> + /*
> + * sensor->mbus is set in isp or d-phy notifier_bound function
> + */
> + switch (sensor->mbus.flags & V4L2_MBUS_CSI2_LANES) {
> + case V4L2_MBUS_CSI2_4_LANE:
> + lanes = 4;
> + break;
> + case V4L2_MBUS_CSI2_3_LANE:
> + lanes = 3;
> + break;
> + case V4L2_MBUS_CSI2_2_LANE:
> + lanes = 2;
> + break;
> + case V4L2_MBUS_CSI2_1_LANE:
> + lanes = 1;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + mipi_ctrl = CIF_MIPI_CTRL_NUM_LANES(lanes - 1) |
> + CIF_MIPI_CTRL_SHUTDOWNLANES(0xf) |
> + CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP |
> + CIF_MIPI_CTRL_CLOCKLANE_ENA;
> +
> + writel(mipi_ctrl, base + CIF_MIPI_CTRL);
> +
> + /* Configure Data Type and Virtual Channel */
> + writel(CIF_MIPI_DATA_SEL_DT(in_fmt->mipi_dt) | CIF_MIPI_DATA_SEL_VC(0),
> + base + CIF_MIPI_IMG_DATA_SEL);
> +
> + /* Clear MIPI interrupts */
> + writel(~0, base + CIF_MIPI_ICR);
> + /*
> + * Disable CIF_MIPI_ERR_DPHY interrupt here temporary for
> + * isp bus may be dead when switch isp.
> + */
> + writel(CIF_MIPI_FRAME_END | CIF_MIPI_ERR_CSI | CIF_MIPI_ERR_DPHY |
> + CIF_MIPI_SYNC_FIFO_OVFLW(0x03) | CIF_MIPI_ADD_DATA_OVFLW,
> + base + CIF_MIPI_IMSC);
> +
> + v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "\n MIPI_CTRL 0x%08x\n"
> + " MIPI_IMG_DATA_SEL 0x%08x\n"
> + " MIPI_STATUS 0x%08x\n"
> + " MIPI_IMSC 0x%08x\n",
> + readl(base + CIF_MIPI_CTRL),
> + readl(base + CIF_MIPI_IMG_DATA_SEL),
> + readl(base + CIF_MIPI_STATUS),
> + readl(base + CIF_MIPI_IMSC));
> +
> + return 0;
> +}
> +
> +/* Configure MUX */
> +static int rkisp1_config_path(struct rkisp1_device *dev)
> +{
> + struct rkisp1_sensor *sensor = dev->active_sensor;
> + u32 dpcl = readl(dev->base_addr + CIF_VI_DPCL);
> + int ret = 0;
> +
> + if (sensor->mbus.type == V4L2_MBUS_BT656 ||
> + sensor->mbus.type == V4L2_MBUS_PARALLEL) {
> + ret = rkisp1_config_dvp(dev);
> + dpcl |= CIF_VI_DPCL_IF_SEL_PARALLEL;
> + } else if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
> + ret = rkisp1_config_mipi(dev);
> + dpcl |= CIF_VI_DPCL_IF_SEL_MIPI;
> + }
> +
> + writel(dpcl, dev->base_addr + CIF_VI_DPCL);
> +
> + return ret;
> +}
> +
> +/* Hareware configure Entry */
> +static int rkisp1_config_cif(struct rkisp1_device *dev)
> +{
> + u32 cif_id;
> + int ret;
> +
> + v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> + "SP streaming = %d, MP streaming = %d\n",
> + dev->stream[RKISP1_STREAM_SP].streaming,
> + dev->stream[RKISP1_STREAM_MP].streaming);
> +
> + cif_id = readl(dev->base_addr + CIF_VI_ID);
> + v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "CIF_ID 0x%08x\n", cif_id);
> +
> + ret = rkisp1_config_isp(dev);
> + if (ret < 0)
> + return ret;
> + ret = rkisp1_config_path(dev);
> + if (ret < 0)
> + return ret;
> + rkisp1_config_ism(dev);
> +
> + return 0;
> +}
> +
> +/* Mess register operations to stop isp */
> +static int rkisp1_isp_stop(struct rkisp1_device *dev)
> +{
> + void __iomem *base = dev->base_addr;
> + u32 val;
> +
> + v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> + "SP streaming = %d, MP streaming = %d\n",
> + dev->stream[RKISP1_STREAM_SP].streaming,
> + dev->stream[RKISP1_STREAM_MP].streaming);
> +
> + /*
> + * ISP(mi) stop in mi frame end -> Stop ISP(mipi) ->
> + * Stop ISP(isp) ->wait for ISP isp off
> + */
> + /* stop and clear MI, MIPI, and ISP interrupts */
> + writel(0, base + CIF_MIPI_IMSC);
> + writel(~0, base + CIF_MIPI_ICR);
> +
> + writel(0, base + CIF_ISP_IMSC);
> + writel(~0, base + CIF_ISP_ICR);
> +
> + writel(0, base + CIF_MI_IMSC);
> + writel(~0, base + CIF_MI_ICR);
> + val = readl(base + CIF_MIPI_CTRL);
> + writel(val & (~CIF_MIPI_CTRL_OUTPUT_ENA), base + CIF_MIPI_CTRL);
> + /* stop ISP */
> + val = readl(base + CIF_ISP_CTRL);
> + val &= ~(CIF_ISP_CTRL_ISP_INFORM_ENABLE | CIF_ISP_CTRL_ISP_ENABLE);
> + writel(val, base + CIF_ISP_CTRL);
> +
> + val = readl(base + CIF_ISP_CTRL);
> + writel(val | CIF_ISP_CTRL_ISP_CFG_UPD, base + CIF_ISP_CTRL);
> +
> + readx_poll_timeout(readl, base + CIF_ISP_RIS,
> + val, val & CIF_ISP_OFF, 20, 100);
> + v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> + "streaming(MP:%d, SP:%d), MI_CTRL:%x, ISP_CTRL:%x, MIPI_CTRL:%x\n",
> + dev->stream[RKISP1_STREAM_SP].streaming,
> + dev->stream[RKISP1_STREAM_MP].streaming,
> + readl(base + CIF_MI_CTRL),
> + readl(base + CIF_ISP_CTRL),
> + readl(base + CIF_MIPI_CTRL));
> +
> + writel(CIF_IRCL_MIPI_SW_RST | CIF_IRCL_ISP_SW_RST, base + CIF_IRCL);
> + writel(0x0, base + CIF_IRCL);
> +
> + return 0;
> +}
> +
> +/* Mess register operations to start isp */
> +static int rkisp1_isp_start(struct rkisp1_device *dev)
> +{
> + struct rkisp1_sensor *sensor = dev->active_sensor;
> + void __iomem *base = dev->base_addr;
> + u32 val;
> +
> + v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> + "SP streaming = %d, MP streaming = %d\n",
> + dev->stream[RKISP1_STREAM_SP].streaming,
> + dev->stream[RKISP1_STREAM_MP].streaming);
> +
> + /* Activate MIPI */
> + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
> + val = readl(base + CIF_MIPI_CTRL);
> + writel(val | CIF_MIPI_CTRL_OUTPUT_ENA, base + CIF_MIPI_CTRL);
> + }
> + /* Activate ISP */
> + val = readl(base + CIF_ISP_CTRL);
> + val |= CIF_ISP_CTRL_ISP_CFG_UPD | CIF_ISP_CTRL_ISP_ENABLE |
> + CIF_ISP_CTRL_ISP_INFORM_ENABLE;
> + writel(val, base + CIF_ISP_CTRL);
> +
> + /* XXX: Is the 1000us too long?
> + * CIF spec says to wait for sufficient time after enabling
> + * the MIPI interface and before starting the sensor output.
> + */
> + usleep_range(1000, 1200);
> +
> + v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> + "SP streaming = %d, MP streaming = %d MI_CTRL 0x%08x\n"
> + " ISP_CTRL 0x%08x MIPI_CTRL 0x%08x\n",
> + dev->stream[RKISP1_STREAM_SP].streaming,
> + dev->stream[RKISP1_STREAM_MP].streaming,
> + readl(base + CIF_MI_CTRL),
> + readl(base + CIF_ISP_CTRL),
> + readl(base + CIF_MIPI_CTRL));
> +
> + return 0;
> +}
> +
> +static void rkisp1_config_clk(struct rkisp1_device *dev)
> +{
> + u32 val = CIF_ICCL_ISP_CLK | CIF_ICCL_CP_CLK | CIF_ICCL_MRSZ_CLK |
> + CIF_ICCL_SRSZ_CLK | CIF_ICCL_JPEG_CLK | CIF_ICCL_MI_CLK |
> + CIF_ICCL_IE_CLK | CIF_ICCL_MIPI_CLK | CIF_ICCL_DCROP_CLK;
> +
> + writel(val, dev->base_addr + CIF_ICCL);
> +}
> +
> +/***************************** isp sub-devs *******************************/
> +
> +static const struct ispsd_in_fmt rkisp1_isp_input_formats[] = {
> + {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW10,
> + .bayer_pat = RAW_BGGR,
> + .bus_width = 10,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW10,
> + .bayer_pat = RAW_RGGB,
> + .bus_width = 10,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW10,
> + .bayer_pat = RAW_GBRG,
> + .bus_width = 10,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW10,
> + .bayer_pat = RAW_GRBG,
> + .bus_width = 10,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW12,
> + .bayer_pat = RAW_RGGB,
> + .bus_width = 12,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW12,
> + .bayer_pat = RAW_BGGR,
> + .bus_width = 12,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW12,
> + .bayer_pat = RAW_GBRG,
> + .bus_width = 12,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW12,
> + .bayer_pat = RAW_GRBG,
> + .bus_width = 12,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW8,
> + .bayer_pat = RAW_RGGB,
> + .bus_width = 8,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW8,
> + .bayer_pat = RAW_BGGR,
> + .bus_width = 8,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW8,
> + .bayer_pat = RAW_GBRG,
> + .bus_width = 8,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
> + .fmt_type = FMT_BAYER,
> + .mipi_dt = CIF_CSI2_DT_RAW8,
> + .bayer_pat = RAW_GRBG,
> + .bus_width = 8,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
> + .fmt_type = FMT_YUV,
> + .mipi_dt = CIF_CSI2_DT_YUV422_8b,
> + .yuv_seq = CIF_ISP_ACQ_PROP_YCBYCR,
> + .bus_width = 16,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
> + .fmt_type = FMT_YUV,
> + .mipi_dt = CIF_CSI2_DT_YUV422_8b,
> + .yuv_seq = CIF_ISP_ACQ_PROP_YCRYCB,
> + .bus_width = 16,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
> + .fmt_type = FMT_YUV,
> + .mipi_dt = CIF_CSI2_DT_YUV422_8b,
> + .yuv_seq = CIF_ISP_ACQ_PROP_CBYCRY,
> + .bus_width = 16,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
> + .fmt_type = FMT_YUV,
> + .mipi_dt = CIF_CSI2_DT_YUV422_8b,
> + .yuv_seq = CIF_ISP_ACQ_PROP_CRYCBY,
> + .bus_width = 16,
> + },
> +};
> +
> +static const struct ispsd_out_fmt rkisp1_isp_output_formats[] = {
> + {
> + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
> + .fmt_type = FMT_YUV,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
> + .fmt_type = FMT_BAYER,
> + }, {
> + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
> + .fmt_type = FMT_BAYER,
> + },
> +};
> +
> +static const struct ispsd_in_fmt *find_in_fmt(u32 mbus_code)
> +{
> + unsigned int i, array_size = ARRAY_SIZE(rkisp1_isp_input_formats);
I think it'd be nicer to just use ARRAY_SIZE(...) in the condition. Same
below.
> + const struct ispsd_in_fmt *fmt;
> +
> + for (i = 0; i < array_size; i++) {
> + fmt = &rkisp1_isp_input_formats[i];
> + if (fmt->mbus_code == mbus_code)
> + return fmt;
> + }
> +
> + return NULL;
> +}
> +
> +static const struct ispsd_out_fmt *find_out_fmt(u32 mbus_code)
> +{
> + unsigned int i, array_size = ARRAY_SIZE(rkisp1_isp_output_formats);
> + const struct ispsd_out_fmt *fmt;
> +
> + for (i = 0; i < array_size; i++) {
> + fmt = &rkisp1_isp_output_formats[i];
> + if (fmt->mbus_code == mbus_code)
> + return fmt;
> + }
> +
> + return NULL;
> +}
> +
> +static int rkisp1_isp_sd_enum_mbus_code(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_mbus_code_enum *code)
> +{
> + unsigned int i = code->index;
> +
> + if ((code->pad != RKISP1_ISP_PAD_SINK) &&
> + (code->pad != RKISP1_ISP_PAD_SOURCE_PATH)) {
> + if (i > 0)
> + return -EINVAL;
> + code->code = MEDIA_BUS_FMT_FIXED;
> + return 0;
> + }
> +
> + if (code->pad == RKISP1_ISP_PAD_SINK) {
> + if (i >= ARRAY_SIZE(rkisp1_isp_input_formats))
> + return -EINVAL;
> + code->code = rkisp1_isp_input_formats[i].mbus_code;
> + } else {
> + if (i >= ARRAY_SIZE(rkisp1_isp_output_formats))
> + return -EINVAL;
> + code->code = rkisp1_isp_output_formats[i].mbus_code;
> + }
> +
> + return 0;
> +}
> +
> +static int rkisp1_isp_sd_init_config(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg)
> +{
> + struct v4l2_rect *mf_in_crop, *mf_out_crop;
> + struct v4l2_mbus_framefmt *mf_in, *mf_out;
> +
> + mf_in = v4l2_subdev_get_try_format(sd, cfg, RKISP1_ISP_PAD_SINK);
> + mf_in->width = RKISP1_DEFAULT_WIDTH;
> + mf_in->height = RKISP1_DEFAULT_HEIGHT;
> + mf_in->field = V4L2_FIELD_NONE;
> + mf_in->code = rkisp1_isp_input_formats[0].mbus_code;
> +
> + mf_in_crop = v4l2_subdev_get_try_crop(sd, cfg, RKISP1_ISP_PAD_SINK);
> + mf_in_crop->width = RKISP1_DEFAULT_WIDTH;
> + mf_in_crop->height = RKISP1_DEFAULT_HEIGHT;
> + mf_in_crop->left = 0;
> + mf_in_crop->top = 0;
> +
> + mf_out = v4l2_subdev_get_try_format(sd, cfg,
> + RKISP1_ISP_PAD_SOURCE_PATH);
> + *mf_out = *mf_in;
> + mf_out->code = rkisp1_isp_output_formats[0].mbus_code;
> + mf_out->quantization = V4L2_QUANTIZATION_FULL_RANGE;
> +
> + mf_out_crop = v4l2_subdev_get_try_crop(sd, cfg,
> + RKISP1_ISP_PAD_SOURCE_PATH);
> + *mf_out_crop = *mf_in_crop;
> +
> + return 0;
> +}
> +
> +static int rkisp1_isp_sd_get_fmt(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_format *fmt)
> +{
> + struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
> + struct v4l2_mbus_framefmt *mf = &fmt->format;
> +
> + if ((fmt->pad != RKISP1_ISP_PAD_SINK) &&
> + (fmt->pad != RKISP1_ISP_PAD_SOURCE_PATH)) {
> + fmt->format.code = MEDIA_BUS_FMT_FIXED;
> + /*
> + * NOTE: setting a format here doesn't make much sense
> + * but v4l2-compliance complains
> + */
> + fmt->format.width = RKISP1_DEFAULT_WIDTH;
> + fmt->format.height = RKISP1_DEFAULT_HEIGHT;
> + fmt->format.field = V4L2_FIELD_NONE;
> + return 0;
> + }
> +
> + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> + mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
> + fmt->format = *mf;
> + return 0;
> + }
> +
> + if (fmt->pad == RKISP1_ISP_PAD_SINK) {
> + *mf = isp_sd->in_frm;
> + } else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
> + /* format of source pad */
> + *mf = isp_sd->in_frm;
> + mf->code = isp_sd->out_fmt.mbus_code;
> + /* window size of source pad */
> + mf->width = isp_sd->out_crop.width;
> + mf->height = isp_sd->out_crop.height;
> + mf->quantization = isp_sd->quantization;
> + }
> + mf->field = V4L2_FIELD_NONE;
> +
> + return 0;
> +}
> +
> +static void rkisp1_isp_sd_try_fmt(struct v4l2_subdev *sd,
> + unsigned int pad,
> + struct v4l2_mbus_framefmt *fmt)
> +{
> + struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
> + struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
> + const struct ispsd_out_fmt *out_fmt;
> + const struct ispsd_in_fmt *in_fmt;
> +
> + switch (pad) {
> + case RKISP1_ISP_PAD_SINK:
> + in_fmt = find_in_fmt(fmt->code);
> + if (in_fmt)
> + fmt->code = in_fmt->mbus_code;
> + else
> + fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
> + fmt->width = clamp_t(u32, fmt->width, CIF_ISP_INPUT_W_MIN,
> + CIF_ISP_INPUT_W_MAX);
> + fmt->height = clamp_t(u32, fmt->height, CIF_ISP_INPUT_H_MIN,
> + CIF_ISP_INPUT_H_MAX);
> + break;
> + case RKISP1_ISP_PAD_SOURCE_PATH:
> + out_fmt = find_out_fmt(fmt->code);
> + if (out_fmt)
> + fmt->code = out_fmt->mbus_code;
> + else
> + fmt->code = rkisp1_isp_output_formats[0].mbus_code;
> + /* window size is set in s_selection */
> + fmt->width = isp_sd->out_crop.width;
> + fmt->height = isp_sd->out_crop.height;
> + /* full range by default */
> + if (!fmt->quantization)
> + fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
> + break;
> + }
> +
> + fmt->field = V4L2_FIELD_NONE;
> +}
> +
> +static int rkisp1_isp_sd_set_fmt(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_format *fmt)
> +{
> + struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
> + struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
> + struct v4l2_mbus_framefmt *mf = &fmt->format;
> +
Note that for sub-device nodes, the driver is itself responsible for
serialising the access to its data structures.
> + if ((fmt->pad != RKISP1_ISP_PAD_SINK) &&
> + (fmt->pad != RKISP1_ISP_PAD_SOURCE_PATH))
> + return rkisp1_isp_sd_get_fmt(sd, cfg, fmt);
> +
> + rkisp1_isp_sd_try_fmt(sd, fmt->pad, mf);
> +
> + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> + struct v4l2_mbus_framefmt *try_mf;
> +
> + try_mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
> + *try_mf = *mf;
> + return 0;
> + }
> +
> + if (fmt->pad == RKISP1_ISP_PAD_SINK) {
> + const struct ispsd_in_fmt *in_fmt;
> +
> + in_fmt = find_in_fmt(mf->code);
> + isp_sd->in_fmt = *in_fmt;
> + isp_sd->in_frm = *mf;
> + } else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
> + const struct ispsd_out_fmt *out_fmt;
> +
> + /* Ignore width/height */
> + out_fmt = find_out_fmt(mf->code);
> + isp_sd->out_fmt = *out_fmt;
> + /*
> + * It is quantization for output,
> + * isp use bt601 limit-range in internal
> + */
> + isp_sd->quantization = mf->quantization;
> + }
> +
> + return 0;
> +}
> +
> +static void rkisp1_isp_sd_try_crop(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_selection *sel)
> +{
> + struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
> + struct v4l2_mbus_framefmt in_frm = isp_sd->in_frm;
> + struct v4l2_rect in_crop = isp_sd->in_crop;
> + struct v4l2_rect *input = &sel->r;
> +
> + if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
> + in_frm = *v4l2_subdev_get_try_format(sd, cfg,
> + RKISP1_ISP_PAD_SINK);
> + in_crop = *v4l2_subdev_get_try_crop(sd, cfg,
> + RKISP1_ISP_PAD_SINK);
> + }
> +
> + input->left = ALIGN(input->left, 2);
> + input->width = ALIGN(input->width, 2);
> +
> + if (sel->pad == RKISP1_ISP_PAD_SINK) {
> + input->left = clamp_t(u32, input->left, 0, in_frm.width);
> + input->top = clamp_t(u32, input->top, 0, in_frm.height);
> + input->width = clamp_t(u32, input->width, CIF_ISP_INPUT_W_MIN,
> + in_frm.width - input->left);
> + input->height = clamp_t(u32, input->height,
> + CIF_ISP_INPUT_H_MIN,
> + in_frm.height - input->top);
> + } else if (sel->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
> + input->left = clamp_t(u32, input->left, 0, in_crop.width);
> + input->top = clamp_t(u32, input->top, 0, in_crop.height);
> + input->width = clamp_t(u32, input->width, CIF_ISP_OUTPUT_W_MIN,
> + in_crop.width - input->left);
> + input->height = clamp_t(u32, input->height,
> + CIF_ISP_OUTPUT_H_MIN,
> + in_crop.height - input->top);
> + }
> +}
> +
> +static int rkisp1_isp_sd_get_selection(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_selection *sel)
> +{
> + struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
> + struct v4l2_mbus_framefmt *frm;
> + struct v4l2_rect *rect;
> +
> + if (sel->pad != RKISP1_ISP_PAD_SOURCE_PATH &&
> + sel->pad != RKISP1_ISP_PAD_SINK)
> + return -EINVAL;
> +
> + switch (sel->target) {
> + case V4L2_SEL_TGT_CROP_BOUNDS:
> + if (sel->pad == RKISP1_ISP_PAD_SINK) {
> + if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
> + frm = v4l2_subdev_get_try_format(sd, cfg,
> + sel->pad);
> + else
> + frm = &isp_sd->in_frm;
> +
> + sel->r.height = frm->height;
> + sel->r.width = frm->width;
> + sel->r.left = 0;
> + sel->r.top = 0;
> + } else {
> + if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
> + rect = v4l2_subdev_get_try_crop(sd, cfg,
> + RKISP1_ISP_PAD_SINK);
> + else
> + rect = &isp_sd->in_crop;
> + sel->r = *rect;
> + }
> + break;
> + case V4L2_SEL_TGT_CROP:
> + if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
> + rect = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
> + else if (sel->pad == RKISP1_ISP_PAD_SINK)
> + rect = &isp_sd->in_crop;
> + else
> + rect = &isp_sd->out_crop;
> + sel->r = *rect;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int rkisp1_isp_sd_set_selection(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_selection *sel)
> +{
> + struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
> + struct rkisp1_device *dev = sd_to_isp_dev(sd);
> +
> + if (sel->pad != RKISP1_ISP_PAD_SOURCE_PATH &&
> + sel->pad != RKISP1_ISP_PAD_SINK)
> + return -EINVAL;
> + if (sel->target != V4L2_SEL_TGT_CROP)
> + return -EINVAL;
> +
> + v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> + "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, sel->pad,
> + sel->r.left, sel->r.top, sel->r.width, sel->r.height);
> + rkisp1_isp_sd_try_crop(sd, cfg, sel);
> +
> + if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
> + struct v4l2_rect *try_sel =
> + v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
> +
> + *try_sel = sel->r;
> + return 0;
> + }
> +
> + if (sel->pad == RKISP1_ISP_PAD_SINK)
> + isp_sd->in_crop = sel->r;
> + else
> + isp_sd->out_crop = sel->r;
> +
> + return 0;
> +}
> +
> +static int mipi_csi2_s_stream_start(struct rkisp1_isp_subdev *isp_sd,
> + struct rkisp1_sensor *sensor)
> +{
> + union phy_configure_opts opts = { 0 };
> + struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
> + struct v4l2_ctrl *pixel_rate;
> + s64 pixel_clock;
> +
> + pixel_rate = v4l2_ctrl_find(sensor->sd->ctrl_handler,
> + V4L2_CID_PIXEL_RATE);
> + if (!pixel_rate) {
> + v4l2_warn(sensor->sd, "No pixel rate control in subdev\n");
> + return -EPIPE;
> + }
> +
> + pixel_clock = v4l2_ctrl_g_ctrl_int64(pixel_rate);
> + if (!pixel_clock) {
> + v4l2_err(sensor->sd, "Invalid pixel rate value\n");
> + return -EINVAL;
> + }
> +
> + phy_mipi_dphy_get_default_config(pixel_clock, isp_sd->in_fmt.bus_width,
> + sensor->lanes, cfg);
> + phy_set_mode(sensor->dphy, PHY_MODE_MIPI_DPHY);
> + phy_configure(sensor->dphy, &opts);
> + phy_power_on(sensor->dphy);
> +
> + return 0;
> +}
> +
> +static void mipi_csi2_s_stream_stop(struct rkisp1_sensor *sensor)
> +{
> + phy_power_off(sensor->dphy);
> +}
> +
> +static int rkisp1_isp_sd_s_stream(struct v4l2_subdev *sd, int on)
> +{
> + struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
> + struct v4l2_subdev *sensor_sd;
> + int ret = 0;
> +
> + if (!on) {
> + ret = rkisp1_isp_stop(isp_dev);
> + if (ret < 0)
> + return ret;
> + mipi_csi2_s_stream_stop(isp_dev->active_sensor);
> + return 0;
> + }
> +
> + sensor_sd = get_remote_sensor(sd);
> + if (!sensor_sd)
> + return -ENODEV;
> +
> + isp_dev->active_sensor = sd_to_sensor(isp_dev, sensor_sd);
> + if (!isp_dev->active_sensor)
> + return -ENODEV;
> +
> + atomic_set(&isp_dev->isp_sdev.frm_sync_seq, 0);
> + ret = rkisp1_config_cif(isp_dev);
> + if (ret < 0)
> + return ret;
> +
> + /* TODO: support other interfaces */
> + if (isp_dev->active_sensor->mbus.type != V4L2_MBUS_CSI2_DPHY)
> + return -EINVAL;
> +
> + ret = mipi_csi2_s_stream_start(&isp_dev->isp_sdev,
> + isp_dev->active_sensor);
> + if (ret < 0)
> + return ret;
> +
> + ret = rkisp1_isp_start(isp_dev);
> + if (ret)
> + mipi_csi2_s_stream_stop(isp_dev->active_sensor);
> +
> + return ret;
> +}
> +
> +static int rkisp1_isp_sd_s_power(struct v4l2_subdev *sd, int on)
If you support runtime PM, you shouldn't implement the s_power op.
You'll still need to call s_power on external subdevs though.
> +{
> + struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
> + int ret;
> +
> + v4l2_dbg(1, rkisp1_debug, &isp_dev->v4l2_dev, "s_power: %d\n", on);
> +
> + if (on) {
> + ret = pm_runtime_get_sync(isp_dev->dev);
> + if (ret < 0)
> + return ret;
> +
> + rkisp1_config_clk(isp_dev);
> + } else {
> + ret = pm_runtime_put(isp_dev->dev);
> + if (ret < 0)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int rkisp1_subdev_link_validate(struct media_link *link)
> +{
> + if (link->source->index == RKISP1_ISP_PAD_SINK_PARAMS)
Is this test correct? The source is the source end of the link, i.e. the
video node.
How about the links that end in a video node?
> + return 0;
> +
> + return v4l2_subdev_link_validate(link);
> +}
> +
> +static int rkisp1_subdev_fmt_link_validate(struct v4l2_subdev *sd,
> + struct media_link *link,
> + struct v4l2_subdev_format *source_fmt,
> + struct v4l2_subdev_format *sink_fmt)
> +{
> + if (source_fmt->format.code != sink_fmt->format.code)
> + return -EINVAL;
> +
> + /* Crop is available */
> + if (source_fmt->format.width < sink_fmt->format.width ||
> + source_fmt->format.height < sink_fmt->format.height)
> + return -EINVAL;
> +
Could you use v4l2_subdev_link_validate_default()?
> + return 0;
> +}
> +
> +static void rkisp1_isp_queue_event_sof(struct rkisp1_isp_subdev *isp)
> +{
> + struct v4l2_event event = {
> + .type = V4L2_EVENT_FRAME_SYNC,
> + .u.frame_sync.frame_sequence =
> + atomic_inc_return(&isp->frm_sync_seq) - 1,
> + };
> + v4l2_event_queue(isp->sd.devnode, &event);
> +}
> +
> +static int rkisp1_isp_sd_subs_evt(struct v4l2_subdev *sd, struct v4l2_fh *fh,
> + struct v4l2_event_subscription *sub)
> +{
> + if (sub->type != V4L2_EVENT_FRAME_SYNC)
> + return -EINVAL;
> +
> + /* Line number. For now only zero accepted. */
> + if (sub->id != 0)
> + return -EINVAL;
> +
> + return v4l2_event_subscribe(fh, sub, 0, NULL);
> +}
> +
> +static const struct v4l2_subdev_pad_ops rkisp1_isp_sd_pad_ops = {
> + .enum_mbus_code = rkisp1_isp_sd_enum_mbus_code,
> + .get_selection = rkisp1_isp_sd_get_selection,
> + .set_selection = rkisp1_isp_sd_set_selection,
> + .init_cfg = rkisp1_isp_sd_init_config,
> + .get_fmt = rkisp1_isp_sd_get_fmt,
> + .set_fmt = rkisp1_isp_sd_set_fmt,
> + .link_validate = rkisp1_subdev_fmt_link_validate,
> +};
> +
> +static const struct media_entity_operations rkisp1_isp_sd_media_ops = {
> + .link_validate = rkisp1_subdev_link_validate,
> +};
> +
> +static const struct v4l2_subdev_video_ops rkisp1_isp_sd_video_ops = {
> + .s_stream = rkisp1_isp_sd_s_stream,
> +};
> +
> +static const struct v4l2_subdev_core_ops rkisp1_isp_core_ops = {
> + .subscribe_event = rkisp1_isp_sd_subs_evt,
> + .unsubscribe_event = v4l2_event_subdev_unsubscribe,
> + .s_power = rkisp1_isp_sd_s_power,
> +};
> +
> +static struct v4l2_subdev_ops rkisp1_isp_sd_ops = {
const
> + .core = &rkisp1_isp_core_ops,
> + .video = &rkisp1_isp_sd_video_ops,
> + .pad = &rkisp1_isp_sd_pad_ops,
> +};
> +
> +static void rkisp1_isp_sd_init_default_fmt(struct rkisp1_isp_subdev *isp_sd)
> +{
> + struct v4l2_mbus_framefmt *in_frm = &isp_sd->in_frm;
> + struct v4l2_rect *in_crop = &isp_sd->in_crop;
> + struct v4l2_rect *out_crop = &isp_sd->out_crop;
> + struct ispsd_in_fmt *in_fmt = &isp_sd->in_fmt;
> + struct ispsd_out_fmt *out_fmt = &isp_sd->out_fmt;
> +
> + *in_fmt = rkisp1_isp_input_formats[0];
> + in_frm->width = RKISP1_DEFAULT_WIDTH;
> + in_frm->height = RKISP1_DEFAULT_HEIGHT;
> + in_frm->code = in_fmt->mbus_code;
> +
> + in_crop->width = in_frm->width;
> + in_crop->height = in_frm->height;
> + in_crop->left = 0;
> + in_crop->top = 0;
> +
> + /* propagate to source */
> + *out_crop = *in_crop;
> + *out_fmt = rkisp1_isp_output_formats[0];
> + isp_sd->quantization = V4L2_QUANTIZATION_FULL_RANGE;
> +}
> +
> +int rkisp1_register_isp_subdev(struct rkisp1_device *isp_dev,
> + struct v4l2_device *v4l2_dev)
> +{
> + struct rkisp1_isp_subdev *isp_sdev = &isp_dev->isp_sdev;
> + struct v4l2_subdev *sd = &isp_sdev->sd;
> + int ret;
> +
> + v4l2_subdev_init(sd, &rkisp1_isp_sd_ops);
> + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
> + sd->entity.ops = &rkisp1_isp_sd_media_ops;
> + snprintf(sd->name, sizeof(sd->name), "rkisp1-isp-subdev");
strscpy()
> +
> + isp_sdev->pads[RKISP1_ISP_PAD_SINK].flags =
> + MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
> + isp_sdev->pads[RKISP1_ISP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK;
> + isp_sdev->pads[RKISP1_ISP_PAD_SOURCE_PATH].flags = MEDIA_PAD_FL_SOURCE;
> + isp_sdev->pads[RKISP1_ISP_PAD_SOURCE_STATS].flags = MEDIA_PAD_FL_SOURCE;
> + sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
> + ret = media_entity_pads_init(&sd->entity, RKISP1_ISP_PAD_MAX,
> + isp_sdev->pads);
> + if (ret < 0)
> + return ret;
> +
> + sd->owner = THIS_MODULE;
> + v4l2_set_subdevdata(sd, isp_dev);
> +
> + sd->grp_id = GRP_ID_ISP;
> + ret = v4l2_device_register_subdev(v4l2_dev, sd);
> + if (ret < 0) {
> + v4l2_err(sd, "Failed to register isp subdev\n");
> + goto err_cleanup_media_entity;
> + }
> +
> + rkisp1_isp_sd_init_default_fmt(isp_sdev);
> +
> + return 0;
A newline would be nice here.
> +err_cleanup_media_entity:
> + media_entity_cleanup(&sd->entity);
And here.
> + return ret;
> +}
> +
> +void rkisp1_unregister_isp_subdev(struct rkisp1_device *isp_dev)
> +{
> + struct v4l2_subdev *sd = &isp_dev->isp_sdev.sd;
> +
> + v4l2_device_unregister_subdev(sd);
> + media_entity_cleanup(&sd->entity);
> +}
> +
> +/**************** Interrupter Handler ****************/
> +
> +void rkisp1_mipi_isr(unsigned int mis, struct rkisp1_device *dev)
> +{
> + struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
> + void __iomem *base = dev->base_addr;
> + u32 val;
> +
> + writel(~0, base + CIF_MIPI_ICR);
> +
> + /*
> + * Disable DPHY errctrl interrupt, because this dphy
> + * erctrl signal is asserted until the next changes
> + * of line state. This time is may be too long and cpu
> + * is hold in this interrupt.
> + */
> + if (mis & CIF_MIPI_ERR_CTRL(0x0f)) {
> + val = readl(base + CIF_MIPI_IMSC);
> + writel(val & ~CIF_MIPI_ERR_CTRL(0x0f), base + CIF_MIPI_IMSC);
> + dev->isp_sdev.dphy_errctrl_disabled = true;
> + }
> +
> + /*
> + * Enable DPHY errctrl interrupt again, if mipi have receive
> + * the whole frame without any error.
> + */
> + if (mis == CIF_MIPI_FRAME_END) {
> + /*
> + * Enable DPHY errctrl interrupt again, if mipi have receive
> + * the whole frame without any error.
> + */
> + if (dev->isp_sdev.dphy_errctrl_disabled) {
> + val = readl(base + CIF_MIPI_IMSC);
> + val |= CIF_MIPI_ERR_CTRL(0x0f);
> + writel(val, base + CIF_MIPI_IMSC);
> + dev->isp_sdev.dphy_errctrl_disabled = false;
> + }
> + } else {
> + v4l2_warn(v4l2_dev, "MIPI mis error: 0x%08x\n", mis);
> + }
> +}
> +
> +void rkisp1_isp_isr(unsigned int isp_mis, struct rkisp1_device *dev)
> +{
> + void __iomem *base = dev->base_addr;
> + unsigned int isp_mis_tmp = 0;
> + unsigned int isp_err = 0;
> +
> + /* start edge of v_sync */
> + if (isp_mis & CIF_ISP_V_START) {
> + rkisp1_isp_queue_event_sof(&dev->isp_sdev);
> +
> + writel(CIF_ISP_V_START, base + CIF_ISP_ICR);
> + isp_mis_tmp = readl(base + CIF_ISP_MIS);
> + if (isp_mis_tmp & CIF_ISP_V_START)
> + v4l2_err(&dev->v4l2_dev, "isp icr v_statr err: 0x%x\n",
> + isp_mis_tmp);
> + }
> +
> + if ((isp_mis & CIF_ISP_PIC_SIZE_ERROR)) {
Extra parentheses.
> + /* Clear pic_size_error */
> + writel(CIF_ISP_PIC_SIZE_ERROR, base + CIF_ISP_ICR);
> + isp_err = readl(base + CIF_ISP_ERR);
> + v4l2_err(&dev->v4l2_dev,
> + "CIF_ISP_PIC_SIZE_ERROR (0x%08x)", isp_err);
> + writel(isp_err, base + CIF_ISP_ERR_CLR);
> + } else if ((isp_mis & CIF_ISP_DATA_LOSS)) {
> + /* Clear data_loss */
> + writel(CIF_ISP_DATA_LOSS, base + CIF_ISP_ICR);
> + v4l2_err(&dev->v4l2_dev, "CIF_ISP_DATA_LOSS\n");
> + writel(CIF_ISP_DATA_LOSS, base + CIF_ISP_ICR);
> + }
> +
> + /* sampled input frame is complete */
> + if (isp_mis & CIF_ISP_FRAME_IN) {
> + writel(CIF_ISP_FRAME_IN, base + CIF_ISP_ICR);
> + isp_mis_tmp = readl(base + CIF_ISP_MIS);
> + if (isp_mis_tmp & CIF_ISP_FRAME_IN)
> + v4l2_err(&dev->v4l2_dev, "isp icr frame_in err: 0x%x\n",
> + isp_mis_tmp);
> + }
> +
> + /* frame was completely put out */
> + if (isp_mis & CIF_ISP_FRAME) {
> + u32 isp_ris = 0;
> + /* Clear Frame In (ISP) */
> + writel(CIF_ISP_FRAME, base + CIF_ISP_ICR);
> + isp_mis_tmp = readl(base + CIF_ISP_MIS);
> + if (isp_mis_tmp & CIF_ISP_FRAME)
> + v4l2_err(&dev->v4l2_dev,
> + "isp icr frame end err: 0x%x\n", isp_mis_tmp);
> +
> + isp_ris = readl(base + CIF_ISP_RIS);
> + if (isp_ris & (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
> + CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY))
> + rkisp1_stats_isr(&dev->stats_vdev, isp_ris);
> + }
> +
> + /*
> + * Then update changed configs. Some of them involve
> + * lot of register writes. Do those only one per frame.
> + * Do the updates in the order of the processing flow.
> + */
> + rkisp1_params_isr(&dev->params_vdev, isp_mis);
> +}
> diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.h b/drivers/media/platform/rockchip/isp1/rkisp1.h
> new file mode 100644
> index 000000000000..b0366e354ec2
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/rkisp1.h
> @@ -0,0 +1,111 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#ifndef _RKISP1_H
> +#define _RKISP1_H
> +
> +#include <linux/platform_device.h>
> +#include <media/v4l2-fwnode.h>
> +
> +#include "common.h"
> +
> +struct rkisp1_stream;
> +
> +/*
> + * struct ispsd_in_fmt - ISP intput-pad format
> + *
> + * Translate mbus_code to hardware format values
> + *
> + * @bus_width: used for parallel
> + */
> +struct ispsd_in_fmt {
> + u32 mbus_code;
> + u8 fmt_type;
> + u32 mipi_dt;
> + u32 yuv_seq;
> + enum rkisp1_fmt_raw_pat_type bayer_pat;
> + u8 bus_width;
> +};
> +
> +struct ispsd_out_fmt {
> + u32 mbus_code;
> + u8 fmt_type;
> +};
> +
> +struct rkisp1_ie_config {
> + unsigned int effect;
> +};
> +
> +enum rkisp1_isp_pad {
> + RKISP1_ISP_PAD_SINK,
> + RKISP1_ISP_PAD_SINK_PARAMS,
> + RKISP1_ISP_PAD_SOURCE_PATH,
> + RKISP1_ISP_PAD_SOURCE_STATS,
> + RKISP1_ISP_PAD_MAX
> +};
> +
> +/*
> + * struct rkisp1_isp_subdev - ISP sub-device
> + *
> + * See Cropping regions of ISP in rkisp1.c for details
> + * @in_frm: input size, don't have to be equal to sensor size
> + * @in_fmt: input format
> + * @in_crop: crop for sink pad
> + * @out_fmt: output format
> + * @out_crop: output size
> + *
> + * @dphy_errctrl_disabled: if dphy errctrl is disabled(avoid endless interrupt)
> + * @frm_sync_seq: frame sequence, to sync frame_id between video devices.
> + * @quantization: output quantization
> + */
> +struct rkisp1_isp_subdev {
> + struct v4l2_subdev sd;
> + struct media_pad pads[RKISP1_ISP_PAD_MAX];
> + struct v4l2_ctrl_handler ctrl_handler;
> + struct v4l2_mbus_framefmt in_frm;
> + struct ispsd_in_fmt in_fmt;
> + struct v4l2_rect in_crop;
> + struct ispsd_out_fmt out_fmt;
> + struct v4l2_rect out_crop;
> + bool dphy_errctrl_disabled;
> + atomic_t frm_sync_seq;
> + enum v4l2_quantization quantization;
> +};
> +
> +int rkisp1_register_isp_subdev(struct rkisp1_device *isp_dev,
> + struct v4l2_device *v4l2_dev);
> +
> +void rkisp1_unregister_isp_subdev(struct rkisp1_device *isp_dev);
> +
> +void rkisp1_mipi_isr(unsigned int mipi_mis, struct rkisp1_device *dev);
> +
> +void rkisp1_isp_isr(unsigned int isp_mis, struct rkisp1_device *dev);
> +
> +static inline
> +struct ispsd_out_fmt *rkisp1_get_ispsd_out_fmt(struct rkisp1_isp_subdev *isp_sdev)
> +{
> + return &isp_sdev->out_fmt;
> +}
> +
> +static inline
> +struct ispsd_in_fmt *rkisp1_get_ispsd_in_fmt(struct rkisp1_isp_subdev *isp_sdev)
> +{
> + return &isp_sdev->in_fmt;
> +}
> +
> +static inline
> +struct v4l2_rect *rkisp1_get_isp_sd_win(struct rkisp1_isp_subdev *isp_sdev)
> +{
> + return &isp_sdev->out_crop;
> +}
I'd just use the struct fields directly in the code as it's easier to
figure out which field in the struct is being accessed.
> +
> +static inline struct rkisp1_isp_subdev *sd_to_isp_sd(struct v4l2_subdev *sd)
> +{
> + return container_of(sd, struct rkisp1_isp_subdev, sd);
> +}
> +
> +#endif /* _RKISP1_H */
--
Kind regards,
Sakari Ailus
sakari.ailus@linux.intel.com
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: Detecting AArch32 support from a AArch64 process in user space
From: Will Deacon @ 2019-08-08 9:15 UTC (permalink / raw)
To: Marc Zyngier; +Cc: ynorov, linux-arm-kernel, Stefan Agner, suzuki.poulose
In-Reply-To: <7bfc8611-0b2c-9d6d-0348-afd580e2a403@arm.com>
On Thu, Aug 08, 2019 at 10:04:27AM +0100, Marc Zyngier wrote:
> On 08/08/2019 08:36, Stefan Agner wrote:
> > I started to ask myself what PER_LINUX32 actually changes. From what I
> > can tell it only changes the behavior of /proc/cpuinfo? The personality
> > seems not to be applied automatically to 32-bit processes, so this is a
> > opt-in backward compatibility feature?
>
> It's all about giving the illusion that the process runs in a "real"
> 32bit environment, with all its warts. It doesn't change the CPU mode
> you're running in (that'd be a bit harsh). It's only once you exec
> something that requires AArch32 that we engage the COMPAT mode.
>
> Provided that your kernel contains 00377277166b or a backport of it (or
> that it predates 4378a7d4be30), the following program should do the
> right thing:
>
> #include <sys/personality.h>
> #include <stdio.h>
>
> int main(int argc, char *argv[])
> {
> int old, new;
>
> old = personality(PER_LINUX32);
> if (old < 0) {
> perror("No 32bit for you");
> return 1;
> }
>
> new = personality(0xffffffff);
> printf("Running with personality %d\n", new);
>
> personality(old);
> new = personality(0xffffffff);
>
> printf("Running with personality %d\n", new);
>
> return 0;
> }
Or you can use the setarch/linux32 utility.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 0/3] arm/arm64: Add support for function error injection
From: Leo Yan @ 2019-08-08 9:09 UTC (permalink / raw)
To: Will Deacon
Cc: Song Liu, Benjamin Herrenschmidt, Alexei Starovoitov,
Oleg Nesterov, Paul Mackerras, H. Peter Anvin, linux-arch,
Daniel Borkmann, Michael Ellerman, x86, Russell King,
clang-built-linux, Ingo Molnar, Catalin Marinas, Yonghong Song,
Naveen N. Rao, Arnd Bergmann, Borislav Petkov, Thomas Gleixner,
linux-arm-kernel, netdev, linux-kernel, Masami Hiramatsu, bpf,
linuxppc-dev, Martin KaFai Lau
In-Reply-To: <20190807160703.pe4jxak7hs7ptvde@willie-the-truck>
On Wed, Aug 07, 2019 at 05:07:03PM +0100, Will Deacon wrote:
> On Tue, Aug 06, 2019 at 06:00:12PM +0800, Leo Yan wrote:
> > This small patch set is to add support for function error injection;
> > this can be used to eanble more advanced debugging feature, e.g.
> > CONFIG_BPF_KPROBE_OVERRIDE.
> >
> > The patch 01/03 is to consolidate the function definition which can be
> > suared cross architectures, patches 02,03/03 are used for enabling
> > function error injection on arm64 and arm architecture respectively.
> >
> > I tested on arm64 platform Juno-r2 and one of my laptop with x86
> > architecture with below steps; I don't test for Arm architecture so
> > only pass compilation.
>
> Thanks. I've queued the first two patches up here:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=for-next/error-injection
Thank you, Will.
Leo.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: Detecting AArch32 support from a AArch64 process in user space
From: Marc Zyngier @ 2019-08-08 9:04 UTC (permalink / raw)
To: Stefan Agner, linux-arm-kernel; +Cc: ynorov, will.deacon, suzuki.poulose
In-Reply-To: <ffbb92107af81971c03ec832cf25116c@agner.ch>
Hi Stefan,
On 08/08/2019 08:36, Stefan Agner wrote:
> [resend this time with the correct mailing list address]
>
> Hello,
>
> I am trying to detect whether an ARMv8 system running in AArch64 state
> supports AArch32 state from a user space process. The arm64_features[]
> in
> arch/arm64/kernel/cpufeature.c lists a CPU feature "32-bit EL0 Support".
> However, afaik this CPU feature is not directly exposed to user-space.
> The features do get printed in the kernel log, but that requires
> privileges and only works directly after boot. There is
> system_supports_32bit_el0() which is used in various places in the arm64
> architecture code. One of the instances where I can make sense of from
> user space is through the personality system call. One idea is to call
> personality(PER_LINUX32). It would then return error code 22 in case
> 32-bit is not supported in user space. However, if successful this
> changes the personality of the current process which might have side
> effects which I do not want...?
You should be able to revert the effects of PER_LINUX_32 by feeding back
the return value of the initial call to personality() to a second
personality() call.
> I started to ask myself what PER_LINUX32 actually changes. From what I
> can tell it only changes the behavior of /proc/cpuinfo? The personality
> seems not to be applied automatically to 32-bit processes, so this is a
> opt-in backward compatibility feature?
It's all about giving the illusion that the process runs in a "real"
32bit environment, with all its warts. It doesn't change the CPU mode
you're running in (that'd be a bit harsh). It's only once you exec
something that requires AArch32 that we engage the COMPAT mode.
Provided that your kernel contains 00377277166b or a backport of it (or
that it predates 4378a7d4be30), the following program should do the
right thing:
#include <sys/personality.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int old, new;
old = personality(PER_LINUX32);
if (old < 0) {
perror("No 32bit for you");
return 1;
}
new = personality(0xffffffff);
printf("Running with personality %d\n", new);
personality(old);
new = personality(0xffffffff);
printf("Running with personality %d\n", new);
return 0;
}
> To be on the safe side, I was thinking about executing the system call
> in a separate process. However, at that point I could also just execute
> a statically linked AArch32 binary and see whether I get a "exec format
> error". I guess this could then be either due to missing AArch32 CPU
> support or the kernel not being compiled with 32-bit compatibility.
Overkill ;-). The above should be enough.
> At last I was considering reading directly from the CPU. But from what I
> understand the register used in the kernel to determine 32-bit
> compatibility (ID_AA64PFR0_EL1) is not accessible by user space (due to
> the suffix _EL1).
Hey, you could create a VM, a vcpu and dump the ID registers by issuing
a set of KVM_GET_ONE_REG ioctls. Not necessarily recommended... ;-)
Cheers,
M.
--
Jazz is not dead. It just smells funny...
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RESEND PATCH v5 2/4] devfreq: exynos-bus: convert to use dev_pm_opp_set_rate()
From: Kamil Konieczny @ 2019-08-08 9:02 UTC (permalink / raw)
To: k.konieczny
Cc: Mark Rutland, Nishanth Menon, linux-samsung-soc, Rob Herring,
linux-arm-kernel, Bartlomiej Zolnierkiewicz, Stephen Boyd,
Viresh Kumar, linux-pm, linux-kernel, Krzysztof Kozlowski,
Chanwoo Choi, Kyungmin Park, Kukjin Kim, MyungJoo Ham, devicetree,
Marek Szyprowski
In-Reply-To: <20190808090234.12577-1-k.konieczny@partner.samsung.com>
Reuse opp core code for setting bus clock and voltage. As a side
effect this allow usage of coupled regulators feature (required
for boards using Exynos5422/5800 SoCs) because dev_pm_opp_set_rate()
uses regulator_set_voltage_triplet() for setting regulator voltage
while the old code used regulator_set_voltage_tol() with fixed
tolerance. This patch also removes no longer needed parsing of DT
property "exynos,voltage-tolerance" (no Exynos devfreq DT node uses
it). After applying changes both functions exynos_bus_passive_target()
and exynos_bus_target() have the same code, so remove
exynos_bus_passive_target(). In exynos_bus_probe() replace it with
exynos_bus_target.
Signed-off-by: Kamil Konieczny <k.konieczny@partner.samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
---
Changes:
v5:
- squashed last patch into this one, as suggested by Chanwoo Choi
v4:
- remove unrelated changes, add newline before comment
---
drivers/devfreq/exynos-bus.c | 130 +++++++----------------------------
1 file changed, 24 insertions(+), 106 deletions(-)
diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index f34fa26f00d0..2aeb6cc07960 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -25,7 +25,6 @@
#include <linux/slab.h>
#define DEFAULT_SATURATION_RATIO 40
-#define DEFAULT_VOLTAGE_TOLERANCE 2
struct exynos_bus {
struct device *dev;
@@ -37,9 +36,8 @@ struct exynos_bus {
unsigned long curr_freq;
- struct regulator *regulator;
+ struct opp_table *opp_table;
struct clk *clk;
- unsigned int voltage_tolerance;
unsigned int ratio;
};
@@ -93,62 +91,29 @@ static int exynos_bus_get_event(struct exynos_bus *bus,
}
/*
- * Must necessary function for devfreq simple-ondemand governor
+ * devfreq function for both simple-ondemand and passive governor
*/
static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
{
struct exynos_bus *bus = dev_get_drvdata(dev);
struct dev_pm_opp *new_opp;
- unsigned long old_freq, new_freq, new_volt, tol;
int ret = 0;
- /* Get new opp-bus instance according to new bus clock */
+ /* Get correct frequency for bus. */
new_opp = devfreq_recommended_opp(dev, freq, flags);
if (IS_ERR(new_opp)) {
dev_err(dev, "failed to get recommended opp instance\n");
return PTR_ERR(new_opp);
}
- new_freq = dev_pm_opp_get_freq(new_opp);
- new_volt = dev_pm_opp_get_voltage(new_opp);
dev_pm_opp_put(new_opp);
- old_freq = bus->curr_freq;
-
- if (old_freq == new_freq)
- return 0;
- tol = new_volt * bus->voltage_tolerance / 100;
-
/* Change voltage and frequency according to new OPP level */
mutex_lock(&bus->lock);
+ ret = dev_pm_opp_set_rate(dev, *freq);
+ if (!ret)
+ bus->curr_freq = *freq;
- if (old_freq < new_freq) {
- ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
- if (ret < 0) {
- dev_err(bus->dev, "failed to set voltage\n");
- goto out;
- }
- }
-
- ret = clk_set_rate(bus->clk, new_freq);
- if (ret < 0) {
- dev_err(dev, "failed to change clock of bus\n");
- clk_set_rate(bus->clk, old_freq);
- goto out;
- }
-
- if (old_freq > new_freq) {
- ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
- if (ret < 0) {
- dev_err(bus->dev, "failed to set voltage\n");
- goto out;
- }
- }
- bus->curr_freq = new_freq;
-
- dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n",
- old_freq, new_freq, clk_get_rate(bus->clk));
-out:
mutex_unlock(&bus->lock);
return ret;
@@ -196,54 +161,10 @@ static void exynos_bus_exit(struct device *dev)
dev_pm_opp_of_remove_table(dev);
clk_disable_unprepare(bus->clk);
- if (bus->regulator)
- regulator_disable(bus->regulator);
-}
-
-/*
- * Must necessary function for devfreq passive governor
- */
-static int exynos_bus_passive_target(struct device *dev, unsigned long *freq,
- u32 flags)
-{
- struct exynos_bus *bus = dev_get_drvdata(dev);
- struct dev_pm_opp *new_opp;
- unsigned long old_freq, new_freq;
- int ret = 0;
-
- /* Get new opp-bus instance according to new bus clock */
- new_opp = devfreq_recommended_opp(dev, freq, flags);
- if (IS_ERR(new_opp)) {
- dev_err(dev, "failed to get recommended opp instance\n");
- return PTR_ERR(new_opp);
- }
-
- new_freq = dev_pm_opp_get_freq(new_opp);
- dev_pm_opp_put(new_opp);
-
- old_freq = bus->curr_freq;
-
- if (old_freq == new_freq)
- return 0;
-
- /* Change the frequency according to new OPP level */
- mutex_lock(&bus->lock);
-
- ret = clk_set_rate(bus->clk, new_freq);
- if (ret < 0) {
- dev_err(dev, "failed to set the clock of bus\n");
- goto out;
+ if (bus->opp_table) {
+ dev_pm_opp_put_regulators(bus->opp_table);
+ bus->opp_table = NULL;
}
-
- *freq = new_freq;
- bus->curr_freq = new_freq;
-
- dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n",
- old_freq, new_freq, clk_get_rate(bus->clk));
-out:
- mutex_unlock(&bus->lock);
-
- return ret;
}
static void exynos_bus_passive_exit(struct device *dev)
@@ -258,21 +179,19 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
struct exynos_bus *bus)
{
struct device *dev = bus->dev;
+ struct opp_table *opp_table;
+ const char *vdd = "vdd";
int i, ret, count, size;
- /* Get the regulator to provide each bus with the power */
- bus->regulator = devm_regulator_get(dev, "vdd");
- if (IS_ERR(bus->regulator)) {
- dev_err(dev, "failed to get VDD regulator\n");
- return PTR_ERR(bus->regulator);
- }
-
- ret = regulator_enable(bus->regulator);
- if (ret < 0) {
- dev_err(dev, "failed to enable VDD regulator\n");
+ opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1);
+ if (IS_ERR(opp_table)) {
+ ret = PTR_ERR(opp_table);
+ dev_err(dev, "failed to set regulators %d\n", ret);
return ret;
}
+ bus->opp_table = opp_table;
+
/*
* Get the devfreq-event devices to get the current utilization of
* buses. This raw data will be used in devfreq ondemand governor.
@@ -313,14 +232,11 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
if (of_property_read_u32(np, "exynos,saturation-ratio", &bus->ratio))
bus->ratio = DEFAULT_SATURATION_RATIO;
- if (of_property_read_u32(np, "exynos,voltage-tolerance",
- &bus->voltage_tolerance))
- bus->voltage_tolerance = DEFAULT_VOLTAGE_TOLERANCE;
-
return 0;
err_regulator:
- regulator_disable(bus->regulator);
+ dev_pm_opp_put_regulators(bus->opp_table);
+ bus->opp_table = NULL;
return ret;
}
@@ -471,7 +387,7 @@ static int exynos_bus_probe(struct platform_device *pdev)
goto out;
passive:
/* Initialize the struct profile and governor data for passive device */
- profile->target = exynos_bus_passive_target;
+ profile->target = exynos_bus_target;
profile->exit = exynos_bus_passive_exit;
/* Get the instance of parent devfreq device */
@@ -511,8 +427,10 @@ static int exynos_bus_probe(struct platform_device *pdev)
dev_pm_opp_of_remove_table(dev);
clk_disable_unprepare(bus->clk);
err_reg:
- if (!passive)
- regulator_disable(bus->regulator);
+ if (!passive) {
+ dev_pm_opp_put_regulators(bus->opp_table);
+ bus->opp_table = NULL;
+ }
return ret;
}
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RESEND PATCH v5 4/4] dt-bindings: devfreq: exynos-bus: remove unused property
From: Kamil Konieczny @ 2019-08-08 9:02 UTC (permalink / raw)
To: k.konieczny
Cc: Mark Rutland, Nishanth Menon, linux-samsung-soc, Rob Herring,
linux-arm-kernel, Bartlomiej Zolnierkiewicz, Stephen Boyd,
Viresh Kumar, linux-pm, linux-kernel, Krzysztof Kozlowski,
Chanwoo Choi, Kyungmin Park, Kukjin Kim, MyungJoo Ham, devicetree,
Marek Szyprowski
In-Reply-To: <20190808090234.12577-1-k.konieczny@partner.samsung.com>
Remove unused DT property "exynos,voltage-tolerance".
Signed-off-by: Kamil Konieczny <k.konieczny@partner.samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
---
Documentation/devicetree/bindings/devfreq/exynos-bus.txt | 2 --
1 file changed, 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
index f8e946471a58..e71f752cc18f 100644
--- a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
+++ b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
@@ -50,8 +50,6 @@ Required properties only for passive bus device:
Optional properties only for parent bus device:
- exynos,saturation-ratio: the percentage value which is used to calibrate
the performance count against total cycle count.
-- exynos,voltage-tolerance: the percentage value for bus voltage tolerance
- which is used to calculate the max voltage.
Detailed correlation between sub-blocks and power line according to Exynos SoC:
- In case of Exynos3250, there are two power line as following:
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RESEND PATCH v5 3/4] ARM: dts: exynos: add initial data for coupled regulators for Exynos5422/5800
From: Kamil Konieczny @ 2019-08-08 9:02 UTC (permalink / raw)
To: k.konieczny
Cc: Mark Rutland, Nishanth Menon, linux-samsung-soc, Rob Herring,
linux-arm-kernel, Bartlomiej Zolnierkiewicz, Stephen Boyd,
Viresh Kumar, linux-pm, linux-kernel, Krzysztof Kozlowski,
Chanwoo Choi, Kyungmin Park, Kukjin Kim, MyungJoo Ham, devicetree,
Marek Szyprowski
In-Reply-To: <20190808090234.12577-1-k.konieczny@partner.samsung.com>
From: Marek Szyprowski <m.szyprowski@samsung.com>
Declare Exynos5422/5800 voltage ranges for opp points for big cpu core and
bus wcore and couple their voltage supllies as vdd_arm and vdd_int should
be in 300mV range.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
[k.konieczny: add missing patch description]
Signed-off-by: Kamil Konieczny <k.konieczny@partner.samsung.com>
Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>
---
arch/arm/boot/dts/exynos5420.dtsi | 34 +++++++++----------
arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 4 +++
arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++
arch/arm/boot/dts/exynos5800.dtsi | 32 ++++++++---------
4 files changed, 41 insertions(+), 33 deletions(-)
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 5fb2326875dc..0cbf74750553 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -48,62 +48,62 @@
opp-shared;
opp-1800000000 {
opp-hz = /bits/ 64 <1800000000>;
- opp-microvolt = <1250000>;
+ opp-microvolt = <1250000 1250000 1500000>;
clock-latency-ns = <140000>;
};
opp-1700000000 {
opp-hz = /bits/ 64 <1700000000>;
- opp-microvolt = <1212500>;
+ opp-microvolt = <1212500 1212500 1500000>;
clock-latency-ns = <140000>;
};
opp-1600000000 {
opp-hz = /bits/ 64 <1600000000>;
- opp-microvolt = <1175000>;
+ opp-microvolt = <1175000 1175000 1500000>;
clock-latency-ns = <140000>;
};
opp-1500000000 {
opp-hz = /bits/ 64 <1500000000>;
- opp-microvolt = <1137500>;
+ opp-microvolt = <1137500 1137500 1500000>;
clock-latency-ns = <140000>;
};
opp-1400000000 {
opp-hz = /bits/ 64 <1400000000>;
- opp-microvolt = <1112500>;
+ opp-microvolt = <1112500 1112500 1500000>;
clock-latency-ns = <140000>;
};
opp-1300000000 {
opp-hz = /bits/ 64 <1300000000>;
- opp-microvolt = <1062500>;
+ opp-microvolt = <1062500 1062500 1500000>;
clock-latency-ns = <140000>;
};
opp-1200000000 {
opp-hz = /bits/ 64 <1200000000>;
- opp-microvolt = <1037500>;
+ opp-microvolt = <1037500 1037500 1500000>;
clock-latency-ns = <140000>;
};
opp-1100000000 {
opp-hz = /bits/ 64 <1100000000>;
- opp-microvolt = <1012500>;
+ opp-microvolt = <1012500 1012500 1500000>;
clock-latency-ns = <140000>;
};
opp-1000000000 {
opp-hz = /bits/ 64 <1000000000>;
- opp-microvolt = < 987500>;
+ opp-microvolt = < 987500 987500 1500000>;
clock-latency-ns = <140000>;
};
opp-900000000 {
opp-hz = /bits/ 64 <900000000>;
- opp-microvolt = < 962500>;
+ opp-microvolt = < 962500 962500 1500000>;
clock-latency-ns = <140000>;
};
opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
- opp-microvolt = < 937500>;
+ opp-microvolt = < 937500 937500 1500000>;
clock-latency-ns = <140000>;
};
opp-700000000 {
opp-hz = /bits/ 64 <700000000>;
- opp-microvolt = < 912500>;
+ opp-microvolt = < 912500 912500 1500000>;
clock-latency-ns = <140000>;
};
};
@@ -1100,23 +1100,23 @@
opp00 {
opp-hz = /bits/ 64 <84000000>;
- opp-microvolt = <925000>;
+ opp-microvolt = <925000 925000 1400000>;
};
opp01 {
opp-hz = /bits/ 64 <111000000>;
- opp-microvolt = <950000>;
+ opp-microvolt = <950000 950000 1400000>;
};
opp02 {
opp-hz = /bits/ 64 <222000000>;
- opp-microvolt = <950000>;
+ opp-microvolt = <950000 950000 1400000>;
};
opp03 {
opp-hz = /bits/ 64 <333000000>;
- opp-microvolt = <950000>;
+ opp-microvolt = <950000 950000 1400000>;
};
opp04 {
opp-hz = /bits/ 64 <400000000>;
- opp-microvolt = <987500>;
+ opp-microvolt = <987500 987500 1400000>;
};
};
diff --git a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
index 25d95de15c9b..65d094256b54 100644
--- a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
+++ b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
@@ -428,6 +428,8 @@
regulator-max-microvolt = <1500000>;
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&buck3_reg>;
+ regulator-coupled-max-spread = <300000>;
};
buck3_reg: BUCK3 {
@@ -436,6 +438,8 @@
regulator-max-microvolt = <1400000>;
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&buck2_reg>;
+ regulator-coupled-max-spread = <300000>;
};
buck4_reg: BUCK4 {
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index e0f470fe54c8..5c1e965ed7e9 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -257,6 +257,8 @@
regulator-always-on;
regulator-boot-on;
regulator-ramp-delay = <12500>;
+ regulator-coupled-with = <&buck3_reg>;
+ regulator-coupled-max-spread = <300000>;
regulator-state-mem {
regulator-off-in-suspend;
};
@@ -269,6 +271,8 @@
regulator-always-on;
regulator-boot-on;
regulator-ramp-delay = <12500>;
+ regulator-coupled-with = <&buck2_reg>;
+ regulator-coupled-max-spread = <300000>;
regulator-state-mem {
regulator-off-in-suspend;
};
diff --git a/arch/arm/boot/dts/exynos5800.dtsi b/arch/arm/boot/dts/exynos5800.dtsi
index 57d3b319fd65..2a74735d161c 100644
--- a/arch/arm/boot/dts/exynos5800.dtsi
+++ b/arch/arm/boot/dts/exynos5800.dtsi
@@ -22,61 +22,61 @@
&cluster_a15_opp_table {
opp-1700000000 {
- opp-microvolt = <1250000>;
+ opp-microvolt = <1250000 1250000 1500000>;
};
opp-1600000000 {
- opp-microvolt = <1250000>;
+ opp-microvolt = <1250000 1250000 1500000>;
};
opp-1500000000 {
- opp-microvolt = <1100000>;
+ opp-microvolt = <1100000 1100000 1500000>;
};
opp-1400000000 {
- opp-microvolt = <1100000>;
+ opp-microvolt = <1100000 1100000 1500000>;
};
opp-1300000000 {
- opp-microvolt = <1100000>;
+ opp-microvolt = <1100000 1100000 1500000>;
};
opp-1200000000 {
- opp-microvolt = <1000000>;
+ opp-microvolt = <1000000 1000000 1500000>;
};
opp-1100000000 {
- opp-microvolt = <1000000>;
+ opp-microvolt = <1000000 1000000 1500000>;
};
opp-1000000000 {
- opp-microvolt = <1000000>;
+ opp-microvolt = <1000000 1000000 1500000>;
};
opp-900000000 {
- opp-microvolt = <1000000>;
+ opp-microvolt = <1000000 1000000 1500000>;
};
opp-800000000 {
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
};
opp-700000000 {
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
};
opp-600000000 {
opp-hz = /bits/ 64 <600000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
opp-500000000 {
opp-hz = /bits/ 64 <500000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
opp-400000000 {
opp-hz = /bits/ 64 <400000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
opp-200000000 {
opp-hz = /bits/ 64 <200000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
};
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RESEND PATCH v5 1/4] devfreq: exynos-bus: correct clock enable sequence
From: Kamil Konieczny @ 2019-08-08 9:02 UTC (permalink / raw)
To: k.konieczny
Cc: Mark Rutland, Nishanth Menon, linux-samsung-soc, Rob Herring,
linux-arm-kernel, Bartlomiej Zolnierkiewicz, Stephen Boyd,
Viresh Kumar, linux-pm, linux-kernel, Krzysztof Kozlowski,
Chanwoo Choi, Kyungmin Park, Kukjin Kim, MyungJoo Ham, devicetree,
Marek Szyprowski
In-Reply-To: <20190808090234.12577-1-k.konieczny@partner.samsung.com>
Regulators should be enabled before clocks to avoid h/w hang. This
require change in exynos_bus_probe() to move exynos_bus_parse_of()
after exynos_bus_parent_parse_of() and change in error handling.
Similar change is needed in exynos_bus_exit() where clock should be
disabled before regulators.
Signed-off-by: Kamil Konieczny <k.konieczny@partner.samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
---
Changes:
v5:
- added Acked-by tag
v4:
- move regulator disable after clock disable
- remove unrelated changes
- add disabling regulators in error path in exynos_bus_probe()
---
drivers/devfreq/exynos-bus.c | 31 +++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 486cc5b422f1..f34fa26f00d0 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -194,11 +194,10 @@ static void exynos_bus_exit(struct device *dev)
if (ret < 0)
dev_warn(dev, "failed to disable the devfreq-event devices\n");
- if (bus->regulator)
- regulator_disable(bus->regulator);
-
dev_pm_opp_of_remove_table(dev);
clk_disable_unprepare(bus->clk);
+ if (bus->regulator)
+ regulator_disable(bus->regulator);
}
/*
@@ -386,6 +385,7 @@ static int exynos_bus_probe(struct platform_device *pdev)
struct exynos_bus *bus;
int ret, max_state;
unsigned long min_freq, max_freq;
+ bool passive = false;
if (!np) {
dev_err(dev, "failed to find devicetree node\n");
@@ -399,27 +399,27 @@ static int exynos_bus_probe(struct platform_device *pdev)
bus->dev = &pdev->dev;
platform_set_drvdata(pdev, bus);
- /* Parse the device-tree to get the resource information */
- ret = exynos_bus_parse_of(np, bus);
- if (ret < 0)
- return ret;
-
profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
- if (!profile) {
- ret = -ENOMEM;
- goto err;
- }
+ if (!profile)
+ return -ENOMEM;
node = of_parse_phandle(dev->of_node, "devfreq", 0);
if (node) {
of_node_put(node);
- goto passive;
+ passive = true;
} else {
ret = exynos_bus_parent_parse_of(np, bus);
+ if (ret < 0)
+ return ret;
}
+ /* Parse the device-tree to get the resource information */
+ ret = exynos_bus_parse_of(np, bus);
if (ret < 0)
- goto err;
+ goto err_reg;
+
+ if (passive)
+ goto passive;
/* Initialize the struct profile and governor data for parent device */
profile->polling_ms = 50;
@@ -510,6 +510,9 @@ static int exynos_bus_probe(struct platform_device *pdev)
err:
dev_pm_opp_of_remove_table(dev);
clk_disable_unprepare(bus->clk);
+err_reg:
+ if (!passive)
+ regulator_disable(bus->regulator);
return ret;
}
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RESEND PATCH v5 0/4] add coupled regulators for Exynos5422/5800
From: Kamil Konieczny @ 2019-08-08 9:02 UTC (permalink / raw)
To: k.konieczny
Cc: Mark Rutland, Nishanth Menon, linux-samsung-soc, Rob Herring,
linux-arm-kernel, Bartlomiej Zolnierkiewicz, Stephen Boyd,
Viresh Kumar, linux-pm, linux-kernel, Krzysztof Kozlowski,
Chanwoo Choi, Kyungmin Park, Kukjin Kim, MyungJoo Ham, devicetree,
Marek Szyprowski
In-Reply-To: <CGME20190808090249eucas1p19944820d79ec211c85d9e1285f892f9c@eucas1p1.samsung.com>
Hi,
The main purpose of this patch series is to add coupled regulators for
Exynos5422/5800 to keep constrain on voltage difference between vdd_arm
and vdd_int to be at most 300mV. In exynos-bus instead of using
regulator_set_voltage_tol() with default voltage tolerance it should be
used regulator_set_voltage_triplet() with volatege range, and this is
already present in opp/core.c code, so it can be reused. While at this,
move setting regulators into opp/core.
This patchset was tested on Odroid XU3.
The DTS coupled regulators patch depends on previous patches.
Changes:
v5:
- squashed last patch "remove exynos_bus_passive_target()" into second
- added Acked-by to patch "correct clock enable sequence"
v4:
- removed "opp: core: add regulators enable and disable" from patchset
as it was applied by Viresh Kumar and changed cover letter
- fix patch "devfreq: exynos-bus: correct clock enable sequence" to
correct order of enable/disable
- removed unrelated changes in "devfreq: exynos-bus: convert to use
dev_pm_opp_set_rate()"
- added new patch "devfreq: exynos-bus: remove exynos_bus_passive_target()"
as suggested by Chanwoo Choi
v3:
- added new exynos-bus patch to correct clock and regulator enabling
and disabling sequence as suggested by Chanwoo Choi
- corrected error path in enable and improved commit message in opp/core
- improve comment in devfreq/exynos-bus.c before devfreq_recommended_opp()
- change cover letter as there is new patch
- added note before Signed-off-by in 4th patch
v2:
- improve regulators enable/disable code in opp/core as suggested by
Viresh Kumar
- add new patch for remove unused dt-bindings as suggested by Krzysztof
Kozlowski
Kamil Konieczny (3):
devfreq: exynos-bus: correct clock enable sequence
devfreq: exynos-bus: convert to use dev_pm_opp_set_rate()
dt-bindings: devfreq: exynos-bus: remove unused property
Marek Szyprowski (1):
ARM: dts: exynos: add initial data for coupled regulators for
Exynos5422/5800
.../bindings/devfreq/exynos-bus.txt | 2 -
arch/arm/boot/dts/exynos5420.dtsi | 34 ++--
arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 4 +
arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +
arch/arm/boot/dts/exynos5800.dtsi | 32 ++--
drivers/devfreq/exynos-bus.c | 153 +++++-------------
6 files changed, 78 insertions(+), 151 deletions(-)
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v5 0/4] add coupled regulators for Exynos5422/5800
From: Kamil Konieczny @ 2019-08-08 9:01 UTC (permalink / raw)
To: Chanwoo Choi
Cc: Mark Rutland, Nishanth Menon, linux-samsung-soc, linux-arm-kernel,
Bartlomiej Zolnierkiewicz, Stephen Boyd, Viresh Kumar, linux-pm,
linux-kernel, Krzysztof Kozlowski, Rob Herring, Kyungmin Park,
Kukjin Kim, MyungJoo Ham, devicetree, Marek Szyprowski
In-Reply-To: <6888b704-1971-4832-d7b9-092368c797d0@samsung.com>
Hi Chanwoo,
On 08.08.2019 03:47, Chanwoo Choi wrote:
> Hi Kamil,
>
> When I applied them to testing branch, those don't have the author name
> only just have the email address as following:
> You have to edit the your git author information with your name.
Sorry, I will resend with proper From: info.
> author k.konieczny@partner.samsung.com <k.konieczny@partner.samsung.com> 2019-08-07 15:38:36 +0200
> committer Chanwoo Choi <cw00.choi@samsung.com> 2019-08-08 10:35:16 +0900
> commit 4304f4ecec93cebd255463d56b0a4f112ee9dc50 (patch)
> tree 2859e566d6f68219f71a61e7c412717c1adba4f5
> parent 57d85421038b458dd87ec268404ff608f90c36ae (diff)
> download linux-4304f4ecec93cebd255463d56b0a4f112ee9dc50.tar.gz
>
> Regards,
> Chanwoo Choi
>
> On 19. 8. 7. 오후 10:38, k.konieczny@partner.samsung.com wrote:
>> [...]
--
Best regards,
Kamil Konieczny
Samsung R&D Institute Poland
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] arm64: dts: renesas: r8a77995: draak: Fix backlight regulator name
From: Geert Uytterhoeven @ 2019-08-08 9:00 UTC (permalink / raw)
To: Simon Horman; +Cc: Linux-Renesas, Magnus Damm, Geert Uytterhoeven, Linux ARM
In-Reply-To: <20190731073744.13963-1-geert+renesas@glider.be>
Hi Simon,
On Wed, Jul 31, 2019 at 9:37 AM Geert Uytterhoeven
<geert+renesas@glider.be> wrote:
> Currently there are two nodes named "regulator1" in the Draak DTS: a
> 3.3V regulator for the eMMC and the LVDS decoder, and a 12V regulator
> for the backlight. This causes the former to be overwritten by the
> latter.
>
> Fix this by renaming all regulators with numerical suffixes to use named
> suffixes, which are less likely to conflict.
>
> Fixes: 4fbd4158fe8967e9 ("arm64: dts: renesas: r8a77995: draak: Add backlight")
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> I guess this is a fix for v5.3?
Do you plan to queue this as a fix for v5.3?
Thanks!
>
> This fix takes a slightly different approach than commit
> 12105cec654cf906 ("arm64: dts: renesas: r8a77990: ebisu: Fix backlight
> regulator numbering"), which just fixed the conflicting numerical
> suffix.
> ---
> arch/arm64/boot/dts/renesas/r8a77995-draak.dts | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
> index 0711170b26b1fe1c..3aa2564dfdc25fff 100644
> --- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
> +++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
> @@ -97,7 +97,7 @@
> reg = <0x0 0x48000000 0x0 0x18000000>;
> };
>
> - reg_1p8v: regulator0 {
> + reg_1p8v: regulator-1p8v {
> compatible = "regulator-fixed";
> regulator-name = "fixed-1.8V";
> regulator-min-microvolt = <1800000>;
> @@ -106,7 +106,7 @@
> regulator-always-on;
> };
>
> - reg_3p3v: regulator1 {
> + reg_3p3v: regulator-3p3v {
> compatible = "regulator-fixed";
> regulator-name = "fixed-3.3V";
> regulator-min-microvolt = <3300000>;
> @@ -115,7 +115,7 @@
> regulator-always-on;
> };
>
> - reg_12p0v: regulator1 {
> + reg_12p0v: regulator-12p0v {
> compatible = "regulator-fixed";
> regulator-name = "D12.0V";
> regulator-min-microvolt = <12000000>;
> --
> 2.17.1
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] dt-bindings: Rename file of DT bindings for Renesas memory controllers
From: Geert Uytterhoeven @ 2019-08-08 8:58 UTC (permalink / raw)
To: Simon Horman; +Cc: Linux-Renesas, Magnus Damm, Linux ARM, Geert Uytterhoeven
In-Reply-To: <20190716112619.ielypcsnclg6sa27@verge.net.au>
Hi Simon,
On Tue, Jul 16, 2019 at 1:26 PM Simon Horman <horms@verge.net.au> wrote:
> On Wed, Jul 03, 2019 at 11:33:36AM +0200, Geert Uytterhoeven wrote:
> > On Wed, Jul 3, 2019 at 10:41 AM Simon Horman <horms+renesas@verge.net.au> wrote:
> > > For consistency with the naming of (most) other documentation files for DT
> > > bindings for Renesas IP blocks rename the Renesas R-Mobile and SH-Mobile
> > > memory controllers documentation file from renesas-memory-controllers.txt
> > > to renesas,dbsc.txt.
> > >
> > > Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
> >
> > Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
>
> Hi Geert,
>
> are you planing to take this through renesas-devel?
Thanks, queued in renesas-devel/renesas-dt-bindings-for-v5.4.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox