* [PATCH v4 0/3] Input: atmel_mxt_ts: Add support for optional regulators
From: Paweł Chmiel @ 2018-12-07 14:28 UTC (permalink / raw)
To: nick
Cc: mark.rutland, devicetree, alexandre.belloni, dmitry.torokhov,
linux-kernel, robh+dt, linux-input, linux-arm-kernel,
Paweł Chmiel
This patch series adds optional regulator support to atmel_mxt_ts.
First patch adds regulators to driver.
Second patch ensures that device is ready for communication.
Third patch updates documentation.
Changes from v3:
- Checkpatch fixes
- Drop punctuation from subject of one of patches
Changes from v2:
- Add reviewed-by to one patch
- Move code for enabling regulators into separate method,
to make code more readable.
- Add wait code, to ensure that device is ready for communication.
Changes from v1:
- Enable regulators only if reset_gpio is present.
- Switch from devm_regulator_get_optional to devm_regulator_get.
Paweł Chmiel (3):
Input: atmel_mxt_ts: Add support for optional regulators
Input: atmel_mxt_ts: Wait for device be ready for communication
Input: atmel_mxt_ts: Document optional voltage regulators
.../bindings/input/atmel,maxtouch.txt | 8 ++
drivers/input/touchscreen/atmel_mxt_ts.c | 76 +++++++++++++++++--
2 files changed, 78 insertions(+), 6 deletions(-)
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 07/19] clk: tegra: dfll: support PWM regulator control
From: Jon Hunter @ 2018-12-07 14:26 UTC (permalink / raw)
To: Joseph Lo, Thierry Reding, Peter De Schrijver
Cc: linux-tegra, linux-clk, linux-arm-kernel
In-Reply-To: <20181204092548.3038-8-josephl@nvidia.com>
On 04/12/2018 09:25, Joseph Lo wrote:
> The DFLL hardware supports two modes (I2C and PWM) for voltage control
> when requesting a frequency. In this patch, we introduce PWM mode support.
>
> To support that, we re-organize the LUT for unifying the table for both
> cases of I2C and PWM mode. And generate that based on regulator info.
> For the PWM-based regulator, we get this info from DT. And do the same as
> the case of I2C LUT, which can help to map the PMIC voltage ID and voltages
> that the regulator supported.
>
> The other parts are the support code for initializing the DFLL hardware
> to support PWM mode. Also, the register debugfs file is slightly
> reworked to only show the i2c registers when I2C mode is in use.
>
> Based on the work of Peter De Schrijver <pdeschrijver@nvidia.com>.
>
> Signed-off-by: Joseph Lo <josephl@nvidia.com>
> ---
> drivers/clk/tegra/clk-dfll.c | 431 ++++++++++++++++++++++++++++++-----
> 1 file changed, 368 insertions(+), 63 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
> index 609e363dabf8..c294a2989f31 100644
> --- a/drivers/clk/tegra/clk-dfll.c
> +++ b/drivers/clk/tegra/clk-dfll.c
> @@ -1,7 +1,7 @@
> /*
> * clk-dfll.c - Tegra DFLL clock source common code
> *
> - * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
> + * Copyright (C) 2012-2018 NVIDIA Corporation. All rights reserved.
> *
> * Aleksandr Frid <afrid@nvidia.com>
> * Paul Walmsley <pwalmsley@nvidia.com>
> @@ -47,6 +47,7 @@
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/of.h>
> +#include <linux/pinctrl/consumer.h>
> #include <linux/pm_opp.h>
> #include <linux/pm_runtime.h>
> #include <linux/regmap.h>
> @@ -243,6 +244,12 @@ enum dfll_tune_range {
> DFLL_TUNE_LOW = 1,
> };
>
> +
> +enum tegra_dfll_pmu_if {
> + TEGRA_DFLL_PMU_I2C = 0,
> + TEGRA_DFLL_PMU_PWM = 1,
> +};
> +
> /**
> * struct dfll_rate_req - target DFLL rate request data
> * @rate: target frequency, after the postscaling
> @@ -294,16 +301,25 @@ struct tegra_dfll {
> u32 ci;
> u32 cg;
> bool cg_scale;
> + u32 reg_init_uV;
Doesn't this belong under PWM interface? Also being picky I dont' find
init_uV very descriptive.
Otherwise the change looks fine to me.
Cheers
Jon
--
nvpublic
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL] Allwinner core changes for 4.21
From: Maxime Ripard @ 2018-12-07 14:25 UTC (permalink / raw)
To: arm; +Cc: Maxime Ripard, Chen-Yu Tsai, linux-arm-kernel
[-- Attachment #1.1: Type: text/plain, Size: 1455 bytes --]
Hi Arnd, Kevin, Olof,
Please pull the following changes for the next merge window.
Thanks!
Maxime
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git tags/sunxi-core-for-4.21
for you to fetch changes up to dabfc8364ca76c8f8a24e8b5efc348869ac35d79:
dt-bindings: watchdog: Add Allwinner ARMv5 F1C100s wdt (2018-12-05 11:58:41 +0100)
----------------------------------------------------------------
Allwinner core changes for 4.21
A few patches to enable a new Allwinner SoC based on an armv5 CPU.
----------------------------------------------------------------
Mesih Kilinc (4):
ARM: Check ARCH_MULTI_V7 to differentiate ARMv5/v7 Allwinner SoCs
dt-bindings: arm: Add new Allwinner ARMv5 F1C100s SoC
ARM: sunxi: add Allwinner ARMv5 SoCs
dt-bindings: watchdog: Add Allwinner ARMv5 F1C100s wdt
Documentation/devicetree/bindings/arm/sunxi.txt | 1 +
.../devicetree/bindings/watchdog/sunxi-wdt.txt | 1 +
arch/arm/mach-sunxi/Kconfig | 19 ++++++++++++++++++-
arch/arm/mach-sunxi/sunxi.c | 9 +++++++++
4 files changed, 29 insertions(+), 1 deletion(-)
--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL 3/6] firmware: tegra: Changes for v4.21-rc1
From: Thierry Reding @ 2018-12-07 14:17 UTC (permalink / raw)
To: arm; +Cc: linux-tegra, Thierry Reding, linux-arm-kernel, Jon Hunter
In-Reply-To: <20181207141739.9085-1-thierry.reding@gmail.com>
Hi ARM SoC maintainers,
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-4.21-firmware
for you to fetch changes up to af51c25fb59d4365c259ab93f388462e0998a2ed:
firmware: tegra: Use in-band messages for firmware version query (2018-11-08 12:49:26 +0100)
Thanks,
Thierry
----------------------------------------------------------------
firmware: tegra: Changes for v4.21-rc1
These changes update the BPMP ABI header and implement a new variant of
the BPMP firmware version tag query if supported.
----------------------------------------------------------------
Timo Alho (5):
firmware: tegra: Add helper to check for supported MRQs
firmware: tegra: Switch to global mrq_is_supported()
firmware: tegra: Print version tag at full
soc/tegra: bpmp: Update ABI header
firmware: tegra: Use in-band messages for firmware version query
drivers/firmware/tegra/bpmp-debugfs.c | 29 +-
drivers/firmware/tegra/bpmp.c | 77 ++-
include/soc/tegra/bpmp-abi.h | 1188 ++++++++++++++++++++++++++-------
include/soc/tegra/bpmp.h | 7 +
4 files changed, 1024 insertions(+), 277 deletions(-)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v5 4/4] arm64: KVM: Enable support for :G/:H perf event modifiers
From: Suzuki K Poulose @ 2018-12-07 14:24 UTC (permalink / raw)
To: Andrew Murray, Christoffer Dall, Marc Zyngier, Catalin Marinas,
Will Deacon, Mark Rutland
Cc: kvmarm, linux-arm-kernel, Julien Thierry
In-Reply-To: <1544023815-16958-5-git-send-email-andrew.murray@arm.com>
On 05/12/2018 15:30, Andrew Murray wrote:
> Enable/disable event counters as appropriate when entering and exiting
> the guest to enable support for guest or host only event counting.
>
> For both VHE and non-VHE we switch the counters between host/guest at
> EL2. EL2 is filtered out by the PMU when we are using the :G modifier.
>
> The PMU may be on when we change which counters are enabled however
> we avoid adding an isb as we instead rely on existing context
> synchronisation events: the isb in kvm_arm_vhe_guest_exit for VHE and
> the eret from the hvc in kvm_call_hyp.
>
> Signed-off-by: Andrew Murray <andrew.murray@arm.com>
> ---
> arch/arm64/kvm/hyp/switch.c | 38 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL] Allwinner arm64 defconfig changes for 4.21
From: Maxime Ripard @ 2018-12-07 14:22 UTC (permalink / raw)
To: arm; +Cc: Maxime Ripard, Chen-Yu Tsai, linux-arm-kernel
[-- Attachment #1.1: Type: text/plain, Size: 1214 bytes --]
Hi Arnd, Kevin, Olof,
Here are a few defconfig changes for arm64 for the next merge window.
Thanks!
Maxime
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git tags/sunxi-config64-for-4.21
for you to fetch changes up to 4f49b7344201616e327a5f94db0f534025ab814b:
arm64: defconfig: Enable PWM_SUN4I (2018-11-13 14:06:40 +0100)
----------------------------------------------------------------
Allwinner arm64 defconfig for 4.21
A bunch of patches to improve the coverage of Allwinner drivers in the
arm64 defconfig, mostly targeted at adding display drivers support.
----------------------------------------------------------------
Jagan Teki (4):
arm64: defconfig: Enable MFD_AXP20X_I2C
arm64: defconfig: Enable DRM_SUN8I_MIXER
arm64: defconfig: Enable DRM_SUN8I_DW_HDMI
arm64: defconfig: Enable PWM_SUN4I
arch/arm64/configs/defconfig | 4 ++++
1 file changed, 4 insertions(+)
--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL] DaVinci SoC updates for v4.21
From: Sekhar Nori @ 2018-12-07 14:19 UTC (permalink / raw)
To: ARM-SoC Maintainers
Cc: Bartosz Golaszewski, Linux ARM Kernel List, Kevin Hilman
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git tags/davinci-for-v4.21/soc
for you to fetch changes up to a2ce9a67051bbbcc961aca2e06dcadd9b72d72fa:
ARM: davinci: da850-evm: remove unnecessary include (2018-12-06 16:19:50 +0530)
----------------------------------------------------------------
DaVinci SoC updates for v4.21
-----------------------------
This set of patches moves DaVinci one step closer to
not relying on at24 platform data by relying on nvmem
cell lookups instead.
Once other dependencies are merged, for v4.22, plan is
to merge another series of patches removing at24
platform data.
----------------------------------------------------------------
Bartosz Golaszewski (7):
ARM: davinci: dm365-evm: use cell nvmem lookup for mac address
ARM: davinci: dm644x-evm: use cell nvmem lookup for mac address
ARM: davinci: dm646x-evm: use cell nvmem lookup for mac address
ARM: davinci: da830-evm: use cell nvmem lookup for mac address
ARM: davinci: mityomapl138: use cell nvmem lookup for mac address
ARM: davinci: dm850-evm: use cell nvmem lookup for mac address
ARM: davinci: da850-evm: remove unnecessary include
arch/arm/mach-davinci/board-da830-evm.c | 26 ++++++++++++++++++++++++++
arch/arm/mach-davinci/board-da850-evm.c | 30 +++++++++++++++++++++++++++++-
arch/arm/mach-davinci/board-dm365-evm.c | 25 +++++++++++++++++++++++++
arch/arm/mach-davinci/board-dm644x-evm.c | 24 ++++++++++++++++++++++++
arch/arm/mach-davinci/board-dm646x-evm.c | 24 ++++++++++++++++++++++++
arch/arm/mach-davinci/board-mityomapl138.c | 29 +++++++++++++++++++++++++++++
6 files changed, 157 insertions(+), 1 deletion(-)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL] Allwinner fixes for 4.20
From: Maxime Ripard @ 2018-12-07 14:18 UTC (permalink / raw)
To: arm; +Cc: Maxime Ripard, Chen-Yu Tsai, linux-arm-kernel
[-- Attachment #1.1: Type: text/plain, Size: 1040 bytes --]
Hi Arnd, Kevin, Olof,
Here is a fix for the 4.20 release.
Thanks!
Maxime
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git tags/sunxi-fixes-for-4.20
for you to fetch changes up to 5f8208f557065163f9a8089ea2ea7888f9d96922:
ARM: dts: sun8i: a83t: bananapi-m3: increase vcc-pd voltage to 3.3V (2018-11-14 15:10:57 +0800)
----------------------------------------------------------------
Allwinner fixes for 4.20
One small fix for a regulator range on the Banana Pi M3
----------------------------------------------------------------
Corentin Labbe (1):
ARM: dts: sun8i: a83t: bananapi-m3: increase vcc-pd voltage to 3.3V
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL 5/6] ARM: tegra: Device tree changes for v4.21-rc1
From: Thierry Reding @ 2018-12-07 14:17 UTC (permalink / raw)
To: arm; +Cc: linux-tegra, Thierry Reding, linux-arm-kernel, Jon Hunter
In-Reply-To: <20181207141739.9085-1-thierry.reding@gmail.com>
Hi ARM SoC maintainers,
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-4.21-arm-dt
for you to fetch changes up to 3dde5a2342cd204df15b6b0b90ee0ed4542225ca:
ARM: tegra: Add VIC on Tegra124 (2018-11-29 17:07:31 +0100)
Thanks,
Thierry
----------------------------------------------------------------
ARM: tegra: Device tree changes for v4.21-rc1
These changes add the external memory controller on Tegra20 as well as
the VIC on Tegra124.
----------------------------------------------------------------
Dmitry Osipenko (2):
ARM: dts: tegra20: Add interrupt entry to External Memory Controller
ARM: dts: tegra20: Add clock entry to External Memory Controller
Thierry Reding (1):
ARM: tegra: Add VIC on Tegra124
arch/arm/boot/dts/tegra124.dtsi | 12 ++++++++++++
arch/arm/boot/dts/tegra20.dtsi | 2 ++
2 files changed, 14 insertions(+)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL 2/6] soc/tegra: Changes for v4.21-rc1
From: Thierry Reding @ 2018-12-07 14:17 UTC (permalink / raw)
To: arm; +Cc: linux-tegra, Thierry Reding, linux-arm-kernel, Jon Hunter
In-Reply-To: <20181207141739.9085-1-thierry.reding@gmail.com>
Hi ARM SoC maintainers,
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-4.21-soc
for you to fetch changes up to e3e403c218cd07b497127a29e604fc26a71e8558:
soc/tegra: pmc: Add initial Tegra194 wake events (2018-11-28 17:32:28 +0100)
Thanks,
Thierry
----------------------------------------------------------------
soc/tegra: Changes for v4.21-rc1
These changes are mostly cleanups to the PMC driver, but they also add
support for wake events on Tegra186 and Tegra194, which can be used to
wake the system from sleep. With this and the corresponding device
tree additions suspend/resume is finally working on these SoCs.
----------------------------------------------------------------
Bo Yan (1):
soc/tegra: fuse: Remove duplicated function declaration
Dmitry Osipenko (1):
soc/tegra: pmc: Drop locking from tegra_powergate_is_powered()
Jon Hunter (1):
soc/tegra: pmc: Don't power-up XUSB power-domains
Sandipan Patra (1):
soc/tegra: pmc: Add sysfs entries for reset info
Thierry Reding (4):
soc/tegra: pmc: Add Tegra194 support
soc/tegra: pmc: Add wake event support
soc/tegra: pmc: Add initial Tegra186 wake events
soc/tegra: pmc: Add initial Tegra194 wake events
Yangtao Li (2):
soc/tegra: Don't leak device tree node reference
soc/tegra: pmc: Change to use DEFINE_SHOW_ATTRIBUTE macro
drivers/soc/tegra/common.c | 6 +-
drivers/soc/tegra/pmc.c | 472 +++++++++++++++++++++++++++++++++++++++++----
include/soc/tegra/fuse.h | 1 -
include/soc/tegra/pmc.h | 21 ++
4 files changed, 462 insertions(+), 38 deletions(-)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL 4/6] memory: tegra: Changes for v4.21-rc1
From: Thierry Reding @ 2018-12-07 14:17 UTC (permalink / raw)
To: arm; +Cc: linux-tegra, Thierry Reding, linux-arm-kernel, Jon Hunter
In-Reply-To: <20181207141739.9085-1-thierry.reding@gmail.com>
Hi ARM SoC maintainers,
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-4.21-memory
for you to fetch changes up to 96e5da7c842424bcf64afe1082b960b42b96190b:
memory: tegra: Introduce Tegra20 EMC driver (2018-11-08 12:50:34 +0100)
Thanks,
Thierry
----------------------------------------------------------------
memory: tegra: Changes for v4.21-rc1
This contains a single commit that adds support for the EMC driver on
Tegra20.
----------------------------------------------------------------
Dmitry Osipenko (1):
memory: tegra: Introduce Tegra20 EMC driver
drivers/memory/tegra/Kconfig | 10 +
drivers/memory/tegra/Makefile | 1 +
drivers/memory/tegra/tegra20-emc.c | 591 +++++++++++++++++++++++++++++++++++++
3 files changed, 602 insertions(+)
create mode 100644 drivers/memory/tegra/tegra20-emc.c
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL 6/6] arm64: tegra: Device tree change for v4.21-rc1
From: Thierry Reding @ 2018-12-07 14:17 UTC (permalink / raw)
To: arm; +Cc: linux-tegra, Thierry Reding, linux-arm-kernel, Jon Hunter
In-Reply-To: <20181207141739.9085-1-thierry.reding@gmail.com>
Hi ARM SoC maintainers,
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-4.21-arm64-dt
for you to fetch changes up to 611a1c69f8ca85fc656f09d0cd56f5934e2af5fb:
arm64: tegra: Set reg property for display-hub on Tegra194 (2018-12-07 12:57:26 +0100)
Note that this pulls in a subset of the code that is also part of the
first pull request in this series in order to satisfy some build-time
dependencies.
Thanks,
Thierry
----------------------------------------------------------------
arm64: tegra: Device tree change for v4.21-rc1
These changes add a bunch of features for Tegra194 and Tegra186, such as
wake events, on-die RTC, temperature sensors, HDA for audio over HDMI
and fan support on Jetson Xavier to allow cooling of the device.
----------------------------------------------------------------
Dmitry Osipenko (3):
dt: bindings: tegra20-emc: Document interrupt property
dt: bindings: tegra20-emc: Document clock property
dt: bindings: Move tegra20-emc binding to memory-controllers directory
Jon Hunter (2):
dt-bindings: usb: xhci-tegra: Add power-domain details
arm64: dts: tegra210: Add power-domains for xHCI
Krishna Reddy (1):
arm64: dts: tegra186: Enable IOMMU for SDHCI
Sameer Pujar (1):
arm64: tegra: Add HDA controller on Tegra194
Thierry Reding (30):
dt-bindings: thermal: tegra-bpmp: Add Tegra194 support
Merge branch 'for-4.21/dt-bindings' into for-4.21/arm64/dt
dt-bindings: tegra186-pmc: Add interrupt controller properties
Merge branch 'for-4.21/dt-bindings' into for-4.21/arm64/dt
arm64: tegra: Add PWM controllers on Tegra194
arm64: tegra: Add PWM fan support on Jetson Xavier
arm64: tegra: Clarify that P2972-0000 is Jetson Xavier
arm64: tegra: Add display support on Tegra194
arm64: tegra: Add VIC support on Tegra194
arm64: tegra: Enable HDMI on P2972-0000
arm64: tegra: Add thermal zones on Tegra194
arm64: tegra: p2972: Enable the CPU, GPU and AUX thermal zones
arm64: tegra: Fix power key interrupt type on Jetson TX2
arm64: tegra: Enable PMC wake events on Tegra186
arm64: tegra: Add RTC support on Tegra186
arm64: tegra: p3310: Enable on-die RTC
arm64: tegra: Enable PMC wake events on Tegra194
arm64: tegra: Add RTC support on Tegra194
arm64: tegra: p2888: Enable on-die RTC
arm64: tegra: Add AON GPIO controller on Tegra194
arm64: tegra: Add gpio-keys on Jetson Xavier
arm64: tegra: Add temperature sensor on P2888
arm64: tegra: Add HDA controller on Tegra186
arm64: tegra: Enable HDA on Jetson TX2
arm64: tegra: Add CEC controller on Tegra186
arm64: tegra: Enable HDA on Jetson Xavier
arm64: tegra: Add CEC controller on Tegra194
arm64: tegra: Enable HDA controller on Jetson TX1
arm64: tegra: Set reg property for display-hub on Tegra186
arm64: tegra: Set reg property for display-hub on Tegra194
.../bindings/arm/tegra/nvidia,tegra186-pmc.txt | 3 +
.../nvidia,tegra20-emc.txt | 4 +
.../thermal/nvidia,tegra186-bpmp-thermal.txt | 3 +-
.../bindings/usb/nvidia,tegra124-xusb.txt | 8 +
arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts | 6 +
arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 4 +
arch/arm64/boot/dts/nvidia/tegra186.dtsi | 45 +-
arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi | 30 +-
arch/arm64/boot/dts/nvidia/tegra194-p2972-0000.dts | 157 +++++-
arch/arm64/boot/dts/nvidia/tegra194.dtsi | 538 ++++++++++++++++++++-
arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 4 +
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 2 +
.../dt-bindings/thermal/tegra194-bpmp-thermal.h | 15 +
13 files changed, 813 insertions(+), 6 deletions(-)
rename Documentation/devicetree/bindings/{arm/tegra => memory-controllers}/nvidia,tegra20-emc.txt (95%)
create mode 100644 include/dt-bindings/thermal/tegra194-bpmp-thermal.h
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL 1/6] dt-bindings: Changes for v4.21-rc1
From: Thierry Reding @ 2018-12-07 14:17 UTC (permalink / raw)
To: arm; +Cc: linux-tegra, Thierry Reding, linux-arm-kernel, Jon Hunter
Hi ARM SoC maintainers,
The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:
Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-4.21-dt-bindings
for you to fetch changes up to b4c7bf003cb57220af64b59e887581e74f0ce527:
dt-bindings: tegra186-pmc: Add interrupt controller properties (2018-11-28 16:42:58 +0100)
Thanks,
Thierry
----------------------------------------------------------------
dt-bindings: Changes for v4.21-rc1
This contains a few cleanups of and additions to existing device tree
bindings, such as XUSB, EMC, PMC and thermal.
----------------------------------------------------------------
Dmitry Osipenko (3):
dt: bindings: tegra20-emc: Document interrupt property
dt: bindings: tegra20-emc: Document clock property
dt: bindings: Move tegra20-emc binding to memory-controllers directory
Jon Hunter (1):
dt-bindings: usb: xhci-tegra: Add power-domain details
Thierry Reding (2):
dt-bindings: thermal: tegra-bpmp: Add Tegra194 support
dt-bindings: tegra186-pmc: Add interrupt controller properties
.../devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt | 3 +++
.../tegra => memory-controllers}/nvidia,tegra20-emc.txt | 4 ++++
.../bindings/thermal/nvidia,tegra186-bpmp-thermal.txt | 3 ++-
.../devicetree/bindings/usb/nvidia,tegra124-xusb.txt | 8 ++++++++
include/dt-bindings/thermal/tegra194-bpmp-thermal.h | 15 +++++++++++++++
5 files changed, 32 insertions(+), 1 deletion(-)
rename Documentation/devicetree/bindings/{arm/tegra => memory-controllers}/nvidia,tegra20-emc.txt (95%)
create mode 100644 include/dt-bindings/thermal/tegra194-bpmp-thermal.h
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 0/7] add UniPhier DVB Frontend system support
From: Mauro Carvalho Chehab @ 2018-12-07 14:17 UTC (permalink / raw)
To: Katsuhiro Suzuki
Cc: Sean Young, Masami Hiramatsu, Brad Love, linux-kernel, Jassi Brar,
Michael Ira Krufky, linux-arm-kernel, linux-media
In-Reply-To: <000301d43ffe$9e6e9f80$db4bde80$@socionext.com>
Hi Katsuhiro-san,
Em Thu, 30 Aug 2018 10:13:11 +0900
"Katsuhiro Suzuki" <suzuki.katsuhiro@socionext.com> escreveu:
> Hello Mauro,
>
> This is ping...
Sorry for taking a long time to look into it.
Reviewing new drivers take some time, and need to be done right.
I usually let the sub-maintainers to do a first look, but they
probably missed this one. So, let me copy them. Hopefully they
can do review on it soon.
I'll try to do a review myself, but I won't be able to do it
until mid next week.
Regards,
Mauro
>
> > -----Original Message-----
> > From: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
> > Sent: Wednesday, August 8, 2018 2:25 PM
> > To: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>;
> > linux-media@vger.kernel.org
> > Cc: Masami Hiramatsu <masami.hiramatsu@linaro.org>; Jassi Brar
> > <jaswinder.singh@linaro.org>; linux-arm-kernel@lists.infradead.org;
> > linux-kernel@vger.kernel.org; Suzuki, Katsuhiro
> > <suzuki.katsuhiro@socionext.com>
> > Subject: [PATCH v2 0/7] add UniPhier DVB Frontend system support
> >
> > This series adds support for DVB Frontend system named HSC support
> > for UniPhier LD11/LD20 SoCs. This driver supports MPEG2-TS serial
> > signal input from external demodulator and DMA MPEG2-TS stream data
> > onto memory.
> >
> > UniPhier HSC driver provides many ports of TS input. Since the HSC
> > has mixed register map for those ports. It hard to split each register
> > areas.
> >
> > ---
> >
> > Changes from v1:
> > DT bindings
> > - Fix mistakes of spelling
> > - Rename uniphier,hsc.txt -> socionext,uniphier-hsc.txt
> > Kconfig, Makefile
> > - Add COMPILE_TEST, REGMAP_MMIO
> > - Add $(srctree) to include path option
> > Headers
> > - Split large patch
> > - Remove more unused definitions
> > - Remove unneeded const
> > - Replace enum that has special value into #define
> > - Remove weird macro from register definitions
> > - Remove field_get/prop inline functions
> > Modules
> > - Split register definitions, function prototypes
> > - Fix include lines
> > - Fix depended config
> > - Remove redundant conditions
> > - Drop adapter patches, and need no patches to build
> > - Merge uniphier-adapter.o into each adapter drivers
> > - Split 3 modules (core, ld11, ld20) to build adapter drivers as
> > module
> > - Fix compile error if build as module
> > - Use hardware spec table to remove weird macro from register
> > definitions
> > - Use usleep_range instead of msleep
> > - Use shift and mask instead of field_get/prop inline functions
> >
> > Katsuhiro Suzuki (7):
> > media: uniphier: add DT bindings documentation for UniPhier HSC
> > media: uniphier: add DMA common file of HSC
> > media: uniphier: add CSS common file of HSC
> > media: uniphier: add TS common file of HSC
> > media: uniphier: add ucode load common file of HSC
> > media: uniphier: add platform driver module of HSC
> > media: uniphier: add LD11/LD20 HSC support
> >
> > .../bindings/media/socionext,uniphier-hsc.txt | 38 ++
> > drivers/media/platform/Kconfig | 1 +
> > drivers/media/platform/Makefile | 2 +
> > drivers/media/platform/uniphier/Kconfig | 19 +
> > drivers/media/platform/uniphier/Makefile | 5 +
> > drivers/media/platform/uniphier/hsc-core.c | 515 ++++++++++++++++++
> > drivers/media/platform/uniphier/hsc-css.c | 250 +++++++++
> > drivers/media/platform/uniphier/hsc-dma.c | 212 +++++++
> > drivers/media/platform/uniphier/hsc-ld11.c | 273 ++++++++++
> > drivers/media/platform/uniphier/hsc-reg.h | 272 +++++++++
> > drivers/media/platform/uniphier/hsc-ts.c | 127 +++++
> > drivers/media/platform/uniphier/hsc-ucode.c | 416 ++++++++++++++
> > drivers/media/platform/uniphier/hsc.h | 389 +++++++++++++
> > 13 files changed, 2519 insertions(+)
> > create mode 100644
> > Documentation/devicetree/bindings/media/socionext,uniphier-hsc.txt
> > create mode 100644 drivers/media/platform/uniphier/Kconfig
> > create mode 100644 drivers/media/platform/uniphier/Makefile
> > create mode 100644 drivers/media/platform/uniphier/hsc-core.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-css.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-dma.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-ld11.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-reg.h
> > create mode 100644 drivers/media/platform/uniphier/hsc-ts.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-ucode.c
> > create mode 100644 drivers/media/platform/uniphier/hsc.h
> >
> > --
> > 2.18.0
>
>
>
Thanks,
Mauro
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 06/19] clk: tegra: dfll: CVB calculation alignment with the regulator
From: Jon Hunter @ 2018-12-07 14:10 UTC (permalink / raw)
To: Joseph Lo, Thierry Reding, Peter De Schrijver
Cc: linux-tegra, linux-clk, linux-arm-kernel
In-Reply-To: <20181204092548.3038-7-josephl@nvidia.com>
On 04/12/2018 09:25, Joseph Lo wrote:
> The CVB table contains calibration data for the CPU DFLL based on
> process charaterization. The regulator step and offset parameters depend
> on the regulator supplying vdd-cpu , not on the specific Tegra SKU.
>
> When using a PWM controlled regulator, the voltage step and offset are
> determined by the regulator type in use. This is specified in DT. When
> using an I2C controlled regulator, we can retrieve them from CPU regulator
> or DT (if specified). Then pass this information to the CVB table
> calculation function.
>
> Based on the work done of "Peter De Schrijver <pdeschrijver@nvidia.com>"
> and "Alex Frid <afrid@nvidia.com>".
>
> Signed-off-by: Joseph Lo <josephl@nvidia.com>
> ---
> drivers/clk/tegra/clk-dfll.h | 6 +-
> drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 65 ++++++++++++++++++++--
> drivers/clk/tegra/cvb.c | 12 ++--
> drivers/clk/tegra/cvb.h | 6 +-
> 4 files changed, 75 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h
> index 83352c8078f2..ecc43cb9b6f1 100644
> --- a/drivers/clk/tegra/clk-dfll.h
> +++ b/drivers/clk/tegra/clk-dfll.h
> @@ -1,6 +1,6 @@
> /*
> * clk-dfll.h - prototypes and macros for the Tegra DFLL clocksource driver
> - * Copyright (C) 2013 NVIDIA Corporation. All rights reserved.
> + * Copyright (C) 2013-2018 NVIDIA Corporation. All rights reserved.
> *
> * Aleksandr Frid <afrid@nvidia.com>
> * Paul Walmsley <pwalmsley@nvidia.com>
> @@ -22,11 +22,14 @@
> #include <linux/reset.h>
> #include <linux/types.h>
>
> +#include "cvb.h"
> +
> /**
> * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
> * @dev: struct device * that holds the OPP table for the DFLL
> * @max_freq: maximum frequency supported on this SoC
> * @cvb: CPU frequency table for this SoC
> + * @alignment: parameters of the regulator step and offset
> * @init_clock_trimmers: callback to initialize clock trimmers
> * @set_clock_trimmers_high: callback to tune clock trimmers for high voltage
> * @set_clock_trimmers_low: callback to tune clock trimmers for low voltage
> @@ -35,6 +38,7 @@ struct tegra_dfll_soc_data {
> struct device *dev;
> unsigned long max_freq;
> const struct cvb_table *cvb;
> + struct rail_alignment alignment;
>
> void (*init_clock_trimmers)(void);
> void (*set_clock_trimmers_high)(void);
> diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
> index 1a2cc113e5c8..071a5c674832 100644
> --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
> +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
> @@ -23,6 +23,7 @@
> #include <linux/init.h>
> #include <linux/of_device.h>
> #include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> #include <soc/tegra/fuse.h>
>
> #include "clk.h"
> @@ -50,9 +51,6 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
> .process_id = -1,
> .min_millivolts = 900,
> .max_millivolts = 1260,
> - .alignment = {
> - .step_uv = 10000, /* 10mV */
> - },
What happens for tegra124-jetson-tk1 when we remove this?
> .speedo_scale = 100,
> .voltage_scale = 1000,
> .entries = {
> @@ -105,11 +103,43 @@ static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
> { },
> };
>
> +static void get_alignment_from_dt(struct device *dev,
> + struct rail_alignment *align)
> +{
> + align->step_uv = 0;
> + align->offset_uv = 0;
> +
> + if (of_property_read_u32(dev->of_node, "nvidia,align-step-uv",
> + &align->step_uv))
> + align->step_uv = 0;
> +
> + if (of_property_read_u32(dev->of_node,
> + "nvidia,align-offset-uv", &align->offset_uv))
> + align->offset_uv = 0;
> +}
> +
> +static int get_alignment_from_regulator(struct device *dev,
> + struct rail_alignment *align)
> +{
> + struct regulator *reg = devm_regulator_get(dev, "vdd-cpu");
> +
> + if (IS_ERR(reg))
> + return PTR_ERR(reg);
> +
> + align->offset_uv = regulator_list_voltage(reg, 0);
> + align->step_uv = regulator_get_linear_step(reg);
> +
> + devm_regulator_put(reg);
> +
> + return 0;
> +}
> +
> static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
> {
> int process_id, speedo_id, speedo_value, err;
> struct tegra_dfll_soc_data *soc;
> const struct dfll_fcpu_data *fcpu_data;
> + struct rail_alignment align;
>
> fcpu_data = of_device_get_match_data(&pdev->dev);
> if (!fcpu_data)
> @@ -135,12 +165,37 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
> return -ENODEV;
> }
>
> + get_alignment_from_dt(&pdev->dev, &align);
> + if (of_property_read_bool(pdev->dev.of_node, "nvidia,pwm-to-pmic")
> + && (!align.step_uv || !align.offset_uv)) {
> + dev_info(&pdev->dev, "Missing required align data in DT");
> + return -EINVAL;
> + } else {
This 'else' clause is not necessary.
> + if (!align.step_uv) {
> + dev_info(&pdev->dev,
> + "no align data in DT, try from vdd-cpu\n");
> + err = get_alignment_from_regulator(&pdev->dev, &align);
dev_warn
> + if (err == -EPROBE_DEFER) {
> + dev_info(&pdev->dev,
> + "defer probe to get vdd-cpu\n");
This dev_info is not necessary.
> + return -EPROBE_DEFER;
> + }
> + }
> + }
> +
> + if (!align.step_uv) {
> + dev_err(&pdev->dev, "missing step uv\n");
> + return -EINVAL;
> + }
> +
> soc->max_freq = fcpu_data->cpu_max_freq_table[speedo_id];
>
> soc->cvb = tegra_cvb_add_opp_table(soc->dev, fcpu_data->cpu_cvb_tables,
> fcpu_data->cpu_cvb_tables_size,
> - process_id, speedo_id, speedo_value,
> - soc->max_freq);
> + &align, process_id, speedo_id,
> + speedo_value, soc->max_freq);
> + soc->alignment = align;
> +
> if (IS_ERR(soc->cvb)) {
> dev_err(&pdev->dev, "couldn't add OPP table: %ld\n",
> PTR_ERR(soc->cvb));
> diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
> index da9e8e7b5ce5..81dcb97a9e0a 100644
> --- a/drivers/clk/tegra/cvb.c
> +++ b/drivers/clk/tegra/cvb.c
> @@ -1,7 +1,7 @@
> /*
> * Utility functions for parsing Tegra CVB voltage tables
> *
> - * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
> + * Copyright (C) 2012-2018 NVIDIA Corporation. All rights reserved.
> *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License version 2 as
> @@ -62,9 +62,9 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up)
> }
>
> static int build_opp_table(struct device *dev, const struct cvb_table *table,
> + struct rail_alignment *align,
> int speedo_value, unsigned long max_freq)
> {
> - const struct rail_alignment *align = &table->alignment;
> int i, ret, dfll_mv, min_mv, max_mv;
>
> min_mv = round_voltage(table->min_millivolts, align, UP);
> @@ -109,8 +109,9 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
> */
> const struct cvb_table *
> tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
> - size_t count, int process_id, int speedo_id,
> - int speedo_value, unsigned long max_freq)
> + size_t count, struct rail_alignment *align,
> + int process_id, int speedo_id, int speedo_value,
> + unsigned long max_freq)
> {
> size_t i;
> int ret;
> @@ -124,7 +125,8 @@ tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
> if (table->process_id != -1 && table->process_id != process_id)
> continue;
>
> - ret = build_opp_table(dev, table, speedo_value, max_freq);
> + ret = build_opp_table(dev, table, align, speedo_value,
> + max_freq);
> return ret ? ERR_PTR(ret) : table;
> }
>
> diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h
> index c1f077993b2a..bcf15a089b93 100644
> --- a/drivers/clk/tegra/cvb.h
> +++ b/drivers/clk/tegra/cvb.h
> @@ -49,7 +49,6 @@ struct cvb_table {
>
> int min_millivolts;
> int max_millivolts;
> - struct rail_alignment alignment;
>
> int speedo_scale;
> int voltage_scale;
> @@ -59,8 +58,9 @@ struct cvb_table {
>
> const struct cvb_table *
> tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
> - size_t count, int process_id, int speedo_id,
> - int speedo_value, unsigned long max_freq);
> + size_t count, struct rail_alignment *align,
> + int process_id, int speedo_id, int speedo_value,
> + unsigned long max_freq);
> void tegra_cvb_remove_opp_table(struct device *dev,
> const struct cvb_table *table,
> unsigned long max_freq);
>
--
nvpublic
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] ARM: dts: sunxi: Fix PMU compatible strings
From: Maxime Ripard @ 2018-12-07 14:08 UTC (permalink / raw)
To: Rob Herring
Cc: devicetree, Chen-Yu Tsai, Will Deacon, linux-kernel,
linux-arm-kernel
In-Reply-To: <20181206191142.14118-1-robh@kernel.org>
[-- Attachment #1.1: Type: text/plain, Size: 421 bytes --]
On Thu, Dec 06, 2018 at 01:11:42PM -0600, Rob Herring wrote:
> "arm,cortex-a15-pmu" is not a valid fallback compatible string for an
> Cortex-A7 PMU, so drop it.
>
> Cc: Maxime Ripard <maxime.ripard@bootlin.com>
> Cc: Chen-Yu Tsai <wens@csie.org>
> Signed-off-by: Rob Herring <robh@kernel.org>
Applied, thanks!
Maxime
--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v5 2/4] arm64: KVM: add accessors to track guest/host only counters
From: Suzuki K Poulose @ 2018-12-07 14:08 UTC (permalink / raw)
To: Andrew Murray
Cc: Mark Rutland, Julien Thierry, Marc Zyngier, Catalin Marinas,
Will Deacon, Christoffer Dall, kvmarm, linux-arm-kernel
In-Reply-To: <20181206192108.GA51311@e119886-lin.cambridge.arm.com>
On 06/12/2018 19:21, Andrew Murray wrote:
> On Thu, Dec 06, 2018 at 06:51:37PM +0000, Suzuki K Poulose wrote:
>>
>>
>> On 06/12/2018 17:21, Suzuki K Poulose wrote:
>>> Hi Andrew,
>>>
>>> On 05/12/2018 15:30, Andrew Murray wrote:
>>>> In order to effeciently enable/disable guest/host only perf counters
>>>> at guest entry/exit we add bitfields to kvm_cpu_context for guest and
>>>> host events as well as accessors for updating them.
>>>>
>>>> Signed-off-by: Andrew Murray <andrew.murray@arm.com>
>>>> ---
>>>> arch/arm64/include/asm/kvm_host.h | 24 ++++++++++++++++++++++++
>>>> 1 file changed, 24 insertions(+)
>>>>
>>>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>>>> index 1550192..800c87b 100644
>>>> --- a/arch/arm64/include/asm/kvm_host.h
>>>> +++ b/arch/arm64/include/asm/kvm_host.h
>>>> @@ -203,6 +203,8 @@ struct kvm_cpu_context {
>>>> };
>>>> struct kvm_vcpu *__hyp_running_vcpu;
>>>> + u32 events_host;
>>>> + u32 events_guest;
>>>> };
>>>> typedef struct kvm_cpu_context kvm_cpu_context_t;
>>>> @@ -467,11 +469,33 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu);
>>>> void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu);
>>>> void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu);
>>>> +#define KVM_PMU_EVENTS_HOST 1
>>>> +#define KVM_PMU_EVENTS_GUEST 2
>>>> +
>>>> #ifdef CONFIG_KVM /* Avoid conflicts with core headers if CONFIG_KVM=n */
>>>> static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
>>>> {
>>>> return kvm_arch_vcpu_run_map_fp(vcpu);
>>>> }
>>>> +static inline void kvm_set_pmu_events(u32 set, int flags)
>>>> +{
>>>> + kvm_cpu_context_t *ctx = this_cpu_ptr(&kvm_host_cpu_state);
>>>> +
>>>> + if (flags & KVM_PMU_EVENTS_HOST)
>>>> + ctx->events_host |= set;
>>>> + if (flags & KVM_PMU_EVENTS_GUEST)
>>>> + ctx->events_guest |= set;
>>>
>>> You seem to be passing a single flag at a time ever, in the next patch.
>>> Either we can batch the calls in the next patch, or make this a real number and
>>> not a flag. g.g, enum { HOST, GUEST } or even a bool.
>>>
>>> I think the former sounds better.
>>
>> Having another look at patch-3, we can never club set() calls for host &
>> guest events, we should go for the latter.
>
> Well we could always do this..
>
> u32 flags = 0;
> if (!attr->exclude_host)
> flags |= KVM_PMU_EVENTS_HOST;
> if (!attr->exclude_guest)
> flags |= KVM_PMU_EVENTS_GUEST;
>
> kvm_set_pmu_events(counter_bits, flags);
Yes, I think this should be fine.
Cheers
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] Fix OMAP4430 SDP Ethernet startup
From: Russell King - ARM Linux @ 2018-12-07 13:57 UTC (permalink / raw)
To: Peter Ujfalusi
Cc: Tony Lindgren, linux-omap, linux-arm-kernel, Santosh Shilimkar
In-Reply-To: <8b8e05e6-f8a1-2dfe-0967-27e5303a2a07@ti.com>
On Fri, Dec 07, 2018 at 03:40:13PM +0200, Peter Ujfalusi wrote:
> Russell,
>
> On 07/12/2018 14.52, Russell King - ARM Linux wrote:
> > It was noticed that unbinding and rebinding the KSZ8851 ethernet
> > resulted in the driver reporting "failed to read device ID" at probe.
> > Probing the reset line with a 'scope while repeatedly attempting to
> > bind the driver in a shell loop revealed that the KSZ8851 RSTN pin is
> > constantly held at zero, meaning the device is held in reset, and
> > does not respond on the SPI bus.
> >
> > Experimentation with the startup delay on the regulator set to 50ms
> > shows that the reset is positively released after 20ms.
> >
> > Schematics for this board are not available, and the traces are buried
> > in the inner layers of the board which makes tracing where the RSTN pin
> > extremely difficult. We can only guess that the RSTN pin is wired to a
> > reset generator chip driven off the ethernet supply, which fits the
> > observed behaviour.
>
> Based on the schematics of the Blaze device (which should be very close
> to SDP4430):
>
> TPS22902YFPR is used as the regulator switch (gpio48 controlled)
> The VOUT is routed to TPS3808G01DBV (SCH Note: Threshold set at 90%.
> Vsense: 0.405V).
>
> According to the TPS3808 data sheet the RESET delay time when Ct is open
> (this is the case in the schema): MIN/TYP/MAX: 12/20/28 ms.
>
> The 20ms you are seeing confirms this setup.
Thanks for the confirmation and information. The Blaze schematics
are also unavailable afaics.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v3 05/10] sun6i: dsi: Convert to generic phy handling
From: Maxime Ripard @ 2018-12-07 13:55 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Boris Brezillon
Cc: Archit Taneja, Rafal Ciepiela, Krzysztof Witos, Maxime Ripard,
linux-kernel, dri-devel, Andrzej Hajda, Chen-Yu Tsai,
Laurent Pinchart, Thomas Petazzoni, linux-arm-kernel, linux-media
In-Reply-To: <cover.ad7c4feb3905658f10b022df4756a5ade280011f.1544190837.git-series.maxime.ripard@bootlin.com>
Now that we have everything in place in the PHY framework to deal in a
generic way with MIPI D-PHY phys, let's convert our PHY driver and its
associated DSI driver to that new API.
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
drivers/gpu/drm/sun4i/Kconfig | 11 +-
drivers/gpu/drm/sun4i/Makefile | 6 +-
drivers/gpu/drm/sun4i/sun6i_mipi_dphy.c | 164 ++++++++++++++-----------
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 31 ++---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 17 +---
5 files changed, 126 insertions(+), 103 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index c2c042287c19..2b8db82c4bab 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -45,10 +45,19 @@ config DRM_SUN6I_DSI
default MACH_SUN8I
select CRC_CCITT
select DRM_MIPI_DSI
+ select DRM_SUN6I_DPHY
help
Choose this option if you want have an Allwinner SoC with
MIPI-DSI support. If M is selected the module will be called
- sun6i-dsi
+ sun6i_mipi_dsi.
+
+config DRM_SUN6I_DPHY
+ tristate "Allwinner A31 MIPI D-PHY Support"
+ select GENERIC_PHY_MIPI_DPHY
+ help
+ Choose this option if you have an Allwinner SoC with
+ MIPI-DSI support. If M is selected, the module will be
+ called sun6i_mipi_dphy.
config DRM_SUN8I_DW_HDMI
tristate "Support for Allwinner version of DesignWare HDMI"
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 0eb38ac8e86e..1e2320d824b5 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -24,9 +24,6 @@ sun4i-tcon-y += sun4i_lvds.o
sun4i-tcon-y += sun4i_tcon.o
sun4i-tcon-y += sun4i_rgb.o
-sun6i-dsi-y += sun6i_mipi_dphy.o
-sun6i-dsi-y += sun6i_mipi_dsi.o
-
obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o
obj-$(CONFIG_DRM_SUN4I) += sun4i-tcon.o
obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
@@ -37,7 +34,8 @@ ifdef CONFIG_DRM_SUN4I_BACKEND
obj-$(CONFIG_DRM_SUN4I) += sun4i-frontend.o
endif
obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o
-obj-$(CONFIG_DRM_SUN6I_DSI) += sun6i-dsi.o
+obj-$(CONFIG_DRM_SUN6I_DPHY) += sun6i_mipi_dphy.o
+obj-$(CONFIG_DRM_SUN6I_DSI) += sun6i_mipi_dsi.o
obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i-drm-hdmi.o
obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
obj-$(CONFIG_DRM_SUN8I_TCON_TOP) += sun8i_tcon_top.o
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dphy.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dphy.c
index e4d19431fa0e..79c8af5c7c1d 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dphy.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dphy.c
@@ -8,11 +8,14 @@
#include <linux/bitops.h>
#include <linux/clk.h>
+#include <linux/module.h>
#include <linux/of_address.h>
+#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
-#include "sun6i_mipi_dsi.h"
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
#define SUN6I_DPHY_GCTL_REG 0x00
#define SUN6I_DPHY_GCTL_LANE_NUM(n) ((((n) - 1) & 3) << 4)
@@ -81,12 +84,46 @@
#define SUN6I_DPHY_DBG5_REG 0xf4
-int sun6i_dphy_init(struct sun6i_dphy *dphy, unsigned int lanes)
+struct sun6i_dphy {
+ struct clk *bus_clk;
+ struct clk *mod_clk;
+ struct regmap *regs;
+ struct reset_control *reset;
+
+ struct phy *phy;
+ struct phy_configure_opts_mipi_dphy config;
+};
+
+static int sun6i_dphy_init(struct phy *phy)
{
+ struct sun6i_dphy *dphy = phy_get_drvdata(phy);
+
reset_control_deassert(dphy->reset);
clk_prepare_enable(dphy->mod_clk);
clk_set_rate_exclusive(dphy->mod_clk, 150000000);
+ return 0;
+}
+
+static int sun6i_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+ struct sun6i_dphy *dphy = phy_get_drvdata(phy);
+ int ret;
+
+ ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
+ if (ret)
+ return ret;
+
+ memcpy(&dphy->config, opts, sizeof(dphy->config));
+
+ return 0;
+}
+
+static int sun6i_dphy_power_on(struct phy *phy)
+{
+ struct sun6i_dphy *dphy = phy_get_drvdata(phy);
+ u8 lanes_mask = GENMASK(dphy->config.lanes - 1, 0);
+
regmap_write(dphy->regs, SUN6I_DPHY_TX_CTL_REG,
SUN6I_DPHY_TX_CTL_HS_TX_CLK_CONT);
@@ -111,16 +148,9 @@ int sun6i_dphy_init(struct sun6i_dphy *dphy, unsigned int lanes)
SUN6I_DPHY_TX_TIME4_HS_TX_ANA1(3));
regmap_write(dphy->regs, SUN6I_DPHY_GCTL_REG,
- SUN6I_DPHY_GCTL_LANE_NUM(lanes) |
+ SUN6I_DPHY_GCTL_LANE_NUM(dphy->config.lanes) |
SUN6I_DPHY_GCTL_EN);
- return 0;
-}
-
-int sun6i_dphy_power_on(struct sun6i_dphy *dphy, unsigned int lanes)
-{
- u8 lanes_mask = GENMASK(lanes - 1, 0);
-
regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG,
SUN6I_DPHY_ANA0_REG_PWS |
SUN6I_DPHY_ANA0_REG_DMPC |
@@ -181,16 +211,20 @@ int sun6i_dphy_power_on(struct sun6i_dphy *dphy, unsigned int lanes)
return 0;
}
-int sun6i_dphy_power_off(struct sun6i_dphy *dphy)
+static int sun6i_dphy_power_off(struct phy *phy)
{
+ struct sun6i_dphy *dphy = phy_get_drvdata(phy);
+
regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA1_REG,
SUN6I_DPHY_ANA1_REG_VTTMODE, 0);
return 0;
}
-int sun6i_dphy_exit(struct sun6i_dphy *dphy)
+static int sun6i_dphy_exit(struct phy *phy)
{
+ struct sun6i_dphy *dphy = phy_get_drvdata(phy);
+
clk_rate_exclusive_put(dphy->mod_clk);
clk_disable_unprepare(dphy->mod_clk);
reset_control_assert(dphy->reset);
@@ -198,6 +232,15 @@ int sun6i_dphy_exit(struct sun6i_dphy *dphy)
return 0;
}
+
+static struct phy_ops sun6i_dphy_ops = {
+ .configure = sun6i_dphy_configure,
+ .power_on = sun6i_dphy_power_on,
+ .power_off = sun6i_dphy_power_off,
+ .init = sun6i_dphy_init,
+ .exit = sun6i_dphy_exit,
+};
+
static struct regmap_config sun6i_dphy_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
@@ -206,87 +249,70 @@ static struct regmap_config sun6i_dphy_regmap_config = {
.name = "mipi-dphy",
};
-static const struct of_device_id sun6i_dphy_of_table[] = {
- { .compatible = "allwinner,sun6i-a31-mipi-dphy" },
- { }
-};
-
-int sun6i_dphy_probe(struct sun6i_dsi *dsi, struct device_node *node)
+static int sun6i_dphy_probe(struct platform_device *pdev)
{
+ struct phy_provider *phy_provider;
struct sun6i_dphy *dphy;
- struct resource res;
+ struct resource *res;
void __iomem *regs;
- int ret;
-
- if (!of_match_node(sun6i_dphy_of_table, node)) {
- dev_err(dsi->dev, "Incompatible D-PHY\n");
- return -EINVAL;
- }
- dphy = devm_kzalloc(dsi->dev, sizeof(*dphy), GFP_KERNEL);
+ dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
if (!dphy)
return -ENOMEM;
- ret = of_address_to_resource(node, 0, &res);
- if (ret) {
- dev_err(dsi->dev, "phy: Couldn't get our resources\n");
- return ret;
- }
-
- regs = devm_ioremap_resource(dsi->dev, &res);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(regs)) {
- dev_err(dsi->dev, "Couldn't map the DPHY encoder registers\n");
+ dev_err(&pdev->dev, "Couldn't map the DPHY encoder registers\n");
return PTR_ERR(regs);
}
- dphy->regs = devm_regmap_init_mmio(dsi->dev, regs,
- &sun6i_dphy_regmap_config);
+ dphy->regs = devm_regmap_init_mmio_clk(&pdev->dev, "bus",
+ regs, &sun6i_dphy_regmap_config);
if (IS_ERR(dphy->regs)) {
- dev_err(dsi->dev, "Couldn't create the DPHY encoder regmap\n");
+ dev_err(&pdev->dev, "Couldn't create the DPHY encoder regmap\n");
return PTR_ERR(dphy->regs);
}
- dphy->reset = of_reset_control_get_shared(node, NULL);
+ dphy->reset = devm_reset_control_get_shared(&pdev->dev, NULL);
if (IS_ERR(dphy->reset)) {
- dev_err(dsi->dev, "Couldn't get our reset line\n");
+ dev_err(&pdev->dev, "Couldn't get our reset line\n");
return PTR_ERR(dphy->reset);
}
- dphy->bus_clk = of_clk_get_by_name(node, "bus");
- if (IS_ERR(dphy->bus_clk)) {
- dev_err(dsi->dev, "Couldn't get the DPHY bus clock\n");
- ret = PTR_ERR(dphy->bus_clk);
- goto err_free_reset;
- }
- regmap_mmio_attach_clk(dphy->regs, dphy->bus_clk);
-
- dphy->mod_clk = of_clk_get_by_name(node, "mod");
+ dphy->mod_clk = devm_clk_get(&pdev->dev, "mod");
if (IS_ERR(dphy->mod_clk)) {
- dev_err(dsi->dev, "Couldn't get the DPHY mod clock\n");
- ret = PTR_ERR(dphy->mod_clk);
- goto err_free_bus;
+ dev_err(&pdev->dev, "Couldn't get the DPHY mod clock\n");
+ return PTR_ERR(dphy->mod_clk);
}
- dsi->dphy = dphy;
+ dphy->phy = devm_phy_create(&pdev->dev, NULL, &sun6i_dphy_ops);
+ if (IS_ERR(dphy->phy)) {
+ dev_err(&pdev->dev, "failed to create PHY\n");
+ return PTR_ERR(dphy->phy);
+ }
- return 0;
+ phy_set_drvdata(dphy->phy, dphy);
+ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
-err_free_bus:
- regmap_mmio_detach_clk(dphy->regs);
- clk_put(dphy->bus_clk);
-err_free_reset:
- reset_control_put(dphy->reset);
- return ret;
+ return PTR_ERR_OR_ZERO(phy_provider);
}
-int sun6i_dphy_remove(struct sun6i_dsi *dsi)
-{
- struct sun6i_dphy *dphy = dsi->dphy;
-
- regmap_mmio_detach_clk(dphy->regs);
- clk_put(dphy->mod_clk);
- clk_put(dphy->bus_clk);
- reset_control_put(dphy->reset);
+static const struct of_device_id sun6i_dphy_of_table[] = {
+ { .compatible = "allwinner,sun6i-a31-mipi-dphy" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sun6i_dphy_of_table);
+
+static struct platform_driver sun6i_dphy_platform_driver = {
+ .probe = sun6i_dphy_probe,
+ .driver = {
+ .name = "sun6i-mipi-dphy",
+ .of_match_table = sun6i_dphy_of_table,
+ },
+};
+module_platform_driver(sun6i_dphy_platform_driver);
- return 0;
-}
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin>");
+MODULE_DESCRIPTION("Allwinner A31 MIPI D-PHY Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index e3b34a345546..7bbce7708265 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
@@ -616,6 +617,8 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
struct mipi_dsi_device *device = dsi->device;
+ union phy_configure_opts opts = { 0 };
+ struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
u16 delay;
DRM_DEBUG_DRIVER("Enabling DSI output\n");
@@ -634,8 +637,15 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
sun6i_dsi_setup_format(dsi, mode);
sun6i_dsi_setup_timings(dsi, mode);
- sun6i_dphy_init(dsi->dphy, device->lanes);
- sun6i_dphy_power_on(dsi->dphy, device->lanes);
+ phy_init(dsi->dphy);
+
+ phy_mipi_dphy_get_default_config(mode->clock * 1000,
+ mipi_dsi_pixel_format_to_bpp(device->format),
+ device->lanes, cfg);
+
+ phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
+ phy_configure(dsi->dphy, &opts);
+ phy_power_on(dsi->dphy);
if (!IS_ERR(dsi->panel))
drm_panel_prepare(dsi->panel);
@@ -673,8 +683,8 @@ static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder)
drm_panel_unprepare(dsi->panel);
}
- sun6i_dphy_power_off(dsi->dphy);
- sun6i_dphy_exit(dsi->dphy);
+ phy_power_off(dsi->dphy);
+ phy_exit(dsi->dphy);
pm_runtime_put(dsi->dev);
}
@@ -967,7 +977,6 @@ static const struct component_ops sun6i_dsi_ops = {
static int sun6i_dsi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *dphy_node;
struct sun6i_dsi *dsi;
struct resource *res;
void __iomem *base;
@@ -1013,10 +1022,8 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
*/
clk_set_rate_exclusive(dsi->mod_clk, 297000000);
- dphy_node = of_parse_phandle(dev->of_node, "phys", 0);
- ret = sun6i_dphy_probe(dsi, dphy_node);
- of_node_put(dphy_node);
- if (ret) {
+ dsi->dphy = devm_phy_get(dev, "dphy");
+ if (IS_ERR(dsi->dphy)) {
dev_err(dev, "Couldn't get the MIPI D-PHY\n");
goto err_unprotect_clk;
}
@@ -1026,7 +1033,7 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
ret = mipi_dsi_host_register(&dsi->host);
if (ret) {
dev_err(dev, "Couldn't register MIPI-DSI host\n");
- goto err_remove_phy;
+ goto err_pm_disable;
}
ret = component_add(&pdev->dev, &sun6i_dsi_ops);
@@ -1039,9 +1046,8 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
err_remove_dsi_host:
mipi_dsi_host_unregister(&dsi->host);
-err_remove_phy:
+err_pm_disable:
pm_runtime_disable(dev);
- sun6i_dphy_remove(dsi);
err_unprotect_clk:
clk_rate_exclusive_put(dsi->mod_clk);
return ret;
@@ -1055,7 +1061,6 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
component_del(&pdev->dev, &sun6i_dsi_ops);
mipi_dsi_host_unregister(&dsi->host);
pm_runtime_disable(dev);
- sun6i_dphy_remove(dsi);
clk_rate_exclusive_put(dsi->mod_clk);
return 0;
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index dbbc5b3ecbda..a07090579f84 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -13,13 +13,6 @@
#include <drm/drm_encoder.h>
#include <drm/drm_mipi_dsi.h>
-struct sun6i_dphy {
- struct clk *bus_clk;
- struct clk *mod_clk;
- struct regmap *regs;
- struct reset_control *reset;
-};
-
struct sun6i_dsi {
struct drm_connector connector;
struct drm_encoder encoder;
@@ -29,7 +22,7 @@ struct sun6i_dsi {
struct clk *mod_clk;
struct regmap *regs;
struct reset_control *reset;
- struct sun6i_dphy *dphy;
+ struct phy *dphy;
struct device *dev;
struct sun4i_drv *drv;
@@ -52,12 +45,4 @@ static inline struct sun6i_dsi *encoder_to_sun6i_dsi(const struct drm_encoder *e
return container_of(encoder, struct sun6i_dsi, encoder);
};
-int sun6i_dphy_probe(struct sun6i_dsi *dsi, struct device_node *node);
-int sun6i_dphy_remove(struct sun6i_dsi *dsi);
-
-int sun6i_dphy_init(struct sun6i_dphy *dphy, unsigned int lanes);
-int sun6i_dphy_power_on(struct sun6i_dphy *dphy, unsigned int lanes);
-int sun6i_dphy_power_off(struct sun6i_dphy *dphy);
-int sun6i_dphy_exit(struct sun6i_dphy *dphy);
-
#endif /* _SUN6I_MIPI_DSI_H_ */
--
git-series 0.9.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 10/10] drm/bridge: cdns: Convert to phy framework
From: Maxime Ripard @ 2018-12-07 13:55 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Boris Brezillon
Cc: Archit Taneja, Rafal Ciepiela, Krzysztof Witos, Maxime Ripard,
linux-kernel, dri-devel, Andrzej Hajda, Chen-Yu Tsai,
Laurent Pinchart, Thomas Petazzoni, linux-arm-kernel, linux-media
In-Reply-To: <cover.ad7c4feb3905658f10b022df4756a5ade280011f.1544190837.git-series.maxime.ripard@bootlin.com>
Now that we have everything we need in the phy framework to allow to tune
the phy parameters, let's convert the Cadence DSI bridge to that API
instead of creating a ad-hoc driver for its phy.
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
drivers/gpu/drm/bridge/cdns-dsi.c | 485 +++----------------------------
1 file changed, 59 insertions(+), 426 deletions(-)
diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c
index 3ac6dd524b6d..7b432257ffbe 100644
--- a/drivers/gpu/drm/bridge/cdns-dsi.c
+++ b/drivers/gpu/drm/bridge/cdns-dsi.c
@@ -21,6 +21,9 @@
#include <linux/pm_runtime.h>
#include <linux/reset.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
+
#define IP_CONF 0x0
#define SP_HS_FIFO_DEPTH(x) (((x) & GENMASK(30, 26)) >> 26)
#define SP_LP_FIFO_DEPTH(x) (((x) & GENMASK(25, 21)) >> 21)
@@ -419,44 +422,11 @@
#define DSI_NULL_FRAME_OVERHEAD 6
#define DSI_EOT_PKT_SIZE 4
-#define REG_WAKEUP_TIME_NS 800
-#define DPHY_PLL_RATE_HZ 108000000
-
-/* DPHY registers */
-#define DPHY_PMA_CMN(reg) (reg)
-#define DPHY_PMA_LCLK(reg) (0x100 + (reg))
-#define DPHY_PMA_LDATA(lane, reg) (0x200 + ((lane) * 0x100) + (reg))
-#define DPHY_PMA_RCLK(reg) (0x600 + (reg))
-#define DPHY_PMA_RDATA(lane, reg) (0x700 + ((lane) * 0x100) + (reg))
-#define DPHY_PCS(reg) (0xb00 + (reg))
-
-#define DPHY_CMN_SSM DPHY_PMA_CMN(0x20)
-#define DPHY_CMN_SSM_EN BIT(0)
-#define DPHY_CMN_TX_MODE_EN BIT(9)
-
-#define DPHY_CMN_PWM DPHY_PMA_CMN(0x40)
-#define DPHY_CMN_PWM_DIV(x) ((x) << 20)
-#define DPHY_CMN_PWM_LOW(x) ((x) << 10)
-#define DPHY_CMN_PWM_HIGH(x) (x)
-
-#define DPHY_CMN_FBDIV DPHY_PMA_CMN(0x4c)
-#define DPHY_CMN_FBDIV_VAL(low, high) (((high) << 11) | ((low) << 22))
-#define DPHY_CMN_FBDIV_FROM_REG (BIT(10) | BIT(21))
-
-#define DPHY_CMN_OPIPDIV DPHY_PMA_CMN(0x50)
-#define DPHY_CMN_IPDIV_FROM_REG BIT(0)
-#define DPHY_CMN_IPDIV(x) ((x) << 1)
-#define DPHY_CMN_OPDIV_FROM_REG BIT(6)
-#define DPHY_CMN_OPDIV(x) ((x) << 7)
-
-#define DPHY_PSM_CFG DPHY_PCS(0x4)
-#define DPHY_PSM_CFG_FROM_REG BIT(0)
-#define DPHY_PSM_CLK_DIV(x) ((x) << 1)
-
struct cdns_dsi_output {
struct mipi_dsi_device *dev;
struct drm_panel *panel;
struct drm_bridge *bridge;
+ union phy_configure_opts phy_opts;
};
enum cdns_dsi_input_id {
@@ -465,14 +435,6 @@ enum cdns_dsi_input_id {
CDNS_DSC_INPUT,
};
-struct cdns_dphy_cfg {
- u8 pll_ipdiv;
- u8 pll_opdiv;
- u16 pll_fbdiv;
- unsigned long lane_bps;
- unsigned int nlanes;
-};
-
struct cdns_dsi_cfg {
unsigned int hfp;
unsigned int hsa;
@@ -481,34 +443,6 @@ struct cdns_dsi_cfg {
unsigned int htotal;
};
-struct cdns_dphy;
-
-enum cdns_dphy_clk_lane_cfg {
- DPHY_CLK_CFG_LEFT_DRIVES_ALL = 0,
- DPHY_CLK_CFG_LEFT_DRIVES_RIGHT = 1,
- DPHY_CLK_CFG_LEFT_DRIVES_LEFT = 2,
- DPHY_CLK_CFG_RIGHT_DRIVES_ALL = 3,
-};
-
-struct cdns_dphy_ops {
- int (*probe)(struct cdns_dphy *dphy);
- void (*remove)(struct cdns_dphy *dphy);
- void (*set_psm_div)(struct cdns_dphy *dphy, u8 div);
- void (*set_clk_lane_cfg)(struct cdns_dphy *dphy,
- enum cdns_dphy_clk_lane_cfg cfg);
- void (*set_pll_cfg)(struct cdns_dphy *dphy,
- const struct cdns_dphy_cfg *cfg);
- unsigned long (*get_wakeup_time_ns)(struct cdns_dphy *dphy);
-};
-
-struct cdns_dphy {
- struct cdns_dphy_cfg cfg;
- void __iomem *regs;
- struct clk *psm_clk;
- struct clk *pll_ref_clk;
- const struct cdns_dphy_ops *ops;
-};
-
struct cdns_dsi_input {
enum cdns_dsi_input_id id;
struct drm_bridge bridge;
@@ -526,7 +460,7 @@ struct cdns_dsi {
struct reset_control *dsi_p_rst;
struct clk *dsi_sys_clk;
bool link_initialized;
- struct cdns_dphy *dphy;
+ struct phy *dphy;
};
static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input)
@@ -550,175 +484,6 @@ static unsigned int mode_to_dpi_hfp(const struct drm_display_mode *mode)
return mode->crtc_hsync_start - mode->crtc_hdisplay;
}
-static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
- struct cdns_dphy_cfg *cfg,
- unsigned int dpi_htotal,
- unsigned int dpi_bpp,
- unsigned int dpi_hz,
- unsigned int dsi_htotal,
- unsigned int dsi_nlanes,
- unsigned int *dsi_hfp_ext)
-{
- u64 dlane_bps, dlane_bps_max, fbdiv, fbdiv_max, adj_dsi_htotal;
- unsigned long pll_ref_hz = clk_get_rate(dphy->pll_ref_clk);
-
- memset(cfg, 0, sizeof(*cfg));
-
- cfg->nlanes = dsi_nlanes;
-
- if (pll_ref_hz < 9600000 || pll_ref_hz >= 150000000)
- return -EINVAL;
- else if (pll_ref_hz < 19200000)
- cfg->pll_ipdiv = 1;
- else if (pll_ref_hz < 38400000)
- cfg->pll_ipdiv = 2;
- else if (pll_ref_hz < 76800000)
- cfg->pll_ipdiv = 4;
- else
- cfg->pll_ipdiv = 8;
-
- /*
- * Make sure DSI htotal is aligned on a lane boundary when calculating
- * the expected data rate. This is done by extending HFP in case of
- * misalignment.
- */
- adj_dsi_htotal = dsi_htotal;
- if (dsi_htotal % dsi_nlanes)
- adj_dsi_htotal += dsi_nlanes - (dsi_htotal % dsi_nlanes);
-
- dlane_bps = (u64)dpi_hz * adj_dsi_htotal;
-
- /* data rate in bytes/sec is not an integer, refuse the mode. */
- if (do_div(dlane_bps, dsi_nlanes * dpi_htotal))
- return -EINVAL;
-
- /* data rate was in bytes/sec, convert to bits/sec. */
- dlane_bps *= 8;
-
- if (dlane_bps > 2500000000UL || dlane_bps < 160000000UL)
- return -EINVAL;
- else if (dlane_bps >= 1250000000)
- cfg->pll_opdiv = 1;
- else if (dlane_bps >= 630000000)
- cfg->pll_opdiv = 2;
- else if (dlane_bps >= 320000000)
- cfg->pll_opdiv = 4;
- else if (dlane_bps >= 160000000)
- cfg->pll_opdiv = 8;
-
- /*
- * Allow a deviation of 0.2% on the per-lane data rate to try to
- * recover a potential mismatch between DPI and PPI clks.
- */
- dlane_bps_max = dlane_bps + DIV_ROUND_DOWN_ULL(dlane_bps, 500);
- fbdiv_max = DIV_ROUND_DOWN_ULL(dlane_bps_max * 2 *
- cfg->pll_opdiv * cfg->pll_ipdiv,
- pll_ref_hz);
- fbdiv = DIV_ROUND_UP_ULL(dlane_bps * 2 * cfg->pll_opdiv *
- cfg->pll_ipdiv,
- pll_ref_hz);
-
- /*
- * Iterate over all acceptable fbdiv and try to find an adjusted DSI
- * htotal length providing an exact match.
- *
- * Note that we could do something even trickier by relying on the fact
- * that a new line is not necessarily aligned on a lane boundary, so,
- * by making adj_dsi_htotal non aligned on a dsi_lanes we can improve a
- * bit the precision. With this, the step would be
- *
- * pll_ref_hz / (2 * opdiv * ipdiv * nlanes)
- *
- * instead of
- *
- * pll_ref_hz / (2 * opdiv * ipdiv)
- *
- * The drawback of this approach is that we would need to make sure the
- * number or lines is a multiple of the realignment periodicity which is
- * a function of the number of lanes and the original misalignment. For
- * example, for NLANES = 4 and HTOTAL % NLANES = 3, it takes 4 lines
- * to realign on a lane:
- * LINE 0: expected number of bytes, starts emitting first byte of
- * LINE 1 on LANE 3
- * LINE 1: expected number of bytes, starts emitting first 2 bytes of
- * LINE 2 on LANES 2 and 3
- * LINE 2: expected number of bytes, starts emitting first 3 bytes of
- * of LINE 3 on LANES 1, 2 and 3
- * LINE 3: one byte less, now things are realigned on LANE 0 for LINE 4
- *
- * I figured this extra complexity was not worth the benefit, but if
- * someone really has unfixable mismatch, that would be something to
- * investigate.
- */
- for (; fbdiv <= fbdiv_max; fbdiv++) {
- u32 rem;
-
- adj_dsi_htotal = (u64)fbdiv * pll_ref_hz * dsi_nlanes *
- dpi_htotal;
-
- /*
- * Do the division in 2 steps to avoid an overflow on the
- * divider.
- */
- rem = do_div(adj_dsi_htotal, dpi_hz);
- if (rem)
- continue;
-
- rem = do_div(adj_dsi_htotal,
- cfg->pll_opdiv * cfg->pll_ipdiv * 2 * 8);
- if (rem)
- continue;
-
- cfg->pll_fbdiv = fbdiv;
- *dsi_hfp_ext = adj_dsi_htotal - dsi_htotal;
- break;
- }
-
- /* No match, let's just reject the display mode. */
- if (!cfg->pll_fbdiv)
- return -EINVAL;
-
- dlane_bps = DIV_ROUND_DOWN_ULL((u64)dpi_hz * adj_dsi_htotal * 8,
- dsi_nlanes * dpi_htotal);
- cfg->lane_bps = dlane_bps;
-
- return 0;
-}
-
-static int cdns_dphy_setup_psm(struct cdns_dphy *dphy)
-{
- unsigned long psm_clk_hz = clk_get_rate(dphy->psm_clk);
- unsigned long psm_div;
-
- if (!psm_clk_hz || psm_clk_hz > 100000000)
- return -EINVAL;
-
- psm_div = DIV_ROUND_CLOSEST(psm_clk_hz, 1000000);
- if (dphy->ops->set_psm_div)
- dphy->ops->set_psm_div(dphy, psm_div);
-
- return 0;
-}
-
-static void cdns_dphy_set_clk_lane_cfg(struct cdns_dphy *dphy,
- enum cdns_dphy_clk_lane_cfg cfg)
-{
- if (dphy->ops->set_clk_lane_cfg)
- dphy->ops->set_clk_lane_cfg(dphy, cfg);
-}
-
-static void cdns_dphy_set_pll_cfg(struct cdns_dphy *dphy,
- const struct cdns_dphy_cfg *cfg)
-{
- if (dphy->ops->set_pll_cfg)
- dphy->ops->set_pll_cfg(dphy, cfg);
-}
-
-static unsigned long cdns_dphy_get_wakeup_time_ns(struct cdns_dphy *dphy)
-{
- return dphy->ops->get_wakeup_time_ns(dphy);
-}
-
static unsigned int dpi_to_dsi_timing(unsigned int dpi_timing,
unsigned int dpi_bpp,
unsigned int dsi_pkt_overhead)
@@ -780,17 +545,20 @@ static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi,
return 0;
}
-static int cdns_dphy_validate(struct cdns_dsi *dsi,
+static int cdns_dsi_adjust_phy_config(struct cdns_dsi *dsi,
struct cdns_dsi_cfg *dsi_cfg,
- struct cdns_dphy_cfg *dphy_cfg,
+ struct phy_configure_opts_mipi_dphy *phy_cfg,
const struct drm_display_mode *mode,
bool mode_valid_check)
{
struct cdns_dsi_output *output = &dsi->output;
+ unsigned long long dlane_bps;
+ unsigned long adj_dsi_htotal;
unsigned long dsi_htotal;
- unsigned int dsi_hfp_ext = 0;
-
- int ret;
+ unsigned long dpi_htotal;
+ unsigned long dpi_hz;
+ unsigned int dsi_hfp_ext;
+ unsigned int lanes = output->dev->lanes;
dsi_htotal = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
@@ -799,25 +567,27 @@ static int cdns_dphy_validate(struct cdns_dsi *dsi,
dsi_htotal += dsi_cfg->hact;
dsi_htotal += dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD;
- if (mode_valid_check)
- ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg,
- mode->htotal,
- mode->clock * 1000,
- mipi_dsi_pixel_format_to_bpp(output->dev->format),
- dsi_htotal,
- output->dev->lanes,
- &dsi_hfp_ext);
- else
- ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg,
- mode->crtc_htotal,
- mipi_dsi_pixel_format_to_bpp(output->dev->format),
- mode->crtc_clock * 1000,
- dsi_htotal,
- output->dev->lanes,
- &dsi_hfp_ext);
- if (ret)
- return ret;
+ /*
+ * Make sure DSI htotal is aligned on a lane boundary when calculating
+ * the expected data rate. This is done by extending HFP in case of
+ * misalignment.
+ */
+ adj_dsi_htotal = dsi_htotal;
+ if (dsi_htotal % lanes)
+ adj_dsi_htotal += lanes - (dsi_htotal % lanes);
+
+ dpi_hz = (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000;
+ dlane_bps = (unsigned long long)dpi_hz * adj_dsi_htotal;
+
+ /* data rate in bytes/sec is not an integer, refuse the mode. */
+ dpi_htotal = mode_valid_check ? mode->htotal : mode->crtc_htotal;
+ if (do_div(dlane_bps, lanes * dpi_htotal))
+ return -EINVAL;
+ /* data rate was in bytes/sec, convert to bits/sec. */
+ phy_cfg->hs_clk_rate = dlane_bps * 8;
+
+ dsi_hfp_ext = adj_dsi_htotal - dsi_htotal;
dsi_cfg->hfp += dsi_hfp_ext;
dsi_cfg->htotal = dsi_htotal + dsi_hfp_ext;
@@ -827,10 +597,10 @@ static int cdns_dphy_validate(struct cdns_dsi *dsi,
static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
const struct drm_display_mode *mode,
struct cdns_dsi_cfg *dsi_cfg,
- struct cdns_dphy_cfg *dphy_cfg,
bool mode_valid_check)
{
struct cdns_dsi_output *output = &dsi->output;
+ struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
unsigned long dsi_hss_hsa_hse_hbp;
unsigned int nlanes = output->dev->lanes;
int ret;
@@ -839,7 +609,15 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
if (ret)
return ret;
- ret = cdns_dphy_validate(dsi, dsi_cfg, dphy_cfg, mode, mode_valid_check);
+ phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
+ mipi_dsi_pixel_format_to_bpp(output->dev->format),
+ nlanes, phy_cfg);
+
+ ret = cdns_dsi_adjust_phy_config(dsi, dsi_cfg, phy_cfg, mode, mode_valid_check);
+ if (ret)
+ return ret;
+
+ ret = phy_validate(dsi->dphy, PHY_MODE_MIPI_DPHY, 0, &output->phy_opts);
if (ret)
return ret;
@@ -852,7 +630,7 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
* is empty before we start a receiving a new line on the DPI
* interface.
*/
- if ((u64)dphy_cfg->lane_bps * mode_to_dpi_hfp(mode) * nlanes <
+ if ((u64)phy_cfg->hs_clk_rate * mode_to_dpi_hfp(mode) * nlanes <
(u64)dsi_hss_hsa_hse_hbp *
(mode_valid_check ? mode->clock : mode->crtc_clock) * 1000)
return -EINVAL;
@@ -882,7 +660,6 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
struct cdns_dsi_output *output = &dsi->output;
- struct cdns_dphy_cfg dphy_cfg;
struct cdns_dsi_cfg dsi_cfg;
int bpp, ret;
@@ -902,7 +679,7 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
if ((mode->hdisplay * bpp) % 32)
return MODE_H_ILLEGAL;
- ret = cdns_dsi_check_conf(dsi, mode, &dsi_cfg, &dphy_cfg, true);
+ ret = cdns_dsi_check_conf(dsi, mode, &dsi_cfg, true);
if (ret)
return MODE_BAD;
@@ -925,9 +702,9 @@ static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
pm_runtime_put(dsi->base.dev);
}
-static void cdns_dsi_hs_init(struct cdns_dsi *dsi,
- const struct cdns_dphy_cfg *dphy_cfg)
+static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
{
+ struct cdns_dsi_output *output = &dsi->output;
u32 status;
/*
@@ -938,30 +715,10 @@ static void cdns_dsi_hs_init(struct cdns_dsi *dsi,
DPHY_CMN_PDN | DPHY_PLL_PDN,
dsi->regs + MCTL_DPHY_CFG0);
- /*
- * Configure the internal PSM clk divider so that the DPHY has a
- * 1MHz clk (or something close).
- */
- WARN_ON_ONCE(cdns_dphy_setup_psm(dsi->dphy));
-
- /*
- * Configure attach clk lanes to data lanes: the DPHY has 2 clk lanes
- * and 8 data lanes, each clk lane can be attache different set of
- * data lanes. The 2 groups are named 'left' and 'right', so here we
- * just say that we want the 'left' clk lane to drive the 'left' data
- * lanes.
- */
- cdns_dphy_set_clk_lane_cfg(dsi->dphy, DPHY_CLK_CFG_LEFT_DRIVES_LEFT);
-
- /*
- * Configure the DPHY PLL that will be used to generate the TX byte
- * clk.
- */
- cdns_dphy_set_pll_cfg(dsi->dphy, dphy_cfg);
-
- /* Start TX state machine. */
- writel(DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN,
- dsi->dphy->regs + DPHY_CMN_SSM);
+ phy_init(dsi->dphy);
+ phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
+ phy_configure(dsi->dphy, &output->phy_opts);
+ phy_power_on(dsi->dphy);
/* Activate the PLL and wait until it's locked. */
writel(PLL_LOCKED, dsi->regs + MCTL_MAIN_STS_CLR);
@@ -971,7 +728,7 @@ static void cdns_dsi_hs_init(struct cdns_dsi *dsi,
status & PLL_LOCKED, 100, 100));
/* De-assert data and clock reset lines. */
writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN |
- DPHY_D_RSTB(dphy_cfg->nlanes) | DPHY_C_RSTB,
+ DPHY_D_RSTB(output->dev->lanes) | DPHY_C_RSTB,
dsi->regs + MCTL_DPHY_CFG0);
}
@@ -1017,7 +774,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
struct cdns_dsi *dsi = input_to_dsi(input);
struct cdns_dsi_output *output = &dsi->output;
struct drm_display_mode *mode;
- struct cdns_dphy_cfg dphy_cfg;
+ struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
unsigned long tx_byte_period;
struct cdns_dsi_cfg dsi_cfg;
u32 tmp, reg_wakeup, div;
@@ -1030,9 +787,9 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format);
nlanes = output->dev->lanes;
- WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, &dphy_cfg, false));
+ WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false));
- cdns_dsi_hs_init(dsi, &dphy_cfg);
+ cdns_dsi_hs_init(dsi);
cdns_dsi_init_link(dsi);
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
@@ -1068,9 +825,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
tmp -= DIV_ROUND_UP(DSI_EOT_PKT_SIZE, nlanes);
tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8,
- dphy_cfg.lane_bps);
- reg_wakeup = cdns_dphy_get_wakeup_time_ns(dsi->dphy) /
- tx_byte_period;
+ phy_cfg->hs_clk_rate);
+ reg_wakeup = (phy_cfg->hs_prepare + phy_cfg->hs_zero) / tx_byte_period;
writel(REG_WAKEUP_TIME(reg_wakeup) | REG_LINE_DURATION(tmp),
dsi->regs + VID_DPHY_TIME);
@@ -1384,8 +1140,6 @@ static int __maybe_unused cdns_dsi_resume(struct device *dev)
reset_control_deassert(dsi->dsi_p_rst);
clk_prepare_enable(dsi->dsi_p_clk);
clk_prepare_enable(dsi->dsi_sys_clk);
- clk_prepare_enable(dsi->dphy->psm_clk);
- clk_prepare_enable(dsi->dphy->pll_ref_clk);
return 0;
}
@@ -1394,8 +1148,6 @@ static int __maybe_unused cdns_dsi_suspend(struct device *dev)
{
struct cdns_dsi *dsi = dev_get_drvdata(dev);
- clk_disable_unprepare(dsi->dphy->pll_ref_clk);
- clk_disable_unprepare(dsi->dphy->psm_clk);
clk_disable_unprepare(dsi->dsi_sys_clk);
clk_disable_unprepare(dsi->dsi_p_clk);
reset_control_assert(dsi->dsi_p_rst);
@@ -1406,121 +1158,6 @@ static int __maybe_unused cdns_dsi_suspend(struct device *dev)
static UNIVERSAL_DEV_PM_OPS(cdns_dsi_pm_ops, cdns_dsi_suspend, cdns_dsi_resume,
NULL);
-static unsigned long cdns_dphy_ref_get_wakeup_time_ns(struct cdns_dphy *dphy)
-{
- /* Default wakeup time is 800 ns (in a simulated environment). */
- return 800;
-}
-
-static void cdns_dphy_ref_set_pll_cfg(struct cdns_dphy *dphy,
- const struct cdns_dphy_cfg *cfg)
-{
- u32 fbdiv_low, fbdiv_high;
-
- fbdiv_low = (cfg->pll_fbdiv / 4) - 2;
- fbdiv_high = cfg->pll_fbdiv - fbdiv_low - 2;
-
- writel(DPHY_CMN_IPDIV_FROM_REG | DPHY_CMN_OPDIV_FROM_REG |
- DPHY_CMN_IPDIV(cfg->pll_ipdiv) |
- DPHY_CMN_OPDIV(cfg->pll_opdiv),
- dphy->regs + DPHY_CMN_OPIPDIV);
- writel(DPHY_CMN_FBDIV_FROM_REG |
- DPHY_CMN_FBDIV_VAL(fbdiv_low, fbdiv_high),
- dphy->regs + DPHY_CMN_FBDIV);
- writel(DPHY_CMN_PWM_HIGH(6) | DPHY_CMN_PWM_LOW(0x101) |
- DPHY_CMN_PWM_DIV(0x8),
- dphy->regs + DPHY_CMN_PWM);
-}
-
-static void cdns_dphy_ref_set_psm_div(struct cdns_dphy *dphy, u8 div)
-{
- writel(DPHY_PSM_CFG_FROM_REG | DPHY_PSM_CLK_DIV(div),
- dphy->regs + DPHY_PSM_CFG);
-}
-
-/*
- * This is the reference implementation of DPHY hooks. Specific integration of
- * this IP may have to re-implement some of them depending on how they decided
- * to wire things in the SoC.
- */
-static const struct cdns_dphy_ops ref_dphy_ops = {
- .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
- .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
- .set_psm_div = cdns_dphy_ref_set_psm_div,
-};
-
-static const struct of_device_id cdns_dphy_of_match[] = {
- { .compatible = "cdns,dphy", .data = &ref_dphy_ops },
- { /* sentinel */ },
-};
-
-static struct cdns_dphy *cdns_dphy_probe(struct platform_device *pdev)
-{
- const struct of_device_id *match;
- struct cdns_dphy *dphy;
- struct of_phandle_args args;
- struct resource res;
- int ret;
-
- ret = of_parse_phandle_with_args(pdev->dev.of_node, "phys",
- "#phy-cells", 0, &args);
- if (ret)
- return ERR_PTR(-ENOENT);
-
- match = of_match_node(cdns_dphy_of_match, args.np);
- if (!match || !match->data)
- return ERR_PTR(-EINVAL);
-
- dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
- if (!dphy)
- return ERR_PTR(-ENOMEM);
-
- dphy->ops = match->data;
-
- ret = of_address_to_resource(args.np, 0, &res);
- if (ret)
- return ERR_PTR(ret);
-
- dphy->regs = devm_ioremap_resource(&pdev->dev, &res);
- if (IS_ERR(dphy->regs))
- return ERR_CAST(dphy->regs);
-
- dphy->psm_clk = of_clk_get_by_name(args.np, "psm");
- if (IS_ERR(dphy->psm_clk))
- return ERR_CAST(dphy->psm_clk);
-
- dphy->pll_ref_clk = of_clk_get_by_name(args.np, "pll_ref");
- if (IS_ERR(dphy->pll_ref_clk)) {
- ret = PTR_ERR(dphy->pll_ref_clk);
- goto err_put_psm_clk;
- }
-
- if (dphy->ops->probe) {
- ret = dphy->ops->probe(dphy);
- if (ret)
- goto err_put_pll_ref_clk;
- }
-
- return dphy;
-
-err_put_pll_ref_clk:
- clk_put(dphy->pll_ref_clk);
-
-err_put_psm_clk:
- clk_put(dphy->psm_clk);
-
- return ERR_PTR(ret);
-}
-
-static void cdns_dphy_remove(struct cdns_dphy *dphy)
-{
- if (dphy->ops->remove)
- dphy->ops->remove(dphy);
-
- clk_put(dphy->pll_ref_clk);
- clk_put(dphy->psm_clk);
-}
-
static int cdns_dsi_drm_probe(struct platform_device *pdev)
{
struct cdns_dsi *dsi;
@@ -1559,13 +1196,13 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- dsi->dphy = cdns_dphy_probe(pdev);
+ dsi->dphy = devm_phy_get(&pdev->dev, "dphy");
if (IS_ERR(dsi->dphy))
return PTR_ERR(dsi->dphy);
ret = clk_prepare_enable(dsi->dsi_p_clk);
if (ret)
- goto err_remove_dphy;
+ return ret;
val = readl(dsi->regs + ID_REG);
if (REV_VENDOR_ID(val) != 0xcad) {
@@ -1623,9 +1260,6 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev)
err_disable_pclk:
clk_disable_unprepare(dsi->dsi_p_clk);
-err_remove_dphy:
- cdns_dphy_remove(dsi->dphy);
-
return ret;
}
@@ -1635,7 +1269,6 @@ static int cdns_dsi_drm_remove(struct platform_device *pdev)
mipi_dsi_host_unregister(&dsi->base);
pm_runtime_disable(&pdev->dev);
- cdns_dphy_remove(dsi->dphy);
return 0;
}
--
git-series 0.9.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 07/10] drm/bridge: cdns: Separate DSI and D-PHY configuration
From: Maxime Ripard @ 2018-12-07 13:55 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Boris Brezillon
Cc: Archit Taneja, Rafal Ciepiela, Krzysztof Witos, Maxime Ripard,
linux-kernel, dri-devel, Andrzej Hajda, Chen-Yu Tsai,
Laurent Pinchart, Thomas Petazzoni, linux-arm-kernel, linux-media
In-Reply-To: <cover.ad7c4feb3905658f10b022df4756a5ade280011f.1544190837.git-series.maxime.ripard@bootlin.com>
The current configuration of the DSI bridge and its associated D-PHY is
intertwined. In order to ease the future conversion to the phy framework
for the D-PHY part, let's split the configuration in two.
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
drivers/gpu/drm/bridge/cdns-dsi.c | 96 ++++++++++++++++++++++----------
1 file changed, 68 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c
index ce9496d13986..3ac6dd524b6d 100644
--- a/drivers/gpu/drm/bridge/cdns-dsi.c
+++ b/drivers/gpu/drm/bridge/cdns-dsi.c
@@ -545,6 +545,11 @@ bridge_to_cdns_dsi_input(struct drm_bridge *bridge)
return container_of(bridge, struct cdns_dsi_input, bridge);
}
+static unsigned int mode_to_dpi_hfp(const struct drm_display_mode *mode)
+{
+ return mode->crtc_hsync_start - mode->crtc_hdisplay;
+}
+
static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
struct cdns_dphy_cfg *cfg,
unsigned int dpi_htotal,
@@ -731,14 +736,12 @@ static unsigned int dpi_to_dsi_timing(unsigned int dpi_timing,
static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi,
const struct drm_display_mode *mode,
struct cdns_dsi_cfg *dsi_cfg,
- struct cdns_dphy_cfg *dphy_cfg,
bool mode_valid_check)
{
- unsigned long dsi_htotal = 0, dsi_hss_hsa_hse_hbp = 0;
struct cdns_dsi_output *output = &dsi->output;
- unsigned int dsi_hfp_ext = 0, dpi_hfp, tmp;
+ unsigned int tmp;
bool sync_pulse = false;
- int bpp, nlanes, ret;
+ int bpp, nlanes;
memset(dsi_cfg, 0, sizeof(*dsi_cfg));
@@ -757,8 +760,6 @@ static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi,
mode->crtc_hsync_end : mode->crtc_hsync_start);
dsi_cfg->hbp = dpi_to_dsi_timing(tmp, bpp, DSI_HBP_FRAME_OVERHEAD);
- dsi_htotal += dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
- dsi_hss_hsa_hse_hbp += dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
if (sync_pulse) {
if (mode_valid_check)
@@ -768,49 +769,90 @@ static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi,
dsi_cfg->hsa = dpi_to_dsi_timing(tmp, bpp,
DSI_HSA_FRAME_OVERHEAD);
- dsi_htotal += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
- dsi_hss_hsa_hse_hbp += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
}
dsi_cfg->hact = dpi_to_dsi_timing(mode_valid_check ?
mode->hdisplay : mode->crtc_hdisplay,
bpp, 0);
- dsi_htotal += dsi_cfg->hact;
+ dsi_cfg->hfp = dpi_to_dsi_timing(mode_to_dpi_hfp(mode), bpp,
+ DSI_HFP_FRAME_OVERHEAD);
- if (mode_valid_check)
- dpi_hfp = mode->hsync_start - mode->hdisplay;
- else
- dpi_hfp = mode->crtc_hsync_start - mode->crtc_hdisplay;
+ return 0;
+}
+
+static int cdns_dphy_validate(struct cdns_dsi *dsi,
+ struct cdns_dsi_cfg *dsi_cfg,
+ struct cdns_dphy_cfg *dphy_cfg,
+ const struct drm_display_mode *mode,
+ bool mode_valid_check)
+{
+ struct cdns_dsi_output *output = &dsi->output;
+ unsigned long dsi_htotal;
+ unsigned int dsi_hfp_ext = 0;
+
+ int ret;
- dsi_cfg->hfp = dpi_to_dsi_timing(dpi_hfp, bpp, DSI_HFP_FRAME_OVERHEAD);
+ dsi_htotal = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
+ if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+ dsi_htotal += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
+
+ dsi_htotal += dsi_cfg->hact;
dsi_htotal += dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD;
if (mode_valid_check)
ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg,
- mode->htotal, bpp,
+ mode->htotal,
mode->clock * 1000,
- dsi_htotal, nlanes,
+ mipi_dsi_pixel_format_to_bpp(output->dev->format),
+ dsi_htotal,
+ output->dev->lanes,
&dsi_hfp_ext);
else
ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg,
- mode->crtc_htotal, bpp,
+ mode->crtc_htotal,
+ mipi_dsi_pixel_format_to_bpp(output->dev->format),
mode->crtc_clock * 1000,
- dsi_htotal, nlanes,
+ dsi_htotal,
+ output->dev->lanes,
&dsi_hfp_ext);
-
if (ret)
return ret;
dsi_cfg->hfp += dsi_hfp_ext;
- dsi_htotal += dsi_hfp_ext;
- dsi_cfg->htotal = dsi_htotal;
+ dsi_cfg->htotal = dsi_htotal + dsi_hfp_ext;
+
+ return 0;
+}
+
+static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
+ const struct drm_display_mode *mode,
+ struct cdns_dsi_cfg *dsi_cfg,
+ struct cdns_dphy_cfg *dphy_cfg,
+ bool mode_valid_check)
+{
+ struct cdns_dsi_output *output = &dsi->output;
+ unsigned long dsi_hss_hsa_hse_hbp;
+ unsigned int nlanes = output->dev->lanes;
+ int ret;
+
+ ret = cdns_dsi_mode2cfg(dsi, mode, dsi_cfg, mode_valid_check);
+ if (ret)
+ return ret;
+
+ ret = cdns_dphy_validate(dsi, dsi_cfg, dphy_cfg, mode, mode_valid_check);
+ if (ret)
+ return ret;
+
+ dsi_hss_hsa_hse_hbp = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
+ if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+ dsi_hss_hsa_hse_hbp += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
/*
* Make sure DPI(HFP) > DSI(HSS+HSA+HSE+HBP) to guarantee that the FIFO
* is empty before we start a receiving a new line on the DPI
* interface.
*/
- if ((u64)dphy_cfg->lane_bps * dpi_hfp * nlanes <
+ if ((u64)dphy_cfg->lane_bps * mode_to_dpi_hfp(mode) * nlanes <
(u64)dsi_hss_hsa_hse_hbp *
(mode_valid_check ? mode->clock : mode->crtc_clock) * 1000)
return -EINVAL;
@@ -842,7 +884,7 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
struct cdns_dsi_output *output = &dsi->output;
struct cdns_dphy_cfg dphy_cfg;
struct cdns_dsi_cfg dsi_cfg;
- int bpp, nlanes, ret;
+ int bpp, ret;
/*
* VFP_DSI should be less than VFP_DPI and VFP_DSI should be at
@@ -860,11 +902,9 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
if ((mode->hdisplay * bpp) % 32)
return MODE_H_ILLEGAL;
- nlanes = output->dev->lanes;
-
- ret = cdns_dsi_mode2cfg(dsi, mode, &dsi_cfg, &dphy_cfg, true);
+ ret = cdns_dsi_check_conf(dsi, mode, &dsi_cfg, &dphy_cfg, true);
if (ret)
- return MODE_CLOCK_RANGE;
+ return MODE_BAD;
return MODE_OK;
}
@@ -990,7 +1030,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format);
nlanes = output->dev->lanes;
- WARN_ON_ONCE(cdns_dsi_mode2cfg(dsi, mode, &dsi_cfg, &dphy_cfg, false));
+ WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, &dphy_cfg, false));
cdns_dsi_hs_init(dsi, &dphy_cfg);
cdns_dsi_init_link(dsi);
--
git-series 0.9.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 04/10] phy: dphy: Add configuration helpers
From: Maxime Ripard @ 2018-12-07 13:55 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Boris Brezillon
Cc: Archit Taneja, Rafal Ciepiela, Krzysztof Witos, Maxime Ripard,
linux-kernel, dri-devel, Andrzej Hajda, Chen-Yu Tsai,
Laurent Pinchart, Thomas Petazzoni, linux-arm-kernel, linux-media
In-Reply-To: <cover.ad7c4feb3905658f10b022df4756a5ade280011f.1544190837.git-series.maxime.ripard@bootlin.com>
The MIPI D-PHY spec defines default values and boundaries for most of the
parameters it defines. Introduce helpers to help drivers get meaningful
values based on their current parameters, and validate the boundaries of
these parameters if needed.
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
drivers/phy/Kconfig | 8 +-
drivers/phy/Makefile | 1 +-
drivers/phy/phy-core-mipi-dphy.c | 166 +++++++++++++++++++++++++++++++-
include/linux/phy/phy-mipi-dphy.h | 6 +-
4 files changed, 181 insertions(+)
create mode 100644 drivers/phy/phy-core-mipi-dphy.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 60f949e2a684..c87a7d49eaab 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -15,6 +15,14 @@ config GENERIC_PHY
phy users can obtain reference to the PHY. All the users of this
framework should select this config.
+config GENERIC_PHY_MIPI_DPHY
+ bool
+ help
+ Generic MIPI D-PHY support.
+
+ Provides a number of helpers a core functions for MIPI D-PHY
+ drivers to us.
+
config PHY_LPC18XX_USB_OTG
tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 0301e25d07c1..baec59cebbab 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -4,6 +4,7 @@
#
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
+obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c
new file mode 100644
index 000000000000..465fa1b91a5f
--- /dev/null
+++ b/drivers/phy/phy-core-mipi-dphy.c
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ * Copyright (C) 2018 Cadence Design Systems Inc.
+ */
+
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/time64.h>
+
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
+
+#define PSEC_PER_SEC 1000000000000LL
+
+/*
+ * Minimum D-PHY timings based on MIPI D-PHY specification. Derived
+ * from the valid ranges specified in Section 6.9, Table 14, Page 41
+ * of the D-PHY specification (v2.1).
+ */
+int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+ unsigned int bpp,
+ unsigned int lanes,
+ struct phy_configure_opts_mipi_dphy *cfg)
+{
+ unsigned long long hs_clk_rate;
+ unsigned long long ui;
+
+ if (!cfg)
+ return -EINVAL;
+
+ hs_clk_rate = pixel_clock * bpp;
+ do_div(hs_clk_rate, lanes);
+
+ ui = ALIGN(PSEC_PER_SEC, hs_clk_rate);
+ do_div(ui, hs_clk_rate);
+
+ cfg->clk_miss = 0;
+ cfg->clk_post = 60000 + 52 * ui;
+ cfg->clk_pre = 8000;
+ cfg->clk_prepare = 38000;
+ cfg->clk_settle = 95000;
+ cfg->clk_term_en = 0;
+ cfg->clk_trail = 60000;
+ cfg->clk_zero = 262000;
+ cfg->d_term_en = 0;
+ cfg->eot = 0;
+ cfg->hs_exit = 100000;
+ cfg->hs_prepare = 40000 + 4 * ui;
+ cfg->hs_zero = 105000 + 6 * ui;
+ cfg->hs_settle = 85000 + 6 * ui;
+ cfg->hs_skip = 40000;
+
+ /*
+ * The MIPI D-PHY specification (Section 6.9, v1.2, Table 14, Page 40)
+ * contains this formula as:
+ *
+ * T_HS-TRAIL = max(n * 8 * ui, 60 + n * 4 * ui)
+ *
+ * where n = 1 for forward-direction HS mode and n = 4 for reverse-
+ * direction HS mode. There's only one setting and this function does
+ * not parameterize on anything other that ui, so this code will
+ * assumes that reverse-direction HS mode is supported and uses n = 4.
+ */
+ cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui);
+
+ cfg->init = 100000000;
+ cfg->lpx = 60000;
+ cfg->ta_get = 5 * cfg->lpx;
+ cfg->ta_go = 4 * cfg->lpx;
+ cfg->ta_sure = 2 * cfg->lpx;
+ cfg->wakeup = 1000000000;
+
+ cfg->hs_clk_rate = hs_clk_rate;
+ cfg->lanes = lanes;
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_mipi_dphy_get_default_config);
+
+/*
+ * Validate D-PHY configuration according to MIPI D-PHY specification
+ * (v1.2, Section Section 6.9 "Global Operation Timing Parameters").
+ */
+int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg)
+{
+ unsigned long long ui;
+
+ if (!cfg)
+ return -EINVAL;
+
+ ui = ALIGN(PSEC_PER_SEC, cfg->hs_clk_rate);
+ do_div(ui, cfg->hs_clk_rate);
+
+ if (cfg->clk_miss > 60000)
+ return -EINVAL;
+
+ if (cfg->clk_post < (60000 + 52 * ui))
+ return -EINVAL;
+
+ if (cfg->clk_pre < 8000)
+ return -EINVAL;
+
+ if (cfg->clk_prepare < 38000 || cfg->clk_prepare > 95000)
+ return -EINVAL;
+
+ if (cfg->clk_settle < 95000 || cfg->clk_settle > 300000)
+ return -EINVAL;
+
+ if (cfg->clk_term_en > 38000)
+ return -EINVAL;
+
+ if (cfg->clk_trail < 60000)
+ return -EINVAL;
+
+ if ((cfg->clk_prepare + cfg->clk_zero) < 300000)
+ return -EINVAL;
+
+ if (cfg->d_term_en > (35000 + 4 * ui))
+ return -EINVAL;
+
+ if (cfg->eot > (105000 + 12 * ui))
+ return -EINVAL;
+
+ if (cfg->hs_exit < 100000)
+ return -EINVAL;
+
+ if (cfg->hs_prepare < (40000 + 4 * ui) ||
+ cfg->hs_prepare > (85000 + 6 * ui))
+ return -EINVAL;
+
+ if ((cfg->hs_prepare + cfg->hs_zero) < (145000 + 10 * ui))
+ return -EINVAL;
+
+ if ((cfg->hs_settle < (85000 + 6 * ui)) ||
+ (cfg->hs_settle > (145000 + 10 * ui)))
+ return -EINVAL;
+
+ if (cfg->hs_skip < 40000 || cfg->hs_skip > (55000 + 4 * ui))
+ return -EINVAL;
+
+ if (cfg->hs_trail < max(8 * ui, 60000 + 4 * ui))
+ return -EINVAL;
+
+ if (cfg->init < 100000000)
+ return -EINVAL;
+
+ if (cfg->lpx < 50000)
+ return -EINVAL;
+
+ if (cfg->ta_get != (5 * cfg->lpx))
+ return -EINVAL;
+
+ if (cfg->ta_go != (4 * cfg->lpx))
+ return -EINVAL;
+
+ if (cfg->ta_sure < cfg->lpx || cfg->ta_sure > (2 * cfg->lpx))
+ return -EINVAL;
+
+ if (cfg->wakeup < 1000000000)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_mipi_dphy_config_validate);
diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h
index 29bf94db88ad..c08aacc0ac35 100644
--- a/include/linux/phy/phy-mipi-dphy.h
+++ b/include/linux/phy/phy-mipi-dphy.h
@@ -276,4 +276,10 @@ struct phy_configure_opts_mipi_dphy {
unsigned char lanes;
};
+int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+ unsigned int bpp,
+ unsigned int lanes,
+ struct phy_configure_opts_mipi_dphy *cfg);
+int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg);
+
#endif /* __PHY_MIPI_DPHY_H_ */
--
git-series 0.9.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 08/10] dt-bindings: phy: Move the Cadence D-PHY bindings
From: Maxime Ripard @ 2018-12-07 13:55 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Boris Brezillon
Cc: Archit Taneja, Rafal Ciepiela, Krzysztof Witos, Maxime Ripard,
linux-kernel, dri-devel, Andrzej Hajda, Chen-Yu Tsai,
Laurent Pinchart, Thomas Petazzoni, linux-arm-kernel, linux-media
In-Reply-To: <cover.ad7c4feb3905658f10b022df4756a5ade280011f.1544190837.git-series.maxime.ripard@bootlin.com>
The Cadence D-PHY bindings was defined as part of the DSI block so far.
However, since it's now going to be a separate driver, we need to move the
binding to a file of its own.
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
Documentation/devicetree/bindings/display/bridge/cdns,dsi.txt | 21 +-------
Documentation/devicetree/bindings/phy/cdns,dphy.txt | 20 +++++++-
2 files changed, 20 insertions(+), 21 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/cdns,dphy.txt
diff --git a/Documentation/devicetree/bindings/display/bridge/cdns,dsi.txt b/Documentation/devicetree/bindings/display/bridge/cdns,dsi.txt
index f5725bb6c61c..525a4bfd8634 100644
--- a/Documentation/devicetree/bindings/display/bridge/cdns,dsi.txt
+++ b/Documentation/devicetree/bindings/display/bridge/cdns,dsi.txt
@@ -31,28 +31,7 @@ Required subnodes:
- one subnode per DSI device connected on the DSI bus. Each DSI device should
contain a reg property encoding its virtual channel.
-Cadence DPHY
-============
-
-Cadence DPHY block.
-
-Required properties:
-- compatible: should be set to "cdns,dphy".
-- reg: physical base address and length of the DPHY registers.
-- clocks: DPHY reference clocks.
-- clock-names: must contain "psm" and "pll_ref".
-- #phy-cells: must be set to 0.
-
-
Example:
- dphy0: dphy@fd0e0000{
- compatible = "cdns,dphy";
- reg = <0x0 0xfd0e0000 0x0 0x1000>;
- clocks = <&psm_clk>, <&pll_ref_clk>;
- clock-names = "psm", "pll_ref";
- #phy-cells = <0>;
- };
-
dsi0: dsi@fd0c0000 {
compatible = "cdns,dsi";
reg = <0x0 0xfd0c0000 0x0 0x1000>;
diff --git a/Documentation/devicetree/bindings/phy/cdns,dphy.txt b/Documentation/devicetree/bindings/phy/cdns,dphy.txt
new file mode 100644
index 000000000000..1095bc4e72d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/cdns,dphy.txt
@@ -0,0 +1,20 @@
+Cadence DPHY
+============
+
+Cadence DPHY block.
+
+Required properties:
+- compatible: should be set to "cdns,dphy".
+- reg: physical base address and length of the DPHY registers.
+- clocks: DPHY reference clocks.
+- clock-names: must contain "psm" and "pll_ref".
+- #phy-cells: must be set to 0.
+
+Example:
+ dphy0: dphy@fd0e0000{
+ compatible = "cdns,dphy";
+ reg = <0x0 0xfd0e0000 0x0 0x1000>;
+ clocks = <&psm_clk>, <&pll_ref_clk>;
+ clock-names = "psm", "pll_ref";
+ #phy-cells = <0>;
+ };
--
git-series 0.9.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 06/10] phy: Move Allwinner A31 D-PHY driver to drivers/phy/
From: Maxime Ripard @ 2018-12-07 13:55 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Boris Brezillon
Cc: Archit Taneja, Rafal Ciepiela, Krzysztof Witos, Maxime Ripard,
linux-kernel, dri-devel, Andrzej Hajda, Chen-Yu Tsai,
Laurent Pinchart, Thomas Petazzoni, linux-arm-kernel, linux-media
In-Reply-To: <cover.ad7c4feb3905658f10b022df4756a5ade280011f.1544190837.git-series.maxime.ripard@bootlin.com>
Now that our MIPI D-PHY driver has been converted to the phy framework,
let's move it into the drivers/phy directory.
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
drivers/gpu/drm/sun4i/Kconfig | 10 +---------
drivers/gpu/drm/sun4i/Makefile | 1 -
drivers/phy/allwinner/Kconfig | 12 ++++++++++++
drivers/phy/allwinner/Makefile | 1 +
.../allwinner/phy-sun6i-mipi-dphy.c} | 0
5 files changed, 14 insertions(+), 10 deletions(-)
rename drivers/{gpu/drm/sun4i/sun6i_mipi_dphy.c => phy/allwinner/phy-sun6i-mipi-dphy.c} (100%)
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 2b8db82c4bab..1dbbc3a1b763 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -45,20 +45,12 @@ config DRM_SUN6I_DSI
default MACH_SUN8I
select CRC_CCITT
select DRM_MIPI_DSI
- select DRM_SUN6I_DPHY
+ select PHY_SUN6I_MIPI_DPHY
help
Choose this option if you want have an Allwinner SoC with
MIPI-DSI support. If M is selected the module will be called
sun6i_mipi_dsi.
-config DRM_SUN6I_DPHY
- tristate "Allwinner A31 MIPI D-PHY Support"
- select GENERIC_PHY_MIPI_DPHY
- help
- Choose this option if you have an Allwinner SoC with
- MIPI-DSI support. If M is selected, the module will be
- called sun6i_mipi_dphy.
-
config DRM_SUN8I_DW_HDMI
tristate "Support for Allwinner version of DesignWare HDMI"
depends on DRM_SUN4I
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 1e2320d824b5..0d04f2447b01 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -34,7 +34,6 @@ ifdef CONFIG_DRM_SUN4I_BACKEND
obj-$(CONFIG_DRM_SUN4I) += sun4i-frontend.o
endif
obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o
-obj-$(CONFIG_DRM_SUN6I_DPHY) += sun6i_mipi_dphy.o
obj-$(CONFIG_DRM_SUN6I_DSI) += sun6i_mipi_dsi.o
obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i-drm-hdmi.o
obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig
index cdc1e745ba47..fb1204bcc454 100644
--- a/drivers/phy/allwinner/Kconfig
+++ b/drivers/phy/allwinner/Kconfig
@@ -17,6 +17,18 @@ config PHY_SUN4I_USB
This driver controls the entire USB PHY block, both the USB OTG
parts, as well as the 2 regular USB 2 host PHYs.
+config PHY_SUN6I_MIPI_DPHY
+ tristate "Allwinner A31 MIPI D-PHY Support"
+ depends on ARCH_SUNXI && HAS_IOMEM && OF
+ depends on RESET_CONTROLLER
+ select GENERIC_PHY
+ select GENERIC_PHY_MIPI_DPHY
+ select REGMAP_MMIO
+ help
+ Choose this option if you have an Allwinner SoC with
+ MIPI-DSI support. If M is selected, the module will be
+ called sun6i_mipi_dphy.
+
config PHY_SUN9I_USB
tristate "Allwinner sun9i SoC USB PHY driver"
depends on ARCH_SUNXI && HAS_IOMEM && OF
diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile
index 8605529c01a1..7d0053efbfaa 100644
--- a/drivers/phy/allwinner/Makefile
+++ b/drivers/phy/allwinner/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
+obj-$(CONFIG_PHY_SUN6I_MIPI_DPHY) += phy-sun6i-mipi-dphy.o
obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dphy.c b/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
similarity index 100%
rename from drivers/gpu/drm/sun4i/sun6i_mipi_dphy.c
rename to drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
--
2.19.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 09/10] phy: Add Cadence D-PHY support
From: Maxime Ripard @ 2018-12-07 13:55 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Boris Brezillon
Cc: Archit Taneja, Rafal Ciepiela, Krzysztof Witos, Maxime Ripard,
linux-kernel, dri-devel, Andrzej Hajda, Chen-Yu Tsai,
Laurent Pinchart, Thomas Petazzoni, linux-arm-kernel, linux-media
In-Reply-To: <cover.ad7c4feb3905658f10b022df4756a5ade280011f.1544190837.git-series.maxime.ripard@bootlin.com>
Cadence has designed a D-PHY that can be used by the, currently in tree,
DSI bridge (DRM), CSI Transceiver and CSI Receiver (v4l2) drivers.
Only the DSI driver has an ad-hoc driver for that phy at the moment, while
the v4l2 drivers are completely missing any phy support. In order to make
that phy support available to all these drivers, without having to
duplicate that code three times, let's create a generic phy framework
driver.
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
drivers/phy/cadence/Kconfig | 13 +-
drivers/phy/cadence/Makefile | 1 +-
drivers/phy/cadence/cdns-dphy.c | 389 +++++++++++++++++++++++++++++++++-
3 files changed, 402 insertions(+), 1 deletion(-)
create mode 100644 drivers/phy/cadence/cdns-dphy.c
diff --git a/drivers/phy/cadence/Kconfig b/drivers/phy/cadence/Kconfig
index 2b8c0851ff33..31f18b67dd7c 100644
--- a/drivers/phy/cadence/Kconfig
+++ b/drivers/phy/cadence/Kconfig
@@ -1,6 +1,7 @@
#
# Phy drivers for Cadence PHYs
#
+
config PHY_CADENCE_DP
tristate "Cadence MHDP DisplayPort PHY driver"
depends on OF
@@ -9,9 +10,19 @@ config PHY_CADENCE_DP
help
Support for Cadence MHDP DisplayPort PHY.
+config PHY_CADENCE_DPHY
+ tristate "Cadence D-PHY Support"
+ depends on HAS_IOMEM && OF
+ select GENERIC_PHY
+ select GENERIC_PHY_MIPI_DPHY
+ help
+ Choose this option if you have a Cadence D-PHY in your
+ system. If M is selected, the module will be called
+ cdns-dphy.
+
config PHY_CADENCE_SIERRA
tristate "Cadence Sierra PHY Driver"
depends on OF && HAS_IOMEM && RESET_CONTROLLER
select GENERIC_PHY
help
- Enable this to support the Cadence Sierra PHY driver
\ No newline at end of file
+ Enable this to support the Cadence Sierra PHY driver
diff --git a/drivers/phy/cadence/Makefile b/drivers/phy/cadence/Makefile
index 412349af0492..2f9e3457b954 100644
--- a/drivers/phy/cadence/Makefile
+++ b/drivers/phy/cadence/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_PHY_CADENCE_DP) += phy-cadence-dp.o
+obj-$(CONFIG_PHY_CADENCE_DPHY) += cdns-dphy.o
obj-$(CONFIG_PHY_CADENCE_SIERRA) += phy-cadence-sierra.o
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
new file mode 100644
index 000000000000..1d0abba03f37
--- /dev/null
+++ b/drivers/phy/cadence/cdns-dphy.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright: 2017-2018 Cadence Design Systems, Inc.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
+
+#define REG_WAKEUP_TIME_NS 800
+#define DPHY_PLL_RATE_HZ 108000000
+
+/* DPHY registers */
+#define DPHY_PMA_CMN(reg) (reg)
+#define DPHY_PMA_LCLK(reg) (0x100 + (reg))
+#define DPHY_PMA_LDATA(lane, reg) (0x200 + ((lane) * 0x100) + (reg))
+#define DPHY_PMA_RCLK(reg) (0x600 + (reg))
+#define DPHY_PMA_RDATA(lane, reg) (0x700 + ((lane) * 0x100) + (reg))
+#define DPHY_PCS(reg) (0xb00 + (reg))
+
+#define DPHY_CMN_SSM DPHY_PMA_CMN(0x20)
+#define DPHY_CMN_SSM_EN BIT(0)
+#define DPHY_CMN_TX_MODE_EN BIT(9)
+
+#define DPHY_CMN_PWM DPHY_PMA_CMN(0x40)
+#define DPHY_CMN_PWM_DIV(x) ((x) << 20)
+#define DPHY_CMN_PWM_LOW(x) ((x) << 10)
+#define DPHY_CMN_PWM_HIGH(x) (x)
+
+#define DPHY_CMN_FBDIV DPHY_PMA_CMN(0x4c)
+#define DPHY_CMN_FBDIV_VAL(low, high) (((high) << 11) | ((low) << 22))
+#define DPHY_CMN_FBDIV_FROM_REG (BIT(10) | BIT(21))
+
+#define DPHY_CMN_OPIPDIV DPHY_PMA_CMN(0x50)
+#define DPHY_CMN_IPDIV_FROM_REG BIT(0)
+#define DPHY_CMN_IPDIV(x) ((x) << 1)
+#define DPHY_CMN_OPDIV_FROM_REG BIT(6)
+#define DPHY_CMN_OPDIV(x) ((x) << 7)
+
+#define DPHY_PSM_CFG DPHY_PCS(0x4)
+#define DPHY_PSM_CFG_FROM_REG BIT(0)
+#define DPHY_PSM_CLK_DIV(x) ((x) << 1)
+
+#define DSI_HBP_FRAME_OVERHEAD 12
+#define DSI_HSA_FRAME_OVERHEAD 14
+#define DSI_HFP_FRAME_OVERHEAD 6
+#define DSI_HSS_VSS_VSE_FRAME_OVERHEAD 4
+#define DSI_BLANKING_FRAME_OVERHEAD 6
+#define DSI_NULL_FRAME_OVERHEAD 6
+#define DSI_EOT_PKT_SIZE 4
+
+struct cdns_dphy_cfg {
+ u8 pll_ipdiv;
+ u8 pll_opdiv;
+ u16 pll_fbdiv;
+ unsigned int nlanes;
+};
+
+enum cdns_dphy_clk_lane_cfg {
+ DPHY_CLK_CFG_LEFT_DRIVES_ALL = 0,
+ DPHY_CLK_CFG_LEFT_DRIVES_RIGHT = 1,
+ DPHY_CLK_CFG_LEFT_DRIVES_LEFT = 2,
+ DPHY_CLK_CFG_RIGHT_DRIVES_ALL = 3,
+};
+
+struct cdns_dphy;
+struct cdns_dphy_ops {
+ int (*probe)(struct cdns_dphy *dphy);
+ void (*remove)(struct cdns_dphy *dphy);
+ void (*set_psm_div)(struct cdns_dphy *dphy, u8 div);
+ void (*set_clk_lane_cfg)(struct cdns_dphy *dphy,
+ enum cdns_dphy_clk_lane_cfg cfg);
+ void (*set_pll_cfg)(struct cdns_dphy *dphy,
+ const struct cdns_dphy_cfg *cfg);
+ unsigned long (*get_wakeup_time_ns)(struct cdns_dphy *dphy);
+};
+
+struct cdns_dphy {
+ struct cdns_dphy_cfg cfg;
+ void __iomem *regs;
+ struct clk *psm_clk;
+ struct clk *pll_ref_clk;
+ const struct cdns_dphy_ops *ops;
+ struct phy *phy;
+};
+
+static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
+ struct cdns_dphy_cfg *cfg,
+ struct phy_configure_opts_mipi_dphy *opts,
+ unsigned int *dsi_hfp_ext)
+{
+ unsigned long pll_ref_hz = clk_get_rate(dphy->pll_ref_clk);
+ u64 dlane_bps;
+
+ memset(cfg, 0, sizeof(*cfg));
+
+ if (pll_ref_hz < 9600000 || pll_ref_hz >= 150000000)
+ return -EINVAL;
+ else if (pll_ref_hz < 19200000)
+ cfg->pll_ipdiv = 1;
+ else if (pll_ref_hz < 38400000)
+ cfg->pll_ipdiv = 2;
+ else if (pll_ref_hz < 76800000)
+ cfg->pll_ipdiv = 4;
+ else
+ cfg->pll_ipdiv = 8;
+
+ dlane_bps = opts->hs_clk_rate;
+
+ if (dlane_bps > 2500000000UL || dlane_bps < 160000000UL)
+ return -EINVAL;
+ else if (dlane_bps >= 1250000000)
+ cfg->pll_opdiv = 1;
+ else if (dlane_bps >= 630000000)
+ cfg->pll_opdiv = 2;
+ else if (dlane_bps >= 320000000)
+ cfg->pll_opdiv = 4;
+ else if (dlane_bps >= 160000000)
+ cfg->pll_opdiv = 8;
+
+ cfg->pll_fbdiv = DIV_ROUND_UP_ULL(dlane_bps * 2 * cfg->pll_opdiv *
+ cfg->pll_ipdiv,
+ pll_ref_hz);
+
+ return 0;
+}
+
+static int cdns_dphy_setup_psm(struct cdns_dphy *dphy)
+{
+ unsigned long psm_clk_hz = clk_get_rate(dphy->psm_clk);
+ unsigned long psm_div;
+
+ if (!psm_clk_hz || psm_clk_hz > 100000000)
+ return -EINVAL;
+
+ psm_div = DIV_ROUND_CLOSEST(psm_clk_hz, 1000000);
+ if (dphy->ops->set_psm_div)
+ dphy->ops->set_psm_div(dphy, psm_div);
+
+ return 0;
+}
+
+static void cdns_dphy_set_clk_lane_cfg(struct cdns_dphy *dphy,
+ enum cdns_dphy_clk_lane_cfg cfg)
+{
+ if (dphy->ops->set_clk_lane_cfg)
+ dphy->ops->set_clk_lane_cfg(dphy, cfg);
+}
+
+static void cdns_dphy_set_pll_cfg(struct cdns_dphy *dphy,
+ const struct cdns_dphy_cfg *cfg)
+{
+ if (dphy->ops->set_pll_cfg)
+ dphy->ops->set_pll_cfg(dphy, cfg);
+}
+
+static unsigned long cdns_dphy_get_wakeup_time_ns(struct cdns_dphy *dphy)
+{
+ return dphy->ops->get_wakeup_time_ns(dphy);
+}
+
+static unsigned long cdns_dphy_ref_get_wakeup_time_ns(struct cdns_dphy *dphy)
+{
+ /* Default wakeup time is 800 ns (in a simulated environment). */
+ return 800;
+}
+
+static void cdns_dphy_ref_set_pll_cfg(struct cdns_dphy *dphy,
+ const struct cdns_dphy_cfg *cfg)
+{
+ u32 fbdiv_low, fbdiv_high;
+
+ fbdiv_low = (cfg->pll_fbdiv / 4) - 2;
+ fbdiv_high = cfg->pll_fbdiv - fbdiv_low - 2;
+
+ writel(DPHY_CMN_IPDIV_FROM_REG | DPHY_CMN_OPDIV_FROM_REG |
+ DPHY_CMN_IPDIV(cfg->pll_ipdiv) |
+ DPHY_CMN_OPDIV(cfg->pll_opdiv),
+ dphy->regs + DPHY_CMN_OPIPDIV);
+ writel(DPHY_CMN_FBDIV_FROM_REG |
+ DPHY_CMN_FBDIV_VAL(fbdiv_low, fbdiv_high),
+ dphy->regs + DPHY_CMN_FBDIV);
+ writel(DPHY_CMN_PWM_HIGH(6) | DPHY_CMN_PWM_LOW(0x101) |
+ DPHY_CMN_PWM_DIV(0x8),
+ dphy->regs + DPHY_CMN_PWM);
+}
+
+static void cdns_dphy_ref_set_psm_div(struct cdns_dphy *dphy, u8 div)
+{
+ writel(DPHY_PSM_CFG_FROM_REG | DPHY_PSM_CLK_DIV(div),
+ dphy->regs + DPHY_PSM_CFG);
+}
+
+/*
+ * This is the reference implementation of DPHY hooks. Specific integration of
+ * this IP may have to re-implement some of them depending on how they decided
+ * to wire things in the SoC.
+ */
+static const struct cdns_dphy_ops ref_dphy_ops = {
+ .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
+ .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
+ .set_psm_div = cdns_dphy_ref_set_psm_div,
+};
+
+static int cdns_dphy_config_from_opts(struct phy *phy,
+ struct phy_configure_opts_mipi_dphy *opts,
+ struct cdns_dphy_cfg *cfg)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+ unsigned int dsi_hfp_ext = 0;
+ int ret;
+
+ ret = phy_mipi_dphy_config_validate(opts);
+ if (ret)
+ return ret;
+
+ ret = cdns_dsi_get_dphy_pll_cfg(dphy, cfg,
+ opts, &dsi_hfp_ext);
+ if (ret)
+ return ret;
+
+ opts->wakeup = cdns_dphy_get_wakeup_time_ns(dphy) * 1000;
+
+ return 0;
+}
+
+static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
+ union phy_configure_opts *opts)
+{
+ struct cdns_dphy_cfg cfg = { 0 };
+
+ if (mode != PHY_MODE_MIPI_DPHY)
+ return -EINVAL;
+
+ return cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
+}
+
+static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+ struct cdns_dphy_cfg cfg = { 0 };
+ int ret;
+
+ ret = cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
+ if (ret)
+ return ret;
+
+ /*
+ * Configure the internal PSM clk divider so that the DPHY has a
+ * 1MHz clk (or something close).
+ */
+ ret = cdns_dphy_setup_psm(dphy);
+ if (ret)
+ return ret;
+
+ /*
+ * Configure attach clk lanes to data lanes: the DPHY has 2 clk lanes
+ * and 8 data lanes, each clk lane can be attache different set of
+ * data lanes. The 2 groups are named 'left' and 'right', so here we
+ * just say that we want the 'left' clk lane to drive the 'left' data
+ * lanes.
+ */
+ cdns_dphy_set_clk_lane_cfg(dphy, DPHY_CLK_CFG_LEFT_DRIVES_LEFT);
+
+ /*
+ * Configure the DPHY PLL that will be used to generate the TX byte
+ * clk.
+ */
+ cdns_dphy_set_pll_cfg(dphy, &cfg);
+
+ return 0;
+}
+
+static int cdns_dphy_power_on(struct phy *phy)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+
+ clk_prepare_enable(dphy->psm_clk);
+ clk_prepare_enable(dphy->pll_ref_clk);
+
+ /* Start TX state machine. */
+ writel(DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN, dphy->regs + DPHY_CMN_SSM);
+
+ return 0;
+}
+
+static int cdns_dphy_power_off(struct phy *phy)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(dphy->pll_ref_clk);
+ clk_disable_unprepare(dphy->psm_clk);
+
+ return 0;
+}
+
+static const struct phy_ops cdns_dphy_ops = {
+ .configure = cdns_dphy_configure,
+ .validate = cdns_dphy_validate,
+ .power_on = cdns_dphy_power_on,
+ .power_off = cdns_dphy_power_off,
+};
+
+static int cdns_dphy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct cdns_dphy *dphy;
+ struct resource *res;
+ int ret;
+
+ dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
+ if (!dphy)
+ return -ENOMEM;
+ dev_set_drvdata(&pdev->dev, dphy);
+
+ dphy->ops = of_device_get_match_data(&pdev->dev);
+ if (!dphy->ops)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dphy->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dphy->regs))
+ return PTR_ERR(dphy->regs);
+
+ dphy->psm_clk = devm_clk_get(&pdev->dev, "psm");
+ if (IS_ERR(dphy->psm_clk))
+ return PTR_ERR(dphy->psm_clk);
+
+ dphy->pll_ref_clk = devm_clk_get(&pdev->dev, "pll_ref");
+ if (IS_ERR(dphy->pll_ref_clk))
+ return PTR_ERR(dphy->pll_ref_clk);
+
+ if (dphy->ops->probe) {
+ ret = dphy->ops->probe(dphy);
+ if (ret)
+ return ret;
+ }
+
+ dphy->phy = devm_phy_create(&pdev->dev, NULL, &cdns_dphy_ops);
+ if (IS_ERR(dphy->phy)) {
+ dev_err(&pdev->dev, "failed to create PHY\n");
+ if (dphy->ops->remove)
+ dphy->ops->remove(dphy);
+ return PTR_ERR(dphy->phy);
+ }
+
+ phy_set_drvdata(dphy->phy, dphy);
+ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static int cdns_dphy_remove(struct platform_device *pdev)
+{
+ struct cdns_dphy *dphy = dev_get_drvdata(&pdev->dev);
+
+ if (dphy->ops->remove)
+ dphy->ops->remove(dphy);
+
+ return 0;
+}
+
+static const struct of_device_id cdns_dphy_of_match[] = {
+ { .compatible = "cdns,dphy", .data = &ref_dphy_ops },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, cdns_dphy_of_match);
+
+static struct platform_driver cdns_dphy_platform_driver = {
+ .probe = cdns_dphy_probe,
+ .remove = cdns_dphy_remove,
+ .driver = {
+ .name = "cdns-mipi-dphy",
+ .of_match_table = cdns_dphy_of_match,
+ },
+};
+module_platform_driver(cdns_dphy_platform_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>");
+MODULE_DESCRIPTION("Cadence MIPI D-PHY Driver");
+MODULE_LICENSE("GPL");
--
git-series 0.9.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ 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