* [PATCH v3 0/8] PCI: leak fixes, removable generic PCI host, assorted stuff
From: Jan Kiszka @ 2018-05-15 5:58 UTC (permalink / raw)
To: linux-arm-kernel
Changes in v3:
- refactor series to be both bisectable and simpler while reworking
of_pci_get_host_bridge_resources()
- include of_pci_get_host_bridge_resources() removal
- include devm_of_pci_get_host_bridge_resources() error path fixes
- effectively, no functional changes to v2
Changes in v2:
- patch 1: commit message reworking as suggested by Lorenzo
- patch 3-6: split-up as suggested by Bjorn
- patch 8: new
- patch 10: select PCI_DOMAINS from PCI_HOST_GENERIC, rather than
allowing manual choice, as suggested by Lorenzo
This primarily enables to unbind the generic PCI host controller without
leaving lots of memory leaks behind. A previous proposal patch 5 was
rejected because of those issues [1].
The fixes have been validated in the Jailhouse setup, where we add and
remove a virtual PCI host controller on hypervisor activation/
deactivation, with the help of kmemleak.
Besides that, there is tiny PCI API cleanup at the beginning and
support for manually enabled PCI domains at the end that enables the
Jailhouse scenario.
Jan
[1] http://lkml.iu.edu/hypermail/linux/kernel/1606.3/00072.html
CC: Jingoo Han <jingoohan1@gmail.com>
CC: Joao Pinto <Joao.Pinto@synopsys.com>
CC: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
CC: Will Deacon <will.deacon@arm.com>
Jan Kiszka (8):
PCI: Make pci_get_new_domain_nr() static
PCI: Fix memory leak of devm_pci_alloc_host_bridge()
PCI: Rename device node parameter of
of_pci_get_host_bridge_resources()
PCI: Replace dev_node parameter of of_pci_get_host_bridge_resources
with device
PCI: Replace pr_*() with dev_*() in of_pci_get_host_bridge_resources()
PCI: Rework of_pci_get_host_bridge_resources() to
devm_of_pci_get_host_bridge_resources()
PCI: Add support for unbinding the generic PCI host controller
PCI: Enable PCI_DOMAINS along with generic PCI host controller
drivers/pci/dwc/pcie-designware-host.c | 2 +-
drivers/pci/host/Kconfig | 1 +
drivers/pci/host/pci-aardvark.c | 5 +--
drivers/pci/host/pci-ftpci100.c | 4 +-
drivers/pci/host/pci-host-common.c | 13 ++++++
drivers/pci/host/pci-host-generic.c | 1 +
drivers/pci/host/pci-v3-semi.c | 3 +-
drivers/pci/host/pci-versatile.c | 3 +-
drivers/pci/host/pci-xgene.c | 3 +-
drivers/pci/host/pcie-altera.c | 5 +--
drivers/pci/host/pcie-iproc-platform.c | 4 +-
drivers/pci/host/pcie-rcar.c | 5 +--
drivers/pci/host/pcie-rockchip.c | 4 +-
drivers/pci/host/pcie-xilinx-nwl.c | 4 +-
drivers/pci/host/pcie-xilinx.c | 4 +-
drivers/pci/of.c | 72 +++++++++++++++-------------------
drivers/pci/pci.c | 6 +--
drivers/pci/probe.c | 4 +-
include/linux/of_pci.h | 4 +-
include/linux/pci-ecam.h | 1 +
include/linux/pci.h | 3 --
21 files changed, 76 insertions(+), 75 deletions(-)
--
2.13.6
^ permalink raw reply
* [PATCH 1/2] ARM64: dts: meson-gxbb: odroidc2: enable sdcard UHS modes
From: Anand Moon @ 2018-05-15 5:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526305693.2897.16.camel@baylibre.com>
Hi Jerome
On 14 May 2018 at 19:18, Jerome Brunet <jbrunet@baylibre.com> wrote:
> On Wed, 2018-05-02 at 00:29 +0530, Anand Moon wrote:
>> Enable UHS modes for sdcard, on odroidc2.
>>
>> Signed-off-by: Anand Moon <linux.amoon@gmail.com>
>> ---
>> arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
>> index 54954b314a45..c90f8b46c60c 100644
>> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
>> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
>> @@ -258,6 +258,11 @@
>> cap-sd-highspeed;
>> max-frequency = <100000000>;
>> disable-wp;
>> + sd-uhs-sdr12;
>> + sd-uhs-sdr25;
>> + sd-uhs-sdr50;
>> + sd-uhs-sdr104;
>> + sd-uhs-ddr50;
>>
>> cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
>> cd-inverted;
>
> Hi Anand,
>
> I tried a few sdcards on the OC2 with your 2 patches.
> Like with the libretech-cc, sdr104 at 200Mhz works "mostly", but, with some
> sdcards, it does not - please see below. The same sdcards appear to be working
> fine on my laptop.
>
> This is something I have not been able to crack yet on the libretech-cc.
>
> I'd suggest dropping sdr104 and keeping the max frequency at 100Mhz until we can
> figure out the problem here.
>
> With this changed:
>
> Tested-by: Jerome Brunet <jbrunet@baylibre.com>
>
> dd if=/dev/mmcblk1 of=/dev/zero bs=4M
> [ 446.925817] mmc1: tuning execution failed: -5
> [ 446.956597] mmc1: tuning execution failed: -5
> [ 489.957810] print_req_error: I/O error, dev mmcblk1, sector 6654424
> [ 490.141975] print_req_error: I/O error, dev mmcblk1, sector 6656440
> [ 490.148304] print_req_error: I/O error, dev mmcblk1, sector 6656944
> [ 490.349650] print_req_error: I/O error, dev mmcblk1, sector 6658456
> [ 491.804382] print_req_error: I/O error, dev mmcblk1, sector 6747688
> [ 492.281246] print_req_error: I/O error, dev mmcblk1, sector 6784992
> [ 492.419034] print_req_error: I/O error, dev mmcblk1, sector 6785496
> [ 492.865878] print_req_error: I/O error, dev mmcblk1, sector 6791800
> [ 493.023809] print_req_error: I/O error, dev mmcblk1, sector 6792192
> [ 493.024435] Buffer I/O error on dev mmcblk1, logical block 849024, async page
> read
> [ 493.217751] print_req_error: I/O error, dev mmcblk1, sector 6792808
> [ 494.891779] mmc1: tuning execution failed: -5
> [ 495.374186] print_req_error: 3 callbacks suppressed
> [ 495.374193] print_req_error: I/O error, dev mmcblk1, sector 6854576
> [ 495.767498] print_req_error: I/O error, dev mmcblk1, sector 6860000
> [ 496.013104] print_req_error: I/O error, dev mmcblk1, sector 6863024
> [ 496.223042] print_req_error: I/O error, dev mmcblk1, sector 6864032
> [ 496.227003] print_req_error: I/O error, dev mmcblk1, sector 6864536
> [ 496.375175] print_req_error: I/O error, dev mmcblk1, sector 6864176
> [ 496.375806] Buffer I/O error on dev mmcblk1, logical block 858022, async page
> read
> [ 496.521229] print_req_error: I/O error, dev mmcblk1, sector 6864184
> [ 496.521852] Buffer I/O error on dev mmcblk1, logical block 858023, async page
> read
> [ 503.596978] print_req_error: I/O error, dev mmcblk1, sector 6983312
> [ 503.597606] Buffer I/O error on dev mmcblk1, logical block 872914, async page
> read
> [ 505.280621] print_req_error: I/O error, dev mmcblk1, sector 7004536
> [ 505.281249] Buffer I/O error on dev mmcblk1, logical block 875567, async page
> read
> [ 507.372560] print_req_error: I/O error, dev mmcblk1, sector 7048696
> [ 507.373192] Buffer I/O error on dev mmcblk1, logical block 881087, async page
> read
> [ 511.355248] print_req_error: I/O error, dev mmcblk1, sector 7131352
> [ 511.355883] Buffer I/O error on dev mmcblk1, logical block 891419, async page
> read
> [ 511.369076] print_req_error: I/O error, dev mmcblk1, sector 7131352
> [ 511.369694] Buffer I/O error on dev mmcblk1, logical block 891419, async page
> read
> dd: error reading '/dev/mmcblk1': Input/output error
> 868+7 records in
> 868+7 records out
> 3651252224 bytes (3.7 GB, 3.4 GiB) copied, 66.7736 s, 54.7 MB/s
Thank for your testing, I will also do some more testing on all the
sdcard and share you the result..
Mean while Sandisk Ultra microSDHC UHS-I card @A1 32GB shows.
On my Odroid C2:
[ 1.165784] meson-gx-mmc d0074000.mmc: allocated mmc-pwrseq
[ 1.403756] meson-gx-mmc d0072000.mmc: Got CD GPIO
[ 1.456160] Waiting for root device /dev/mmcblk1p2...
[ 1.608180] mmc1: new ultra high speed SDR104 SDHC card at address aaaa
[ 1.610002] mmcblk1: mmc1:aaaa JULIE 29.7 GiB
[ 1.617811] mmcblk1: p1 p2
Also I did not encounter and read/write failure on the sdcard but I
will re-test them.
root at odroid64:~# dd if=/dev/mmcblk1 of=/dev/zero bs=4M
7609+1 records in
7609+1 records out
31914983424 bytes (32 GB, 30 GiB) copied, 368.637 s, 86.6 MB/s
root at odroid64:~#
Best Regards
-Anand
^ permalink raw reply
* [PATCH V3] ARM: dts: da850-evm: Enable LCD and Backlight
From: Laurent Pinchart @ 2018-05-15 5:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHCN7xKgop-SMZpQm4jca3NB0rrc_CCcMG8JL6mayLx4u+zW9w@mail.gmail.com>
Hi Adam,
On Monday, 14 May 2018 21:04:07 EEST Adam Ford wrote:
> On Mon, May 14, 2018 at 7:35 AM, Sekhar Nori <nsekhar@ti.com> wrote:
> > On Monday 14 May 2018 04:22 PM, Adam Ford wrote:
> >> On Mon, May 14, 2018 at 12:29 AM, Sekhar Nori <nsekhar@ti.com> wrote:
> >>> Hi Adam,
>
> Added Tomi, Laurent, and Jyri for feedback.
>
> >>> On Monday 14 May 2018 04:50 AM, Adam Ford wrote:
> >>>> When using the board files the LCD works, but not with the DT.
> >>>> This adds enables the original da850-evm to work with the same
> >>>> LCD in device tree mode.
> >>>>
> >>>> The EVM has a gpio for the regulator and a gpio enable. The LCD and
> >>>> the vpif display pins are mutually exclusive, so if using the LCD,
> >>>> do not load the vpif driver.
> >>>
> >>> Its not sufficient just note this in patch description.
> >>>
> >>> a) Disable (status = "disabled") the VPIF node which clashes for pins
> >>> with LCD.
> >>> b) Add a comment on top of the status = "disabled" giving information on
> >>> how user can enable it (disable lcdc node and then change to status =
> >>> "okay").
> >>>
> >>>> Signed-off-by: Adam Ford <aford173@gmail.com>
> >>>> ---
> >>>> V3: Fix errant GPIO, label GPIO pins, and rename the regulator to be
> >>>> more explict to backlight which better matches the schematic.
> >>>> Updated the description to explain that it cannot be used at the
> >>>> same time as the vpif driver.
> >>>>
> >>>> V2: Add regulator and GPIO enable pins. Remove PWM backlight and
> >>>> replace with GPIO
> >>>>
> >>>> diff --git a/arch/arm/boot/dts/da850-evm.dts
> >>>> b/arch/arm/boot/dts/da850-evm.dts index 2e817da37fdb..3f1c8be07efe
> >>>> 100644
> >>>> --- a/arch/arm/boot/dts/da850-evm.dts
> >>>> +++ b/arch/arm/boot/dts/da850-evm.dts
> >>>> @@ -27,6 +27,50 @@
> >>>> spi0 = &spi1;
> >>>> };
> >>>>
> >>>> + backlight {
> >>>> + compatible = "gpio-backlight";
> >>>> + enable-gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; /* GP0[7] */
> >>>
> >>> The gpio-backlight binding does not describe a property called
> >>> enable-gpios. It should just be gpios.
> >>
> >> I will fix that.
> >>
> >>> a) Are you using gpio-backlight because you are not able to get the PWM
> >>> to work?
> >>
> >> Yes, You told me not to worry about doing a PWM backlight because the
> >> legacy board does not PWM either.
> >
> > Yeah, I meant not to add backlight control till the time we are able to
> > get it working using PWM. Is this needed for the basic LCD functionality
> > to work? I would like to avoid the churn of adding it using GPIO now and
> > changing to PWM later, if possible.
> >
> >>> b) What is GP0[7] connected to in the schematic you have? In the
> >>> schematic I have I see LCD_PWM0 is connected to
> >>> SPI1_SCS[0]/EPWM1B/GP2[14]/TM64P3_IN12.
> >>
> >> I have schematic 1016572 dated Wednesday, August 18, 2010. According
> >> to it, AXR15 / EPWMN0_TZ[0] / ECAP2_APWM2 / GPIO0[7] connects to U25,
> >> Pin 46 to generate M_LCD_PWM0. You might have one of the early,
> >> pre-release versions.
> >
> > Ah, okay. In your schematic, is GP2[14] connected to anything?
> >
> >>> c) The /* GP0[7] */ comment is not really useful on its own as it can be
> >>> computed. What I wanted to see is the schematic symbol like "LCD_PWM0".
> >>> Same for other places like this below.
> >>
> >> I can do that.
> >>
> >>>> @@ -35,6 +79,16 @@
> >>>> regulator-boot-on;
> >>>> };
> >>>>
> >>>> + backlight_reg: backlight-regulator {
> >>>> + compatible = "regulator-fixed";
> >>>> + regulator-name = "lcd_backlight_pwr";
> >>>> + regulator-min-microvolt = <3300000>;
> >>>> + regulator-max-microvolt = <3300000>;
> >>>> + gpio = <&gpio 47 GPIO_ACTIVE_HIGH>; /* GP2[15] */
> >>>> + regulator-always-on;
> >>>
> >>> Why should this regulator never be disabled?
> >>
> >> The gpio-backlight does not have a way that I can see to associate the
> >> regulator to it. I read through the bindings, but I didn't see an
> >> option to associate a regulator it. I use this regulator to drive
> >> lcd_backlight_pwr and the backlight driver to write lcd_pwm0. Without
> >> this option, the system disables lcd_backlight_pwr and the screen is
> >> blank
> >
> > It sounds like this is a hack to enable backlight on this board. I think
> > either the backlight driver needs to gain functionality to enable the
> > GPIO. Or backlight could be treated as part of the panel and enabled
> > using enable-gpios property in the panel. TBH, I will be okay either
> > way. Can you check with Jyri, Tomi and rest of the DRM folks on what
> > should be right way of dealing with this?
>
> Per your request I added them into this thread. I added Tomi, Jyri,
> and Laurent to this as Laurent's name is associated with the gpio
> backlight driver.
>
> I am not sure why you think it's a hack. I pulled up the schematic
> for the LCD to see what it's doing, and the lcd_backlight_pwr pin
> controls the power-on sequence of the back-light controller. Without
> this, there is no power, so it seems to me that the 'regulator-fixed'
> device is the correct way to do it.
It's a hack because keeping the backlight power on when the display is off
will consume power unnecessarily. The backlight power should be turned off in
that case.
> The separate pin associated to the gpio is used to tell the backlight
> IC to actually turn on/off the back-light. Ideally it seems like it
> would nice to have the gpio-backlight driver be able to specify the
> regulator, so when the backlight is in use, it would power the
> regulator, but until that's available, the it seems like
> 'regulator-always-on' is the way to make it stay on.
>
> Laurent, Jyri, Tomi, do you have any thoughts on this matter?
This has been attempted 6 years ago, and got rejected. See https://lwn.net/
Articles/525422/.
The problem is that the number of power supplies, the order in which they need
to be sequenced, and the related timings (as in delays required between
turning power supplies on/off) is highly hardware-specific. We can't hardcode
a specific sequence and specific timings in the gpio-backlight (or pwm-
backlight) driver, and specifying the sequence in DT was considered to be
over-engineered.
You thus have two options, either creating a custom backlight driver that will
handle the power supplies specific to your backlight controller, or
integrating backlight power supply control in your panel driver. If the power
supplies also power the panel and not just the backlight, or if their
sequencing depends in any way on the panel model in which the backlight
controller is integrated, I'd go for the latter, otherwise you can pick any of
the two methods.
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH V3] ARM: dts: da850-evm: Enable LCD and Backlight
From: Sekhar Nori @ 2018-05-15 5:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHCN7xKgop-SMZpQm4jca3NB0rrc_CCcMG8JL6mayLx4u+zW9w@mail.gmail.com>
On Monday 14 May 2018 11:34 PM, Adam Ford wrote:
> On Mon, May 14, 2018 at 7:35 AM, Sekhar Nori <nsekhar@ti.com> wrote:
>> On Monday 14 May 2018 04:22 PM, Adam Ford wrote:
>>> On Mon, May 14, 2018 at 12:29 AM, Sekhar Nori <nsekhar@ti.com> wrote:
>>>> Hi Adam,
>
> Added Tomi, Laurent, and Jyri for feedback.
>
>>>>
>>>> On Monday 14 May 2018 04:50 AM, Adam Ford wrote:
>>>>> When using the board files the LCD works, but not with the DT.
>>>>> This adds enables the original da850-evm to work with the same
>>>>> LCD in device tree mode.
>>>>>
>>>>> The EVM has a gpio for the regulator and a gpio enable. The LCD and
>>>>> the vpif display pins are mutually exclusive, so if using the LCD,
>>>>> do not load the vpif driver.
>>>>
>>>> Its not sufficient just note this in patch description.
>>>>
>>>> a) Disable (status = "disabled") the VPIF node which clashes for pins
>>>> with LCD.
>>>> b) Add a comment on top of the status = "disabled" giving information on
>>>> how user can enable it (disable lcdc node and then change to status =
>>>> "okay").
>>>>
>>>>>
>>>>> Signed-off-by: Adam Ford <aford173@gmail.com>
>>>>> ---
>>>>> V3: Fix errant GPIO, label GPIO pins, and rename the regulator to be more explict to
>>>>> backlight which better matches the schematic. Updated the description to explain
>>>>> that it cannot be used at the same time as the vpif driver.
>>>>>
>>>>> V2: Add regulator and GPIO enable pins. Remove PWM backlight and replace with GPIO
>>>>>
>>>>> diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
>>>>> index 2e817da37fdb..3f1c8be07efe 100644
>>>>> --- a/arch/arm/boot/dts/da850-evm.dts
>>>>> +++ b/arch/arm/boot/dts/da850-evm.dts
>>>>> @@ -27,6 +27,50 @@
>>>>> spi0 = &spi1;
>>>>> };
>>>>>
>>>>> + backlight {
>>>>> + compatible = "gpio-backlight";
>>>>> + enable-gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; /* GP0[7] */
>>>>
>>>> The gpio-backlight binding does not describe a property called
>>>> enable-gpios. It should just be gpios.
>>>
>>> I will fix that.
>>>
>>>>
>>>> a) Are you using gpio-backlight because you are not able to get the PWM
>>>> to work?
>>>>
>>> Yes, You told me not to worry about doing a PWM backlight because the
>>> legacy board does not PWM either.
>>
>> Yeah, I meant not to add backlight control till the time we are able to
>> get it working using PWM. Is this needed for the basic LCD functionality
>> to work? I would like to avoid the churn of adding it using GPIO now and
>> changing to PWM later, if possible.
>>
>>>
>>>> b) What is GP0[7] connected to in the schematic you have? In the
>>>> schematic I have I see LCD_PWM0 is connected to
>>>> SPI1_SCS[0]/EPWM1B/GP2[14]/TM64P3_IN12.
>>>
>>> I have schematic 1016572 dated Wednesday, August 18, 2010. According
>>> to it, AXR15 / EPWMN0_TZ[0] / ECAP2_APWM2 / GPIO0[7] connects to U25,
>>> Pin 46 to generate M_LCD_PWM0. You might have one of the early,
>>> pre-release versions.
>>
>> Ah, okay. In your schematic, is GP2[14] connected to anything?
>>
>>>
>>>>
>>>> c) The /* GP0[7] */ comment is not really useful on its own as it can be
>>>> computed. What I wanted to see is the schematic symbol like "LCD_PWM0".
>>>> Same for other places like this below.
>>>
>>> I can do that.
>>>>
>>>>> @@ -35,6 +79,16 @@
>>>>> regulator-boot-on;
>>>>> };
>>>>>
>>>>> + backlight_reg: backlight-regulator {
>>>>> + compatible = "regulator-fixed";
>>>>> + regulator-name = "lcd_backlight_pwr";
>>>>> + regulator-min-microvolt = <3300000>;
>>>>> + regulator-max-microvolt = <3300000>;
>>>>> + gpio = <&gpio 47 GPIO_ACTIVE_HIGH>; /* GP2[15] */
>>>>> + regulator-always-on;
>>>>
>>>> Why should this regulator never be disabled?
>>>
>>> The gpio-backlight does not have a way that I can see to associate the
>>> regulator to it. I read through the bindings, but I didn't see an
>>> option to associate a regulator it. I use this regulator to drive
>>> lcd_backlight_pwr and the backlight driver to write lcd_pwm0. Without
>>> this option, the system disables lcd_backlight_pwr and the screen is
>>> blank
>>
>> It sounds like this is a hack to enable backlight on this board. I think
>> either the backlight driver needs to gain functionality to enable the
>> GPIO. Or backlight could be treated as part of the panel and enabled
>> using enable-gpios property in the panel. TBH, I will be okay either
>> way. Can you check with Jyri, Tomi and rest of the DRM folks on what
>> should be right way of dealing with this?
>
> Per your request I added them into this thread. I added Tomi, Jyri,
> and Laurent to this as Laurent's name is associated with the gpio
> backlight driver.
Okay. The reason I did not loop them in myself is because I thought a
fresh thread with background will be better. But okay.
> I am not sure why you think it's a hack. I pulled up the schematic
> for the LCD to see what it's doing, and the lcd_backlight_pwr pin
> controls the power-on sequence of the back-light controller. Without
> this, there is no power, so it seems to me that the 'regulator-fixed'
> device is the correct way to do it.
Not questioning modeling the GPIO as a regulator.
>
> The separate pin associated to the gpio is used to tell the backlight
> IC to actually turn on/off the back-light. Ideally it seems like it
> would nice to have the gpio-backlight driver be able to specify the
> regulator, so when the backlight is in use, it would power the
> regulator, but until that's available, the it seems like
> 'regulator-always-on' is the way to make it stay on.
We need to add support for this in backlight driver. Using
regulator-always-on to paper over this lack of support in backlight
driver is what I am calling a hack. 'regulator-always-on' means the
regulator cannot be turned off. Thats certainly not the case as you have
pointed out.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v9 06/11] arm64: kexec_file: allow for loading Image-format kernel
From: AKASHI Takahiro @ 2018-05-15 5:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6f0df3a8-a691-80f1-85de-3e0ead852f12@arm.com>
James,
On Fri, May 11, 2018 at 06:07:06PM +0100, James Morse wrote:
> Hi Akashi,
>
> On 07/05/18 08:21, AKASHI Takahiro wrote:
> > On Tue, May 01, 2018 at 06:46:11PM +0100, James Morse wrote:
> >> On 25/04/18 07:26, AKASHI Takahiro wrote:
> >>> This patch provides kexec_file_ops for "Image"-format kernel. In this
> >>> implementation, a binary is always loaded with a fixed offset identified
> >>> in text_offset field of its header.
>
> >>> diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
> >>> index e4de1223715f..3cba4161818a 100644
> >>> --- a/arch/arm64/include/asm/kexec.h
> >>> +++ b/arch/arm64/include/asm/kexec.h
> >>> @@ -102,6 +102,56 @@ struct kimage_arch {
> >>> void *dtb_buf;
> >>> };
> >>>
> >>> +/**
> >>> + * struct arm64_image_header - arm64 kernel image header
> >>> + *
> >>> + * @pe_sig: Optional PE format 'MZ' signature
To be precise, this is NOT a PE signature but MS-DOS header's magic.
(There is another "PE" signature in PE COFF file header pointed to by
'pe_header'.)
I will correct its name.
> >>> + * @branch_code: Instruction to branch to stext
> >>> + * @text_offset: Image load offset, little endian
> >>> + * @image_size: Effective image size, little endian
> >>> + * @flags:
> >>> + * Bit 0: Kernel endianness. 0=little endian, 1=big endian
> >>
> >> Page size? What about 'phys_base'?, (whatever that is...)
> >> Probably best to refer to Documentation/arm64/booting.txt here, its the
> >> authoritative source of what these fields mean.
> >
> > While we don't care other bit fields for now, I will add the reference
> > to the Documentation file.
>
> Thanks, I don't want to create a second, incomplete set of documentation!
I will leave a minimum of description of parameters here.
>
>
> >>> + u64 reserved[3];
> >>> + u8 magic[4];
> >>> + u32 pe_header;
> >>> +};
> >>
> >> I'm surprised we don't have a definition for this already, I guess its always
> >> done in asm. We have kernel/image.h that holds some of this stuff, if we are
> >> going to validate the flags, is it worth adding the code there, (and moving it
> >> to include/asm)?
> >
> > A comment at the beginning of this file says,
> > #ifndef LINKER_SCRIPT
> > #error This file should only be included in vmlinux.lds.S
> > #endif
> > Let me think about.
>
> Ah, I missed that.
>
> Having two definitions of something makes me nervous that they can become
> different... looks like that header belongs to the linker, and shouldn't be used
> here then.
OK.
>
> >> I guess you skip the MZ prefix as its not present for !EFI?
Correct, but MZ checking in probe function is just an informative message.
> >
> > CONFIG_KEXEC_IMAGE_VERIFY_SIG depends on the fact that the file
> > format is PE (that is, EFI is enabled).
>
> So if the signature checking is enabled, its already been checked.
The signature, either MZ or PE, in a file will be actually checked
in verify_pefile_signature().
>
> >> Could we check branch_code is non-zero, and text-offset points within image-size?
> >
> > We could do it, but I don't think this check is very useful.
> >
> >>
> >> We could check that this platform supports the page-size/endian config that this
> >> Image was built with... We get a message from the EFI stub if the page-size
> >> can't be supported, it would be nice to do the same here (as we can).
> >
> > There is no restriction on page-size or endianness for kexec.
>
> No, but it won't boot if the hardware doesn't support it. The kernel will spin
> at a magic address that is, difficult, to debug without JTAG. The bug report
> will be "it didn't boot".
OK.
Added sanity checks for cpu features, endianness as well as page size.
>
> > What will be the purpose of this check?
>
> These values are in the header so that the bootloader can check them, then print
> a meaningful error. Here, kexec_file_load() is playing the part of the bootloader.
>
> I'm assuming kexec_file_load() can only be used to kexec linux... unlike regular
> kexec. Is this where I'm going wrong?
>
>
> >>> diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
> >>> new file mode 100644
> >>> index 000000000000..4dd524ad6611
> >>> --- /dev/null
> >>> +++ b/arch/arm64/kernel/kexec_image.c
> >>> @@ -0,0 +1,79 @@
> >>
> >>> +static void *image_load(struct kimage *image,
> >>> + char *kernel, unsigned long kernel_len,
> >>> + char *initrd, unsigned long initrd_len,
> >>> + char *cmdline, unsigned long cmdline_len)
> >>> +{
> >>> + struct kexec_buf kbuf;
> >>> + struct arm64_image_header *h = (struct arm64_image_header *)kernel;
> >>> + unsigned long text_offset;
> >>> + int ret;
> >>> +
> >>> + /* Load the kernel */
> >>> + kbuf.image = image;
> >>> + kbuf.buf_min = 0;
> >>> + kbuf.buf_max = ULONG_MAX;
> >>> + kbuf.top_down = false;
> >>> +
> >>> + kbuf.buffer = kernel;
> >>> + kbuf.bufsz = kernel_len;
> >>> + kbuf.memsz = le64_to_cpu(h->image_size);
> >>> + text_offset = le64_to_cpu(h->text_offset);
> >>> + kbuf.buf_align = SZ_2M;
> >>
> >>> + /* Adjust kernel segment with TEXT_OFFSET */
> >>> + kbuf.memsz += text_offset;
> >>> +
> >>> + ret = kexec_add_buffer(&kbuf);
> >>> + if (ret)
> >>> + goto out;
> >>> +
> >>> + image->arch.kern_segment = image->nr_segments - 1;
> >>
> >> You only seem to use kern_segment here, and in load_other_segments() called
> >> below. Could it not be a local variable passed in? Instead of arch-specific data
> >> we keep forever?
> >
> > No, kern_segment is also used in load_other_segments() in machine_kexec_file.c.
> > To optimize memory hole allocation logic in locate_mem_hole_callback(),
> > we need to know the exact range of kernel image (start and end).
>
> That's the second user. My badly-made point is one calls the other, but passes
> the data via some until-kexec lifetime struct. (its not important, just an
> indicator this worked differently in the past and hasn't been cleaned up).
> I meant something like [0].
OK, but instead of adding kern_seg, I want to change the interface to:
| extern int load_other_segments(struct kimage *image,
| unsigned long kernel_load_addr, unsigned long kernel_size,
| char *initrd, unsigned long initrd_len,
| char *cmdline, unsigned long cmdline_len);
This way, we will in future be able to address an issue I mentioned in
my previous e-mail. (If we support vmlinux, the kernel occupies two segments
for text and data, respectively.)
Thanks,
-Takahiro AKASHI
>
> Thanks,
>
> James
>
>
> [0] a diff is worth a thousand words:
> --------------------%<--------------------
> diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_
> kexec_file.c
> index 762f9102899c..c50ce844f09e 100644
> --- a/arch/arm64/kernel/machine_kexec_file.c
> +++ b/arch/arm64/kernel/machine_kexec_file.c
> @@ -325,11 +325,10 @@ static int prepare_elf_headers(void **addr, unsigned long *sz)
> return ret;
> }
>
> -int load_other_segments(struct kimage *image,
> +int load_other_segments(struct kimage *image, struct kexec_segment *kern_seg,
> char *initrd, unsigned long initrd_len,
> char *cmdline, unsigned long cmdline_len)
> {
> - struct kexec_segment *kern_seg;
> struct kexec_buf kbuf;
> void *hdrs_addr;
> unsigned long hdrs_sz;
> @@ -368,7 +367,6 @@ int load_other_segments(struct kimage *image,
> image->arch.elf_load_addr, hdrs_sz, hdrs_sz);
> }
>
> - kern_seg = &image->segment[image->arch.kern_segment];
> kbuf.image = image;
> /* not allocate anything below the kernel */
> kbuf.buf_min = kern_seg->mem + kern_seg->memsz;
> diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
> index 891f2484969d..085cb69293ca 100644
> --- a/arch/arm64/include/asm/kexec.h
> +++ b/arch/arm64/include/asm/kexec.h
> @@ -173,8 +172,10 @@ static inline int arm64_header_check_pe_sig(const struct ar
> m64_image_header *h)
> extern const struct kexec_file_ops kexec_image_ops;
>
> struct kimage;
> +struct kexec_segment;
>
> extern int load_other_segments(struct kimage *image,
> + struct kexec_segment *kern_seg,
> char *initrd, unsigned long initrd_len,
> char *cmdline, unsigned long cmdline_len);
> #endif
> diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
> index 7c11beefe65f..0e032d30a79c 100644
> --- a/arch/arm64/kernel/kexec_image.c
> +++ b/arch/arm64/kernel/kexec_image.c
> @@ -37,6 +37,7 @@ static void *image_load(struct kimage *image,
> char *cmdline, unsigned long cmdline_len)
> {
> struct kexec_buf kbuf;
> + struct kexec_segment *kern_seg;
> struct arm64_image_header *h = (struct arm64_image_header *)kernel;
> unsigned long text_offset;
> int ret;
> @@ -65,17 +66,17 @@ static void *image_load(struct kimage *image,
> if (ret)
> goto out;
>
> - image->arch.kern_segment = image->nr_segments - 1;
> - image->segment[image->arch.kern_segment].mem += text_offset;
> - image->segment[image->arch.kern_segment].memsz -= text_offset;
> - image->start = image->segment[image->arch.kern_segment].mem;
> + kern_seg = &image->segment[image->nr_segments - 1];
> + kern_seg->mem += text_offset;
> + kern_seg->memsz -= text_offset;
> + image->start = kern_seg->mem;
>
> pr_debug("Loaded kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> - image->segment[image->arch.kern_segment].mem,
> + kern_seg->mem,
> kbuf.bufsz, kbuf.memsz);
>
> /* Load additional data */
> - ret = load_other_segments(image, initrd, initrd_len,
> + ret = load_other_segments(image, kern_seg, initrd, initrd_len,
> cmdline, cmdline_len);
>
> out:
> --------------------%<--------------------
^ permalink raw reply
* [PATCH v9 03/11] arm64: kexec_file: invoke the kernel without purgatory
From: AKASHI Takahiro @ 2018-05-15 4:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ece8d3cc-127f-6855-52fb-24e4a1d4e823@arm.com>
James,
On Fri, May 11, 2018 at 06:03:49PM +0100, James Morse wrote:
> Hi Akashi,
>
> On 07/05/18 06:22, AKASHI Takahiro wrote:
> > On Tue, May 01, 2018 at 06:46:06PM +0100, James Morse wrote:
> >> On 25/04/18 07:26, AKASHI Takahiro wrote:
> >>> diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
> >>> index f76ea92dff91..f7dbba00be10 100644
> >>> --- a/arch/arm64/kernel/machine_kexec.c
> >>> +++ b/arch/arm64/kernel/machine_kexec.c
> >>> @@ -205,10 +205,17 @@ void machine_kexec(struct kimage *kimage)
>
> >>> cpu_soft_restart(kimage != kexec_crash_image,
> >>> - reboot_code_buffer_phys, kimage->head, kimage->start, 0);
> >>> + reboot_code_buffer_phys, kimage->head, kimage->start,
> >>> +#ifdef CONFIG_KEXEC_FILE
> >>> + kimage->purgatory_info.purgatory_buf ?
> >>> + 0 : kimage->arch.dtb_mem);
> >>> +#else
> >>> + 0);
> >>> +#endif
>
>
> >> purgatory_buf seems to only be set in kexec_purgatory_setup_kbuf(), called from
> >> kexec_load_purgatory(), which we don't use. How does this get a value?
> >>
> >> Would it be better to always use kimage->arch.dtb_mem, and ensure that is 0 for
> >> regular kexec (as we can't know where the dtb is)? (image_arg may then be a
> >> better name).
> >
> > The problem is arch.dtb_mem is currently defined only if CONFIG_KEXEC_FILE.
>
> I thought it was ARCH_HAS_KIMAGE_ARCH, which we can define all the time if
> that's what we want.
>
>
> > So I would like to
> > - merge this patch with patch#8
> > - change the condition
> > #ifdef CONFIG_KEXEC_FILE
> > kimage->file_mode ? kimage->arch.dtb_mem : 0);
> > #else
> > 0);
> > #endif
>
> If we can avoid even this #ifdef by always having kimage->arch, I'd prefer that.
> If we do that 'dtb_mem' would need some thing that indicates its for kexec_file,
> as kexec has a DTB too, we just don't know where it is...
OK, but I want to have a minimum of kexec.arch always exist.
How about this?
| #define ARCH_HAS_KIMAGE_ARCH
|
| struct kimage_arch {
| phys_addr_t dtb_mem;
| #ifdef CONFIG_KEXEC_FILE
| void *dtb_buf;
| /* Core ELF header buffer */
| void *elf_headers;
| unsigned long elf_headers_sz;
| unsigned long elf_load_addr;
| #endif
| void machine_kexec(struct kimage *kimage)
| {
| ...
| cpu_soft_restart(kimage != kexec_crash_image,
| reboot_code_buffer_phys, kimage->head, kimage->start,
| kimage->arch.dtb_mem);
Thanks
-Takahiro AKASHI
>
>
> Thanks,
>
> James
^ permalink raw reply
* [PATCH v2] arm64: dts: qcom: sdm845: Sort nodes in the reserved mem by address
From: Douglas Anderson @ 2018-05-15 4:43 UTC (permalink / raw)
To: linux-arm-kernel
Let's keep the reserved-memory node tidy and neat and keep it sorted
by address. This should have no functional change.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2:
- Oops! v1 accidentally changed the node name. Fixed.
arch/arm64/boot/dts/qcom/sdm845.dtsi | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 7c85e7c596db..73f71061fef8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -31,6 +31,12 @@
no-map;
};
+ memory at 85fe0000 {
+ compatible = "qcom,cmd-db";
+ reg = <0x0 0x85fe0000 0x0 0x20000>;
+ no-map;
+ };
+
smem_mem: memory at 86000000 {
reg = <0x0 0x86000000 0x0 0x200000>;
no-map;
@@ -40,12 +46,6 @@
reg = <0 0x86200000 0 0x2d00000>;
no-map;
};
-
- memory at 85fe0000 {
- compatible = "qcom,cmd-db";
- reg = <0x0 0x85fe0000 0x0 0x20000>;
- no-map;
- };
};
cpus {
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH] arm64: dts: qcom: sdm845: Sort nodes in the reserved mem by address
From: Douglas Anderson @ 2018-05-15 4:37 UTC (permalink / raw)
To: linux-arm-kernel
Let's keep the reserved-memory node tidy and neat and keep it sorted
by address. This should have no functional change.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
arch/arm64/boot/dts/qcom/sdm845.dtsi | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 7c85e7c596db..63026133feab 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -31,6 +31,12 @@
no-map;
};
+ reserved-memory at 85fe0000 {
+ compatible = "qcom,cmd-db";
+ reg = <0x0 0x85fe0000 0x0 0x20000>;
+ no-map;
+ };
+
smem_mem: memory at 86000000 {
reg = <0x0 0x86000000 0x0 0x200000>;
no-map;
@@ -40,12 +46,6 @@
reg = <0 0x86200000 0 0x2d00000>;
no-map;
};
-
- memory at 85fe0000 {
- compatible = "qcom,cmd-db";
- reg = <0x0 0x85fe0000 0x0 0x20000>;
- no-map;
- };
};
cpus {
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH v9 04/11] arm64: kexec_file: allocate memory walking through memblock list
From: AKASHI Takahiro @ 2018-05-15 4:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180507055906.GE11326@linaro.org>
James,
On Mon, May 07, 2018 at 02:59:07PM +0900, AKASHI Takahiro wrote:
> James,
>
> On Tue, May 01, 2018 at 06:46:09PM +0100, James Morse wrote:
> > Hi Akashi,
> >
> > On 25/04/18 07:26, AKASHI Takahiro wrote:
> > > We need to prevent firmware-reserved memory regions, particularly EFI
> > > memory map as well as ACPI tables, from being corrupted by loading
> > > kernel/initrd (or other kexec buffers). We also want to support memory
> > > allocation in top-down manner in addition to default bottom-up.
> > > So let's have arm64 specific arch_kexec_walk_mem() which will search
> > > for available memory ranges in usable memblock list,
> > > i.e. !NOMAP & !reserved,
> >
> > > instead of system resource tree.
> >
> > Didn't we try to fix the system-resource-tree in order to fix regular-kexec to
> > be safe in the EFI-memory-map/ACPI-tables case?
> >
> > It would be good to avoid having two ways of doing this, and I would like to
> > avoid having extra arch code...
>
> I know what you mean.
> /proc/iomem or system resource is, in my opinion, not the best place to
> describe memory usage of kernel but rather to describe *physical* hardware
> layout. As we are still discussing about "reserved" memory, I don't want
> to depend on it.
> Along with memblock list, we will have more accurate control over memory
> usage.
If you don't have further objection, I will take memblock approach
(with factoring out powerpc's arch_kexec_walk_mem()).
Thanks,
-Takahiro AKASHI
> >
> > > diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
> > > new file mode 100644
> > > index 000000000000..f9ebf54ca247
> > > --- /dev/null
> > > +++ b/arch/arm64/kernel/machine_kexec_file.c
> > > @@ -0,0 +1,57 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * kexec_file for arm64
> > > + *
> > > + * Copyright (C) 2018 Linaro Limited
> > > + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > + *
> >
> > > + * Most code is derived from arm64 port of kexec-tools
> >
> > How does kexec-tools walk memblock?
>
> Will remove this comment from this patch.
> Obviously, this comment is for the rest of the code which will be
> added to succeeding patches (patch #5 and #7).
>
>
> >
> > > + */
> > > +
> > > +#define pr_fmt(fmt) "kexec_file: " fmt
> > > +
> > > +#include <linux/ioport.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/kexec.h>
> > > +#include <linux/memblock.h>
> > > +
> > > +int arch_kexec_walk_mem(struct kexec_buf *kbuf,
> > > + int (*func)(struct resource *, void *))
> > > +{
> > > + phys_addr_t start, end;
> > > + struct resource res;
> > > + u64 i;
> > > + int ret = 0;
> > > +
> > > + if (kbuf->image->type == KEXEC_TYPE_CRASH)
> > > + return func(&crashk_res, kbuf);
> > > +
> > > + if (kbuf->top_down)
> > > + for_each_mem_range_rev(i, &memblock.memory, &memblock.reserved,
> > > + NUMA_NO_NODE, MEMBLOCK_NONE,
> > > + &start, &end, NULL) {
> >
> > for_each_free_mem_range_reverse() is a more readable version of this helper.
>
> OK. I used to use my own limited list of reserved memory instead of
> memblock.reserved here to exclude verbose ranges.
>
>
> > > + if (!memblock_is_map_memory(start))
> > > + continue;
> >
> > Passing MEMBLOCK_NONE means this walk will never find MEMBLOCK_NOMAP memory.
>
> Sure, I confirmed it.
>
> >
> > > + res.start = start;
> > > + res.end = end;
> > > + ret = func(&res, kbuf);
> > > + if (ret)
> > > + break;
> > > + }
> > > + else
> > > + for_each_mem_range(i, &memblock.memory, &memblock.reserved,
> > > + NUMA_NO_NODE, MEMBLOCK_NONE,
> > > + &start, &end, NULL) {
> >
> > for_each_free_mem_range()?
>
> OK.
>
> > > + if (!memblock_is_map_memory(start))
> > > + continue;
> > > +
> > > + res.start = start;
> > > + res.end = end;
> > > + ret = func(&res, kbuf);
> > > + if (ret)
> > > + break;
> > > + }
> > > +
> > > + return ret;
> > > +}
> > >
> >
> > With these changes, what we have is almost:
> > arch/powerpc/kernel/machine_kexec_file_64.c::arch_kexec_walk_mem() !
> > (the difference being powerpc doesn't yet support crash-kernels here)
> >
> > If the argument is walking memblock gives a better answer than the stringy
> > walk_system_ram_res() thing, is there any mileage in moving this code into
> > kexec_file.c, and using it if !IS_ENABLED(CONFIG_ARCH_DISCARD_MEMBLOCK)?
> >
> > This would save arm64/powerpc having near-identical implementations.
> > 32bit arm keeps memblock if it has kexec, so it may be useful there too if
> > kexec_file_load() support is added.
>
> Thanks. I've forgot ppc.
>
> -Takahiro AKASHI
>
>
> >
> > Thanks,
> >
> > James
^ permalink raw reply
* [PATCH] media: dvb-frontends: add Socionext SC1501A ISDB-S/T demodulator driver
From: kbuild test robot @ 2018-05-15 4:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180515003749.9980-1-suzuki.katsuhiro@socionext.com>
Hi Katsuhiro,
I love your patch! Perhaps something to improve:
[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v4.17-rc5 next-20180514]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Katsuhiro-Suzuki/media-dvb-frontends-add-Socionext-SC1501A-ISDB-S-T-demodulator-driver/20180515-091453
base: git://linuxtv.org/media_tree.git master
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
>> drivers/media/dvb-frontends/sc1501a.c:313:47: sparse: constant 211243671486 is so big it is long
vim +313 drivers/media/dvb-frontends/sc1501a.c
258
259 static int sc1501a_s_read_status(struct sc1501a_priv *chip,
260 struct dtv_frontend_properties *c,
261 enum fe_status *status)
262 {
263 struct regmap *r_s = chip->regmap_s;
264 u32 cpmon, tmpu, tmpl, flg;
265 u64 tmp;
266
267 /* Sync detection */
268 regmap_read(r_s, CPMON1_S, &cpmon);
269
270 *status = 0;
271 if (cpmon & CPMON1_S_FSYNC)
272 *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
273 if (cpmon & CPMON1_S_W2LOCK)
274 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
275
276 /* Signal strength */
277 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
278
279 if (*status & FE_HAS_SIGNAL) {
280 u32 agc;
281
282 regmap_read(r_s, AGCREAD_S, &tmpu);
283 agc = tmpu << 8;
284
285 c->strength.len = 1;
286 c->strength.stat[0].scale = FE_SCALE_RELATIVE;
287 c->strength.stat[0].uvalue = agc;
288 }
289
290 /* C/N rate */
291 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
292
293 if (*status & FE_HAS_VITERBI) {
294 u32 cnr = 0, x, y, d;
295 u64 d_3 = 0;
296
297 regmap_read(r_s, CNRDXU_S, &tmpu);
298 regmap_read(r_s, CNRDXL_S, &tmpl);
299 x = (tmpu << 8) | tmpl;
300 regmap_read(r_s, CNRDYU_S, &tmpu);
301 regmap_read(r_s, CNRDYL_S, &tmpl);
302 y = (tmpu << 8) | tmpl;
303
304 /* CNR[dB]: 10 * log10(D) - 30.74 / D^3 - 3 */
305 /* D = x^2 / (2^15 * y - x^2) */
306 d = (y << 15) - x * x;
307 if (d > 0) {
308 /* (2^4 * D)^3 = 2^12 * D^3 */
309 /* 3.074 * 2^(12 + 24) = 211243671486 */
310 d_3 = div_u64(16 * x * x, d);
311 d_3 = d_3 * d_3 * d_3;
312 if (d_3)
> 313 d_3 = div_u64(211243671486, d_3);
314 }
315
316 if (d_3) {
317 /* 0.3 * 2^24 = 5033164 */
318 tmp = (s64)2 * intlog10(x) - intlog10(abs(d)) - d_3
319 - 5033164;
320 cnr = div_u64(tmp * 10000, 1 << 24);
321 }
322
323 if (cnr) {
324 c->cnr.len = 1;
325 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
326 c->cnr.stat[0].uvalue = cnr;
327 }
328 }
329
330 /* BER */
331 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
332 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
333
334 regmap_read(r_s, BERCNFLG_S, &flg);
335
336 if ((*status & FE_HAS_VITERBI) && (flg & BERCNFLG_S_BERVRDY)) {
337 u32 bit_err, bit_cnt;
338
339 regmap_read(r_s, BERVRDU_S, &tmpu);
340 regmap_read(r_s, BERVRDL_S, &tmpl);
341 bit_err = (tmpu << 8) | tmpl;
342 bit_cnt = (1 << 13) * 204;
343
344 if (bit_cnt) {
345 c->post_bit_error.len = 1;
346 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
347 c->post_bit_error.stat[0].uvalue = bit_err;
348 c->post_bit_count.len = 1;
349 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
350 c->post_bit_count.stat[0].uvalue = bit_cnt;
351 }
352 }
353
354 return 0;
355 }
356
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* [PATCH v6 14/14] dt: qcom: Add qcom-cpufreq-kryo driver configuration
From: Viresh Kumar @ 2018-05-15 4:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526303520-5843-15-git-send-email-ilialin@codeaurora.org>
On 14-05-18, 16:12, Ilia Lin wrote:
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
> arch/arm64/boot/dts/qcom/apq8096-db820c.dts | 2 +-
> arch/arm64/boot/dts/qcom/msm8996.dtsi | 310 +++++++++++++++++++++++++++-
> 2 files changed, 309 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
> index 230e9c8..da23bda 100644
> --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
> +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
> @@ -17,5 +17,5 @@
>
> / {
> model = "Qualcomm Technologies, Inc. DB820c";
> - compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc";
> + compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc", "qcom,apq8096";
> };
> diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> index d7adef9..fbf92f6 100644
> --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> @@ -174,218 +174,519 @@
> };
>
> cluster0_opp: opp_table0 {
> - compatible = "operating-points-v2";
> + compatible = "operating-points-v2-kryo-cpu";
I think you need to mention both the above compatible strings here
with the kyro one mentioned first.
--
viresh
^ permalink raw reply
* [PATCH v6 13/14] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu
From: Viresh Kumar @ 2018-05-15 4:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526303520-5843-14-git-send-email-ilialin@codeaurora.org>
On 14-05-18, 16:11, Ilia Lin wrote:
> In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
> that have KRYO processors, the CPU ferequencies subset and voltage value
> of each OPP varies based on the silicon variant in use.
> Qualcomm Technologies, Inc. Process Voltage Scaling Tables
> defines the voltage and frequency value based on the msm-id in SMEM
> and speedbin blown in the efuse combination.
> The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
> to provide the OPP framework with required information.
> This is used to determine the voltage and frequency value for each OPP of
> operating-points-v2 table when it is parsed by the OPP framework.
>
> This change adds documentation.
>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
> .../devicetree/bindings/opp/kryo-cpufreq.txt | 680 +++++++++++++++++++++
> 1 file changed, 680 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH v6 12/14] cpufreq: Add Kryo CPU scaling driver
From: Viresh Kumar @ 2018-05-15 4:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526303520-5843-13-git-send-email-ilialin@codeaurora.org>
On 14-05-18, 16:11, Ilia Lin wrote:
> +static int __init qcom_cpufreq_kryo_driver_init(void)
> +{
> + size_t len;
> + int ret;
> + u32 versions;
> + enum _msm8996_version msm8996_version;
> + u8 *speedbin;
> + struct device *cpu_dev;
> + struct device_node *np;
> + struct nvmem_cell *speedbin_nvmem;
> + struct opp_table *opp_temp = NULL;
> +
> + cpu_dev = get_cpu_device(SILVER_LEAD);
> + if (IS_ERR_OR_NULL(cpu_dev))
> + return PTR_ERR(cpu_dev);
> +
> + msm8996_version = qcom_cpufreq_kryo_get_msm_id();
> + if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
> + dev_err(cpu_dev, "Not Snapdragon 820/821!");
> + return -ENODEV;
> + }
> +
> + np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
> + if (IS_ERR_OR_NULL(np))
> + return PTR_ERR(np);
> +
> + if (!of_device_is_compatible(np, "operating-points-v2-kryo-cpu")) {
> + ret = -ENOENT;
> + goto free_np;
> + }
> +
> + speedbin_nvmem = of_nvmem_cell_get(np, NULL);
> + if (IS_ERR(speedbin_nvmem)) {
> + ret = PTR_ERR(speedbin_nvmem);
> + dev_err(cpu_dev, "Could not get nvmem cell: %d\n", ret);
> + goto free_np;
> + }
> +
> + speedbin = nvmem_cell_read(speedbin_nvmem, &len);
> +
> + switch (msm8996_version) {
> + case MSM8996_V3:
> + versions = 1 << (unsigned int)(*speedbin);
> + break;
> + case MSM8996_SG:
> + versions = 1 << ((unsigned int)(*speedbin) + 4);
> + break;
> + default:
> + BUG();
> + break;
> + }
> +
> + ret = PTR_ERR_OR_ZERO(opp_temp = \
Why back slash here ?
> + dev_pm_opp_set_supported_hw(cpu_dev,&versions,1));
> + if (0 > ret)
> + goto free_np;
> +
> + dev_pm_opp_put_supported_hw(opp_temp);
> +
> + cpu_dev = get_cpu_device(GOLD_LEAD);
> + ret = PTR_ERR_OR_ZERO(opp_temp = \
And here.
> + dev_pm_opp_set_supported_hw(cpu_dev,&versions,1));
> + if (0 > ret)
> + goto free_np;
> +
> + ret = PTR_ERR_OR_ZERO(platform_device_register_simple("cpufreq-dt", \
and here.
> + -1, NULL, 0));
> +
> + dev_pm_opp_put_supported_hw(opp_temp);
And this is wrong. You don't need to call this in success case here.
It may have worked for you as cpufreq-dt driver would have already
been initialized, but that's not the case always. For example try
inserting cpufreq-dt module after kernel boots and it will fail.
> +
> +free_np:
> + of_node_put(np);
> +
> + return ret;
> +}
> +late_initcall(qcom_cpufreq_kryo_driver_init);
> +
> +MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver");
> +MODULE_LICENSE("GPL v2");
> --
> 1.9.1
--
viresh
^ permalink raw reply
* [PATCH v6 11/14] dt: qcom: Add SAW regulator for 8x96 CPUs
From: Viresh Kumar @ 2018-05-15 4:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526303520-5843-12-git-send-email-ilialin@codeaurora.org>
On 14-05-18, 16:11, Ilia Lin wrote:
> 1. Add syscon node for the SAW CPU registers
> 2. Add SAW regulators gang definition for s8-s11
> 3. Add voltages to the OPP tables
> 4. Add the s11 SAW regulator as CPU regulator
>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
> arch/arm64/boot/dts/qcom/msm8996.dtsi | 75 +++++++++++++++++++++++++++++++++++
> 1 file changed, 75 insertions(+)
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH v6 08/14] dt: qcom: Add opp and thermal to the msm8996
From: Viresh Kumar @ 2018-05-15 4:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526303520-5843-9-git-send-email-ilialin@codeaurora.org>
On 14-05-18, 16:11, Ilia Lin wrote:
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
> arch/arm64/boot/dts/qcom/msm8996.dtsi | 269 ++++++++++++++++++++++++++++++++--
> 1 file changed, 260 insertions(+), 9 deletions(-)
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH v2] arm64: dts: qcom: sdm845: Sort nodes in the soc by address
From: Douglas Anderson @ 2018-05-15 3:59 UTC (permalink / raw)
To: linux-arm-kernel
This is pure-churn and should be a no-op. I'm doing it in the hopes
of reducing merge conflicts. When things are sorted in a sane way
(and by base address seems sane) then it's less likely that future
patches will cause merge conflicts.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
Changes in v2:
- rebase atop tree today
arch/arm64/boot/dts/qcom/sdm845.dtsi | 96 ++++++++++++++--------------
1 file changed, 48 insertions(+), 48 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 7c85e7c596db..96dd4b2a41d6 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -198,6 +198,54 @@
ranges = <0 0 0 0xffffffff>;
compatible = "simple-bus";
+ gcc: clock-controller at 100000 {
+ compatible = "qcom,gcc-sdm845";
+ reg = <0x100000 0x1f0000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ tcsr_mutex_regs: syscon at 1f40000 {
+ compatible = "syscon";
+ reg = <0x1f40000 0x40000>;
+ };
+
+ tlmm: pinctrl at 3400000 {
+ compatible = "qcom,sdm845-pinctrl";
+ reg = <0x03400000 0xc00000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ spmi_bus: spmi at c440000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0xc440000 0x1100>,
+ <0xc600000 0x2000000>,
+ <0xe600000 0x100000>,
+ <0xe700000 0xa0000>,
+ <0xc40a000 0x26000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 481 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ cell-index = <0>;
+ };
+
+ apss_shared: mailbox at 17990000 {
+ compatible = "qcom,sdm845-apss-shared";
+ reg = <0x17990000 0x1000>;
+ #mbox-cells = <1>;
+ };
+
intc: interrupt-controller at 17a00000 {
compatible = "arm,gic-v3";
#address-cells = <1>;
@@ -218,24 +266,6 @@
};
};
- gcc: clock-controller at 100000 {
- compatible = "qcom,gcc-sdm845";
- reg = <0x100000 0x1f0000>;
- #clock-cells = <1>;
- #reset-cells = <1>;
- #power-domain-cells = <1>;
- };
-
- tlmm: pinctrl at 3400000 {
- compatible = "qcom,sdm845-pinctrl";
- reg = <0x03400000 0xc00000>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
timer at 17c90000 {
#address-cells = <1>;
#size-cells = <1>;
@@ -293,35 +323,5 @@
status = "disabled";
};
};
-
- spmi_bus: spmi at c440000 {
- compatible = "qcom,spmi-pmic-arb";
- reg = <0xc440000 0x1100>,
- <0xc600000 0x2000000>,
- <0xe600000 0x100000>,
- <0xe700000 0xa0000>,
- <0xc40a000 0x26000>;
- reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
- interrupt-names = "periph_irq";
- interrupts = <GIC_SPI 481 IRQ_TYPE_LEVEL_HIGH>;
- qcom,ee = <0>;
- qcom,channel = <0>;
- #address-cells = <2>;
- #size-cells = <0>;
- interrupt-controller;
- #interrupt-cells = <4>;
- cell-index = <0>;
- };
-
- tcsr_mutex_regs: syscon at 1f40000 {
- compatible = "syscon";
- reg = <0x1f40000 0x40000>;
- };
-
- apss_shared: mailbox at 17990000 {
- compatible = "qcom,sdm845-apss-shared";
- reg = <0x17990000 0x1000>;
- #mbox-cells = <1>;
- };
};
};
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH v4 4/4] drm/rockchip: support dp training outside dp firmware
From: Lin Huang @ 2018-05-15 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526354560-23135-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>
---
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
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..7efd070
--- /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 v4 3/4] phy: rockchip-typec: support variable phy config value
From: Lin Huang @ 2018-05-15 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526354560-23135-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
drivers/phy/rockchip/phy-rockchip-typec.c | 306 ++++++++++++++++++++----------
include/soc/rockchip/rockchip_phy_typec.h | 63 ++++++
2 files changed, 271 insertions(+), 98 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..5d8692d 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)
@@ -323,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
@@ -349,51 +358,7 @@
#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;
-};
+#define DP_DEFAULT_RATE 162000
struct phy_reg {
u16 value;
@@ -417,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 },
@@ -436,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,
@@ -463,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;
@@ -484,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);
}
@@ -498,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;
+ }
+
+ clk_ctrl |= DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE;
+ writel(clk_ctrl, tcphy->base + DP_CLK_CTL);
- /* set the default mode to RBR */
- writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR,
- 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)
@@ -535,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));
@@ -545,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,
@@ -754,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);
@@ -990,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");
@@ -999,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;
}
@@ -1023,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);
@@ -1031,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);
@@ -1047,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)) {
@@ -1087,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;
}
@@ -1171,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) {
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 v4 2/4] Documentation: bindings: add phy_config for Rockchip USB Type-C PHY
From: Lin Huang @ 2018-05-15 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526354560-23135-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
Change in v4:
- None
.../devicetree/bindings/phy/phy-rockchip-typec.txt | 29 +++++++++++++++++++++-
1 file changed, 28 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..af298f2 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,8 @@ 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.
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 +51,19 @@ 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 +88,19 @@ 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 v4 1/4] drm/rockchip: add transfer function for cdn-dp
From: Lin Huang @ 2018-05-15 3:22 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
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 v2 5/5] hisi: Consolidate the Kconfigs for the CLOCK_STUB and the MAILBOX
From: Leo Yan @ 2018-05-15 2:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526352795-6991-1-git-send-email-leo.yan@linaro.org>
From: Daniel Lezcano <daniel.lezcano@linaro.org>
The current defconfig is inconsistent as it selects the mailbox and
the clock for the hi6220 and the hi3660 without having their Kconfigs
making sure the dependencies are correct. It ends up when selecting
different versions for the kernel (for example when git bisecting)
those options disappear and they don't get back, leading to unexpected
behaviors. In our case, the cpufreq driver does no longer work because
the clock fails to initialize due to the clock stub and the mailbox
missing.
In order to have the dependencies correctly set when defaulting, let's
do the same as commit 3a49afb84ca074e ("clk: enable hi655x common clk
automatically") where we select automatically the driver when the
parent driver is selected. With sensible defaults in place, we can leave
other choices for EXPERT.
Acked-by: Stephen Boyd <sboyd@kernel.org>
Acked-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
arch/arm64/configs/defconfig | 1 -
drivers/clk/hisilicon/Kconfig | 13 ++++++++-----
drivers/mailbox/Kconfig | 12 ++++++++----
3 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index ecf6137..1d9d8b9 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -549,7 +549,6 @@ CONFIG_HWSPINLOCK_QCOM=y
CONFIG_ARM_MHU=y
CONFIG_PLATFORM_MHU=y
CONFIG_BCM2835_MBOX=y
-CONFIG_HI6220_MBOX=y
CONFIG_QCOM_APCS_IPC=y
CONFIG_ROCKCHIP_IOMMU=y
CONFIG_TEGRA_IOMMU_SMMU=y
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
index 1bd4355..becdb1d 100644
--- a/drivers/clk/hisilicon/Kconfig
+++ b/drivers/clk/hisilicon/Kconfig
@@ -44,14 +44,17 @@ config RESET_HISI
Build reset controller driver for HiSilicon device chipsets.
config STUB_CLK_HI6220
- bool "Hi6220 Stub Clock Driver"
- depends on COMMON_CLK_HI6220 && MAILBOX
- default ARCH_HISI
+ bool "Hi6220 Stub Clock Driver" if EXPERT
+ depends on (COMMON_CLK_HI6220 || COMPILE_TEST)
+ depends on MAILBOX
+ default COMMON_CLK_HI6220
help
Build the Hisilicon Hi6220 stub clock driver.
config STUB_CLK_HI3660
- bool "Hi3660 Stub Clock Driver"
- depends on COMMON_CLK_HI3660 && MAILBOX
+ bool "Hi3660 Stub Clock Driver" if EXPERT
+ depends on (COMMON_CLK_HI3660 || COMPILE_TEST)
+ depends on MAILBOX
+ default COMMON_CLK_HI3660
help
Build the Hisilicon Hi3660 stub clock driver.
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index a2bb274..567cd02 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -109,16 +109,20 @@ config TI_MESSAGE_MANAGER
platform has support for the hardware block.
config HI3660_MBOX
- tristate "Hi3660 Mailbox"
- depends on ARCH_HISI && OF
+ tristate "Hi3660 Mailbox" if EXPERT
+ depends on (ARCH_HISI || COMPILE_TEST)
+ depends on OF
+ default ARCH_HISI
help
An implementation of the hi3660 mailbox. It is used to send message
between application processors and other processors/MCU/DSP. Select
Y here if you want to use Hi3660 mailbox controller.
config HI6220_MBOX
- tristate "Hi6220 Mailbox"
- depends on ARCH_HISI
+ tristate "Hi6220 Mailbox" if EXPERT
+ depends on (ARCH_HISI || COMPILE_TEST)
+ depends on OF
+ default ARCH_HISI
help
An implementation of the hi6220 mailbox. It is used to send message
between application processors and MCU. Say Y here if you want to
--
1.9.1
^ permalink raw reply related
* [PATCH v2 4/5] arm64: dts: hi3660: Add thermal cooling management
From: Leo Yan @ 2018-05-15 2:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526352795-6991-1-git-send-email-leo.yan@linaro.org>
From: Tao Wang <jean.wangtao@linaro.org>
Add nodes and properties for thermal cooling management support.
Signed-off-by: Tao Wang <jean.wangtao@linaro.org>
Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 44 +++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index a39da09..e20edd9 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/hi3660-clock.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
compatible = "hisilicon,hi3660";
@@ -64,6 +65,8 @@
capacity-dmips-mhz = <592>;
clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
operating-points-v2 = <&cluster0_opp>;
+ #cooling-cells = <2>;
+ dynamic-power-coefficient = <110>;
};
cpu1: cpu at 1 {
@@ -112,6 +115,8 @@
capacity-dmips-mhz = <1024>;
clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
operating-points-v2 = <&cluster1_opp>;
+ #cooling-cells = <2>;
+ dynamic-power-coefficient = <550>;
};
cpu5: cpu at 101 {
@@ -1073,5 +1078,44 @@
interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
#thermal-sensor-cells = <1>;
};
+
+ thermal-zones {
+
+ cls0: cls0 {
+ polling-delay = <1000>;
+ polling-delay-passive = <100>;
+ sustainable-power = <4500>;
+
+ /* sensor ID */
+ thermal-sensors = <&tsensor 1>;
+
+ trips {
+ threshold: trip-point at 0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ target: trip-point at 1 {
+ temperature = <75000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&target>;
+ contribution = <1024>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ map1 {
+ trip = <&target>;
+ contribution = <512>;
+ cooling-device = <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
};
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2 3/5] arm64: dts: hi3660: Add CPU frequency scaling support
From: Leo Yan @ 2018-05-15 2:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526352795-6991-1-git-send-email-leo.yan@linaro.org>
Add two CPU OPP tables, one table is corresponding to one cluster,
which allow CPU frequency scaling on hi3660 platforms.
Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 86 +++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index 3a3bcff..a39da09 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -62,6 +62,8 @@
next-level-cache = <&A53_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <592>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu1: cpu at 1 {
@@ -72,6 +74,8 @@
next-level-cache = <&A53_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <592>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu2: cpu at 2 {
@@ -82,6 +86,8 @@
next-level-cache = <&A53_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <592>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu3: cpu at 3 {
@@ -92,6 +98,8 @@
next-level-cache = <&A53_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <592>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu4: cpu at 100 {
@@ -102,6 +110,8 @@
next-level-cache = <&A73_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
capacity-dmips-mhz = <1024>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
+ operating-points-v2 = <&cluster1_opp>;
};
cpu5: cpu at 101 {
@@ -112,6 +122,8 @@
next-level-cache = <&A73_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
capacity-dmips-mhz = <1024>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
+ operating-points-v2 = <&cluster1_opp>;
};
cpu6: cpu at 102 {
@@ -122,6 +134,8 @@
next-level-cache = <&A73_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
capacity-dmips-mhz = <1024>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
+ operating-points-v2 = <&cluster1_opp>;
};
cpu7: cpu at 103 {
@@ -132,6 +146,8 @@
next-level-cache = <&A73_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
capacity-dmips-mhz = <1024>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
+ operating-points-v2 = <&cluster1_opp>;
};
idle-states {
@@ -174,6 +190,76 @@
};
};
+ cluster0_opp: opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <533000000>;
+ opp-microvolt = <700000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp01 {
+ opp-hz = /bits/ 64 <999000000>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp02 {
+ opp-hz = /bits/ 64 <1402000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp03 {
+ opp-hz = /bits/ 64 <1709000000>;
+ opp-microvolt = <1000000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp04 {
+ opp-hz = /bits/ 64 <1844000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <300000>;
+ };
+ };
+
+ cluster1_opp: opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp10 {
+ opp-hz = /bits/ 64 <903000000>;
+ opp-microvolt = <700000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp11 {
+ opp-hz = /bits/ 64 <1421000000>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp12 {
+ opp-hz = /bits/ 64 <1805000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp13 {
+ opp-hz = /bits/ 64 <2112000000>;
+ opp-microvolt = <1000000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp14 {
+ opp-hz = /bits/ 64 <2362000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <300000>;
+ };
+ };
+
gic: interrupt-controller at e82b0000 {
compatible = "arm,gic-400";
reg = <0x0 0xe82b1000 0 0x1000>, /* GICD */
--
1.9.1
^ permalink raw reply related
* [PATCH v2 2/5] arm64: dts: hi3660: Add stub clock node
From: Leo Yan @ 2018-05-15 2:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526352795-6991-1-git-send-email-leo.yan@linaro.org>
From: Kaihua Zhong <zhongkaihua@huawei.com>
Add stub clock node for hi3660 platform.
Reviewed-by: Leo Yan <leo.yan@linaro.org>
Signed-off-by: Kaihua Zhong <zhongkaihua@huawei.com>
Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index b9e7c91..3a3bcff 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -282,6 +282,13 @@
#mbox-cells = <3>;
};
+ stub_clock: stub_clock at e896b500 {
+ compatible = "hisilicon,hi3660-stub-clk";
+ reg = <0x0 0xe896b500 0x0 0x0100>;
+ #clock-cells = <1>;
+ mboxes = <&mailbox 13 3 0>;
+ };
+
dual_timer0: timer at fff14000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x0 0xfff14000 0x0 0x1000>;
--
1.9.1
^ permalink raw reply related
* [PATCH v2 1/5] arm64: dts: hi3660: Add mailbox node
From: Leo Yan @ 2018-05-15 2:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526352795-6991-1-git-send-email-leo.yan@linaro.org>
From: Kaihua Zhong <zhongkaihua@huawei.com>
Add the mailbox controller node for hi3660 platform.
Signed-off-by: Kaihua Zhong <zhongkaihua@huawei.com>
Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index ec3eb8e..b9e7c91 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -274,6 +274,14 @@
#reset-cells = <2>;
};
+ mailbox: mailbox at e896b000 {
+ compatible = "hisilicon,hi3660-mbox";
+ reg = <0x0 0xe896b000 0x0 0x1000>;
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <3>;
+ };
+
dual_timer0: timer at fff14000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x0 0xfff14000 0x0 0x1000>;
--
1.9.1
^ permalink raw reply related
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