* [PATCH v6 4/9] dt-bindings: input: touchscreen: resistive-adc-touch: create bindings
From: Eugen Hristev @ 2018-05-21 10:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526898477-9952-1-git-send-email-eugen.hristev@microchip.com>
Added bindings for generic resistive touchscreen ADC.
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
Changes in v5:
- changed property name touchscreen-threshold-pressure to
touchscreen-min-pressure
Changes in v3:
- renamed file and compatible to exclude "generic" keyword
- removed the pressure threshold property, added it as a common
touchscreen property in the touchscreen common bindings in a separate
commit.
Changes in v2:
- modified bindings to have a generic resistive touchscreen adc driver
instead of specific architecture one.
.../input/touchscreen/resistive-adc-touch.txt | 30 ++++++++++++++++++++++
1 file changed, 30 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
diff --git a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
new file mode 100644
index 0000000..51456c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
@@ -0,0 +1,30 @@
+Generic resistive touchscreen ADC
+
+Required properties:
+
+ - compatible: must be "resistive-adc-touch"
+The device must be connected to an ADC device that provides channels for
+position measurement and optional pressure.
+Refer to ../iio/iio-bindings.txt for details
+ - iio-channels: must have at least two channels connected to an ADC device.
+These should correspond to the channels exposed by the ADC device and should
+have the right index as the ADC device registers them. These channels
+represent the relative position on the "x" and "y" axes.
+ - iio-channel-names: must have all the channels' names. Mandatory channels
+are "x" and "y".
+
+Optional properties:
+ - iio-channels: The third channel named "pressure" is optional and can be
+used if the ADC device also measures pressure besides position.
+If this channel is missing, pressure will be ignored and the touchscreen
+will only report position.
+ - iio-channel-names: optional channel named "pressure".
+
+Example:
+
+ resistive_touch: resistive_touch {
+ compatible = "resistive-adc-touch";
+ touchscreen-min-pressure = <50000>;
+ io-channels = <&adc 24>, <&adc 25>, <&adc 26>;
+ io-channel-names = "x", "y", "pressure";
+ };
--
2.7.4
^ permalink raw reply related
* [PATCH v6 3/9] dt-bindings: input: touchscreen: add minimum pressure touchscreen property
From: Eugen Hristev @ 2018-05-21 10:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526898477-9952-1-git-send-email-eugen.hristev@microchip.com>
Add a common touchscreen optional property that will specify
the minimum pressure applied to the screen that is needed
such that the driver will report the touch event.
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
Changes in v5:
- Modified property name to touchscreen-min-pressure from
touchscreen-threshold-property
Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
index 537643e..d092d5d 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
@@ -7,6 +7,9 @@ Optional properties for Touchscreens:
(in pixels)
- touchscreen-max-pressure : maximum reported pressure (arbitrary range
dependent on the controller)
+ - touchscreen-min-pressure : minimum pressure on the touchscreen to be
+ achieved in order for the touchscreen
+ driver to report a touch event.
- touchscreen-fuzz-x : horizontal noise value of the absolute input
device (in pixels)
- touchscreen-fuzz-y : vertical noise value of the absolute input
--
2.7.4
^ permalink raw reply related
* [PATCH v6 2/9] iio: Add channel for Position Relative
From: Eugen Hristev @ 2018-05-21 10:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526898477-9952-1-git-send-email-eugen.hristev@microchip.com>
Add new channel type for relative position on a pad.
These type of analog sensor offers the position of a pen
on a touchpad, and is represented as a voltage, which can be
converted to a position on X and Y axis on the pad.
The channel will hand the relative position on the pad in both directions.
The channel can then be consumed by a touchscreen driver or
read as-is for a raw indication of the touchpen on a touchpad.
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
---
Changes in v2:
- modified channel name to relative position as suggested.
- modified kernel version to 4.18 (presumable)
Documentation/ABI/testing/sysfs-bus-iio | 12 ++++++++++++
drivers/iio/industrialio-core.c | 1 +
include/uapi/linux/iio/types.h | 1 +
tools/iio/iio_event_monitor.c | 2 ++
4 files changed, 16 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 6a5f34b..42a9287 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -190,6 +190,18 @@ Description:
but should match other such assignments on device).
Units after application of scale and offset are m/s^2.
+What: /sys/bus/iio/devices/iio:deviceX/in_positionrelative_x_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_positionrelative_y_raw
+KernelVersion: 4.18
+Contact: linux-iio at vger.kernel.org
+Description:
+ Relative position in direction x or y on a pad (may be
+ arbitrarily assigned but should match other such assignments on
+ device).
+ Units after application of scale and offset are milli percents
+ from the pad's size in both directions. Should be calibrated by
+ the consumer.
+
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_raw
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_raw
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_raw
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 19bdf3d..14bf3d24 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -85,6 +85,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_COUNT] = "count",
[IIO_INDEX] = "index",
[IIO_GRAVITY] = "gravity",
+ [IIO_POSITIONRELATIVE] = "positionrelative",
};
static const char * const iio_modifier_names[] = {
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index 4213cdf..033c7d2 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -44,6 +44,7 @@ enum iio_chan_type {
IIO_COUNT,
IIO_INDEX,
IIO_GRAVITY,
+ IIO_POSITIONRELATIVE,
};
enum iio_modifier {
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index b61245e..148f69d 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -58,6 +58,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_PH] = "ph",
[IIO_UVINDEX] = "uvindex",
[IIO_GRAVITY] = "gravity",
+ [IIO_POSITIONRELATIVE] = "positionrelative",
};
static const char * const iio_ev_type_text[] = {
@@ -151,6 +152,7 @@ static bool event_is_known(struct iio_event_data *event)
case IIO_PH:
case IIO_UVINDEX:
case IIO_GRAVITY:
+ case IIO_POSITIONRELATIVE:
break;
default:
return false;
--
2.7.4
^ permalink raw reply related
* [PATCH v6 1/9] MAINTAINERS: add generic resistive touchscreen adc
From: Eugen Hristev @ 2018-05-21 10:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526898477-9952-1-git-send-email-eugen.hristev@microchip.com>
Add MAINTAINERS entry for generic resistive touchscreen adc
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
---
Changes in v3:
- Changed source file name
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 3bdc260..ce9720f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5943,6 +5943,12 @@ F: drivers/base/power/domain*.c
F: include/linux/pm_domain.h
F: Documentation/devicetree/bindings/power/power_domain.txt
+GENERIC RESISTIVE TOUCHSCREEN ADC DRIVER
+M: Eugen Hristev <eugen.hristev@microchip.com>
+L: linux-input at vger.kernel.org
+S: Maintained
+F: drivers/input/touchscreen/resistive-adc-touch.c
+
GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <mst@redhat.com>
L: kvm at vger.kernel.org
--
2.7.4
^ permalink raw reply related
* [PATCH v6 0/9] Add support for SAMA5D2 touchscreen
From: Eugen Hristev @ 2018-05-21 10:27 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
This patch series is a rework of my previous series named:
[PATCH 00/14] iio: triggers: add consumer support
This is the version 6 of the series, and addresses the received feedback
on the v2 series named:
[PATCH v2 00/10] Add support for SAMA5D2 touchscreen
and the v3 series named
[PATCH v3 00/11] Add support for SAMA5D2 touchscreen
and the v4 series named
[PATCH v4 0/9] Add support for SAMA5D2 touchscreen
and fixes one bug found in series named
[PATCH v5 0/9] Add support for SAMA5D2 touchscreen
This series applies on top of fixes-togreg branch of iio.git,
specifically on top of commit:
"f0c8d1f" : iio: adc: at91-sama5d2_adc:
fix channel configuration for differential channels
Jonathan, if you need me to rebase this on top of testing, let me know.
Changes in v3, v4, v5 and v6 are presented at the end of the cover letter below.
Thanks everyone for the feedback. Below is the original v2 cover letter:
In few words, this is the implementation of splitting the functionality
of the IP block ADC device in SAMA5D2 SoC from ADC with touchscreen
support. In order to avoid having a MFD device, two separate
drivers that would work on same register base and split the IRQ,etc,
as advised on the mailing list, I created a consumer driver for the
channels, that will connect to the ADC as described in the device tree.
I have collected feedback from everyone and here is the result:
I have added a new generic resistive touchscreen driver, which acts
as a iio consumer for the given channels and will create an input
device and report the events. It uses a callback buffer to register
to the IIO device and waits for data to be pushed.
Inside the IIO device, I have kept a similar approach with the first version
of the series, except that now the driver can take multiple buffers, and
will configure the touchscreen part of the hardware device if the specific
channels are requested.
The SAMA5D2 ADC driver registers three new channels: two for the
position on the X and Y axis, and one for the touch pressure.
When channels are requested, it will check if the touchscreen channel mask
includes the requested channels (it is possible that the consumer driver
will not request pressure for example). If it's the case, it will work
in touchscreen mode, and will refuse to do usual analog-digital conversion,
because we have a single trigger and the touchscreen needs it.
When the scan mask will include only old channels, the driver will function
in the same way as before. If the scan mask somehow is a mix of the two (the
masks intersect), the driver will refuse to work whatsoever (cannot have both
in the same time).
The driver allows reading raw data for the new channels, if claim direct
mode works: no touchscreen driver requested anything. The new channels can
act like the old ones. However, when requesting these channels, the usual
trigger will not work and will not be enabled. The touchscreen channels
require special trigger and irq configuration: pen detect, no pen detect
and a periodic trigger to sample the touchscreen position and pressure.
If the user attempts to use another trigger while there is a buffer
that already requested the touchscreen channels (thus the trigger), the
driver will refuse to comply.
In order to have defines for the channel numbers, I added a bindings include
file that goes on a separate commit :
dt-bindings: iio: adc: at91-sama5d2_adc: add channel specific consumer info
This should go in the same tree with the following commits :
ARM: dts: at91: sama5d2: add channel cells for ADC device
ARM: dts: at91: sama5d2: Add resistive touch device
as build will break because these commits depend on the binding one
which creates the included header file.
V5 update: After discussing with Alexandre Belloni on Mailing list, the two
DTS patches are to be taken in the next version after bindings reach mainline.
Changes in v6:
- Fixed a crash in ADC driver , explained in driver patch changelog.
- changed a dev_err to dev_dbg in input driver.
- added Reviewed-by Rob Herring.
Changes in v5:
- renamed property touchscreen-threshold-pressure to touchscreen-min-pressure
- added one return in touchscreen driver
Changes in v4:
- removed patch for inkern module get/set kref
- addressed feedback on both the ADC and the touchscreen driver. each
patch has a history inside the patch file for the specific changes.
- patch that fixes the channel fix
[PATCH v3 01/11] iio: adc: at91-sama5d2_adc:
fix channel configuration for differential channels
was accepted in fixes-togreg branch thus removed from this series.
- added Reviewed-by for the bindings by Rob Herring
Changes in v3:
- changed input driver name according to feedback and reworked in commits
to adapt to binding changes and new name.
- moved channel index fix in at91-sama5d2_adc at the beginning of the series
(PATCH 01/11)
- created a new optional binding for the touchscreen as a separate commit
and added it to the series :
[PATCH v3 04/11] dt-bindings: input: touchscreen: add pressure
threshold touchscreen property
- changed at91-sama5d2_adc driver patch to address the comments. Exact changes
are in the patch file for the driver source file.
Eugen Hristev (9):
MAINTAINERS: add generic resistive touchscreen adc
iio: Add channel for Position Relative
dt-bindings: input: touchscreen: add minimum pressure touchscreen
property
dt-bindings: input: touchscreen: resistive-adc-touch: create bindings
iio: adc: at91-sama5d2_adc: add support for position and pressure
channels
input: touchscreen: resistive-adc-touch: add generic resistive ADC
touchscreen
dt-bindings: iio: adc: at91-sama5d2_adc: add channel specific consumer
info
ARM: dts: at91: sama5d2: add channel cells for ADC device
ARM: dts: at91: sama5d2: Add resistive touch device
Documentation/ABI/testing/sysfs-bus-iio | 12 +
.../bindings/iio/adc/at91-sama5d2_adc.txt | 9 +
.../input/touchscreen/resistive-adc-touch.txt | 30 +
.../bindings/input/touchscreen/touchscreen.txt | 3 +
MAINTAINERS | 6 +
arch/arm/boot/dts/sama5d2.dtsi | 12 +
drivers/iio/adc/at91-sama5d2_adc.c | 609 +++++++++++++++++++--
drivers/iio/industrialio-core.c | 1 +
drivers/input/touchscreen/Kconfig | 13 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/resistive-adc-touch.c | 201 +++++++
include/dt-bindings/iio/adc/at91-sama5d2_adc.h | 16 +
include/uapi/linux/iio/types.h | 1 +
tools/iio/iio_event_monitor.c | 2 +
14 files changed, 858 insertions(+), 58 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
create mode 100644 drivers/input/touchscreen/resistive-adc-touch.c
create mode 100644 include/dt-bindings/iio/adc/at91-sama5d2_adc.h
--
2.7.4
^ permalink raw reply
* [kvmarm:queue 13/29] arch/arm/kvm/../../../virt/kvm/arm/arm.c:1598:6: error: implicit declaration of function 'system_supports_sve'
From: Dave Martin @ 2018-05-21 10:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201805210615.tc7bzjhx%fengguang.wu@intel.com>
On Mon, May 21, 2018 at 06:12:16AM +0800, kbuild test robot wrote:
> tree: https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git queue
> head: f2d1aab22d57235b58db391d318727d3e5ef1e89
> commit: 61d47b5d95db9a4ce12c50ffaa6918a40619984f [13/29] KVM: arm64: Save host SVE context as appropriate
> config: arm-axm55xx_defconfig (attached as .config)
> compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
> reproduce:
> wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> git checkout 61d47b5d95db9a4ce12c50ffaa6918a40619984f
> # save the attached .config to linux build tree
> make.cross ARCH=arm
>
> All errors (new ones prefixed by >>):
>
> arch/arm/kvm/../../../virt/kvm/arm/arm.c: In function 'kvm_arch_vcpu_ioctl_run':
> arch/arm/kvm/../../../virt/kvm/arm/arm.c:785:3: error: implicit declaration of function 'kvm_arch_vcpu_ctxsync_fp'; did you mean 'kvm_arch_vcpu_put_fp'? [-Werror=implicit-function-declaration]
> kvm_arch_vcpu_ctxsync_fp(vcpu);
> ^~~~~~~~~~~~~~~~~~~~~~~~
> kvm_arch_vcpu_put_fp
> arch/arm/kvm/../../../virt/kvm/arm/arm.c: In function 'kvm_arch_init':
> >> arch/arm/kvm/../../../virt/kvm/arm/arm.c:1598:6: error: implicit declaration of function 'system_supports_sve' [-Werror=implicit-function-declaration]
> if (system_supports_sve() && !has_vhe()) {
> ^~~~~~~~~~~~~~~~~~~
> cc1: some warnings being treated as errors
>
> vim +/system_supports_sve +1598 arch/arm/kvm/../../../virt/kvm/arm/arm.c
>
> 1564
> 1565 /**
> 1566 * Initialize Hyp-mode and memory mappings on all CPUs.
> 1567 */
> 1568 int kvm_arch_init(void *opaque)
> 1569 {
> 1570 int err;
> 1571 int ret, cpu;
> 1572 bool in_hyp_mode;
> 1573
> 1574 if (!is_hyp_mode_available()) {
> 1575 kvm_info("HYP mode not available\n");
> 1576 return -ENODEV;
> 1577 }
> 1578
> 1579 for_each_online_cpu(cpu) {
> 1580 smp_call_function_single(cpu, check_kvm_target_cpu, &ret, 1);
> 1581 if (ret < 0) {
> 1582 kvm_err("Error, CPU %d not supported!\n", cpu);
> 1583 return -ENODEV;
> 1584 }
> 1585 }
> 1586
> 1587 /*
> 1588 * VHE is a prerequisite for SVE in the Arm architecture, and
> 1589 * Kconfig ensures that if system_supports_sve() here then
> 1590 * CONFIG_ARM64_VHE is enabled, so if VHE support wasn't already
> 1591 * detected and enabled, the CPU is architecturally
> 1592 * noncompliant.
> 1593 *
> 1594 * Just in case this mismatch is seen, detect it, warn and give
> 1595 * up. Supporting this forbidden configuration in Hyp would be
> 1596 * pointless.
> 1597 */
> > 1598 if (system_supports_sve() && !has_vhe()) {
OK, these were a couple of brainos in a late version of the branch that
I didn't rebuild for arm, where things got renamed or I inserted
arm64-specific calls in common code. My bad :(
I'll push out fixes today.
Cheers
---Dave
^ permalink raw reply
* [PATCH v9 02/12] drivers: base: cacheinfo: setup DT cache properties early
From: Sudeep Holla @ 2018-05-21 10:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7c9a4921-d4da-f1db-85ed-7d7f917be30c@arm.com>
On 21/05/18 10:27, Sudeep Holla wrote:
>
>
> On 18/05/18 22:50, Andy Shevchenko wrote:
>> On Thu, May 17, 2018 at 6:47 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>> Is below patch does what you were looking for ?
>>
>> Somewhat.
>> See below for some minors.
>>
>
> Thanks
>
>>> of_property_read_u64 searches for a property in a device node and read
>>> a 64-bit value from it. Instead of using of_get_property to get the
>>> property and then read 64-bit value using of_read_number, we can make
>>> use of of_property_read_u64.
>>
>> Suggested-by?
>>
>
> Yes indeed, added it locally after I sent out this patch. Will send out
> a proper patch soon.
>
>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>
>>
>>> - cache_size = of_get_property(np, propname, NULL);
>>> - if (cache_size)
>>> - this_leaf->size = of_read_number(cache_size, 1);
>>> + if (!of_property_read_u64(np, propname, &cache_size))
>>> + this_leaf->size = cache_size;
>>
>> I suppose it's something like this
>>
>> ret = of_property_...(..., &this_leaf->VAR);
>> if (ret)
>> warning / set default / etc
>
> OK, I do prefer this but once I was told not to use structure elements
> directly like that, but should be harmless in this particular case, will
> do so.
>
I spoke too early, I need to retain local u64 variable otherwise we get
incompatible pointer type(expected 'u64 *' but argument is of type
?unsigned int *?) error with Werror=incompatible-pointer-types.
--
Regards,
Sudeep
^ permalink raw reply
* [PATCH v9 07/11] arm64: kexec_file: add crash dump support
From: AKASHI Takahiro @ 2018-05-21 10:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518153552.GA23468@rob-hp-laptop>
Hi Rob,
On Fri, May 18, 2018 at 10:35:52AM -0500, Rob Herring wrote:
> On Tue, May 15, 2018 at 06:12:59PM +0100, James Morse wrote:
> > Hi guys,
> >
> > (CC: +RobH, devicetree list)
>
> Thanks.
>
> > On 25/04/18 07:26, AKASHI Takahiro wrote:
> > > Enabling crash dump (kdump) includes
> > > * prepare contents of ELF header of a core dump file, /proc/vmcore,
> > > using crash_prepare_elf64_headers(), and
> > > * add two device tree properties, "linux,usable-memory-range" and
> > > "linux,elfcorehdr", which represent repsectively a memory range
> > > to be used by crash dump kernel and the header's location
>
> BTW, I intend to move existing parsing these out of the arch code.
> Please don't add more DT handling to arch/ unless it is *really* arch
> specific. I'd assume that the next arch to add kexec support will use
> these bindings instead of the powerpc way.
So do you expect all the fdt-related stuff in my current implementation
for arm64 to be put into libfdt, or at least drivers/of, from the beginning?
I'm not sure how arch-specific the properties here are. For instance,
it is only arm64 that uses "linux,usable-memory-range" right now but
if some other arch follows, it is no more arch-specific.
# I remember that you didn't like this property :)
> > kexec_file_load() on arm64 needs to be able to create a prop encoded array to
> > the FDT, but there doesn't appear to be a libfdt helper to do this.
> >
> > Akashi's code below adds fdt_setprop_range() to the arch code, and duplicates
> > bits of libfdt_internal.h to do the work.
> >
> > How should this be done? I'm assuming this is something we need a new API in
> > libfdt.h for. How do these come about, and is there an interim step we can use
> > until then?
>
> Submit patches to upstream dtc and then we can pull it in. Ahead of that
> you can add it to drivers/of/fdt.c (or maybe fdt_address.c because
> that's really what this is dealing with).
OK, I'm going to try to follow your suggestion.
> libfdt has only recently gained the beginnings of address handling.
>
> >
> > Thanks!
> >
> > James
> >
> > > diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
> > > index 37c0a9dc2e47..ec674f4d267c 100644
> > > --- a/arch/arm64/kernel/machine_kexec_file.c
> > > +++ b/arch/arm64/kernel/machine_kexec_file.c
> > > @@ -76,6 +81,78 @@ int arch_kexec_walk_mem(struct kexec_buf *kbuf,
> > > return ret;
> > > }
> > >
> > > +static int __init arch_kexec_file_init(void)
> > > +{
> > > + /* Those values are used later on loading the kernel */
> > > + __dt_root_addr_cells = dt_root_addr_cells;
> > > + __dt_root_size_cells = dt_root_size_cells;
>
> I intend to make dt_root_*_cells private, so don't add another user
> outside of drivers/of/.
Once cells_size_fitted() moves to drivers/of, there will be no users.
> > > +
> > > + return 0;
> > > +}
> > > +late_initcall(arch_kexec_file_init);
> > > +
> > > +#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
> > > +#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
> > > +
> > > +static int fdt_prop_len(const char *prop_name, int len)
> > > +{
> > > + return (strlen(prop_name) + 1) +
> > > + sizeof(struct fdt_property) +
> > > + FDT_TAGALIGN(len);
> > > +}
> > > +
> > > +static bool cells_size_fitted(unsigned long base, unsigned long size)
>
> I can't imagine this would happen. However, when this is moved to
> drivers/of/ or dtc, these need to be u64 types to work on 32-bit.
OK.
> > > + /* if *_cells >= 2, cells can hold 64-bit values anyway */
> > > + if ((__dt_root_addr_cells == 1) && (base >= (1ULL << 32)))
> > > + return false;
> > > +
> > > + if ((__dt_root_size_cells == 1) && (size >= (1ULL << 32)))
> > > + return false;
> > > +
> > > + return true;
> > > +}
> > > +
> > > +static void fill_property(void *buf, u64 val64, int cells)
> > > +{
> > > + u32 val32;
>
> This should be a __be32 or fdt32 type. So should buf.
OK for val32, but buf is a local pointer address.
> > > +
> > > + if (cells == 1) {
> > > + val32 = cpu_to_fdt32((u32)val64);
> > > + memcpy(buf, &val32, sizeof(val32));
> > > + } else {
> > > + memset(buf, 0, cells * sizeof(u32) - sizeof(u64));
> > > + buf += cells * sizeof(u32) - sizeof(u64);
> > > +
> > > + val64 = cpu_to_fdt64(val64);
> > > + memcpy(buf, &val64, sizeof(val64));
>
> Look how of_read_number() is implemented. You should be able to do
> something similar here looping and avoiding the if/else.
Ah, excellent!
> > > + }
> > > +}
> > > +
> > > +static int fdt_setprop_range(void *fdt, int nodeoffset, const char *name,
> > > + unsigned long addr, unsigned long size)
>
> A very generic sounding function, but really only works on addresses in
> children of the root node.
>
> > > +{
> > > + void *buf, *prop;
> > > + size_t buf_size;
> > > + int result;
> > > +
> > > + buf_size = (__dt_root_addr_cells + __dt_root_size_cells) * sizeof(u32);
> > > + prop = buf = vmalloc(buf_size);
>
> This can go on the stack instead (and would be required to to work in
> libfdt).
Well, I can't agree with you here since we are now in effort, as far as
I correctly understand, of purging all the variable-sized arrays on a local
stack out of the kernel code.
Thank you for your review.
-Takahiro AKASHI
> > > + if (!buf)
> > > + return -ENOMEM;
> > > +
> > > + fill_property(prop, addr, __dt_root_addr_cells);
> > > + prop += __dt_root_addr_cells * sizeof(u32);
> > > +
> > > + fill_property(prop, size, __dt_root_size_cells);
> > > +
> > > + result = fdt_setprop(fdt, nodeoffset, name, buf, buf_size);
> > > +
> > > + vfree(buf);
> > > +
> > > + return result;
> > > +}
> > > +
> > > static int setup_dtb(struct kimage *image,
> > > unsigned long initrd_load_addr, unsigned long initrd_len,
> > > char *cmdline, unsigned long cmdline_len,
> > > @@ -88,10 +165,26 @@ static int setup_dtb(struct kimage *image,
> > > int range_len;
> > > int ret;
> > >
> > > + /* check ranges against root's #address-cells and #size-cells */
> > > + if (image->type == KEXEC_TYPE_CRASH &&
> > > + (!cells_size_fitted(image->arch.elf_load_addr,
> > > + image->arch.elf_headers_sz) ||
> > > + !cells_size_fitted(crashk_res.start,
> > > + crashk_res.end - crashk_res.start + 1))) {
> > > + pr_err("Crash memory region doesn't fit into DT's root cell sizes.\n");
> > > + ret = -EINVAL;
> > > + goto out_err;
> > > + }
> > > +
> > > /* duplicate dt blob */
> > > buf_size = fdt_totalsize(initial_boot_params);
> > > range_len = (__dt_root_addr_cells + __dt_root_size_cells) * sizeof(u32);
> > >
> > > + if (image->type == KEXEC_TYPE_CRASH)
> > > + buf_size += fdt_prop_len("linux,elfcorehdr", range_len)
> > > + + fdt_prop_len("linux,usable-memory-range",
> > > + range_len);
> > > +
> > > if (initrd_load_addr)
> > > buf_size += fdt_prop_len("linux,initrd-start", sizeof(u64))
> > > + fdt_prop_len("linux,initrd-end", sizeof(u64));
> > > @@ -113,6 +206,23 @@ static int setup_dtb(struct kimage *image,
> > > if (nodeoffset < 0)
> > > goto out_err;
> > >
> > > + if (image->type == KEXEC_TYPE_CRASH) {
> > > + /* add linux,elfcorehdr */
> > > + ret = fdt_setprop_range(buf, nodeoffset, "linux,elfcorehdr",
> > > + image->arch.elf_load_addr,
> > > + image->arch.elf_headers_sz);
> > > + if (ret)
> > > + goto out_err;
> > > +
> > > + /* add linux,usable-memory-range */
> > > + ret = fdt_setprop_range(buf, nodeoffset,
> > > + "linux,usable-memory-range",
> > > + crashk_res.start,
> > > + crashk_res.end - crashk_res.start + 1);
> > > + if (ret)
> > > + goto out_err;
> > > + }
> > > +
> > > /* add bootargs */
> > > if (cmdline) {
> > > ret = fdt_setprop(buf, nodeoffset, "bootargs",
> >
^ permalink raw reply
* [PATCH v7 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle
From: Lorenzo Pieralisi @ 2018-05-21 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518195154.GB41790@bhelgaas-glaptop.roam.corp.google.com>
On Fri, May 18, 2018 at 02:51:54PM -0500, Bjorn Helgaas wrote:
> On Fri, May 04, 2018 at 01:47:33PM +0800, honghui.zhang at mediatek.com wrote:
> > From: Honghui Zhang <honghui.zhang@mediatek.com>
> >
> > Using irq_chip solution to setup IRQs in order to consist
> > with IRQ framework.
> >
> > Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> > Acked-by: Ryder Lee <ryder.lee@mediatek.com>
> > ---
> > drivers/pci/host/pcie-mediatek.c | 206 ++++++++++++++++++++++-----------------
> > 1 file changed, 115 insertions(+), 91 deletions(-)
> >
> > diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> > index c3dc549..dabf1086 100644
> > --- a/drivers/pci/host/pcie-mediatek.c
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > ...
>
> > -static int mtk_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
> > - irq_hw_number_t hwirq)
> > +static struct msi_domain_info mtk_msi_domain_info = {
>
> I think this patch should be amended to include this:
>
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index 0d0177ce436c..368b70d9371b 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -193,7 +193,7 @@ config PCIE_MEDIATEK
> bool "MediaTek PCIe controller"
> depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
> depends on OF
> - depends on PCI
> + depends on PCI_MSI_IRQ_DOMAIN
> select PCIEPORTBUS
> help
> Say Y here if you want to enable PCIe controller support on
>
>
> Lorenzo, if you want to fold that in and update your branch, I can pull it.
> If not, I can add a patch on top, which should only break compile-testing
> bisection.
I folded the patch above and pushed into pci/mediatek, thanks !
Lorenzo
^ permalink raw reply
* [PATCH 3/6] ASoC: ams_delta: use GPIO lookup table
From: Mark Brown @ 2018-05-21 10:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518210954.29044-3-jmkrzyszt@gmail.com>
On Fri, May 18, 2018 at 11:09:51PM +0200, Janusz Krzysztofik wrote:
> Now as the Amstrad Delta board provides GPIO lookup tables, switch from
> GPIO numbers to GPIO descriptors and use the table to locate required
> GPIO pins.
Acked-by: Mark Brown <broonie@kernel.org>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180521/1da3f49e/attachment.sig>
^ permalink raw reply
* [PULL v8] KVM: arm64: Optimise FPSIMD context switching
From: Dave Martin @ 2018-05-21 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180520141441.3d999f16@why.wild-wind.fr.eu.org>
On Sun, May 20, 2018 at 02:14:41PM +0100, Marc Zyngier wrote:
> On Wed, 16 May 2018 11:49:42 +0100
> Dave Martin <Dave.Martin@arm.com> wrote:
>
> Hi Dave,
>
> > Hi Marc,
> >
> > This is a trivial update to the previously posted v7 [1]. The only
> > changes are a couple of minor cosmetic changes requested by reviewers,
> > on-list and the addition of Acked-by/Reviewed-by tags received since the
> > series was posted.
> >
> > Let me know if you need anything else on this.
>
> So I've taken this, merged in Linus' top of tree, started a guest on a
> dual A53 board, and immediately hit the following:
>
> root at sy-borg:~# [ 287.226184] Unable to handle kernel NULL pointer dereference at virtual address 00000000
> [ 287.231672] Mem abort info:
> [ 287.234537] ESR = 0x96000044
> [ 287.237674] Exception class = DABT (current EL), IL = 32 bits
> [ 287.243765] SET = 0, FnV = 0
> [ 287.246900] EA = 0, S1PTW = 0
> [ 287.250126] Data abort info:
> [ 287.253083] ISV = 0, ISS = 0x00000044
> [ 287.257025] CM = 0, WnR = 1
> [ 287.260076] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000b8483f75
> [ 287.266882] [0000000000000000] pgd=0000000000000000
> [ 287.271903] Internal error: Oops: 96000044 [#1] PREEMPT SMP
> [ 287.277636] Modules linked in:
> [ 287.280776] CPU: 1 PID: 3098 Comm: kworker/u4:3 Not tainted 4.17.0-rc5-00166-gd84e81cca249 #136
> [ 287.289730] Hardware name: Globalscale Marvell ESPRESSOBin Board (DT)
> [ 287.296364] pstate: 40000085 (nZcv daIf -PAN -UAO)
> [ 287.301301] pc : fpsimd_save_state+0x0/0x54
> [ 287.305595] lr : fpsimd_save+0x50/0x100
> [ 287.309531] sp : ffff00000dde3af0
> [ 287.312936] x29: ffff00000dde3af0 x28: ffff000008cd565c
> [ 287.318401] x27: ffff800078ee9c80 x26: ffff80007b207628
> [ 287.323867] x25: ffff0000093f9000 x24: 0000000000000001
> [ 287.329333] x23: ffff0000093d4000 x22: ffff80007b207000
> [ 287.334798] x21: ffff80007efd7d80 x20: ffff80007b207000
> [ 287.340264] x19: 0000000000000000 x18: 0000000000040f0b
> [ 287.345729] x17: 0000ffffb70752b8 x16: 0000ffffb708e008
> [ 287.351195] x15: 0000000000000000 x14: 0000000000000400
> [ 287.356661] x13: 0000000000000001 x12: 0000000000000001
> [ 287.362127] x11: 0000000000000001 x10: 0000000000000000
> [ 287.367592] x9 : 0000000000000253 x8 : ffff80007b207200
> [ 287.373057] x7 : ffff80007b207100 x6 : ffff80007c378f18
> [ 287.378523] x5 : 00000042c2094c00 x4 : 0000000000000000
> [ 287.383990] x3 : 00000042e0033450 x2 : 0000000000000000
> [ 287.389454] x1 : 0000800075bf6000 x0 : 0000000000000000
> [ 287.394922] Process kworker/u4:3 (pid: 3098, stack limit = 0x00000000ca0dd8c6)
> [ 287.402358] Call trace:
> [ 287.404873] fpsimd_save_state+0x0/0x54
> [ 287.408813] fpsimd_thread_switch+0x28/0xa0
> [ 287.413114] __switch_to+0x1c/0xd0
> [ 287.416609] __schedule+0x1b8/0x730
> [ 287.420191] preempt_schedule_common+0x24/0x48
> [ 287.424760] preempt_schedule.part.23+0x1c/0x28
> [ 287.429419] preempt_schedule+0x1c/0x28
> [ 287.433363] _raw_spin_unlock+0x34/0x48
> [ 287.437308] flush_old_exec+0x45c/0x6a0
> [ 287.441250] load_elf_binary+0x324/0x1198
> [ 287.445372] search_binary_handler+0xac/0x230
> [ 287.449851] do_execveat_common.isra.14+0x508/0x6e0
> [ 287.454867] do_execve+0x28/0x30
> [ 287.458185] call_usermodehelper_exec_async+0xdc/0x140
> [ 287.463468] ret_from_fork+0x10/0x18
> [ 287.467143] Code: a9425bf5 a8c37bfd d65f03c0 d65f03c0 (ad000400)
> [ 287.473414] ---[ end trace c4346b99cc877f8e ]---
>
> It happened just after having loaded the guest kernel, so I presume
> we're missing some kind of initialization. I couldn't subsequently
> reproduce it on the same machine, and the same kernel is doing
> absolutely fine on a Seattle box.
Curious, this is a kernel thread, which shouldn't have any fpsimd state
of its own. It would be interesting to know what ran before, but tricky
to find that out now unless we can find a way to repoduce...
Maybe a thread flag has ended up in the wrong state.
> I can't immediately see how st would be NULL, unless we somehow are
> missing some state tracking somewhere...
This might be a race, or a missing piece of logic somewhere... I'll
take a look.
Cheers
---Dave
^ permalink raw reply
* [PATCH v3 2/3] arm64: dts: renesas: draak: Describe CVBS input
From: jacopo mondi @ 2018-05-21 9:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1569661.saMqNra8vc@avalon>
Hi Laurent,
On Fri, May 18, 2018 at 06:12:15PM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Friday, 18 May 2018 17:47:57 EEST Jacopo Mondi wrote:
> > Describe CVBS video input through analog video decoder ADV7180
> > connected to video input interface VIN4.
> >
> > The video input signal path is shared with HDMI video input, and
> > selected by on-board switches SW-53 and SW-54 with CVBS input selected
> > by the default switches configuration.
> >
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > Reviewed-by: Niklas S?derlund <niklas.soderlund+renesas@ragnatech.se>
> >
> > ---
> > v2 -> v3:
> > - Add comment to describe the shared input video path
> > - Add my SoB and Niklas' R-b tags
> > ---
> > arch/arm64/boot/dts/renesas/r8a77995-draak.dts | 42 +++++++++++++++++++++++
> > 1 file changed, 42 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
> > b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts index 9d73de8..95745fc
> > 100644
> > --- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
> > +++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
> > @@ -142,6 +142,11 @@
> > groups = "usb0";
> > function = "usb0";
> > };
> > +
> > + vin4_pins_cvbs: vin4 {
> > + groups = "vin4_data8", "vin4_sync", "vin4_clk";
> > + function = "vin4";
> > + };
> > };
> >
> > &i2c0 {
> > @@ -154,6 +159,23 @@
> > reg = <0x50>;
> > pagesize = <8>;
> > };
> > +
> > + analog-video at 20 {
> > + compatible = "adi,adv7180";
> > + reg = <0x20>;
> > +
> > + port {
>
> The adv7180 DT bindings document the output port as 3 or 6 (respectively for
> the CP and ST versions of the chip). You should thus number the port. Apart
> from that the patch looks good.
I admit I have barely copied this from Gen-2 boards DTS, but reading
the driver code and binding description again, I think this is
correct, as the output port numbering and mandatory input port (which
is missing here) only apply to adv7180cp/st chip versions.
Here we describe plain adv7180, no need to number output ports afaict.
Thanks
j
>
> > + /*
> > + * The VIN4 video input path is shared between
> > + * CVBS and HDMI inputs through SW[49-54] switches.
> > + *
> > + * CVBS is the default selection, link it to VIN4 here.
> > + */
> > + adv7180_out: endpoint {
> > + remote-endpoint = <&vin4_in>;
> > + };
> > + };
> > + };
> > };
> >
> > &i2c1 {
> > @@ -246,3 +268,23 @@
> > timeout-sec = <60>;
> > status = "okay";
> > };
> > +
> > +&vin4 {
> > + pinctrl-0 = <&vin4_pins_cvbs>;
> > + pinctrl-names = "default";
> > +
> > + status = "okay";
> > +
> > + ports {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > +
> > + port at 0 {
> > + reg = <0>;
> > +
> > + vin4_in: endpoint {
> > + remote-endpoint = <&adv7180_out>;
> > + };
> > + };
> > + };
> > +};
>
> --
> Regards,
>
> Laurent Pinchart
>
>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180521/0d3a8d16/attachment-0001.sig>
^ permalink raw reply
* [GIT PULL] Allwinner H3/H5 changes for 4.18
From: Maxime Ripard @ 2018-05-21 9:55 UTC (permalink / raw)
To: linux-arm-kernel
Hi Arnd, Olof,
Here is our usual PR with the changes that apply to the H3 and H5,
shared between arm and arm64.
Maxime
The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:
Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git tags/sunxi-h3-h5-for-4.18
for you to fetch changes up to 06139c822c5011ff79341000f44eca96151aac92:
ARM: dts: sun8i: h3: Add SY8106A regulator to Orange Pi PC (2018-05-11 10:00:28 +0200)
----------------------------------------------------------------
Allwinner H3/H5 support for 4.18
Here is our usual bunch of changes for the H3 and H5 SoCs that share the
same SoC design but with different CPUs.
This time, most of the changes are about supporting CPUFreq on these SoCs,
with voltage scaling being enabled for a number of boards.
----------------------------------------------------------------
Chen-Yu Tsai (5):
ARM: dts: sun8i: h3: fix ALL-H3-CC H3 ver VCC-1V2 regulator voltage
ARM: dts: sun8i: h2-plus: Sort dtb entries in Makefile
ARM: dts: sun8i: h2+: Add Libre Computer Board ALL-H3-CC H2+ ver.
arm64: dts: allwinner: h5: Add cpu0 label for first cpu
arm64: dts: allwinner: Sort dtb entries in Makefile
Icenowy Zheng (5):
ARM: dts: sun8i: h3: add operating-points-v2 table for CPU
ARM: dts: sun8i: h2+: add SY8113B regulator used by Orange Pi Zero board
ARM: dts: sun8i: h3: add SY8113B regulator used by Orange Pi One board
ARM: dts: sun8i: h3: fix ALL-H3-CC H3 ver VDD-CPUX voltage
ARM: dts: sun8i: h3: set the cpu-supply to VDD-CPUX on ALL-H3-CC H3 ver
Neil Armstrong (2):
arm: dts: sun8i: h3: libretech-all-h3-cc: Move board definition to common dtsi
arm64: dts: allwinner: Add dts file for Libre Computer Board ALL-H3-CC H5 ver.
Ondrej Jirman (3):
ARM: dts: sunxi: h3/h5: Add r_i2c pinmux node
ARM: dts: sunxi: h3/h5: Add r_i2c I2C controller
ARM: dts: sun8i: h3: Add SY8106A regulator to Orange Pi PC
arch/arm/boot/dts/Makefile | 3 +-
.../boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts | 13 ++
arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts | 21 ++
arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts | 206 +-------------------
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 21 ++
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 28 +++
arch/arm/boot/dts/sun8i-h3.dtsi | 32 ++-
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 18 ++
arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi | 215 +++++++++++++++++++++
arch/arm64/boot/dts/allwinner/Makefile | 5 +-
.../allwinner/sun50i-h5-libretech-all-h3-cc.dts | 14 ++
arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 2 +-
12 files changed, 368 insertions(+), 210 deletions(-)
create mode 100644 arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts
create mode 100644 arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts
--
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180521/74f9de15/attachment.sig>
^ permalink raw reply
* [xlnx:xlnx_rebase_v4.14 937/937] drivers/clk/idt/clk-idt8t49n24x-core.c:50:4: sparse: symbol 'q0_ns1_options' was not declared. Should it be static?
From: kbuild test robot @ 2018-05-21 9:53 UTC (permalink / raw)
To: linux-arm-kernel
tree: https://github.com/Xilinx/linux-xlnx xlnx_rebase_v4.14
head: 6588700bdabc9bb1a0156770ed2ac41da7d823dd
commit: 6588700bdabc9bb1a0156770ed2ac41da7d823dd [937/937] clk: Add ccf driver for IDT 8T49N24x UFT
reproduce:
# apt-get install sparse
git checkout 6588700bdabc9bb1a0156770ed2ac41da7d823dd
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
>> drivers/clk/idt/clk-idt8t49n24x-core.c:50:4: sparse: symbol 'q0_ns1_options' was not declared. Should it be static?
>> drivers/clk/idt/clk-idt8t49n24x-core.c:691:9: sparse: right shift by bigger than source value
drivers/clk/idt/clk-idt8t49n24x-core.c:696:39: sparse: right shift by bigger than source value
--
>> drivers/clk/idt/clk-idt8t49n24x-debugfs.c:19:24: sparse: symbol 'idt24x_chip_fordebugfs' was not declared. Should it be static?
>> drivers/clk/idt/clk-idt8t49n24x-debugfs.c:246:47: sparse: dereference of noderef expression
drivers/clk/idt/clk-idt8t49n24x-debugfs.c:247:32: sparse: dereference of noderef expression
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* [RFC PATCH xlnx] clk: q0_ns1_options[] can be static
From: kbuild test robot @ 2018-05-21 9:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201805211727.w7Yi11Xp%fengguang.wu@intel.com>
Fixes: 6588700bdabc ("clk: Add ccf driver for IDT 8T49N24x UFT")
Signed-off-by: kbuild test robot <fengguang.wu@intel.com>
---
clk-idt8t49n24x-core.c | 2 +-
clk-idt8t49n24x-debugfs.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/idt/clk-idt8t49n24x-core.c b/drivers/clk/idt/clk-idt8t49n24x-core.c
index fb8f4db..5fce51e 100644
--- a/drivers/clk/idt/clk-idt8t49n24x-core.c
+++ b/drivers/clk/idt/clk-idt8t49n24x-core.c
@@ -47,7 +47,7 @@
#define IDT24x_VCO_OPT 3500000000u
#define IDT24x_MIN_INT_DIVIDER 6
-u8 q0_ns1_options[3] = { 4, 5, 6 };
+static u8 q0_ns1_options[3] = { 4, 5, 6 };
/**
* bits_to_shift - num bits to shift given specified mask
diff --git a/drivers/clk/idt/clk-idt8t49n24x-debugfs.c b/drivers/clk/idt/clk-idt8t49n24x-debugfs.c
index d8fcf4e..0b259cb 100644
--- a/drivers/clk/idt/clk-idt8t49n24x-debugfs.c
+++ b/drivers/clk/idt/clk-idt8t49n24x-debugfs.c
@@ -16,7 +16,7 @@
#include "clk-idt8t49n24x-debugfs.h"
-struct clk_idt24x_chip *idt24x_chip_fordebugfs;
+static struct clk_idt24x_chip *idt24x_chip_fordebugfs;
static int idt24x_read_all_settings(
struct clk_idt24x_chip *chip, char *output_buffer, int count)
^ permalink raw reply related
* [PATCH v3 4/5] ARM: perf: Allow the use of the PMUv3 driver on 32bit ARM
From: Marc Zyngier @ 2018-05-21 9:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f40d8620-eb57-37be-a2f0-b7bf7a74c087@arm.com>
On 21/05/18 10:34, Vladimir Murzin wrote:
> On 18/05/18 15:39, Marc Zyngier wrote:
>> +static inline int read_pmuver(void)
>> +{
>> + /* PMUVers is not a signed field */
>> + u32 dfr0 = read_cpuid_ext(CPUID_EXT_DFR0);
>> + return (dfr0 >> 24) & 0xf;
>> +}
>
> Should we rule out versions prior v3 here or in __armv8pmu_probe_pmu()?
I'm in two minds about it: The ARM ARM is quite clear about the fact
that this is not legal ("In any ARMv8 implementation the values 0001 and
0010 are not permitted."), and DT clearly lied to us in that case.
If we want to consistently handle that case, it should probably be done
in __armv8pmu_probe_pmu, bailing out if the version is our of scope for
the driver.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [GIT PULL] Allwinner DT changes for 4.18
From: Maxime Ripard @ 2018-05-21 9:48 UTC (permalink / raw)
To: linux-arm-kernel
Hi Arnd, Olof,
Here is our usual bunch of arm32 DT changes for the next release.
Thanks!
Maxime
The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:
Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git tags/sunxi-dt-for-4.18
for you to fetch changes up to 5d9ef839f874f4e3923c8a9ae7b136c6c3912cd5:
ARM: dts: sun7i: Add Olimex A20-SOM-EVB-eMMC board (2018-05-21 11:41:03 +0200)
----------------------------------------------------------------
Allwinner DT additions for 4.18
Here is our usual bunch of DT changes for our arm SoCs, with most
significantly:
- MIPI-DSI support for the A33
- NAND support for the A33
- SMP support for the A83t
- GMAC support for the R40
- And some new boards: Olimex A20-SOM-EVB-eMMC, Nintendo NES and SuperNES
Classic
----------------------------------------------------------------
Chen-Yu Tsai (3):
ARM: dts: sun8i: r40: bananapi-m2-ultra: Sort device node dereferences
ARM: dts: sun8i: r40: Add device node and RGMII pinmux node for GMAC
ARM: dts: sun8i: r40: bananapi-m2-ultra: Enable GMAC ethernet controller
Icenowy Zheng (1):
ARM: sun8i: v40: enable USB host ports for Banana Pi M2 Berry
Maxime Ripard (1):
ARM: dts: sun8i: a33: Add the DSI-related nodes
Miquel Raynal (2):
ARM: dts: sun8i: a23/a33: declare NAND pins
ARM: dts: nes: add Nintendo NES/SuperNES Classic Edition support
Myl?ne Josserand (4):
ARM: dts: sun8i: Add CPUCFG device node for A83T dtsi
ARM: dts: sun8i: Add R_CPUCFG device node for the A83T dtsi
ARM: dts: sun8i: a83t: Add CCI-400 node
ARM: dts: sun8i: Add enable-method for SMP support for the A83T SoC
Stefan Mavrodiev (1):
ARM: dts: sun7i: Add Olimex A20-SOM-EVB-eMMC board
Tuomas Tynkkynen (1):
ARM: dts: sunxi: Change sun7i-a20-olimex-som204-evb to not use cd-inverted
kevans at FreeBSD.org (1):
ARM: dts: sunxi: Add sid for a83t
.../bindings/nvmem/allwinner,sunxi-sid.txt | 1 +
arch/arm/boot/dts/Makefile | 3 +
.../arm/boot/dts/sun7i-a20-olimex-som-evb-emmc.dts | 37 ++++++++
arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts | 3 +-
arch/arm/boot/dts/sun8i-a23-a33.dtsi | 33 ++++++++
arch/arm/boot/dts/sun8i-a33.dtsi | 44 ++++++++++
arch/arm/boot/dts/sun8i-a83t.dtsi | 64 ++++++++++++++
.../boot/dts/sun8i-r16-nintendo-nes-classic.dts | 56 ++++++++++++
.../dts/sun8i-r16-nintendo-super-nes-classic.dts | 11 +++
arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts | 99 ++++++++++++++--------
arch/arm/boot/dts/sun8i-r40.dtsi | 34 ++++++++
arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts | 10 +++
12 files changed, 359 insertions(+), 36 deletions(-)
create mode 100644 arch/arm/boot/dts/sun7i-a20-olimex-som-evb-emmc.dts
create mode 100644 arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts
create mode 100644 arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts
--
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180521/bde72701/attachment.sig>
^ permalink raw reply
* [PATCH v9 07/11] arm64: kexec_file: add crash dump support
From: AKASHI Takahiro @ 2018-05-21 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <fa2468a8-ffc9-1447-933d-de41bea50d1f@arm.com>
James,
On Fri, May 18, 2018 at 05:00:55PM +0100, James Morse wrote:
> Hi Akashi,
>
> On 18/05/18 11:39, AKASHI Takahiro wrote:
> > On Tue, May 15, 2018 at 06:11:15PM +0100, James Morse wrote:
> >> On 25/04/18 07:26, AKASHI Takahiro wrote:
> >>> Enabling crash dump (kdump) includes
> >>> * prepare contents of ELF header of a core dump file, /proc/vmcore,
> >>> using crash_prepare_elf64_headers(), and
> >>> * add two device tree properties, "linux,usable-memory-range" and
> >>> "linux,elfcorehdr", which represent repsectively a memory range
>
> >>> diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
> >>> index 37c0a9dc2e47..ec674f4d267c 100644
> >>> --- a/arch/arm64/kernel/machine_kexec_file.c
> >>> +++ b/arch/arm64/kernel/machine_kexec_file.c
>
> >>> +static void fill_property(void *buf, u64 val64, int cells)
> >>> +{
> >>> + u32 val32;
> >>> +
> >>> + if (cells == 1) {
> >>> + val32 = cpu_to_fdt32((u32)val64);
> >>> + memcpy(buf, &val32, sizeof(val32));
> >>> + } else {
> >>
> >>> + memset(buf, 0, cells * sizeof(u32) - sizeof(u64));
> >>> + buf += cells * sizeof(u32) - sizeof(u64);
> >>
> >> Is this trying to clear the 'top' cells and shuffle the pointer to point at the
> >> 'bottom' 2? I'm pretty sure this isn't endian safe.
> >>
> >> Do we really expect a system to have #address-cells > 2?
> >
> > I don't know, but just for safety.
>
> Okay, so this is aiming to be a cover-all-cases library function.
>
>
> >>> + val64 = cpu_to_fdt64(val64);
> >>> + memcpy(buf, &val64, sizeof(val64));
> >>> + }
> >>> +}
> >>> +
> >>> +static int fdt_setprop_range(void *fdt, int nodeoffset, const char *name,
> >>> + unsigned long addr, unsigned long size)
> >>
> >> (the device-tree spec describes a 'ranges' property, which had me confused. This
> >> is encoding a prop-encoded-array)
> >
> > Should we rename it to, say, fdt_setprop_reg()?
>
> Sure, but I'd really like this code to come from libfdt. I'm hoping for some
> temporary workaround, lets see what the DT folk say.
OK, I will follow Rob's suggestion.
> >>> + if (!buf)
> >>> + return -ENOMEM;
> >>> +
> >>> + fill_property(prop, addr, __dt_root_addr_cells);
> >>> + prop += __dt_root_addr_cells * sizeof(u32);
> >>> +
> >>> + fill_property(prop, size, __dt_root_size_cells);
> >>> +
> >>> + result = fdt_setprop(fdt, nodeoffset, name, buf, buf_size);
> >>> +
> >>> + vfree(buf);
> >>> +
> >>> + return result;
> >>> +}
> >>
> >> Doesn't this stuff belong in libfdt? I guess there is no 'add array element' api
> >> because this the first time we've wanted to create a node with more than
> >> key=fixed-size-value.
> >>
> >> I don't think this belongs in arch C code. Do we have a plan for getting libfdt
> >> to support encoding prop-arrays? Can we put it somewhere anyone else duplicating
> >> this will find it, until we can (re)move it?
> >
> > I will temporarily move all fdt-related stuff to a separate file, but
> >
> >> I have no idea how that happens... it looks like the devicetree list is the
> >> place to ask.
> >
> > should we always sync with the original dtc/libfdt repository?
>
> I thought so, libfdt is one of those external libraries that the kernel
> consumes, like acpica. For acpica at least the rule is changes go upstream, then
> get sync'd back.
Same above.
> >>> static int setup_dtb(struct kimage *image,
> >>> unsigned long initrd_load_addr, unsigned long initrd_len,
> >>> char *cmdline, unsigned long cmdline_len,
> >>> @@ -88,10 +165,26 @@ static int setup_dtb(struct kimage *image,
> >>> int range_len;
> >>> int ret;
> >>>
> >>> + /* check ranges against root's #address-cells and #size-cells */
> >>> + if (image->type == KEXEC_TYPE_CRASH &&
> >>> + (!cells_size_fitted(image->arch.elf_load_addr,
> >>> + image->arch.elf_headers_sz) ||
> >>> + !cells_size_fitted(crashk_res.start,
> >>> + crashk_res.end - crashk_res.start + 1))) {
> >>> + pr_err("Crash memory region doesn't fit into DT's root cell sizes.\n");
> >>> + ret = -EINVAL;
> >>> + goto out_err;
> >>> + }
> >>
> >> To check I've understood this properly: This can happen if the firmware provided
> >> a DTB with 32bit address/size cells, but at least some of the memory requires 64
> >> bit address/size cells. This could only happen on a UEFI system where the
> >> firmware-DTB doesn't describe memory. ACPI-only systems would have the EFIstub DT.
> >
> > Probably, yes. I assumed the case where #address-cells and #size-cells
> > were just missing in fdt.
>
> Ah, that's another one. I just wanted to check we could boot on a system where
> this can happen.
>
>
> >>> /* duplicate dt blob */
> >>> buf_size = fdt_totalsize(initial_boot_params);
> >>> range_len = (__dt_root_addr_cells + __dt_root_size_cells) * sizeof(u32);
> >>>
> >>> + if (image->type == KEXEC_TYPE_CRASH)
> >>> + buf_size += fdt_prop_len("linux,elfcorehdr", range_len)
> >>> + + fdt_prop_len("linux,usable-memory-range",
> >>> + range_len);
>
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> [...]
>
> >> Don't you need to add "linux,usable-memory-range" to the buf_size estimate?
> >
> > I think the code exists. See above.
>
> Sorry, turns out I can't read!
>
>
> >>> + if (ret)
> >>> + goto out_err;
> >>> + }
> >>
> >>> @@ -148,17 +258,109 @@ static int setup_dtb(struct kimage *image,
> >>
> >>> +static struct crash_mem *get_crash_memory_ranges(void)
> >>> +{
> >>> + unsigned int nr_ranges;
> >>> + struct crash_mem *cmem;
> >>> +
> >>> + nr_ranges = 1; /* for exclusion of crashkernel region */
> >>> + walk_system_ram_res(0, -1, &nr_ranges, get_nr_ranges_callback);
> >>> +
> >>> + cmem = vmalloc(sizeof(struct crash_mem) +
> >>> + sizeof(struct crash_mem_range) * nr_ranges);
> >>> + if (!cmem)
> >>> + return NULL;
> >>> +
> >>> + cmem->max_nr_ranges = nr_ranges;
> >>> + cmem->nr_ranges = 0;
> >>> + walk_system_ram_res(0, -1, cmem, add_mem_range_callback);
> >>> +
> >>> + /* Exclude crashkernel region */
> >>> + if (crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end)) {
> >>> + vfree(cmem);
> >>> + return NULL;
> >>> + }
> >>> +
> >>> + return cmem;
> >>> +}
> >>
> >> Could this function be included in prepare_elf_headers() so that the alloc() and
> >> free() occur together.
> >
> > Or aiming that arm64 and x86 have similar-look code?
>
> What's the advantage in things looking the same? If they are the same, it
> probably shouldn't be in per-arch code. Otherwise it should be as simple as
> possible, otherwise we can't spot the bugs/leaks.
>
> But I think walking memblock here will remove all 'looks the same' properties here.
OK, I will unfold the function in prepare_elf_headers().
>
> >>> +static int prepare_elf_headers(void **addr, unsigned long *sz)
> >>> +{
> >>> + struct crash_mem *cmem;
> >>> + int ret = 0;
> >>> +
> >>> + cmem = get_crash_memory_ranges();
> >>> + if (!cmem)
> >>> + return -ENOMEM;
> >>> +
> >>> + ret = crash_prepare_elf64_headers(cmem, true, addr, sz);
> >>> +
> >>> + vfree(cmem);
> >>
> >>> + return ret;
> >>> +}
> >>
> >> All this is moving memory-range information from core-code's
> >> walk_system_ram_res() into core-code's struct crash_mem, and excluding
> >> crashk_res, which again is accessible to the core code.
> >>
> >> It looks like this is duplicated in arch/x86 and arch/arm64 because arm64
> >> doesn't have a second 'crashk_low_res' region, and always wants elf64, instead
> >> of when IS_ENABLED(CONFIG_X86_64).
> >> If we can abstract just those two, more of this could be moved to core code
> >> where powerpc can make use of it if they want to support kdump with
> >> kexec_file_load().
> >>
> >> But, its getting late for cross-architecture dependencies, lets put that on the
> >> for-later list. (assuming there isn't a powerpc-kdump series out there adding a
> >> third copy of this)
> >
> > Sure. X86 code has so many exceptional lines in the code :)
>
> They also pass the e820 'usable-memory' map on the cmdline...
Well, according to Dave(RedHat)'s past comment, this type of kernel
parameters are in a old style, and x86 now has a dedicated memory region
passed for this sake.
Thanks,
-Takahiro AKASHI
>
> Thanks,
>
> James
^ permalink raw reply
* [PATCH] EDAC, ghes: Make platform-based whitelisting x86-only
From: Zhengqiang @ 2018-05-21 9:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518112028.GD17285@pd.tnic>
Thanks, it works for me.
On 2018/5/18 19:20, Borislav Petkov wrote:
> From: Borislav Petkov <bp@suse.de>
>
> ARM machines all have DMI tables so if they request hw error reporting
> through GHES, then the driver should be able to detect DIMMs and report
> errors successfully (famous last words :)).
>
> Make the platform-based list x86-specific so that ghes_edac can load on
> ARM.
>
> Signed-off-by: Borislav Petkov <bp@suse.de>
> Reviewed-by: James Morse <james.morse@arm.com>
> Tested-by: James Morse <james.morse@arm.com>
> Cc: Qiang Zheng <zhengqiang10@huawei.com>
> Link: https://lkml.kernel.org/r/1526039543-180996-1-git-send-email-zhengqiang10 at huawei.com
Tested-by: Qiang Zheng <zhengqiang10@huawei.com>
> ---
> drivers/edac/ghes_edac.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
> index 863fbf3db29f..473aeec4b1da 100644
> --- a/drivers/edac/ghes_edac.c
> +++ b/drivers/edac/ghes_edac.c
> @@ -440,12 +440,16 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
> struct mem_ctl_info *mci;
> struct edac_mc_layer layers[1];
> struct ghes_edac_dimm_fill dimm_fill;
> - int idx;
> + int idx = -1;
>
> - /* Check if safe to enable on this system */
> - idx = acpi_match_platform_list(plat_list);
> - if (!force_load && idx < 0)
> - return -ENODEV;
> + if (IS_ENABLED(CONFIG_X86)) {
> + /* Check if safe to enable on this system */
> + idx = acpi_match_platform_list(plat_list);
> + if (!force_load && idx < 0)
> + return -ENODEV;
> + } else {
> + idx = 0;
> + }
>
> /*
> * We have only one logical memory controller to which all DIMMs belong.
>
^ permalink raw reply
* [PATCH v6 5/5] drm/rockchip: support dp training outside dp firmware
From: Lin Huang @ 2018-05-21 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526895424-22894-1-git-send-email-hl@rock-chips.com>
DP firmware uses fixed phy config values to do training, but some
boards need to adjust these values to fit for their unique hardware
design. So get phy config values from dts and use software link training
instead of relying on firmware, if software training fail, keep firmware
training as a fallback if sw training fails.
Signed-off-by: Chris Zhong <zyw@rock-chips.com>
Signed-off-by: Lin Huang <hl@rock-chips.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- use variable fw_training instead sw_training_success
- base on DP SPCE, if training fail use lower link rate to retry training
Changes in v4:
- improve cdn_dp_get_lower_link_rate() and cdn_dp_software_train_link() follow Sean suggest
Changes in v5:
- fix some whitespcae issue
Changes in v6:
- None
drivers/gpu/drm/rockchip/Makefile | 3 +-
drivers/gpu/drm/rockchip/cdn-dp-core.c | 24 +-
drivers/gpu/drm/rockchip/cdn-dp-core.h | 2 +
drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 420 ++++++++++++++++++++++++
drivers/gpu/drm/rockchip/cdn-dp-reg.c | 31 +-
drivers/gpu/drm/rockchip/cdn-dp-reg.h | 38 ++-
6 files changed, 505 insertions(+), 13 deletions(-)
create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index a314e21..b932f62 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \
+ cdn-dp-link-training.o
rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index cce64c1..d9d0d4d 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
goto out;
}
}
-
- ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
- if (ret) {
- DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret);
- goto out;
+ if (dp->use_fw_training == true) {
+ ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+ if (ret) {
+ DRM_DEV_ERROR(dp->dev,
+ "Failed to idle video %d\n", ret);
+ goto out;
+ }
}
ret = cdn_dp_config_video(dp);
@@ -642,11 +644,15 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
goto out;
}
- ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
- if (ret) {
- DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
- goto out;
+ if (dp->use_fw_training == true) {
+ ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+ if (ret) {
+ DRM_DEV_ERROR(dp->dev,
+ "Failed to valid video %d\n", ret);
+ goto out;
+ }
}
+
out:
mutex_unlock(&dp->lock);
}
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 46159b2..77a9793 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -84,6 +84,7 @@ struct cdn_dp_device {
bool connected;
bool active;
bool suspended;
+ bool use_fw_training;
const struct firmware *fw; /* cdn dp firmware */
unsigned int fw_version; /* cdn fw version */
@@ -106,6 +107,7 @@ struct cdn_dp_device {
u8 ports;
u8 lanes;
int active_port;
+ u8 train_set[4];
u8 dpcd[DP_RECEIVER_CAP_SIZE];
bool sink_has_audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
new file mode 100644
index 0000000..73c3290
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <zyw@rock-chips.com>
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/phy/phy.h>
+#include <soc/rockchip/rockchip_phy_typec.h>
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+static void cdn_dp_set_signal_levels(struct cdn_dp_device *dp)
+{
+ struct cdn_dp_port *port = dp->port[dp->active_port];
+ struct rockchip_typec_phy *tcphy = phy_get_drvdata(port->phy);
+
+ int rate = drm_dp_bw_code_to_link_rate(dp->link.rate);
+ u8 swing = (dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) >>
+ DP_TRAIN_VOLTAGE_SWING_SHIFT;
+ u8 pre_emphasis = (dp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
+ >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
+
+ tcphy->typec_phy_config(port->phy, rate, dp->link.num_lanes,
+ swing, pre_emphasis);
+}
+
+static int cdn_dp_set_pattern(struct cdn_dp_device *dp, uint8_t dp_train_pat)
+{
+ u32 phy_config, global_config;
+ int ret;
+ uint8_t pattern = dp_train_pat & DP_TRAINING_PATTERN_MASK;
+
+ global_config = NUM_LANES(dp->link.num_lanes - 1) | SST_MODE |
+ GLOBAL_EN | RG_EN | ENC_RST_DIS | WR_VHSYNC_FALL;
+
+ phy_config = DP_TX_PHY_ENCODER_BYPASS(0) |
+ DP_TX_PHY_SKEW_BYPASS(0) |
+ DP_TX_PHY_DISPARITY_RST(0) |
+ DP_TX_PHY_LANE0_SKEW(0) |
+ DP_TX_PHY_LANE1_SKEW(1) |
+ DP_TX_PHY_LANE2_SKEW(2) |
+ DP_TX_PHY_LANE3_SKEW(3) |
+ DP_TX_PHY_10BIT_ENABLE(0);
+
+ if (pattern != DP_TRAINING_PATTERN_DISABLE) {
+ global_config |= NO_VIDEO;
+ phy_config |= DP_TX_PHY_TRAINING_ENABLE(1) |
+ DP_TX_PHY_SCRAMBLER_BYPASS(1) |
+ DP_TX_PHY_TRAINING_PATTERN(pattern);
+ }
+
+ ret = cdn_dp_reg_write(dp, DP_FRAMER_GLOBAL_CONFIG, global_config);
+ if (ret) {
+ DRM_ERROR("fail to set DP_FRAMER_GLOBAL_CONFIG, error: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = cdn_dp_reg_write(dp, DP_TX_PHY_CONFIG_REG, phy_config);
+ if (ret) {
+ DRM_ERROR("fail to set DP_TX_PHY_CONFIG_REG, error: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = cdn_dp_reg_write(dp, DPTX_LANE_EN, BIT(dp->link.num_lanes) - 1);
+ if (ret) {
+ DRM_ERROR("fail to set DPTX_LANE_EN, error: %d\n", ret);
+ return ret;
+ }
+
+ if (drm_dp_enhanced_frame_cap(dp->dpcd))
+ ret = cdn_dp_reg_write(dp, DPTX_ENHNCD, 1);
+ else
+ ret = cdn_dp_reg_write(dp, DPTX_ENHNCD, 0);
+ if (ret)
+ DRM_ERROR("failed to set DPTX_ENHNCD, error: %x\n", ret);
+
+ return ret;
+}
+
+static u8 cdn_dp_pre_emphasis_max(u8 voltage_swing)
+{
+ switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+ case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
+ return DP_TRAIN_PRE_EMPH_LEVEL_3;
+ case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
+ return DP_TRAIN_PRE_EMPH_LEVEL_2;
+ case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
+ return DP_TRAIN_PRE_EMPH_LEVEL_1;
+ default:
+ return DP_TRAIN_PRE_EMPH_LEVEL_0;
+ }
+}
+
+static void cdn_dp_get_adjust_train(struct cdn_dp_device *dp,
+ uint8_t link_status[DP_LINK_STATUS_SIZE])
+{
+ int i;
+ uint8_t v = 0, p = 0;
+ uint8_t preemph_max;
+
+ for (i = 0; i < dp->link.num_lanes; i++) {
+ v = max(v, drm_dp_get_adjust_request_voltage(link_status, i));
+ p = max(p, drm_dp_get_adjust_request_pre_emphasis(link_status,
+ i));
+ }
+
+ if (v >= VOLTAGE_LEVEL_2)
+ v = VOLTAGE_LEVEL_2 | DP_TRAIN_MAX_SWING_REACHED;
+
+ preemph_max = cdn_dp_pre_emphasis_max(v);
+ if (p >= preemph_max)
+ p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+ for (i = 0; i < dp->link.num_lanes; i++)
+ dp->train_set[i] = v | p;
+}
+
+/*
+ * Pick training pattern for channel equalization. Training Pattern 3 for HBR2
+ * or 1.2 devices that support it, Training Pattern 2 otherwise.
+ */
+static u32 cdn_dp_select_chaneq_pattern(struct cdn_dp_device *dp)
+{
+ u32 training_pattern = DP_TRAINING_PATTERN_2;
+
+ /*
+ * cdn dp support HBR2 also support TPS3. TPS3 support is also mandatory
+ * for downstream devices that support HBR2. However, not all sinks
+ * follow the spec.
+ */
+ if (drm_dp_tps3_supported(dp->dpcd))
+ training_pattern = DP_TRAINING_PATTERN_3;
+ else
+ DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n");
+
+ return training_pattern;
+}
+
+
+static bool cdn_dp_link_max_vswing_reached(struct cdn_dp_device *dp)
+{
+ int lane;
+
+ for (lane = 0; lane < dp->link.num_lanes; lane++)
+ if ((dp->train_set[lane] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+ return false;
+
+ return true;
+}
+
+static int cdn_dp_update_link_train(struct cdn_dp_device *dp)
+{
+ int ret;
+
+ cdn_dp_set_signal_levels(dp);
+
+ ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
+ dp->train_set, dp->link.num_lanes);
+ if (ret != dp->link.num_lanes)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int cdn_dp_set_link_train(struct cdn_dp_device *dp,
+ uint8_t dp_train_pat)
+{
+ uint8_t buf[sizeof(dp->train_set) + 1];
+ int ret, len;
+
+ buf[0] = dp_train_pat;
+ if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) ==
+ DP_TRAINING_PATTERN_DISABLE) {
+ /* don't write DP_TRAINING_LANEx_SET on disable */
+ len = 1;
+ } else {
+ /* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */
+ memcpy(buf + 1, dp->train_set, dp->link.num_lanes);
+ len = dp->link.num_lanes + 1;
+ }
+
+ ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_PATTERN_SET,
+ buf, len);
+ if (ret != len)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int cdn_dp_reset_link_train(struct cdn_dp_device *dp,
+ uint8_t dp_train_pat)
+{
+ int ret;
+
+ memset(dp->train_set, 0, sizeof(dp->train_set));
+
+ cdn_dp_set_signal_levels(dp);
+
+ ret = cdn_dp_set_pattern(dp, dp_train_pat);
+ if (ret)
+ return ret;
+
+ return cdn_dp_set_link_train(dp, dp_train_pat);
+}
+
+/* Enable corresponding port and start training pattern 1 */
+static int cdn_dp_link_training_clock_recovery(struct cdn_dp_device *dp)
+{
+ u8 voltage;
+ u8 link_status[DP_LINK_STATUS_SIZE];
+ u32 voltage_tries, max_vswing_tries;
+ int ret;
+
+ /* clock recovery */
+ ret = cdn_dp_reset_link_train(dp, DP_TRAINING_PATTERN_1 |
+ DP_LINK_SCRAMBLING_DISABLE);
+ if (ret) {
+ DRM_ERROR("failed to start link train\n");
+ return ret;
+ }
+
+ voltage_tries = 1;
+ max_vswing_tries = 0;
+ for (;;) {
+ drm_dp_link_train_clock_recovery_delay(dp->dpcd);
+ if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) !=
+ DP_LINK_STATUS_SIZE) {
+ DRM_ERROR("failed to get link status\n");
+ return -EINVAL;
+ }
+
+ if (drm_dp_clock_recovery_ok(link_status, dp->link.num_lanes)) {
+ DRM_DEBUG_KMS("clock recovery OK\n");
+ return 0;
+ }
+
+ if (voltage_tries >= 5) {
+ DRM_DEBUG_KMS("Same voltage tried 5 times\n");
+ return -EINVAL;
+ }
+
+ if (max_vswing_tries >= 1) {
+ DRM_DEBUG_KMS("Max Voltage Swing reached\n");
+ return -EINVAL;
+ }
+
+ voltage = dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+ /* Update training set as requested by target */
+ cdn_dp_get_adjust_train(dp, link_status);
+ if (cdn_dp_update_link_train(dp)) {
+ DRM_ERROR("failed to update link training\n");
+ return -EINVAL;
+ }
+
+ if ((dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) ==
+ voltage)
+ ++voltage_tries;
+ else
+ voltage_tries = 1;
+
+ if (cdn_dp_link_max_vswing_reached(dp))
+ ++max_vswing_tries;
+ }
+}
+
+static int cdn_dp_link_training_channel_equalization(struct cdn_dp_device *dp)
+{
+ int tries, ret;
+ u32 training_pattern;
+ uint8_t link_status[DP_LINK_STATUS_SIZE];
+
+ training_pattern = cdn_dp_select_chaneq_pattern(dp);
+ training_pattern |= DP_LINK_SCRAMBLING_DISABLE;
+
+ ret = cdn_dp_set_pattern(dp, training_pattern);
+ if (ret)
+ return ret;
+
+ ret = cdn_dp_set_link_train(dp, training_pattern);
+ if (ret) {
+ DRM_ERROR("failed to start channel equalization\n");
+ return ret;
+ }
+
+ for (tries = 0; tries < 5; tries++) {
+ drm_dp_link_train_channel_eq_delay(dp->dpcd);
+ if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) !=
+ DP_LINK_STATUS_SIZE) {
+ DRM_ERROR("failed to get link status\n");
+ break;
+ }
+
+ /* Make sure clock is still ok */
+ if (!drm_dp_clock_recovery_ok(link_status,
+ dp->link.num_lanes)) {
+ DRM_DEBUG_KMS("Clock recovery check failed\n");
+ break;
+ }
+
+ if (drm_dp_channel_eq_ok(link_status, dp->link.num_lanes)) {
+ DRM_DEBUG_KMS("Channel EQ done\n");
+ return 0;
+ }
+
+ /* Update training set as requested by target */
+ cdn_dp_get_adjust_train(dp, link_status);
+ if (cdn_dp_update_link_train(dp)) {
+ DRM_ERROR("failed to update link training\n");
+ break;
+ }
+ }
+
+ /* Try 5 times, else fail and try at lower BW */
+ if (tries == 5)
+ DRM_DEBUG_KMS("Channel equalization failed 5 times\n");
+
+ return -EINVAL;
+}
+
+static int cdn_dp_stop_link_train(struct cdn_dp_device *dp)
+{
+ int ret = cdn_dp_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
+
+ if (ret)
+ return ret;
+
+ return cdn_dp_set_link_train(dp, DP_TRAINING_PATTERN_DISABLE);
+}
+
+static int cdn_dp_get_lower_link_rate(struct cdn_dp_device *dp)
+{
+ switch (dp->link.rate) {
+ case DP_LINK_BW_1_62:
+ return -EINVAL;
+ case DP_LINK_BW_2_7:
+ dp->link.rate = DP_LINK_BW_1_62;
+ break;
+ case DP_LINK_BW_5_4:
+ dp->link.rate = DP_LINK_BW_2_7;
+ break;
+ default:
+ dp->link.rate = DP_LINK_BW_5_4;
+ break;
+ }
+
+ return 0;
+}
+
+int cdn_dp_software_train_link(struct cdn_dp_device *dp)
+{
+ int ret, stop_err;
+ u8 link_config[2];
+ u32 rate, sink_max, source_max;
+
+ ret = drm_dp_dpcd_read(&dp->aux, DP_DPCD_REV, dp->dpcd,
+ sizeof(dp->dpcd));
+ if (ret < 0) {
+ DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
+ return ret;
+ }
+
+ source_max = dp->lanes;
+ sink_max = drm_dp_max_lane_count(dp->dpcd);
+ dp->link.num_lanes = min(source_max, sink_max);
+
+ source_max = drm_dp_bw_code_to_link_rate(CDN_DP_MAX_LINK_RATE);
+ sink_max = drm_dp_max_link_rate(dp->dpcd);
+ rate = min(source_max, sink_max);
+ dp->link.rate = drm_dp_link_rate_to_bw_code(rate);
+
+ link_config[0] = 0;
+ link_config[1] = 0;
+ if (dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & 0x01)
+ link_config[1] = DP_SET_ANSI_8B10B;
+ drm_dp_dpcd_write(&dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
+
+ while (true) {
+
+ /* Write the link configuration data */
+ link_config[0] = dp->link.rate;
+ link_config[1] = dp->link.num_lanes;
+ if (drm_dp_enhanced_frame_cap(dp->dpcd))
+ link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+ drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, link_config, 2);
+
+ ret = cdn_dp_link_training_clock_recovery(dp);
+ if (ret) {
+ if (!cdn_dp_get_lower_link_rate(dp))
+ continue;
+
+ DRM_ERROR("training clock recovery failed: %d\n", ret);
+ break;
+ }
+
+ ret = cdn_dp_link_training_channel_equalization(dp);
+ if (ret) {
+ if (!cdn_dp_get_lower_link_rate(dp))
+ continue;
+
+ DRM_ERROR("training channel eq failed: %d\n", ret);
+ break;
+ }
+
+ break;
+ }
+
+ stop_err = cdn_dp_stop_link_train(dp);
+ if (stop_err) {
+ DRM_ERROR("stop training fail, error: %d\n", stop_err);
+ return stop_err;
+ }
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index 979355d..e1273e6 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -17,7 +17,9 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
+#include <linux/phy/phy.h>
#include <linux/reset.h>
+#include <soc/rockchip/rockchip_phy_typec.h>
#include "cdn-dp-core.h"
#include "cdn-dp-reg.h"
@@ -189,7 +191,7 @@ static int cdn_dp_mailbox_send(struct cdn_dp_device *dp, u8 module_id,
return 0;
}
-static int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val)
+int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val)
{
u8 msg[6];
@@ -609,6 +611,31 @@ int cdn_dp_train_link(struct cdn_dp_device *dp)
{
int ret;
+ /*
+ * DP firmware uses fixed phy config values to do training, but some
+ * boards need to adjust these values to fit for their unique hardware
+ * design. So if the phy is using custom config values, do software
+ * link training instead of relying on firmware, if software training
+ * fail, keep firmware training as a fallback if sw training fails.
+ */
+ ret = cdn_dp_software_train_link(dp);
+ if (ret) {
+ DRM_DEV_ERROR(dp->dev,
+ "Failed to do software training %d\n", ret);
+ goto do_fw_training;
+ }
+ ret = cdn_dp_reg_write(dp, SOURCE_HDTX_CAR, 0xf);
+ if (ret) {
+ DRM_DEV_ERROR(dp->dev,
+ "Failed to write SOURCE_HDTX_CAR register %d\n", ret);
+ goto do_fw_training;
+ }
+ dp->use_fw_training = false;
+ return 0;
+
+do_fw_training:
+ dp->use_fw_training = true;
+ DRM_DEV_DEBUG_KMS(dp->dev, "use fw training\n");
ret = cdn_dp_training_start(dp);
if (ret) {
DRM_DEV_ERROR(dp->dev, "Failed to start training %d\n", ret);
@@ -623,7 +650,7 @@ int cdn_dp_train_link(struct cdn_dp_device *dp)
DRM_DEV_DEBUG_KMS(dp->dev, "rate:0x%x, lanes:%d\n", dp->link.rate,
dp->link.num_lanes);
- return ret;
+ return 0;
}
int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active)
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index 6580b11..3420771 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -137,7 +137,7 @@
#define HPD_EVENT_MASK 0x211c
#define HPD_EVENT_DET 0x2120
-/* dpyx framer addr */
+/* dptx framer addr */
#define DP_FRAMER_GLOBAL_CONFIG 0x2200
#define DP_SW_RESET 0x2204
#define DP_FRAMER_TU 0x2208
@@ -431,6 +431,40 @@
/* Reference cycles when using lane clock as reference */
#define LANE_REF_CYC 0x8000
+/* register CM_VID_CTRL */
+#define LANE_VID_REF_CYC(x) (((x) & (BIT(24) - 1)) << 0)
+#define NMVID_MEAS_TOLERANCE(x) (((x) & 0xf) << 24)
+
+/* register DP_TX_PHY_CONFIG_REG */
+#define DP_TX_PHY_TRAINING_ENABLE(x) ((x) & 1)
+#define DP_TX_PHY_TRAINING_TYPE_PRBS7 (0 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_TPS1 (1 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_TPS2 (2 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_TPS3 (3 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_TPS4 (4 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_PLTPAT (5 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_D10_2 (6 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_HBR2CPAT (8 << 1)
+#define DP_TX_PHY_TRAINING_PATTERN(x) ((x) << 1)
+#define DP_TX_PHY_SCRAMBLER_BYPASS(x) (((x) & 1) << 5)
+#define DP_TX_PHY_ENCODER_BYPASS(x) (((x) & 1) << 6)
+#define DP_TX_PHY_SKEW_BYPASS(x) (((x) & 1) << 7)
+#define DP_TX_PHY_DISPARITY_RST(x) (((x) & 1) << 8)
+#define DP_TX_PHY_LANE0_SKEW(x) (((x) & 7) << 9)
+#define DP_TX_PHY_LANE1_SKEW(x) (((x) & 7) << 12)
+#define DP_TX_PHY_LANE2_SKEW(x) (((x) & 7) << 15)
+#define DP_TX_PHY_LANE3_SKEW(x) (((x) & 7) << 18)
+#define DP_TX_PHY_10BIT_ENABLE(x) (((x) & 1) << 21)
+
+/* register DP_FRAMER_GLOBAL_CONFIG */
+#define NUM_LANES(x) ((x) & 3)
+#define SST_MODE (0 << 2)
+#define RG_EN (0 << 4)
+#define GLOBAL_EN BIT(3)
+#define NO_VIDEO BIT(5)
+#define ENC_RST_DIS BIT(6)
+#define WR_VHSYNC_FALL BIT(7)
+
enum voltage_swing_level {
VOLTAGE_LEVEL_0,
VOLTAGE_LEVEL_1,
@@ -476,6 +510,7 @@ int cdn_dp_set_host_cap(struct cdn_dp_device *dp, u8 lanes, bool flip);
int cdn_dp_event_config(struct cdn_dp_device *dp);
u32 cdn_dp_get_event(struct cdn_dp_device *dp);
int cdn_dp_get_hpd_status(struct cdn_dp_device *dp);
+int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val);
ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr,
u8 *data, u16 len);
ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr,
@@ -489,4 +524,5 @@ int cdn_dp_config_video(struct cdn_dp_device *dp);
int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
+int cdn_dp_software_train_link(struct cdn_dp_device *dp);
#endif /* _CDN_DP_REG_H */
--
2.7.4
^ permalink raw reply related
* [PATCH v6 4/5] phy: rockchip-typec: support variable phy config value
From: Lin Huang @ 2018-05-21 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526895424-22894-1-git-send-email-hl@rock-chips.com>
the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.
Signed-off-by: Chris Zhong <zyw@rock-chips.com>
Signed-off-by: Lin Huang <hl@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- delete need_software_training variable
- add default phy config value, if dts do not define phy config value, use these value
Changes in v4:
- rename variable config to tcphy_default_config
Changes in v5:
- None
Changes in v6:
- split the header file to new patch
drivers/phy/rockchip/phy-rockchip-typec.c | 261 ++++++++++++++++++++++++------
1 file changed, 208 insertions(+), 53 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index 795055f..4c4b925 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -324,21 +324,29 @@
* clock 0: PLL 0 div 1
* clock 1: PLL 1 div 2
*/
-#define CLK_PLL_CONFIG 0X30
+#define CLK_PLL1_DIV1 0x20
+#define CLK_PLL1_DIV2 0x30
#define CLK_PLL_MASK 0x33
#define CMN_READY BIT(0)
+#define DP_PLL_CLOCK_ENABLE_ACK BIT(3)
#define DP_PLL_CLOCK_ENABLE BIT(2)
+#define DP_PLL_ENABLE_ACK BIT(1)
#define DP_PLL_ENABLE BIT(0)
#define DP_PLL_DATA_RATE_RBR ((2 << 12) | (4 << 8))
#define DP_PLL_DATA_RATE_HBR ((2 << 12) | (4 << 8))
#define DP_PLL_DATA_RATE_HBR2 ((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK 0xff00
-#define DP_MODE_A0 BIT(4)
-#define DP_MODE_A2 BIT(6)
-#define DP_MODE_ENTER_A0 0xc101
-#define DP_MODE_ENTER_A2 0xc104
+#define DP_MODE_MASK 0xf
+#define DP_MODE_ENTER_A0 BIT(0)
+#define DP_MODE_ENTER_A2 BIT(2)
+#define DP_MODE_ENTER_A3 BIT(3)
+#define DP_MODE_A0_ACK BIT(4)
+#define DP_MODE_A2_ACK BIT(6)
+#define DP_MODE_A3_ACK BIT(7)
+#define DP_LINK_RESET_DEASSERTED BIT(8)
#define PHY_MODE_SET_TIMEOUT 100000
@@ -350,6 +358,8 @@
#define MODE_DFP_USB BIT(1)
#define MODE_DFP_DP BIT(2)
+#define DP_DEFAULT_RATE 162000
+
struct phy_reg {
u16 value;
u32 addr;
@@ -372,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
{ 0x8, CMN_DIAG_PLL0_LF_PROG },
};
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
{ 0xf0, CMN_PLL1_VCOCAL_INIT },
{ 0x18, CMN_PLL1_VCOCAL_ITER },
{ 0x30b9, CMN_PLL1_VCOCAL_START },
- { 0x21c, CMN_PLL1_INTDIV },
+ { 0x87, CMN_PLL1_INTDIV },
{ 0, CMN_PLL1_FRACDIV },
- { 0x5, CMN_PLL1_HIGH_THR },
- { 0x35, CMN_PLL1_SS_CTRL1 },
- { 0x7f1e, CMN_PLL1_SS_CTRL2 },
+ { 0x22, CMN_PLL1_HIGH_THR },
+ { 0x8000, CMN_PLL1_SS_CTRL1 },
+ { 0, CMN_PLL1_SS_CTRL2 },
{ 0x20, CMN_PLL1_DSM_DIAG },
{ 0, CMN_PLLSM1_USER_DEF_CTRL },
{ 0, CMN_DIAG_PLL1_OVRD },
@@ -391,9 +401,52 @@ struct phy_reg dp_pll_cfg[] = {
{ 0x8, CMN_DIAG_PLL1_LF_PROG },
{ 0x100, CMN_DIAG_PLL1_PTATIS_TUNE1 },
{ 0x7, CMN_DIAG_PLL1_PTATIS_TUNE2 },
- { 0x4, CMN_DIAG_PLL1_INCLK_CTRL },
+ { 0x1, CMN_DIAG_PLL1_INCLK_CTRL },
};
+struct phy_reg dp_pll_hbr_cfg[] = {
+ { 0xf0, CMN_PLL1_VCOCAL_INIT },
+ { 0x18, CMN_PLL1_VCOCAL_ITER },
+ { 0x30b4, CMN_PLL1_VCOCAL_START },
+ { 0xe1, CMN_PLL1_INTDIV },
+ { 0, CMN_PLL1_FRACDIV },
+ { 0x5, CMN_PLL1_HIGH_THR },
+ { 0x8000, CMN_PLL1_SS_CTRL1 },
+ { 0, CMN_PLL1_SS_CTRL2 },
+ { 0x20, CMN_PLL1_DSM_DIAG },
+ { 0x1000, CMN_PLLSM1_USER_DEF_CTRL },
+ { 0, CMN_DIAG_PLL1_OVRD },
+ { 0, CMN_DIAG_PLL1_FBH_OVRD },
+ { 0, CMN_DIAG_PLL1_FBL_OVRD },
+ { 0x7, CMN_DIAG_PLL1_V2I_TUNE },
+ { 0x45, CMN_DIAG_PLL1_CP_TUNE },
+ { 0x8, CMN_DIAG_PLL1_LF_PROG },
+ { 0x1, CMN_DIAG_PLL1_PTATIS_TUNE1 },
+ { 0x1, CMN_DIAG_PLL1_PTATIS_TUNE2 },
+ { 0x1, CMN_DIAG_PLL1_INCLK_CTRL },
+};
+
+struct phy_reg dp_pll_hbr2_cfg[] = {
+ { 0xf0, CMN_PLL1_VCOCAL_INIT },
+ { 0x18, CMN_PLL1_VCOCAL_ITER },
+ { 0x30b4, CMN_PLL1_VCOCAL_START },
+ { 0xe1, CMN_PLL1_INTDIV },
+ { 0, CMN_PLL1_FRACDIV },
+ { 0x5, CMN_PLL1_HIGH_THR },
+ { 0x8000, CMN_PLL1_SS_CTRL1 },
+ { 0, CMN_PLL1_SS_CTRL2 },
+ { 0x20, CMN_PLL1_DSM_DIAG },
+ { 0x1000, CMN_PLLSM1_USER_DEF_CTRL },
+ { 0, CMN_DIAG_PLL1_OVRD },
+ { 0, CMN_DIAG_PLL1_FBH_OVRD },
+ { 0, CMN_DIAG_PLL1_FBL_OVRD },
+ { 0x7, CMN_DIAG_PLL1_V2I_TUNE },
+ { 0x45, CMN_DIAG_PLL1_CP_TUNE },
+ { 0x8, CMN_DIAG_PLL1_LF_PROG },
+ { 0x1, CMN_DIAG_PLL1_PTATIS_TUNE1 },
+ { 0x1, CMN_DIAG_PLL1_PTATIS_TUNE2 },
+ { 0x1, CMN_DIAG_PLL1_INCLK_CTRL },
+};
static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
{
.reg = 0xff7c0000,
@@ -418,6 +471,24 @@ static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
{ /* sentinel */ }
};
+/* default phy config */
+static const struct phy_config tcphy_default_config[3][4] = {
+ {{ .swing = 0x2a, .pe = 0x00 },
+ { .swing = 0x1f, .pe = 0x15 },
+ { .swing = 0x14, .pe = 0x22 },
+ { .swing = 0x02, .pe = 0x2b } },
+
+ {{ .swing = 0x21, .pe = 0x00 },
+ { .swing = 0x12, .pe = 0x15 },
+ { .swing = 0x02, .pe = 0x22 },
+ { .swing = 0, .pe = 0 } },
+
+ {{ .swing = 0x15, .pe = 0x00 },
+ { .swing = 0x00, .pe = 0x15 },
+ { .swing = 0, .pe = 0 },
+ { .swing = 0, .pe = 0 } },
+};
+
static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
{
u32 i, rdata;
@@ -439,7 +510,7 @@ static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
rdata &= ~CLK_PLL_MASK;
- rdata |= CLK_PLL_CONFIG;
+ rdata |= CLK_PLL1_DIV2;
writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
}
@@ -453,17 +524,44 @@ static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy)
tcphy->base + usb3_pll_cfg[i].addr);
}
-static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
+static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy, int link_rate)
{
- u32 i;
+ struct phy_reg *phy_cfg;
+ u32 clk_ctrl;
+ u32 i, cfg_size, hsclk_sel;
+
+ hsclk_sel = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
+ hsclk_sel &= ~CLK_PLL_MASK;
+
+ switch (link_rate) {
+ case 162000:
+ clk_ctrl = DP_PLL_DATA_RATE_RBR;
+ hsclk_sel |= CLK_PLL1_DIV2;
+ phy_cfg = dp_pll_rbr_cfg;
+ cfg_size = ARRAY_SIZE(dp_pll_rbr_cfg);
+ break;
+ case 270000:
+ clk_ctrl = DP_PLL_DATA_RATE_HBR;
+ hsclk_sel |= CLK_PLL1_DIV2;
+ phy_cfg = dp_pll_hbr_cfg;
+ cfg_size = ARRAY_SIZE(dp_pll_hbr_cfg);
+ break;
+ case 540000:
+ clk_ctrl = DP_PLL_DATA_RATE_HBR2;
+ hsclk_sel |= CLK_PLL1_DIV1;
+ phy_cfg = dp_pll_hbr2_cfg;
+ cfg_size = ARRAY_SIZE(dp_pll_hbr2_cfg);
+ break;
+ }
- /* set the default mode to RBR */
- writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR,
- tcphy->base + DP_CLK_CTL);
+ clk_ctrl |= DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE;
+ writel(clk_ctrl, tcphy->base + DP_CLK_CTL);
+
+ writel(hsclk_sel, tcphy->base + CMN_DIAG_HSCLK_SEL);
/* load the configuration of PLL1 */
- for (i = 0; i < ARRAY_SIZE(dp_pll_cfg); i++)
- writel(dp_pll_cfg[i].value, tcphy->base + dp_pll_cfg[i].addr);
+ for (i = 0; i < cfg_size; i++)
+ writel(phy_cfg[i].value, tcphy->base + phy_cfg[i].addr);
}
static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
@@ -490,9 +588,10 @@ static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
}
-static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
+static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, int link_rate,
+ u8 swing, u8 pre_emp, u32 lane)
{
- u16 rdata;
+ u16 val;
writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
writel(0x6799, tcphy->base + TX_PSC_A0(lane));
@@ -500,25 +599,31 @@ static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
writel(0x98, tcphy->base + TX_PSC_A2(lane));
writel(0x98, tcphy->base + TX_PSC_A3(lane));
- writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
- writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
- writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
- writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
- writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
- writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
- writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
- writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
- writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
- writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
- writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
- writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
-
- writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
- writel(0x400, tcphy->base + TX_DIAG_TX_DRV(lane));
-
- rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
- rdata = (rdata & 0x8fff) | 0x6000;
- writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+ writel(tcphy->config[swing][pre_emp].swing,
+ tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+ writel(tcphy->config[swing][pre_emp].pe,
+ tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
+
+ if (swing == 2 && pre_emp == 0 && link_rate != 540000) {
+ writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
+ writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+ } else {
+ writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+ writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane));
+ }
+
+ val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+ val = val & 0x8fff;
+ switch (link_rate) {
+ case 162000:
+ case 270000:
+ val |= (6 << 12);
+ break;
+ case 540000:
+ val |= (4 << 12);
+ break;
+ }
+ writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
}
static inline int property_enable(struct rockchip_typec_phy *tcphy,
@@ -709,30 +814,33 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
tcphy_cfg_24m(tcphy);
if (mode == MODE_DFP_DP) {
- tcphy_cfg_dp_pll(tcphy);
+ tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
for (i = 0; i < 4; i++)
- tcphy_dp_cfg_lane(tcphy, i);
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, i);
writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG);
} else {
tcphy_cfg_usb3_pll(tcphy);
- tcphy_cfg_dp_pll(tcphy);
+ tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
if (tcphy->flip) {
tcphy_tx_usb3_cfg_lane(tcphy, 3);
tcphy_rx_usb3_cfg_lane(tcphy, 2);
- tcphy_dp_cfg_lane(tcphy, 0);
- tcphy_dp_cfg_lane(tcphy, 1);
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 0);
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 1);
} else {
tcphy_tx_usb3_cfg_lane(tcphy, 0);
tcphy_rx_usb3_cfg_lane(tcphy, 1);
- tcphy_dp_cfg_lane(tcphy, 2);
- tcphy_dp_cfg_lane(tcphy, 3);
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 2);
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 3);
}
writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG);
}
- writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+ val = readl(tcphy->base + DP_MODE_CTL);
+ val &= ~DP_MODE_MASK;
+ val |= DP_MODE_ENTER_A2 | DP_LINK_RESET_DEASSERTED;
+ writel(val, tcphy->base + DP_MODE_CTL);
reset_control_deassert(tcphy->uphy_rst);
@@ -945,7 +1053,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
property_enable(tcphy, &cfg->uphy_dp_sel, 1);
ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
- val, val & DP_MODE_A2, 1000,
+ val, val & DP_MODE_A2_ACK, 1000,
PHY_MODE_SET_TIMEOUT);
if (ret < 0) {
dev_err(tcphy->dev, "failed to wait TCPHY enter A2\n");
@@ -954,13 +1062,19 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
tcphy_dp_aux_calibration(tcphy);
- writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL);
+ /* enter A0 mode */
+ val = readl(tcphy->base + DP_MODE_CTL);
+ val &= ~DP_MODE_MASK;
+ val |= DP_MODE_ENTER_A0;
+ writel(val, tcphy->base + DP_MODE_CTL);
ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
- val, val & DP_MODE_A0, 1000,
+ val, val & DP_MODE_A0_ACK, 1000,
PHY_MODE_SET_TIMEOUT);
if (ret < 0) {
- writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+ val &= ~DP_MODE_MASK;
+ val |= DP_MODE_ENTER_A2;
+ writel(val, tcphy->base + DP_MODE_CTL);
dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
goto power_on_finish;
}
@@ -978,6 +1092,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
static int rockchip_dp_phy_power_off(struct phy *phy)
{
struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+ u32 val;
mutex_lock(&tcphy->lock);
@@ -986,7 +1101,10 @@ static int rockchip_dp_phy_power_off(struct phy *phy)
tcphy->mode &= ~MODE_DFP_DP;
- writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+ val = readl(tcphy->base + DP_MODE_CTL);
+ val &= ~DP_MODE_MASK;
+ val |= DP_MODE_ENTER_A2;
+ writel(val, tcphy->base + DP_MODE_CTL);
if (tcphy->mode == MODE_DISCONNECT)
tcphy_phy_deinit(tcphy);
@@ -1002,9 +1120,35 @@ static const struct phy_ops rockchip_dp_phy_ops = {
.owner = THIS_MODULE,
};
+static int typec_dp_phy_config(struct phy *phy, int link_rate,
+ int lanes, u8 swing, u8 pre_emp)
+{
+ struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+ u8 i;
+
+ tcphy_cfg_dp_pll(tcphy, link_rate);
+
+ if (tcphy->mode == MODE_DFP_DP) {
+ for (i = 0; i < 4; i++)
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, i);
+ } else {
+ if (tcphy->flip) {
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 0);
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 1);
+ } else {
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 2);
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 3);
+ }
+ }
+
+ return 0;
+}
+
static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
struct device *dev)
{
+ int ret;
+
tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
"rockchip,grf");
if (IS_ERR(tcphy->grf_regs)) {
@@ -1042,6 +1186,16 @@ static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
return PTR_ERR(tcphy->tcphy_rst);
}
+ /*
+ * check if phy_config pass from dts, if no,
+ * use default phy config value.
+ */
+ ret = of_property_read_u32_array(dev->of_node, "rockchip,phy-config",
+ (u32 *)tcphy->config, sizeof(tcphy->config) / sizeof(u32));
+ if (ret)
+ memcpy(tcphy->config, tcphy_default_config,
+ sizeof(tcphy->config));
+
return 0;
}
@@ -1126,6 +1280,7 @@ static int rockchip_typec_phy_probe(struct platform_device *pdev)
}
}
+ tcphy->typec_phy_config = typec_dp_phy_config;
pm_runtime_enable(dev);
for_each_available_child_of_node(np, child_np) {
--
2.7.4
^ permalink raw reply related
* [PATCH v6 3/5] soc: rockchip: split rockchip_typec_phy struct to separate header
From: Lin Huang @ 2018-05-21 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526895424-22894-1-git-send-email-hl@rock-chips.com>
we may use rockchip_phy_typec struct in other driver, so split
it to separate header.
Signed-off-by: Lin Huang <hl@rock-chips.com>
---
Changes in v2:
- None
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- new patch here
drivers/phy/rockchip/phy-rockchip-typec.c | 47 +----------------------
include/soc/rockchip/rockchip_phy_typec.h | 63 +++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+), 46 deletions(-)
create mode 100644 include/soc/rockchip/rockchip_phy_typec.h
diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..795055f 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@
#include <linux/mfd/syscon.h>
#include <linux/phy/phy.h>
+#include <soc/rockchip/rockchip_phy_typec.h>
#define CMN_SSM_BANDGAP (0x21 << 2)
#define CMN_SSM_BIAS (0x22 << 2)
@@ -349,52 +350,6 @@
#define MODE_DFP_USB BIT(1)
#define MODE_DFP_DP BIT(2)
-struct usb3phy_reg {
- u32 offset;
- u32 enable_bit;
- u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
- unsigned int reg;
- struct usb3phy_reg typec_conn_dir;
- struct usb3phy_reg usb3tousb2_en;
- struct usb3phy_reg external_psm;
- struct usb3phy_reg pipe_status;
- struct usb3phy_reg usb3_host_disable;
- struct usb3phy_reg usb3_host_port;
- struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
- struct device *dev;
- void __iomem *base;
- struct extcon_dev *extcon;
- struct regmap *grf_regs;
- struct clk *clk_core;
- struct clk *clk_ref;
- struct reset_control *uphy_rst;
- struct reset_control *pipe_rst;
- struct reset_control *tcphy_rst;
- const struct rockchip_usb3phy_port_cfg *port_cfgs;
- /* mutex to protect access to individual PHYs */
- struct mutex lock;
-
- bool flip;
- u8 mode;
-};
-
struct phy_reg {
u16 value;
u32 addr;
diff --git a/include/soc/rockchip/rockchip_phy_typec.h b/include/soc/rockchip/rockchip_phy_typec.h
new file mode 100644
index 0000000..be6af0e
--- /dev/null
+++ b/include/soc/rockchip/rockchip_phy_typec.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Lin Huang <hl@rock-chips.com>
+ */
+
+#ifndef __SOC_ROCKCHIP_PHY_TYPEC_H
+#define __SOC_ROCKCHIP_PHY_TYPEC_H
+
+struct usb3phy_reg {
+ u32 offset;
+ u32 enable_bit;
+ u32 write_enable;
+};
+
+/**
+ * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
+ * @reg: the base address for usb3-phy config.
+ * @typec_conn_dir: the register of type-c connector direction.
+ * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
+ * @external_psm: the register of type-c phy external psm clock.
+ * @pipe_status: the register of type-c phy pipe status.
+ * @usb3_host_disable: the register of type-c usb3 host disable.
+ * @usb3_host_port: the register of type-c usb3 host port.
+ * @uphy_dp_sel: the register of type-c phy DP select control.
+ */
+struct rockchip_usb3phy_port_cfg {
+ unsigned int reg;
+ struct usb3phy_reg typec_conn_dir;
+ struct usb3phy_reg usb3tousb2_en;
+ struct usb3phy_reg external_psm;
+ struct usb3phy_reg pipe_status;
+ struct usb3phy_reg usb3_host_disable;
+ struct usb3phy_reg usb3_host_port;
+ struct usb3phy_reg uphy_dp_sel;
+};
+
+struct phy_config {
+ int swing;
+ int pe;
+};
+
+struct rockchip_typec_phy {
+ struct device *dev;
+ void __iomem *base;
+ struct extcon_dev *extcon;
+ struct regmap *grf_regs;
+ struct clk *clk_core;
+ struct clk *clk_ref;
+ struct reset_control *uphy_rst;
+ struct reset_control *pipe_rst;
+ struct reset_control *tcphy_rst;
+ const struct rockchip_usb3phy_port_cfg *port_cfgs;
+ /* mutex to protect access to individual PHYs */
+ struct mutex lock;
+ struct phy_config config[3][4];
+ bool flip;
+ u8 mode;
+ int (*typec_phy_config)(struct phy *phy, int link_rate,
+ int lanes, u8 swing, u8 pre_emp);
+};
+
+#endif
--
2.7.4
^ permalink raw reply related
* [PATCH v6 2/5] Documentation: dt-bindings: phy: add phy_config for Rockchip USB Type-C PHY
From: Lin Huang @ 2018-05-21 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526895424-22894-1-git-send-email-hl@rock-chips.com>
If want to do training outside DP Firmware, need phy voltage swing
and pre_emphasis value.
Signed-off-by: Lin Huang <hl@rock-chips.com>
---
Changes in v2:
- None
Changes in v3:
- modify property description and add this property to Example
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- change rockchip,phy_config to rockchip,phy-config and descript it in detail.
.../devicetree/bindings/phy/phy-rockchip-typec.txt | 36 +++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
index 960da7f..40d5e7a 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,11 @@ Required properties:
Optional properties:
- extcon : extcon specifier for the Power Delivery
-
+ - rockchip,phy-config : A list of voltage swing(mV) and pre-emphasis
+ (dB) pairs. They are 3 blocks of 4 entries and
+ correspond to s0p0 ~ s0p3, s1p0 ~ s1p3,
+ s2p0 ~ s2p3, s3p0 ~ s2p3 swing and pre-emphasis
+ values.
Required nodes : a sub-node is required for each port the phy provides.
The sub-node name is used to identify dp or usb3 port,
and shall be the following entries:
@@ -50,6 +54,21 @@ Example:
<&cru SRST_P_UPHY0_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
+ rockchip,phy-config = <0x2a 0x00>,
+ <0x1f 0x15>,
+ <0x14 0x22>,
+ <0x02 0x2b>,
+
+ <0x21 0x00>,
+ <0x12 0x15>,
+ <0x02 0x22>,
+ <0 0>,
+
+ <0x15 0x00>,
+ <0x00 0x15>,
+ <0 0>,
+ <0 0>;
+
tcphy0_dp: dp-port {
#phy-cells = <0>;
};
@@ -74,6 +93,21 @@ Example:
<&cru SRST_P_UPHY1_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
+ rockchip,phy-config = <0x2a 0x00>,
+ <0x1f 0x15>,
+ <0x14 0x22>,
+ <0x02 0x2b>,
+
+ <0x21 0x00>,
+ <0x12 0x15>,
+ <0x02 0x22>,
+ <0 0>,
+
+ <0x15 0x00>,
+ <0x00 0x15>,
+ <0 0>,
+ <0 0>;
+
tcphy1_dp: dp-port {
#phy-cells = <0>;
};
--
2.7.4
^ permalink raw reply related
* [PATCH v6 1/5] drm/rockchip: add transfer function for cdn-dp
From: Lin Huang @ 2018-05-21 9:37 UTC (permalink / raw)
To: linux-arm-kernel
From: Chris Zhong <zyw@rock-chips.com>
We may support training outside firmware, so we need support
dpcd read/write to get the message or do some setting with
display.
Signed-off-by: Chris Zhong <zyw@rock-chips.com>
Signed-off-by: Lin Huang <hl@rock-chips.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Enric Balletbo <enric.balletbo@collabora.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- None
drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 +++++++++++++++++++++++----
drivers/gpu/drm/rockchip/cdn-dp-core.h | 1 +
drivers/gpu/drm/rockchip/cdn-dp-reg.c | 69 ++++++++++++++++++++++++++++++----
drivers/gpu/drm/rockchip/cdn-dp-reg.h | 14 ++++++-
4 files changed, 122 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index c6fbdcd..cce64c1 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, u8 *sink_count)
u8 value;
*sink_count = 0;
- ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, &value, 1);
- if (ret)
+ ret = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, &value, 1);
+ if (ret < 0)
return ret;
*sink_count = DP_GET_SINK_COUNT(value);
@@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp)
if (!cdn_dp_check_sink_connection(dp))
return -ENODEV;
- ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
- DP_RECEIVER_CAP_SIZE);
- if (ret) {
+ ret = drm_dp_dpcd_read(&dp->aux, DP_DPCD_REV, dp->dpcd,
+ sizeof(dp->dpcd));
+ if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
return ret;
}
@@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device *dp)
if (!port || !dp->link.rate || !dp->link.num_lanes)
return false;
- if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
- DP_LINK_STATUS_SIZE)) {
+ if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) !=
+ DP_LINK_STATUS_SIZE) {
DRM_ERROR("Failed to get link status\n");
return false;
}
@@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
return NOTIFY_DONE;
}
+static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
+ struct drm_dp_aux_msg *msg)
+{
+ struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
+ int ret;
+ u8 status;
+
+ switch (msg->request & ~DP_AUX_I2C_MOT) {
+ case DP_AUX_NATIVE_WRITE:
+ case DP_AUX_I2C_WRITE:
+ case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+ ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
+ msg->size);
+ break;
+ case DP_AUX_NATIVE_READ:
+ case DP_AUX_I2C_READ:
+ ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
+ msg->size);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ status = cdn_dp_get_aux_status(dp);
+ if (status == AUX_STATUS_ACK)
+ msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+ else if (status == AUX_STATUS_NACK)
+ msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+ else if (status == AUX_STATUS_DEFER)
+ msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+
+ return ret;
+}
+
static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
{
struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
dp->active = false;
dp->active_port = -1;
dp->fw_loaded = false;
+ dp->aux.name = "DP-AUX";
+ dp->aux.transfer = cdn_dp_aux_transfer;
+ dp->aux.dev = dev;
+
+ ret = drm_dp_aux_register(&dp->aux);
+ if (ret)
+ return ret;
INIT_WORK(&dp->event_work, cdn_dp_pd_event_work);
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index f57e296..46159b2 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -78,6 +78,7 @@ struct cdn_dp_device {
struct platform_device *audio_pdev;
struct work_struct event_work;
struct edid *edid;
+ struct drm_dp_aux aux;
struct mutex lock;
bool connected;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index eb3042c..979355d 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -221,7 +221,12 @@ static int cdn_dp_reg_write_bit(struct cdn_dp_device *dp, u16 addr,
sizeof(field), field);
}
-int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
+/*
+ * Returns the number of bytes transferred on success, or a negative
+ * error code on failure. -ETIMEDOUT is returned if mailbox message was
+ * not send successfully;
+ */
+ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
{
u8 msg[5], reg[5];
int ret;
@@ -247,24 +252,41 @@ int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
goto err_dpcd_read;
ret = cdn_dp_mailbox_read_receive(dp, data, len);
+ if (!ret)
+ return len;
err_dpcd_read:
+ DRM_DEV_ERROR(dp->dev, "dpcd read failed: %d\n", ret);
return ret;
}
-int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
+#define CDN_AUX_HEADER_SIZE 5
+#define CDN_AUX_MSG_SIZE 20
+/*
+ * Returns the number of bytes transferred on success, or a negative error
+ * code on failure. -ETIMEDOUT is returned if mailbox message was not send
+ * success; -EINVAL is returned if get the wrong data size after message
+ * is sent
+ */
+ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
{
- u8 msg[6], reg[5];
+ u8 msg[CDN_AUX_MSG_SIZE + CDN_AUX_HEADER_SIZE];
+ u8 reg[CDN_AUX_HEADER_SIZE];
int ret;
- msg[0] = 0;
- msg[1] = 1;
+ if (WARN_ON(len > CDN_AUX_MSG_SIZE) || WARN_ON(len <= 0))
+ return -EINVAL;
+
+ msg[0] = (len >> 8) & 0xff;
+ msg[1] = len & 0xff;
msg[2] = (addr >> 16) & 0xff;
msg[3] = (addr >> 8) & 0xff;
msg[4] = addr & 0xff;
- msg[5] = value;
+
+ memcpy(msg + CDN_AUX_HEADER_SIZE, data, len);
+
ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_DPCD,
- sizeof(msg), msg);
+ CDN_AUX_HEADER_SIZE + len, msg);
if (ret)
goto err_dpcd_write;
@@ -277,8 +299,12 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
if (ret)
goto err_dpcd_write;
- if (addr != (reg[2] << 16 | reg[3] << 8 | reg[4]))
+ if ((len != (reg[0] << 8 | reg[1])) ||
+ (addr != (reg[2] << 16 | reg[3] << 8 | reg[4]))) {
ret = -EINVAL;
+ } else {
+ return len;
+ }
err_dpcd_write:
if (ret)
@@ -286,6 +312,33 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
return ret;
}
+int cdn_dp_get_aux_status(struct cdn_dp_device *dp)
+{
+ u8 status;
+ int ret;
+
+ ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX,
+ DPTX_GET_LAST_AUX_STAUS, 0, NULL);
+ if (ret)
+ goto err_get_hpd;
+
+ ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX,
+ DPTX_GET_LAST_AUX_STAUS,
+ sizeof(status));
+ if (ret)
+ goto err_get_hpd;
+
+ ret = cdn_dp_mailbox_read_receive(dp, &status, sizeof(status));
+ if (ret)
+ goto err_get_hpd;
+
+ return status;
+
+err_get_hpd:
+ DRM_DEV_ERROR(dp->dev, "get aux status failed: %d\n", ret);
+ return ret;
+}
+
int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
u32 i_size, const u32 *d_mem, u32 d_size)
{
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6580b11 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -328,6 +328,13 @@
#define GENERAL_BUS_SETTINGS 0x03
#define GENERAL_TEST_ACCESS 0x04
+/* AUX status*/
+#define AUX_STATUS_ACK 0
+#define AUX_STATUS_NACK 1
+#define AUX_STATUS_DEFER 2
+#define AUX_STATUS_SINK_ERROR 3
+#define AUX_STATUS_BUS_ERROR 4
+
#define DPTX_SET_POWER_MNG 0x00
#define DPTX_SET_HOST_CAPABILITIES 0x01
#define DPTX_GET_EDID 0x02
@@ -469,8 +476,11 @@ int cdn_dp_set_host_cap(struct cdn_dp_device *dp, u8 lanes, bool flip);
int cdn_dp_event_config(struct cdn_dp_device *dp);
u32 cdn_dp_get_event(struct cdn_dp_device *dp);
int cdn_dp_get_hpd_status(struct cdn_dp_device *dp);
-int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value);
-int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len);
+ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr,
+ u8 *data, u16 len);
+ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr,
+ u8 *data, u16 len);
+int cdn_dp_get_aux_status(struct cdn_dp_device *dp);
int cdn_dp_get_edid_block(void *dp, u8 *edid,
unsigned int block, size_t length);
int cdn_dp_train_link(struct cdn_dp_device *dp);
--
2.7.4
^ permalink raw reply related
* [PATCH v3 4/5] ARM: perf: Allow the use of the PMUv3 driver on 32bit ARM
From: Vladimir Murzin @ 2018-05-21 9:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518143913.26306-5-marc.zyngier@arm.com>
On 18/05/18 15:39, Marc Zyngier wrote:
> +static inline int read_pmuver(void)
> +{
> + /* PMUVers is not a signed field */
> + u32 dfr0 = read_cpuid_ext(CPUID_EXT_DFR0);
> + return (dfr0 >> 24) & 0xf;
> +}
Should we rule out versions prior v3 here or in __armv8pmu_probe_pmu()?
Thanks
Vladimir
^ 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