From 5b115837394e7a408638c0d46cde1b689d03832f Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 21 Oct 2020 18:04:18 -0400 Subject: Rework for AGL UCB integration Changes include: - The provided kernel patches have been reworked to not modify the salvator-x(s) devicetree source, but to introduce new files for the reference hardware instead. There is some possibility that the reference hardware devicetree could be based off the the salvator-x with some work and perhaps splitting of the salvator-x source, but for now the aim is to avoid breaking the salvator-x(s) with the reference hardware changes. - The modifications to the r8a7795 pinctrl driver have been replaced with a splitting of the USB interface OVC pins into their own pin groups, which has previously been done for other older Renesas hardware. This allows booting the reference hardware off of the same kernel as other H3 boards, at the expense of minor devicetree modifications for them (e.g. h3ulcb). There is likely some more work required if this needs to be upstreamed, as the ulcb.dtsi changes would mean that the pinctrl drivers for M3 would also need the new pin groups. - All changes for the ST asm330lhh driver addtion have been moved to that patch to the kernel. - A machine conf file has been added for "agl-refhw-h3", and the firmware documentation updated to document how to set up a build of the firmware using it. This is required due to the firmware options from this layer's arm-trusted-firmware bbappend not being compatible with other H3 boards (eMMC versus Hyperflash boot). A definition of the COMPATIBLE_MACHINE variable has been added to that bbappend to make sure that attempting to use it with another H3 machine will trigger an error. In AGL, the bbappend will need to be masked out with BBMASK for now. - The top-level README file has been updated to reflect the expected integration in AGL. Bug-AGL: SPEC-3658 Signed-off-by: Scott Murray --- README | 78 +- meta-agl-refhw-gen3/conf/machine/agl-refhw-h3.conf | 16 + meta-agl-refhw-gen3/docs/ReferenceHW_Rcar_gen3.md | 58 +- .../arm-trusted-firmware_%.bbappend | 11 +- .../linux/files/0001-add-agl-refhw.patch | 1418 +++++++++++++ .../linux/files/0001-add-st_asm330lhh-driver.patch | 2112 -------------------- ...0001-create-r8a7795-usb-ovc-pinmux-groups.patch | 410 ++++ ...-Introduce-dts-file-for-refhw-r-car-board.patch | 90 - .../linux/files/0002-add-st_asm330lhh-driver.patch | 2112 ++++++++++++++++++++ .../0002-agl-reference-hardware-sample-bsp.patch | 846 -------- .../recipes-kernel/linux/linux-renesas_%.bbappend | 10 +- 11 files changed, 4067 insertions(+), 3094 deletions(-) create mode 100644 meta-agl-refhw-gen3/conf/machine/agl-refhw-h3.conf create mode 100644 meta-agl-refhw-gen3/recipes-kernel/linux/files/0001-add-agl-refhw.patch delete mode 100644 meta-agl-refhw-gen3/recipes-kernel/linux/files/0001-add-st_asm330lhh-driver.patch create mode 100644 meta-agl-refhw-gen3/recipes-kernel/linux/files/0001-create-r8a7795-usb-ovc-pinmux-groups.patch delete mode 100644 meta-agl-refhw-gen3/recipes-kernel/linux/files/0002-Introduce-dts-file-for-refhw-r-car-board.patch create mode 100644 meta-agl-refhw-gen3/recipes-kernel/linux/files/0002-add-st_asm330lhh-driver.patch delete mode 100644 meta-agl-refhw-gen3/recipes-kernel/linux/files/0002-agl-reference-hardware-sample-bsp.patch diff --git a/README b/README index e806db8..aa8e63d 100644 --- a/README +++ b/README @@ -1,54 +1,65 @@ This README file contains information on the contents of the meta-agl-refhw-gen3 -layer which provides the reference hardware support for AGL environment. +layer which provides support for the Renesas R-Car H3 based AGL reference +hardware. -Dependency -========== +Dependencies +============ -- Yocto layers of AGL Happy Halibut. - Especially depends on meta-renesas-rcar-gen3. +This layer depends on: + + URI: git://git.openembedded.org/openembedded-core + layers: meta + branch: dunfell + + URI: git://git.openembedded.org/meta-openembedded + layers: meta-oe, meta-python + branch: dunfell + + URI: https://github.com/renesas-rcar/meta-renesas + branch: dunfell-dev-4.14 Build Instructions ================== - I. Adding the meta-agl-refhw-gen3 layer to your AGL environment + I. Building with the layer in the AGL environment II. Build agl-demo-platform by using meta-agl-refhw-gen3 -III. Update firmware. +III. Updating firmware IV. Notes I. Adding the meta-agl-refhw-gen3 layer to your AGL environment -============================================================== - -You can add this layer to your AGL HH environemnt as following: +=============================================================== -1. Put meta-refhw folder into the "$AGL_TOP/bsp" directory where AGL BSP layers - like meta-renesas-rcar-gen3/ are placed. - # See "Downloading AGL Software" in AGL developper site. +This layer has been integrated into the AGL build environment for the UCB 11.0 +(Kooky Koi) release, so manual integration is no longer required. See section +(II) below for how to build an image, and the "How to build the Firmware" section +in the document meta-agl-refhw-gen3/docs/ReferenceHW_Rcar_gen3.md for how to +configure a standalone build without AGL. -2. Put refhw-h3 folder into the meta-agl/templates/machine where other machine - configuration files are placed. II. Build for Reference Hardware ================================ -You should follow the instructions in "Building for Supported Renesas Boards" -section in AGL developper site to build images for reference hardware. -The modification needed is to set machine to "refhw-h3" when execute -aglsetup.sh (parameter of "-m" option). +You should follow the instructions in the "Building for Supported Renesas Boards" +section on the AGL developer site to build images for the reference hardware. + +Use the "h3ulcb" machine when configuring, e.g.: $ cd $AGL_TOP - $ source meta-agl/scripts/aglsetup.sh -m refhw-h3 -b build \ - agl-devel agl-demo agl-netboot agl-appfw-smack agl-localdev + $ source meta-agl/scripts/aglsetup.sh -m h3uclb -b build \ + agl-devel agl-demo agl-localdev -The "real" MACHINE in the internal building is set to "salvator-x" so that we -can divert the configurations defined for salvator-x. While, the DTB file used -by reference hardware is "r8a7795-refhw.dtb". so the settings in u-boot is -expected as following (in case of booting from the Micro SD card in SD#0): +This works as the AGL reference hardware support has been integrated with the +"h3ulcb" (and "h3ulcb-nogfx") machine templates in the AGL UCB tree. In the +resulting build, the image can be used on the reference hardware by using the +DTB file "r8a7795-agl-refhw.dtb". In the reference hardware u-boot settings, +this can be done with the following (in case of booting from the Micro SD card +in SD#0): => setenv bootargs 'console=ttySC0,115200 root=/dev/mmcblk1p1 rootwait ro rootfstype=ext4' => setenv bootcmd 'run load_ker; run load_dtb; booti 0x48080000 - 0x48000000' - => setenv load_dtb 'ext4load mmc 0:1 0x48000000 /boot/r8a7795-refhw.dtb' + => setenv load_dtb 'ext4load mmc 0:1 0x48000000 /boot/r8a7795-agl-refhw.dtb' => setenv load_ker 'ext4load mmc 0:1 0x48080000 /boot/Image' => saveenv @@ -56,16 +67,19 @@ expected as following (in case of booting from the Micro SD card in SD#0): ... bootargs=console=ttySC0,115200 root=/dev/mmcblk1p1 rootwait ro rootfstype=ext4 bootcmd=run load_ker; run load_dtb; booti 0x48080000 - 0x48000000 - load_dtb=ext4load mmc 0:1 0x48000000 /boot/r8a7795-refhw.dtb + load_dtb=ext4load mmc 0:1 0x48000000 /boot/r8a7795-agl-refhw.dtb load_ker=ext4load mmc 0:1 0x48080000 /boot/Image .. -III. Update firmware. -===================== -Please refer to meta-agl-refhw-gen3/docs/ReferenceHW_Rcar_gen3.md for detail. + +III. Updating firmware +====================== + +Please refer to meta-agl-refhw-gen3/docs/ReferenceHW_Rcar_gen3.md for details. + IV. Notes -========== +========= 1. SD#1 is not supported. -2. There are suspicious HDMI0/1 interrupts detected and disabled forcely by +2. There are suspicious HDMI0/1 interrupts detected and disabled forcibly by the kernel during boot. The reason is under investigation. diff --git a/meta-agl-refhw-gen3/conf/machine/agl-refhw-h3.conf b/meta-agl-refhw-gen3/conf/machine/agl-refhw-h3.conf new file mode 100644 index 0000000..f302d45 --- /dev/null +++ b/meta-agl-refhw-gen3/conf/machine/agl-refhw-h3.conf @@ -0,0 +1,16 @@ +# Using H3, needs to be defined before pulling in salvator-x as a base +SOC_FAMILY = "r8a7795" + +require conf/machine/salvator-x.conf + +# This is a bit of a hack, we add salvator-x to avoid having to +# bbappend various recipes to update COMPATIBLE_MACHINE. Ideally, +# we would want the ordering salvator-x:, but that is +# non-trivial to accomplish and not absolutely necessary for our +# expected use. +MACHINEOVERRIDES_append = ":salvator-x" + +# Reference hardware has USB3 +MACHINE_FEATURES_append = " usb3" + +KERNEL_DEVICETREE_append = " renesas/r8a7795-agl-refhw.dtb" diff --git a/meta-agl-refhw-gen3/docs/ReferenceHW_Rcar_gen3.md b/meta-agl-refhw-gen3/docs/ReferenceHW_Rcar_gen3.md index 9e826dc..92d3642 100644 --- a/meta-agl-refhw-gen3/docs/ReferenceHW_Rcar_gen3.md +++ b/meta-agl-refhw-gen3/docs/ReferenceHW_Rcar_gen3.md @@ -1,4 +1,4 @@ -# Reference Hardware Board +# Reference Hardware Board - [About](#about) - [Difference to Salvator-XS When Flashing Firmware](#difference-to-salvator-xs-when-flashing-firmware) @@ -42,6 +42,56 @@ using serial download. Output the following image. ./AArch64_output/AArch64_Flash_writer_SCIF_DUMMY_CERT_E6300400_salvator-x.mot +## How to build the Firmware + +1. In a temporary working directory, clone poky the poky repository and check out the dunfell branch: +``` + git clone git://git.yoctoproject.org/poky + cd poky + git checkout dunfell + .. +``` +2. Clone the Renesas BSP and it's dependent layers: +``` + git clone https://github.com/renesas-rcar/meta-renesas + cd meta-renesas + git checkout dunfell-dev-4.14 + cd .. + git clone git://git.openembedded.org/meta-openembedded + cd meta-openembedded + git checkout dunfell + cd .. +``` +3. Clone the reference hardware BSP layer: +``` + git clone https://gerrit.automotivelinux.org/gerrit/AGL/meta-agl-refhw +``` +4. Create a build environment: +``` + . ./poky/oe-init-build-env build +``` +5. Add the layers to `conf/bblayers.conf`, the `BBLAYERS` variable definition should look like: +``` + BBLAYERS ?= " \ + /home/user/workdir/poky/meta \ + /home/user/workdir/poky/meta-poky \ + /home/user/poky/meta-yocto-bsp \ + /home/user/workdir/meta-openembedded/meta-oe \ + /home/user/workdir/meta-openembedded/meta-python \ + /home/user/workdir/meta-renesas/meta-rcar-gen3 \ + /home/user/workdir/meta-agl-refhw/meta-agl-refhw-gen3 \ + " +``` +6. Add the machine setting to `conf/local.conf`, for example: +``` + echo MACHINE=agl-refhw-h3 >> conf/local.conf +``` +7. Build the firmware: +``` + bitbake arm-trusted-firmware u-boot +``` +8. Afterwards, the firmware files will be in the directory `tmp/deploy/images/agl-refhw-h3`. + ## How to Flash Firmware 1. Connect reference hardware board to the development PC by using USB serial @@ -129,10 +179,10 @@ Output the following image. Name | Load address | eMMC partition | Flash address | Description --------------------------------------|-----------------------|-----------------------|-----------------------|----------------------------- bootparam_sa0-4x2g.srec | H'E6320000 | 1 | H'000000 | Boot parameter - bl2-salvator-x-4x2g.srec | H'E6304000 | 1 | H'00001E | bl2 loader + bl2-agl-refhw-h3-4x2g.srec | H'E6304000 | 1 | H'00001E | bl2 loader cert_header_sa6-4x2g.srec | H'E6320000 | 1 | H'000180 | Certification - bl31-salvator-x-4x2g.srec | H'44000000 | 1 | H'000200 | bl3 loader - tee-salvator-x.srec | H'44100000 | 1 | H'001000 | OP-Tee + bl31-agl-refhw-h3-4x2g.srec | H'44000000 | 1 | H'000200 | bl3 loader + tee-agl-refhw-h3.srec | H'44100000 | 1 | H'001000 | OP-Tee u-boot-elf-salvator-xs-4x2g.srec | H'50000000 | 2 | H'000000 | U-boot You can find these firmwares in the AGL build directory $AGL_TOP/build/tmp/deploy/images/salvator-x diff --git a/meta-agl-refhw-gen3/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware_%.bbappend b/meta-agl-refhw-gen3/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware_%.bbappend index 1fccf80..951a34f 100644 --- a/meta-agl-refhw-gen3/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware_%.bbappend +++ b/meta-agl-refhw-gen3/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware_%.bbappend @@ -1,4 +1,7 @@ -#FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/:" +# It is believed the eMMC configuration below makes the result AGL +# reference hardware specific, mark it as such to try to prevent +# unintended usage on other boards. +COMPATIBLE_MACHINE = "agl-refhw-h3" # There are hardware issues in using hyperflash. arm-trusted-firmware, optee and # u-boot have to be stored into eMMC by using serial donwload. @@ -6,20 +9,20 @@ EMMC_BOOT_OPTION = "RCAR_SA6_TYPE=1" DDR_8G_OPTION= "RCAR_DRAM_LPDDR4_MEMCONF=1" -ATFW_OPT_append_refhw = " ${EMMC_BOOT_OPTION} " +ATFW_OPT_append_agl-refhw-h3 = " ${EMMC_BOOT_OPTION}" # In arm-trusted-firmware-control.inc, a "extra_ipl_opt" task is appended to # create firmware for 4x2g or 2x2g variation. it is supposed to use # EXTRA_ATFW_OPT to customize the compiler opton. # -#EXTRA_ATFW_OPT_append_refhw = " ${EMMC_BOOT_OPTION} ${DDR_8G_OPTION} " +#EXTRA_ATFW_OPT_append_agl-refhw-h3 = " ${EMMC_BOOT_OPTION} ${DDR_8G_OPTION}" # # Unfortunately in do_extra_ipl_opt() it use d.setVar() instead of d.appendVar() # to setup EXTRA_ATFW_OPT variable which makes it impossible to customize it properly # by others... Override it. # # -do_ipl_opt_compile_refhw () { +do_ipl_opt_compile_agl-refhw-h3 () { oe_runmake distclean oe_runmake bl2 bl31 dummytool PLAT=${PLATFORM} ${EXTRA_ATFW_OPT} ${ATFW_OPT_LOSSY} ${EMMC_BOOT_OPTION} ${DDR_8G_OPTION} } diff --git a/meta-agl-refhw-gen3/recipes-kernel/linux/files/0001-add-agl-refhw.patch b/meta-agl-refhw-gen3/recipes-kernel/linux/files/0001-add-agl-refhw.patch new file mode 100644 index 0000000..d6bf869 --- /dev/null +++ b/meta-agl-refhw-gen3/recipes-kernel/linux/files/0001-add-agl-refhw.patch @@ -0,0 +1,1418 @@ +Add AGL reference hardware support + +Upstream-Status: pending + +Signed-off-by: Scott Murray + +--- + arch/arm64/boot/dts/renesas/agl-refhw-common.dtsi | 912 ++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a7795-agl-refhw.dts | 378 +++++++++ + drivers/media/i2c/adv748x/adv748x-core.c | 48 +- + drivers/media/i2c/adv748x/adv748x.h | 12 + + 4 files changed, 1346 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/agl-refhw-common.dtsi b/arch/arm64/boot/dts/renesas/agl-refhw-common.dtsi +new file mode 100644 +index 000000000000..a35cd24b27b9 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/agl-refhw-common.dtsi +@@ -0,0 +1,912 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Device Tree Source for common parts of AGL Reference Hardware board variants ++ * ++ * Copyright (C) 2015-2017 Renesas Electronics Corp. ++ * Copyright (C) 2020 Konsulko Group ++ */ ++ ++/* ++ * This file is derived from salvator-common.dtsi ++ * ++ * It is currently unclear if the modifications made are such that they could ++ * be done on top of salvator-common.dtsi to allow removing the duplication. ++ * It is likely that the common pieces with salvator-common.dtsi would need to ++ * be factored out into a new common file, which is perhaps hard to justify. ++ */ ++ ++/* ++ * SSI-AK4613 ++ * ++ * This command is required when Playback/Capture ++ * ++ * amixer set "DVC Out" 100% ++ * amixer set "DVC In" 100% ++ * ++ * You can use Mute ++ * ++ * amixer set "DVC Out Mute" on ++ * amixer set "DVC In Mute" on ++ * ++ * You can use Volume Ramp ++ * ++ * amixer set "DVC Out Ramp Up Rate" "0.125 dB/64 steps" ++ * amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps" ++ * amixer set "DVC Out Ramp" on ++ * aplay xxx.wav & ++ * amixer set "DVC Out" 80% // Volume Down ++ * amixer set "DVC Out" 100% // Volume Up ++ */ ++ ++#include ++ ++/ { ++ aliases { ++ serial0 = &scif2; ++ serial1 = &scif1; ++ serial2 = &scif5; ++ serial3 = &hscif1; ++ serial4 = &hscif0; ++ serial5 = &hscif2; ++ ethernet0 = &avb; ++ }; ++ ++ chosen { ++ bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp"; ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ audio_clkout: audio-clkout { ++ /* ++ * This is same as <&rcar_sound 0> ++ * but needed to avoid cs2000/rcar_sound probe dead-lock ++ */ ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <12288000>; ++ }; ++ ++ avb-mch@ec5a0100 { ++ compatible = "renesas,avb-mch-gen3"; ++ reg = <0 0xec5a0100 0 0x100>; /* ADG_AVB */ ++ reg-name = "adg_avb"; ++ ++ clocks = <&cpg CPG_MOD 922>; ++ clock-names = "adg"; ++ resets = <&cpg 922>; ++ }; ++ ++ hdmi0-in { ++ compatible = "hdmi-connector"; ++ label = "HDMI0 IN"; ++ type = "a"; ++ ++ port { ++ hdmi_in_con: endpoint { ++ remote-endpoint = <&adv7481_hdmi>; ++ }; ++ }; ++ }; ++ ++ hdmi2-in { ++ compatible = "hdmi-connector"; ++ label = "HDMI2 IN"; ++ type = "a"; ++ ++ port { ++ hdmi_in_con2: endpoint { ++ remote-endpoint = <&adv7481_hdmi2>; ++ }; ++ }; ++ }; ++ ++ reg_1p8v: regulator0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ reg_3p3v: regulator1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ reg_12v: regulator2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-12V"; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ sound_card: sound { ++ compatible = "audio-graph-card"; ++ ++ label = "rcar-sound"; ++ ++ dais = <&rsnd_port0>; ++ }; ++ ++ vcc_sdhi0: regulator-vcc-sdhi0 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI0 Vcc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vccq_sdhi0: regulator-vccq-sdhi0 { ++ compatible = "regulator-gpio"; ++ ++ regulator-name = "SDHI0 VccQ"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; ++ gpios-states = <1>; ++ states = <3300000 1 ++ 1800000 0>; ++ }; ++ ++ vcc_sdhi3: regulator-vcc-sdhi3 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 Vcc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio3 15 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vccq_sdhi3: regulator-vccq-sdhi3 { ++ compatible = "regulator-gpio"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>; ++ gpios-states = <1>; ++ states = <3300000 1 ++ 1800000 0>; ++ }; ++ ++ hdmi0-out { ++ compatible = "hdmi-connector"; ++ label = "HDMI0 OUT"; ++ type = "a"; ++ ++ port { ++ hdmi0_con: endpoint { ++ }; ++ }; ++ }; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ label = "HDMI1 OUT"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ }; ++ }; ++ }; ++ ++ x12_clk: x12 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24576000>; ++ }; ++ ++ /* External DU dot clocks */ ++ x21_clk: x21-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <33000000>; ++ }; ++ ++ x22_clk: x22-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <33000000>; ++ }; ++ ++ x23_clk: x23-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <25000000>; ++ }; ++}; ++ ++&a57_0 { ++ cpu-supply = <&dvfs>; ++}; ++ ++&audio_clk_a { ++ clock-frequency = <22579200>; ++}; ++ ++&avb { ++ pinctrl-0 = <&avb_pins>; ++ pinctrl-names = "default"; ++ phy-handle = <&phy0>; ++ phy-mode = "rgmii-txid"; ++ status = "okay"; ++ ++ phy0: ethernet-phy@0 { ++ rxc-skew-ps = <1500>; ++ reg = <0>; ++ interrupt-parent = <&gpio2>; ++ interrupts = <11 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ reg = <0>; ++ ++ csi40_in: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&adv7481_txa>; ++ }; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ reg = <0>; ++ ++ csi41_in: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&adv7481_txa2>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ status = "okay"; ++ ++}; ++ ++&ehci0 { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&ehci1 { ++ status = "okay"; ++}; ++ ++&extalr_clk { ++ clock-frequency = <32768>; ++}; ++ ++&hscif0 { ++ pinctrl-0 = <&hscif0_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ status = "okay"; ++}; ++ ++&hscif1 { ++ pinctrl-0 = <&hscif1_pins>; ++ pinctrl-names = "default"; ++ ++ /* Please use exclusively to the scif1 node */ ++ status = "okay"; ++}; ++ ++&hscif2 { ++ pinctrl-0 = <&hscif2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hsusb { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&i2c2 { ++ pinctrl-0 = <&i2c2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ clock-frequency = <100000>; ++ ++ video-receiver@70 { ++ compatible = "adi,adv7481"; ++ reg = <0x70>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ interrupt-parent = <&gpio0>; ++ interrupt-names = "intrq1", "intrq3"; ++ interrupts = <4 IRQ_TYPE_LEVEL_LOW>, ++ <5 IRQ_TYPE_LEVEL_LOW>; ++ ++ port@8 { ++ reg = <8>; ++ ++ adv7481_hdmi: endpoint { ++ remote-endpoint = <&hdmi_in_con>; ++ }; ++ }; ++ ++ port@a { ++ reg = <10>; ++ ++ adv7481_txa: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&csi40_in>; ++ }; ++ }; ++ ++ }; ++ ++ video-receiver@71 { ++ compatible = "adi,adv7481"; ++ reg = <0x71>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ interrupt-parent = <&gpio6>; ++ interrupt-names = "intrq1", "intrq3"; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>, ++ <1 IRQ_TYPE_LEVEL_LOW>; ++ ++ port@8 { ++ reg = <8>; ++ ++ adv7481_hdmi2: endpoint { ++ remote-endpoint = <&hdmi_in_con2>; ++ }; ++ }; ++ ++ port@a { ++ reg = <10>; ++ ++ adv7481_txa2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&csi41_in>; ++ }; ++ }; ++ }; ++ ++ cs2000: clk_multiplier@4f { ++ #clock-cells = <0>; ++ compatible = "cirrus,cs2000-cp"; ++ reg = <0x4f>; ++ clocks = <&audio_clkout>, <&x12_clk>; ++ clock-names = "clk_in", "ref_clk"; ++ ++ assigned-clocks = <&cs2000>; ++ assigned-clock-rates = <24576000>; /* 1/1 divide */ ++ }; ++}; ++ ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ clock-frequency = <100000>; ++ ++ asm330lhh@6a { ++ compatible = "st,asm330lhh"; ++ reg = <0x6a>; ++ ++ interrupt-names = "int1", "int2"; ++ interrupts = <&gpio6 23 IRQ_TYPE_EDGE_RISING>, ++ <&gpio2 6 IRQ_TYPE_EDGE_RISING>; ++ }; ++}; ++ ++&i2c4 { ++ status = "okay"; ++ ++ versaclock5: clock-generator@68 { ++ compatible = "idt,9fgv0841"; ++ reg = <0x68>; ++ #clock-cells = <1>; ++ clocks = <&x23_clk>; ++ clock-names = "xin"; ++ }; ++}; ++ ++&i2c5 { ++ pinctrl-0 = <&i2c5_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ clock-frequency = <100000>; ++ ++ ak4613: codec@10 { ++ compatible = "asahi-kasei,ak4613"; ++ #sound-dai-cells = <0>; ++ reg = <0x10>; ++ clocks = <&rcar_sound 3>; ++ ++ asahi-kasei,in1-single-end; ++ asahi-kasei,in2-single-end; ++ asahi-kasei,out1-single-end; ++ asahi-kasei,out2-single-end; ++ asahi-kasei,out3-single-end; ++ asahi-kasei,out4-single-end; ++ asahi-kasei,out5-single-end; ++ asahi-kasei,out6-single-end; ++ ++ port { ++ ak4613_endpoint: endpoint { ++ remote-endpoint = <&rsnd_endpoint0>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c_dvfs { ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ pmic: pmic@30 { ++ pinctrl-0 = <&irq0_pins>; ++ pinctrl-names = "default"; ++ ++ compatible = "rohm,bd9571mwv"; ++ reg = <0x30>; ++ interrupt-parent = <&intc_ex>; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ rohm,ddr-backup-power = <0xf>; ++ rohm,rstbmode-level; ++ ++ regulators { ++ dvfs: dvfs { ++ regulator-name = "dvfs"; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1030000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ eeprom@50 { ++ compatible = "rohm,br24t01", "atmel,24c01"; ++ reg = <0x50>; ++ pagesize = <8>; ++ }; ++}; ++ ++&ohci0 { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&ohci1 { ++ status = "okay"; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&pfc { ++ pinctrl-0 = <&scif_clk_pins>; ++ pinctrl-names = "default"; ++ ++ avb_pins: avb { ++ mux { ++ groups = "avb_link", "avb_mdio", "avb_mii"; ++ function = "avb"; ++ }; ++ ++ pins_mdio { ++ groups = "avb_mdio"; ++ drive-strength = <24>; ++ }; ++ ++ pins_mii_tx { ++ pins = "PIN_AVB_TX_CTL", "PIN_AVB_TXC", "PIN_AVB_TD0", ++ "PIN_AVB_TD1", "PIN_AVB_TD2", "PIN_AVB_TD3"; ++ drive-strength = <12>; ++ }; ++ }; ++ ++ hscif0_pins: hscif0 { ++ groups = "hscif0_data", "hscif0_ctrl"; ++ function = "hscif0"; ++ }; ++ ++ hscif1_pins: hscif1 { ++ groups = "hscif1_data_a"; ++ function = "hscif1"; ++ }; ++ ++ hscif2_pins: hscif2 { ++ groups = "hscif2_data_c"; ++ function = "hscif2"; ++ }; ++ ++ i2c2_pins: i2c2 { ++ groups = "i2c2_a"; ++ function = "i2c2"; ++ }; ++ ++ i2c3_pins: i2c3 { ++ groups = "i2c3"; ++ function = "i2c3"; ++ }; ++ ++ i2c5_pins: i2c5 { ++ groups = "i2c5"; ++ function = "i2c5"; ++ }; ++ ++ irq0_pins: irq0 { ++ groups = "intc_ex_irq0"; ++ function = "intc_ex"; ++ }; ++ ++ scif1_pins: scif1 { ++ groups = "scif1_data_b"; ++ function = "scif1"; ++ }; ++ ++ scif2_pins: scif2 { ++ groups = "scif2_data_a"; ++ function = "scif2"; ++ }; ++ ++ scif5_pins: scif5 { ++ groups = "scif5_data_a"; ++ function = "scif5"; ++ }; ++ ++ scif_clk_pins: scif_clk { ++ groups = "scif_clk_a"; ++ function = "scif_clk"; ++ }; ++ ++ sdhi0_pins: sd0 { ++ groups = "sdhi0_data4", "sdhi0_ctrl"; ++ function = "sdhi0"; ++ power-source = <3300>; ++ }; ++ ++ sdhi0_pins_uhs: sd0_uhs { ++ groups = "sdhi0_data4", "sdhi0_ctrl"; ++ function = "sdhi0"; ++ power-source = <1800>; ++ }; ++ ++ sdhi2_pins: sd2 { ++ groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds"; ++ function = "sdhi2"; ++ power-source = <3300>; ++ }; ++ ++ sdhi2_pins_uhs: sd2_uhs { ++ groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds"; ++ function = "sdhi2"; ++ power-source = <1800>; ++ }; ++ ++ sdhi3_pins: sd3 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <3300>; ++ }; ++ ++ sdhi3_pins_uhs: sd3_uhs { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <1800>; ++ }; ++ ++ sound_pins: sound { ++ groups = "ssi349_ctrl", "ssi3_data", "ssi4_data"; ++ function = "ssi"; ++ }; ++ ++ sound_clk_pins: sound_clk { ++ groups = "audio_clk_a_a", "audio_clk_b_a", ++ "audio_clkout_a", "audio_clkout3_b"; ++ function = "audio_clk"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++ ++ usb1_pins: usb1 { ++ groups = "usb1"; ++ function = "usb1"; ++ }; ++ ++ usb30_pins: usb30 { ++ groups = "usb30", "usb30_ovc"; ++ function = "usb30"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++}; ++ ++&rcar_sound { ++ pinctrl-0 = <&sound_pins &sound_clk_pins>; ++ pinctrl-names = "default"; ++ ++ /* Single DAI */ ++ #sound-dai-cells = <0>; ++ ++ /* audio_clkout0/1/2/3 */ ++ #clock-cells = <1>; ++ clock-frequency = <12288000 11289600>; ++ ++ status = "okay"; ++ ++ /* update to */ ++ clocks = <&cpg CPG_MOD 1005>, ++ <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>, ++ <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>, ++ <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>, ++ <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>, ++ <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>, ++ <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>, ++ <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>, ++ <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>, ++ <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>, ++ <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>, ++ <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, ++ <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, ++ <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>, ++ <&audio_clk_a>, <&cs2000>, ++ <&audio_clk_c>, ++ <&cpg CPG_CORE CPG_AUDIO_CLK_I>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ rsnd_port0: port@0 { ++ reg = <0>; ++ rsnd_endpoint0: endpoint { ++ remote-endpoint = <&ak4613_endpoint>; ++ ++ dai-format = "left_j"; ++ bitclock-master = <&rsnd_endpoint0>; ++ frame-master = <&rsnd_endpoint0>; ++ ++ playback = <&ssi3>; //ssi0 -> ssi3 ++ capture = <&ssi4>; //ssi1 -> ssi4 ++ }; ++ }; ++ }; ++}; ++ ++&rwdt { ++ timeout-sec = <60>; ++ status = "okay"; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ ++ uart-has-rtscts; ++ /* Please use exclusively to the hscif1 node */ ++ status = "okay"; ++}; ++ ++&scif2 { ++ pinctrl-0 = <&scif2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif5 { ++ pinctrl-0 = <&scif5_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif_clk { ++ clock-frequency = <14745600>; ++}; ++ ++&sdhi0 { ++ pinctrl-0 = <&sdhi0_pins>; ++ pinctrl-1 = <&sdhi0_pins_uhs>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ vmmc-supply = <&vcc_sdhi0>; ++ vqmmc-supply = <&vccq_sdhi0>; ++ cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; ++ wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; ++ bus-width = <4>; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ status = "okay"; ++}; ++ ++&sdhi2 { ++ /* used for on-board 8bit eMMC */ ++ pinctrl-0 = <&sdhi2_pins>; ++ pinctrl-1 = <&sdhi2_pins_uhs>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ iommus = <&ipmmu_ds1 34>; ++ ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_1p8v>; ++ bus-width = <8>; ++ mmc-hs200-1_8v; ++ mmc-hs400-1_8v; ++ no-sd; ++ no-sdio; ++ non-removable; ++ fixed-emmc-driver-type = <1>; ++ status = "okay"; ++}; ++ ++&sdhi3 { ++ pinctrl-0 = <&sdhi3_pins>; ++ pinctrl-1 = <&sdhi3_pins_uhs>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ vmmc-supply = <&vcc_sdhi3>; ++ vqmmc-supply = <&vccq_sdhi3>; ++ cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; ++ wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>; ++ bus-width = <4>; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ status = "okay"; ++}; ++ ++&ssi4 { ++ shared-pin; ++}; ++ ++&usb_extal_clk { ++ clock-frequency = <50000000>; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&usb2_phy1 { ++ pinctrl-0 = <&usb1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&usb3_peri0 { ++ phys = <&usb3_phy0>; ++ phy-names = "usb"; ++ ++ status = "okay"; ++}; ++ ++&usb3_phy0 { ++ status = "okay"; ++}; ++ ++&usb3s0_clk { ++ clock-frequency = <100000000>; ++}; ++ ++&vin0 { ++ status = "okay"; ++}; ++ ++&vin1 { ++ status = "okay"; ++}; ++ ++&vin2 { ++ status = "okay"; ++}; ++ ++&vin3 { ++ status = "okay"; ++}; ++ ++&vin4 { ++ status = "okay"; ++}; ++ ++&vin5 { ++ status = "okay"; ++}; ++ ++&vin6 { ++ status = "okay"; ++}; ++ ++&vin7 { ++ status = "okay"; ++}; ++ ++&xhci0 { ++ pinctrl-0 = <&usb30_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-agl-refhw.dts b/arch/arm64/boot/dts/renesas/r8a7795-agl-refhw.dts +new file mode 100644 +index 000000000000..0a63d2e7a64b +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-agl-refhw.dts +@@ -0,0 +1,378 @@ ++/* ++ * Device Tree Source for the AGL reference hardware board with R-Car H3 ES3.0 ++ * ++ * Copyright (C) 2019 Panasonic Corp. ++ * Copyright (C) 2020 Konsulko Group ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/* ++ * This file is for the most part derived from: ++ * ++ * - r8a7795-salvator-xs-4x2g.dts ++ * - r8a7795-salvator-xs.dts ++ * - salvator-xs.dtsi ++ * ++ * With agl-refhw-common.dtsi replacing (and derived from) salvator-common.dtsi. ++ */ ++ ++/dts-v1/; ++#include "r8a7795.dtsi" ++#include "agl-refhw-common.dtsi" ++ ++/ { ++ model = "AGL Reference Hardware based on r8a7795 ES3.0+ with 8GiB (4 x 2 GiB)"; ++ compatible = "agl,refhw-h3", "renesas,r8a7795"; ++ ++ memory@48000000 { ++ device_type = "memory"; ++ /* first 128MB is reserved for secure area. */ ++ reg = <0x0 0x48000000 0x0 0x78000000>; ++ }; ++ ++ memory@500000000 { ++ device_type = "memory"; ++ reg = <0x5 0x00000000 0x0 0x80000000>; ++ }; ++ ++ memory@600000000 { ++ device_type = "memory"; ++ reg = <0x6 0x00000000 0x0 0x80000000>; ++ }; ++ ++ memory@700000000 { ++ device_type = "memory"; ++ reg = <0x7 0x00000000 0x0 0x80000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress@54000000 { ++ no-map; ++ reg = <0x00000000 0x54000000 0x0 0x03000000>; ++ }; ++ ++ /* For Audio DSP */ ++ adsp_reserved: linux,adsp@57000000 { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x57000000 0x0 0x01000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma@58000000 { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x58000000 0x0 0x18000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ mmp_reserved: linux,multimedia@70000000 { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x70000000 0x0 0x10000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&mmp_reserved>, <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ ++ vga { ++ port { ++ vga_in: endpoint { ++ /delete-property/remote-endpoint; ++ }; ++ }; ++ }; ++ ++ vga-encoder { ++ ports { ++ port@0 { ++ adv7123_in: endpoint { ++ /delete-property/remote-endpoint; ++ }; ++ }; ++ ++ port@1 { ++ adv7123_out: endpoint { ++ /delete-property/remote-endpoint; ++ }; ++ }; ++ }; ++ }; ++ ++}; ++ ++&adsp { ++ status = "okay"; ++ memory-region = <&adsp_reserved>; ++}; ++ ++&du { ++ clocks = <&cpg CPG_MOD 724>, ++ <&cpg CPG_MOD 723>, ++ <&cpg CPG_MOD 722>, ++ <&cpg CPG_MOD 721>, ++ <&versaclock6 1>, ++ <&x21_clk>, ++ <&x22_clk>, ++ <&versaclock6 2>; ++ clock-names = "du.0", "du.1", "du.2", "du.3", ++ "dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3"; ++}; ++ ++&ehci2 { ++ status = "okay"; ++}; ++ ++&ehci3 { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&hsusb3 { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&sound_card { ++ dais = <&rsnd_port0 /* ak4613 */ ++ &rsnd_port1 /* HDMI0 */ ++ &rsnd_port2>; /* HDMI1 */ ++}; ++ ++&hdmi0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi0_out: endpoint { ++ remote-endpoint = <&hdmi0_con>; ++ }; ++ }; ++ port@2 { ++ reg = <2>; ++ dw_hdmi0_snd_in: endpoint { ++ remote-endpoint = <&rsnd_endpoint1>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi0_con { ++ remote-endpoint = <&rcar_dw_hdmi0_out>; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ port@2 { ++ reg = <2>; ++ dw_hdmi1_snd_in: endpoint { ++ remote-endpoint = <&rsnd_endpoint2>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1_con { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++}; ++ ++&ohci2 { ++ status = "okay"; ++}; ++ ++&ohci3 { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&rcar_sound { ++ ports { ++ /* rsnd_port0 is on salvator-common */ ++ rsnd_port1: port@1 { ++ reg = <1>; ++ rsnd_endpoint1: endpoint { ++ remote-endpoint = <&dw_hdmi0_snd_in>; ++ ++ dai-format = "i2s"; ++ bitclock-master = <&rsnd_endpoint1>; ++ frame-master = <&rsnd_endpoint1>; ++ ++ playback = <&ssi2>; ++ }; ++ }; ++ rsnd_port2: port@2 { ++ reg = <2>; ++ rsnd_endpoint2: endpoint { ++ remote-endpoint = <&dw_hdmi1_snd_in>; ++ ++ dai-format = "i2s"; ++ bitclock-master = <&rsnd_endpoint2>; ++ frame-master = <&rsnd_endpoint2>; ++ ++ playback = <&ssi3>; ++ }; ++ }; ++ }; ++}; ++ ++&pfc { ++ usb2_pins: usb2 { ++ groups = "usb2", "usb2_ovc"; ++ function = "usb2"; ++ }; ++ ++ /* ++ * - On Salvator-X[S], GP6_3[01] are connected to ADV7482 as irq pins ++ * (when SW31 is the default setting on Salvator-XS). ++ * - If SW31 is the default setting, you cannot use USB2.0 ch3 on ++ * r8a7795 with Salvator-XS. ++ * Hence the SW31 setting must be changed like 2) below. ++ * 1) Default setting of SW31: ON-ON-OFF-OFF-OFF-OFF: ++ * - Connect GP6_3[01] to ADV7842. ++ * 2) Changed setting of SW31: OFF-OFF-ON-ON-ON-ON: ++ * - Connect GP6_3[01] to BD082065 (USB2.0 ch3's host power). ++ * - Connect GP6_{04,21} to ADV7842. ++ */ ++ usb2_ch3_pins: usb2_ch3 { ++ groups = "usb2_ch3"; ++ function = "usb2_ch3"; ++ }; ++}; ++ ++&usb2_phy2 { ++ pinctrl-0 = <&usb2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&usb2_phy3 { ++ pinctrl-0 = <&usb2_ch3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&vspbc { ++ status = "okay"; ++}; ++ ++&vspbd { ++ status = "okay"; ++}; ++ ++&vspi0 { ++ status = "okay"; ++}; ++ ++&vspi1 { ++ status = "okay"; ++}; ++ ++/* End r8a7795-salvator-xs.dts content */ ++ ++ ++/* Start r8a7795-salvator-xs-4x2g.dts content */ ++ ++&pciec0 { ++ /* Map all possible DDR as inbound ranges */ ++ dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; ++}; ++ ++&pciec1 { ++ /* Map all possible DDR as inbound ranges */ ++ dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; ++}; ++ ++/* End r8a7795-salvator-xs-4x2g.dts content */ ++ ++ ++/* Start salvator-xs.dts content */ ++ ++&extal_clk { ++ clock-frequency = <16640000>; ++}; ++ ++&i2c4 { ++ clock-frequency = <400000>; ++ ++ versaclock6: clock-generator@6a { ++ compatible = "idt,5p49v6901"; ++ reg = <0x6a>; ++ #clock-cells = <1>; ++ clocks = <&x23_clk>; ++ clock-names = "xin"; ++ }; ++}; ++ ++/* End salvator-xs.dts content */ ++ ++ ++/* Start reference hardware specific tweaks */ ++ ++&du { ++ ports { ++ port@0 { ++ endpoint { ++ /delete-property/remote-endpoint; ++ }; ++ }; ++ ++ port@3 { ++ endpoint { ++ /delete-property/remote-endpoint; ++ }; ++ }; ++ }; ++}; ++ ++&lvds0 { ++ status = "disabled"; ++}; ++ ++&pwm1 { ++ status = "disabled"; ++}; ++ ++&scif_clk { ++ clock-frequency = <0>; ++}; ++ ++&sdhi0 { ++ /delete-property/ wp-gpios; ++ non-removable; ++}; ++ ++&sdhi3 { ++ /delete-property/ wp-gpios; ++ non-removable; ++}; +diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c +index da8f0621a10b..c2b37f70f711 100644 +--- a/drivers/media/i2c/adv748x/adv748x-core.c ++++ b/drivers/media/i2c/adv748x/adv748x-core.c +@@ -165,6 +165,21 @@ static int adv748x_i2c_addresses[ADV748X_PAGE_MAX] = { + ADV748X_I2C_TXA, + }; + ++/* Default addresses for the I2C pages 0x71*/ ++static int adv748x_i2c_addresses2[ADV748X_PAGE_MAX] = { ++ ADV748X_I2C_IO2, ++ ADV748X_I2C_DPLL2, ++ ADV748X_I2C_CP2, ++ ADV748X_I2C_HDMI2, ++ ADV748X_I2C_EDID2, ++ ADV748X_I2C_REPEATER2, ++ ADV748X_I2C_INFOFRAME2, ++ ADV748X_I2C_CEC2, ++ ADV748X_I2C_SDP2, ++ ADV748X_I2C_TXB2, ++ ADV748X_I2C_TXA2, ++}; ++ + static int adv748x_read_check(struct adv748x_state *state, + int client_page, u8 reg) + { +@@ -238,9 +253,16 @@ static int adv748x_initialise_clients(struct adv748x_state *state) + int ret; + + for (i = ADV748X_PAGE_DPLL; i < ADV748X_PAGE_MAX; ++i) { +- state->i2c_clients[i] = +- adv748x_dummy_client(state, adv748x_i2c_addresses[i], +- ADV748X_IO_SLAVE_ADDR_BASE + i); ++ if((state->client->addr << 1) == 0xe0) { ++ state->i2c_clients[i] = ++ adv748x_dummy_client(state, adv748x_i2c_addresses[i], ++ ADV748X_IO_SLAVE_ADDR_BASE + i); ++ } else { ++ state->i2c_clients[i] = ++ adv748x_dummy_client(state, adv748x_i2c_addresses2[i], ++ ADV748X_IO_SLAVE_ADDR_BASE + i); ++ } ++ + if (state->i2c_clients[i] == NULL) { + adv_err(state, "failed to create i2c client %u\n", i); + return -ENOMEM; +@@ -508,6 +530,20 @@ static const struct adv748x_reg_value adv748x_set_slave_address[] = { + {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ + }; + ++static const struct adv748x_reg_value adv748x_set_slave_address2[] = { ++ {ADV748X_PAGE_IO, 0xf3, ADV748X_I2C_DPLL2 << 1}, ++ {ADV748X_PAGE_IO, 0xf4, ADV748X_I2C_CP2 << 1}, ++ {ADV748X_PAGE_IO, 0xf5, ADV748X_I2C_HDMI2 << 1}, ++ {ADV748X_PAGE_IO, 0xf6, ADV748X_I2C_EDID2 << 1}, ++ {ADV748X_PAGE_IO, 0xf7, ADV748X_I2C_REPEATER2 << 1}, ++ {ADV748X_PAGE_IO, 0xf8, ADV748X_I2C_INFOFRAME2 << 1}, ++ {ADV748X_PAGE_IO, 0xfa, ADV748X_I2C_CEC2 << 1}, ++ {ADV748X_PAGE_IO, 0xfb, ADV748X_I2C_SDP2 << 1}, ++ {ADV748X_PAGE_IO, 0xfc, ADV748X_I2C_TXB2 << 1}, ++ {ADV748X_PAGE_IO, 0xfd, ADV748X_I2C_TXA2 << 1}, ++ {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ ++}; ++ + /* Supported Formats For Script Below */ + /* - 01-29 HDMI to MIPI TxA CSI 4-Lane - RGB888: */ + static const struct adv748x_reg_value adv748x_init_txa_4lane[] = { +@@ -683,7 +719,11 @@ static int adv748x_reset(struct adv748x_state *state) + if (ret < 0) + return ret; + +- ret = adv748x_write_regs(state, adv748x_set_slave_address); ++ if((state->client->addr << 1) == 0xe0) { ++ ret = adv748x_write_regs(state, adv748x_set_slave_address); //i2c address 0x70 ++ } else { ++ ret = adv748x_write_regs(state, adv748x_set_slave_address2); //i2c address 0x71 ++ } + if (ret < 0) + return ret; + +diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h +index fb30bfade946..ac50a9e41b08 100644 +--- a/drivers/media/i2c/adv748x/adv748x.h ++++ b/drivers/media/i2c/adv748x/adv748x.h +@@ -40,6 +40,18 @@ + #define ADV748X_I2C_TXB 0x48 /* CSI-TXB Map */ + #define ADV748X_I2C_TXA 0x4a /* CSI-TXA Map */ + ++#define ADV748X_I2C_IO2 0x71 /* IO Map */ ++#define ADV748X_I2C_DPLL2 0x27 /* DPLL Map */ ++#define ADV748X_I2C_CP2 0x23 /* CP Map */ ++#define ADV748X_I2C_HDMI2 0x35 /* HDMI Map */ ++#define ADV748X_I2C_EDID2 0x37 /* EDID Map */ ++#define ADV748X_I2C_REPEATER2 0x33 /* HDMI RX Repeater Map */ ++#define ADV748X_I2C_INFOFRAME2 0x30 /* HDMI RX InfoFrame Map */ ++#define ADV748X_I2C_CEC2 0x42 /* CEC Map */ ++#define ADV748X_I2C_SDP2 0x78 /* SDP Map */ ++#define ADV748X_I2C_TXB2 0x49 /* CSI-TXB Map */ ++#define ADV748X_I2C_TXA2 0x4b /* CSI-TXA Map */ ++ + enum adv748x_page { + ADV748X_PAGE_IO, + ADV748X_PAGE_DPLL, diff --git a/meta-agl-refhw-gen3/recipes-kernel/linux/files/0001-add-st_asm330lhh-driver.patch b/meta-agl-refhw-gen3/recipes-kernel/linux/files/0001-add-st_asm330lhh-driver.patch deleted file mode 100644 index c779b39..0000000 --- a/meta-agl-refhw-gen3/recipes-kernel/linux/files/0001-add-st_asm330lhh-driver.patch +++ /dev/null @@ -1,2112 +0,0 @@ ---- - drivers/iio/imu/st_asm330lhh/Kconfig | 22 + - drivers/iio/imu/st_asm330lhh/Makefile | 5 + - drivers/iio/imu/st_asm330lhh/README.md | 201 +++++ - drivers/iio/imu/st_asm330lhh/st_asm330lhh.h | 247 ++++++ - drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c | 540 ++++++++++++++ - drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c | 824 +++++++++++++++++++++ - drivers/iio/imu/st_asm330lhh/st_asm330lhh_i2c.c | 94 +++ - drivers/iio/imu/st_asm330lhh/st_asm330lhh_spi.c | 109 +++ - 8 files changed, 2042 insertions(+) - create mode 100644 drivers/iio/imu/st_asm330lhh/Kconfig - create mode 100644 drivers/iio/imu/st_asm330lhh/Makefile - create mode 100644 drivers/iio/imu/st_asm330lhh/README.md - create mode 100644 drivers/iio/imu/st_asm330lhh/st_asm330lhh.h - create mode 100644 drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c - create mode 100644 drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c - create mode 100644 drivers/iio/imu/st_asm330lhh/st_asm330lhh_i2c.c - create mode 100644 drivers/iio/imu/st_asm330lhh/st_asm330lhh_spi.c - -diff --git a/drivers/iio/imu/st_asm330lhh/Kconfig b/drivers/iio/imu/st_asm330lhh/Kconfig -new file mode 100644 -index 0000000..0e8920e ---- /dev/null -+++ b/drivers/iio/imu/st_asm330lhh/Kconfig -@@ -0,0 +1,22 @@ -+config IIO_ST_ASM330LHH -+ tristate "STMicroelectronics ASM330LHH sensor" -+ depends on (I2C || SPI) -+ select IIO_BUFFER -+ select IIO_KFIFO_BUF -+ select IIO_ST_ASM330LHH_I2C if (I2C) -+ select IIO_ST_ASM330LHH_SPI if (SPI_MASTER) -+ help -+ Say yes here to build support for STMicroelectronics ASM330LHH imu -+ sensor. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called st_asm330lhh. -+ -+config IIO_ST_ASM330LHH_I2C -+ tristate -+ depends on IIO_ST_ASM330LHH -+ -+config IIO_ST_ASM330LHH_SPI -+ tristate -+ depends on IIO_ST_ASM330LHH -+ -diff --git a/drivers/iio/imu/st_asm330lhh/Makefile b/drivers/iio/imu/st_asm330lhh/Makefile -new file mode 100644 -index 0000000..7af80de ---- /dev/null -+++ b/drivers/iio/imu/st_asm330lhh/Makefile -@@ -0,0 +1,5 @@ -+st_asm330lhh-y := st_asm330lhh_core.o st_asm330lhh_buffer.o -+ -+obj-$(CONFIG_IIO_ST_ASM330LHH) += st_asm330lhh.o -+obj-$(CONFIG_IIO_ST_ASM330LHH_I2C) += st_asm330lhh_i2c.o -+obj-$(CONFIG_IIO_ST_ASM330LHH_SPI) += st_asm330lhh_spi.o -diff --git a/drivers/iio/imu/st_asm330lhh/README.md b/drivers/iio/imu/st_asm330lhh/README.md -new file mode 100644 -index 0000000..d471530 ---- /dev/null -+++ b/drivers/iio/imu/st_asm330lhh/README.md -@@ -0,0 +1,201 @@ -+Index -+======= -+ * Introduction -+ * Driver Integration details -+ * Android SensorHAL integration -+ * Linux SensorHAL integration -+ * More information -+ * Copyright -+ -+ -+Introduction -+============== -+This repository contains asm330lhh IMU STMicroelectronics MEMS sensor linux driver support for kernel version 4.14. -+ -+Data collected by asm330lhh STM sensor are pushed to userland through the kernel buffers of Linux IIO framework. User space applications can get sensor events by reading the related IIO devices created in the /dev directory (*/dev/iio{x}*). Please see [IIO][1] for more information. -+ -+Asm330lhh IMU STM MEMS sensor support *I2C/SPI* digital interface. Please refer to [I2C][2] and [SPI][3] for detailed documentation. -+ -+The STM Hardware Abstraction Layer (*HAL*) defines a standard interface for STM sensors allowing Android to be agnostic about low level driver implementation. The HAL library is packaged into modules (.so) file and loaded by the Android or Linux system at the appropriate time. For more information see [AOSP HAL Interface](https://source.android.com/devices/sensors/hal-interface.html) -+ -+STM Sensor HAL is leaning on [Linux IIO framework](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/iio) to gather data from sensor device drivers and to forward samples to the Android Framework -+ -+Driver Integration details -+===================== -+ -+In order to explain how to integrate Asm330lhh IMU STM sensor into the kernel, please consider the following example -+ -+### Source code integration -+ -+> * Copy driver source code into your linux kernel target directory (e.g. *drivers/iio/imu*) -+> * Edit related Kconfig (e.g. *drivers/iio/imu/Kconfig*) adding *ASM330LHH* support: -+ -+> source "drivers/iio/imu/st_asm330lhh/Kconfig" -+ -+> * Edit related Makefile (e.g. *drivers/iio/imu/Makefile*) adding the following line: -+ -+> obj-y += st_asm330lhh/ -+ -+### Device Tree configuration -+ -+> To enable driver probing, add the asm330lhh node to the platform device tree as described below. -+ -+> **Required properties:** -+ -+> *- compatible*: "st,asm330lhh" -+ -+> *- reg*: the I2C address or SPI chip select the device will respond to -+ -+> *- interrupt-parent*: phandle to the parent interrupt controller as documented in [interrupts][4] -+ -+> *- interrupts*: interrupt mapping for IRQ as documented in [interrupts][4] -+> -+>**Recommended properties for SPI bus usage:** -+ -+> *- spi-max-frequency*: maximum SPI bus frequency as documented in [SPI][3] -+> -+> **Optional properties:** -+ -+> *- st,drdy-int-pin*: MEMS sensor interrupt line to use (default 1) -+ -+> I2C example (based on Raspberry PI 3): -+ -+> &i2c0 { -+> status = "ok"; -+> #address-cells = <0x1>; -+> #size-cells = <0x0>; -+> asm330lhh@6b { -+> compatible = "st,asm330lhh"; -+> reg = <0x6b>; -+> interrupt-parent = <&gpio>; -+> interrupts = <26 IRQ_TYPE_EDGE_RISING>; -+> }; -+ -+> SPI example (based on Raspberry PI 3): -+ -+> &spi0 { -+> status = "ok"; -+> #address-cells = <0x1>; -+> #size-cells = <0x0>; -+> asm330lhh@0 { -+> spi-max-frequency = <500000>; -+> compatible = "st,asm330lhh"; -+> reg = <0>; -+> interrupt-parent = <&gpio>; -+> interrupts = <26 IRQ_TYPE_EDGE_RISING>; -+> }; -+ -+### Kernel configuration -+ -+Configure kernel with *make menuconfig* (alternatively use *make xconfig* or *make qconfig*) -+ -+> Device Drivers ---> -+> Industrial I/O support ---> -+> Inertial measurement units ---> -+> STMicroelectronics ASM330LHH sensor ---> -+ -+ -+Android SensorHAL integration -+============== -+ -+STM Sensor HAL is written in *C++* language using object-oriented design. For each hw sensor there is a custom class file (*Accelerometer.cpp*, *Gyroscope.cpp*) which extends the common base class (*SensorBase.cpp*). -+ -+Copy the HAL source code into */hardware/STMicroelectronics/SensorHAL_IIO* folder. During building process Android will include automatically the SensorHAL Android.mk. -+In */device///device.mk* add package build information: -+ -+ PRODUCT_PACKAGES += sensors.{TARGET_BOARD_PLATFORM} -+ -+ Note: device.mk can not read $(TARGET_BOARD_PLATFORM) variable, read and replace the value from your BoardConfig.mk (e.g. PRODUCT_PACKAGES += sensors.msm8974 for Nexus 5) -+ -+To compile the SensorHAL_IIO just build AOSP source code from *$TOP* folder -+ -+ $ cd -+ $ source build/envsetup.sh -+ $ lunch ++ $ make V=99 ++ ++The compiled library will be placed in */out/target/product//system/vendor/lib/hw/sensor.{TARGET_BOARD_PLATFORM}.so* ++ ++To configure sensor the Sensor HAL IIO use mm utility from HAL root folder ++ ++ since Android 7 ++ $mm sensors-defconfig (default configuration) ++ $mm sensors-menuconfig ++ ++ after Android 7 ++ make -f Makefile_config sensors-defconfig (default configuration) ++ make -f Makefile_config sensors-menuconfig ++ ++Linux SensorHAL integration ++============== ++ ++Linux Sensor HAL share the same source code of Android Sensor HAL. Before compiling the Linux Sensor HAL IIO ++you need to follow the same procedure listed in previous chapter "Android SensorHAL integration" ++To cross compile Linux Sensor HAL must export the following shell variables ++ ++> export AOSP_DIR= ++> export ARCH= ++> export CROSS_COMPILE= ++ ++then in */hardware/STMicroelectronics/SensorHAL_IIO* folder type ++> make ++ ++it will produce a SensorHAL.so file containing the library. ++In relative pat Documentation/LinuxHal/ there are some examples explaining how to use Linux Sensor HAL ++ ++Copyright ++======== ++Copyright (C) 2017 STMicroelectronics ++ ++Licensed under the Apache License, Version 2.0 (the "License"); ++you may not use this file except in compliance with the License. ++You may obtain a copy of the License at ++ ++http://www.apache.org/licenses/LICENSE-2.0 ++ ++Unless required by applicable law or agreed to in writing, software ++distributed under the License is distributed on an "AS IS" BASIS, ++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++See the License for the specific language governing permissions and ++limitations under the License. ++ ++ ++More Information ++================= ++[http://st.com](http://st.com) ++ ++[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/iio](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/input) ++ ++[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/i2c](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/i2c) ++ ++[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/spi](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/spi) ++ ++[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bings/interrupt-controller/interrupts.txt](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt) ++ ++ ++Copyright Driver ++=========== ++Copyright (C) 2017 STMicroelectronics ++ ++This software is distributed under the GNU General Public License - see the accompanying COPYING file for more details. ++ ++[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/iio/iio_configfs.txt "IIO" ++[2]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/i2c "I2C" ++[3]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/spi "SPI" ++[4]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt "interrupts" ++ ++Copyright SensorHAL ++======== ++Copyright (C) 2017 STMicroelectronics ++ ++Licensed under the Apache License, Version 2.0 (the "License"); ++you may not use this file except in compliance with the License. ++You may obtain a copy of the License at ++ ++http://www.apache.org/licenses/LICENSE-2.0 ++ ++Unless required by applicable law or agreed to in writing, software ++distributed under the License is distributed on an "AS IS" BASIS, ++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++See the License for the specific language governing permissions and ++limitations under the License. +diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h +new file mode 100644 +index 0000000..a2f6e02 +--- /dev/null ++++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h +@@ -0,0 +1,247 @@ ++/* ++ * STMicroelectronics st_asm330lhh sensor driver ++ * ++ * Copyright 2018 STMicroelectronics Inc. ++ * ++ * Lorenzo Bianconi ++ * ++ * Licensed under the GPL-2. ++ */ ++ ++#ifndef ST_ASM330LHH_H ++#define ST_ASM330LHH_H ++ ++#include ++#include ++ ++#define ST_ASM330LHH_REVISION "2.0.1" ++#define ST_ASM330LHH_PATCH "2" ++ ++#define ST_ASM330LHH_VERSION "v" \ ++ ST_ASM330LHH_REVISION \ ++ "-" \ ++ ST_ASM330LHH_PATCH ++ ++#define ST_ASM330LHH_DEV_NAME "asm330lhh" ++ ++#define ST_ASM330LHH_SAMPLE_SIZE 6 ++#define ST_ASM330LHH_TS_SAMPLE_SIZE 4 ++#define ST_ASM330LHH_TAG_SIZE 1 ++#define ST_ASM330LHH_FIFO_SAMPLE_SIZE (ST_ASM330LHH_SAMPLE_SIZE + \ ++ ST_ASM330LHH_TAG_SIZE) ++#define ST_ASM330LHH_MAX_FIFO_DEPTH 416 ++ ++#define ST_ASM330LHH_REG_FIFO_BATCH_ADDR 0x09 ++#define ST_ASM330LHH_REG_FIFO_CTRL4_ADDR 0x0a ++#define ST_ASM330LHH_REG_STATUS_ADDR 0x1e ++#define ST_ASM330LHH_REG_STATUS_TDA BIT(2) ++#define ST_ASM330LHH_REG_OUT_TEMP_L_ADDR 0x20 ++#define ST_ASM330LHH_REG_OUT_TEMP_H_ADDR 0x21 ++ ++#define ST_ASM330LHH_MAX_ODR 416 ++ ++/* Define Custom events for FIFO flush */ ++#define CUSTOM_IIO_EV_DIR_FIFO_EMPTY (IIO_EV_DIR_NONE + 1) ++#define CUSTOM_IIO_EV_DIR_FIFO_DATA (IIO_EV_DIR_NONE + 2) ++#define CUSTOM_IIO_EV_TYPE_FIFO_FLUSH (IIO_EV_TYPE_CHANGE + 1) ++ ++#define ST_ASM330LHH_CHANNEL(chan_type, addr, mod, ch2, scan_idx, \ ++ rb, sb, sg) \ ++{ \ ++ .type = chan_type, \ ++ .address = addr, \ ++ .modified = mod, \ ++ .channel2 = ch2, \ ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ ++ BIT(IIO_CHAN_INFO_SCALE), \ ++ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ ++ .scan_index = scan_idx, \ ++ .scan_type = { \ ++ .sign = sg, \ ++ .realbits = rb, \ ++ .storagebits = sb, \ ++ .endianness = IIO_LE, \ ++ }, \ ++} ++ ++static const struct iio_event_spec st_asm330lhh_flush_event = { ++ .type = CUSTOM_IIO_EV_TYPE_FIFO_FLUSH, ++ .dir = IIO_EV_DIR_EITHER, ++}; ++ ++#define ST_ASM330LHH_FLUSH_CHANNEL(dtype) \ ++{ \ ++ .type = dtype, \ ++ .modified = 0, \ ++ .scan_index = -1, \ ++ .indexed = -1, \ ++ .event_spec = &st_asm330lhh_flush_event, \ ++ .num_event_specs = 1, \ ++} ++ ++#define ST_ASM330LHH_RX_MAX_LENGTH 8 ++#define ST_ASM330LHH_TX_MAX_LENGTH 8 ++ ++struct st_asm330lhh_transfer_buffer { ++ u8 rx_buf[ST_ASM330LHH_RX_MAX_LENGTH]; ++ u8 tx_buf[ST_ASM330LHH_TX_MAX_LENGTH] ____cacheline_aligned; ++}; ++ ++struct st_asm330lhh_transfer_function { ++ int (*read)(struct device *dev, u8 addr, int len, u8 *data); ++ int (*write)(struct device *dev, u8 addr, int len, u8 *data); ++}; ++ ++struct st_asm330lhh_reg { ++ u8 addr; ++ u8 mask; ++}; ++ ++struct st_asm330lhh_odr { ++ u16 hz; ++ u8 val; ++}; ++ ++#define ST_ASM330LHH_ODR_LIST_SIZE 7 ++struct st_asm330lhh_odr_table_entry { ++ struct st_asm330lhh_reg reg; ++ struct st_asm330lhh_odr odr_avl[ST_ASM330LHH_ODR_LIST_SIZE]; ++}; ++ ++struct st_asm330lhh_fs { ++ u32 gain; ++ u8 val; ++}; ++ ++#define ST_ASM330LHH_FS_ACC_LIST_SIZE 4 ++#define ST_ASM330LHH_FS_GYRO_LIST_SIZE 6 ++#define ST_ASM330LHH_FS_TEMP_LIST_SIZE 1 ++#define ST_ASM330LHH_FS_LIST_SIZE 6 ++struct st_asm330lhh_fs_table_entry { ++ u32 size; ++ struct st_asm330lhh_reg reg; ++ struct st_asm330lhh_fs fs_avl[ST_ASM330LHH_FS_LIST_SIZE]; ++}; ++ ++enum st_asm330lhh_sensor_id { ++ ST_ASM330LHH_ID_ACC, ++ ST_ASM330LHH_ID_GYRO, ++ ST_ASM330LHH_ID_TEMP, ++ ST_ASM330LHH_ID_MAX, ++}; ++ ++enum st_asm330lhh_fifo_mode { ++ ST_ASM330LHH_FIFO_BYPASS = 0x0, ++ ST_ASM330LHH_FIFO_CONT = 0x6, ++}; ++ ++enum { ++ ST_ASM330LHH_HW_FLUSH, ++ ST_ASM330LHH_HW_OPERATIONAL, ++}; ++ ++/** ++ * struct st_asm330lhh_sensor - ST IMU sensor instance ++ * @id: Sensor identifier. ++ * @hw: Pointer to instance of struct st_asm330lhh_hw. ++ * @gain: Configured sensor sensitivity. ++ * @odr: Output data rate of the sensor [Hz]. ++ * @watermark: Sensor watermark level. ++ * @batch_mask: Sensor mask for FIFO batching register ++ */ ++struct st_asm330lhh_sensor { ++ enum st_asm330lhh_sensor_id id; ++ struct st_asm330lhh_hw *hw; ++ ++ u32 gain; ++ u16 odr; ++ u32 offset; ++ ++ __le16 old_data; ++ ++ u8 std_samples; ++ u8 std_level; ++ ++ u16 watermark; ++ u8 batch_mask; ++ u8 batch_addr; ++}; ++ ++/** ++ * struct st_asm330lhh_hw - ST IMU MEMS hw instance ++ * @dev: Pointer to instance of struct device (I2C or SPI). ++ * @irq: Device interrupt line (I2C or SPI). ++ * @lock: Mutex to protect read and write operations. ++ * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO. ++ * @fifo_mode: FIFO operating mode supported by the device. ++ * @state: hw operational state. ++ * @enable_mask: Enabled sensor bitmask. ++ * @ts_offset: Hw timestamp offset. ++ * @hw_val: Latest hw timestamp value. ++ * @hw_val_old: The hw saved timestamp value. ++ * @hw_ts: Latest hw timestamp from the sensor. ++ * @hw_ts_high: MSB of HW timestamp for rollover mamagenemt. ++ * @delta_ts: Delta time between two consecutive interrupts. ++ * @ts: Latest timestamp from irq handler. ++ * @tsample: Sample timestamp. ++ * @hw_ts_old: Prev. timestamp value. ++ * @delta_hw_ts: Estimated delta hw timestamp. ++ * @odr: Timestamp sample ODR. ++ * @iio_devs: Pointers to acc/gyro iio_dev instances. ++ * @tf: Transfer function structure used by I/O operations. ++ * @tb: Transfer buffers used by SPI I/O operations. ++ */ ++struct st_asm330lhh_hw { ++ struct device *dev; ++ int irq; ++ ++ struct mutex lock; ++ struct mutex fifo_lock; ++ ++ enum st_asm330lhh_fifo_mode fifo_mode; ++ unsigned long state; ++ u8 enable_mask; ++ ++ s64 ts_offset; ++ u32 hw_val; ++ u32 hw_val_old; ++ s64 hw_ts; ++ s64 hw_ts_high; ++ s64 delta_ts; ++ s64 ts; ++ s64 tsample; ++ s64 hw_ts_old; ++ s64 delta_hw_ts; ++ ++ u16 odr; ++ ++ struct iio_dev *iio_devs[ST_ASM330LHH_ID_MAX]; ++ ++ const struct st_asm330lhh_transfer_function *tf; ++ struct st_asm330lhh_transfer_buffer tb; ++}; ++ ++extern const struct dev_pm_ops st_asm330lhh_pm_ops; ++ ++int st_asm330lhh_probe(struct device *dev, int irq, ++ const struct st_asm330lhh_transfer_function *tf_ops); ++int st_asm330lhh_sensor_set_enable(struct st_asm330lhh_sensor *sensor, ++ bool enable); ++int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw); ++int st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw, u8 addr, u8 mask, ++ u8 val); ++int st_asm330lhh_get_odr_val(enum st_asm330lhh_sensor_id id, u16 odr, u8 *val); ++ssize_t st_asm330lhh_flush_fifo(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size); ++ssize_t st_asm330lhh_get_max_watermark(struct device *dev, ++ struct device_attribute *attr, char *buf); ++ssize_t st_asm330lhh_get_watermark(struct device *dev, ++ struct device_attribute *attr, char *buf); ++ssize_t st_asm330lhh_set_watermark(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size); ++int st_asm330lhh_set_fifo_mode(struct st_asm330lhh_hw *hw, ++ enum st_asm330lhh_fifo_mode fifo_mode); ++int st_asm330lhh_suspend_fifo(struct st_asm330lhh_hw *hw); ++#endif /* ST_ASM330LHH_H */ +diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c +new file mode 100644 +index 0000000..c414a06 +--- /dev/null ++++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c +@@ -0,0 +1,540 @@ ++/* ++ * STMicroelectronics st_asm330lhh FIFO buffer library driver ++ * ++ * Copyright 2018 STMicroelectronics Inc. ++ * ++ * Lorenzo Bianconi ++ * ++ * Licensed under the GPL-2. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "st_asm330lhh.h" ++ ++#define ST_ASM330LHH_REG_FIFO_THL_ADDR 0x07 ++#define ST_ASM330LHH_REG_FIFO_LEN_MASK GENMASK(8, 0) ++#define ST_ASM330LHH_REG_FIFO_MODE_MASK GENMASK(2, 0) ++#define ST_ASM330LHH_REG_DEC_TS_MASK GENMASK(7, 6) ++#define ST_ASM330LHH_REG_HLACTIVE_ADDR 0x12 ++#define ST_ASM330LHH_REG_HLACTIVE_MASK BIT(5) ++#define ST_ASM330LHH_REG_PP_OD_ADDR 0x12 ++#define ST_ASM330LHH_REG_PP_OD_MASK BIT(4) ++#define ST_ASM330LHH_REG_FIFO_DIFFL_ADDR 0x3a ++#define ST_ASM330LHH_REG_TS0_ADDR 0x40 ++#define ST_ASM330LHH_REG_TS2_ADDR 0x42 ++#define ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR 0x78 ++#define ST_ASM330LHH_GYRO_TAG 0x01 ++#define ST_ASM330LHH_ACC_TAG 0x02 ++#define ST_ASM330LHH_TS_TAG 0x04 ++ ++#define ST_ASM330LHH_TS_DELTA_NS 25000ULL /* 25us/LSB */ ++ ++static inline s64 st_asm330lhh_get_time_ns(void) ++{ ++ struct timespec ts; ++ ++ get_monotonic_boottime(&ts); ++ return timespec_to_ns(&ts); ++} ++ ++#define ST_ASM330LHH_EWMA_LEVEL 120 ++#define ST_ASM330LHH_EWMA_DIV 128 ++static inline s64 st_asm330lhh_ewma(s64 old, s64 new, int weight) ++{ ++ s64 diff, incr; ++ ++ diff = new - old; ++ incr = div_s64((ST_ASM330LHH_EWMA_DIV - weight) * diff, ++ ST_ASM330LHH_EWMA_DIV); ++ ++ return old + incr; ++} ++ ++static inline int st_asm330lhh_reset_hwts(struct st_asm330lhh_hw *hw) ++{ ++ u8 data = 0xaa; ++ ++ hw->ts = st_asm330lhh_get_time_ns(); ++ hw->ts_offset = hw->ts; ++ hw->hw_ts_old = 0ull; ++ hw->tsample = 0ull; ++ hw->hw_ts_high = 0ull; ++ hw->hw_val_old = 0ull; ++ ++ return hw->tf->write(hw->dev, ST_ASM330LHH_REG_TS2_ADDR, sizeof(data), ++ &data); ++} ++ ++int st_asm330lhh_set_fifo_mode(struct st_asm330lhh_hw *hw, ++ enum st_asm330lhh_fifo_mode fifo_mode) ++{ ++ int err; ++ ++ err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_FIFO_CTRL4_ADDR, ++ ST_ASM330LHH_REG_FIFO_MODE_MASK, ++ fifo_mode); ++ if (err < 0) ++ return err; ++ ++ hw->fifo_mode = fifo_mode; ++ ++ return 0; ++} ++ ++static int st_asm330lhh_set_sensor_batching_odr(struct st_asm330lhh_sensor *sensor, ++ bool enable) ++{ ++ struct st_asm330lhh_hw *hw = sensor->hw; ++ u8 data = 0; ++ int err; ++ ++ if (enable) { ++ err = st_asm330lhh_get_odr_val(sensor->id, sensor->odr, &data); ++ if (err < 0) ++ return err; ++ } ++ ++ return st_asm330lhh_write_with_mask(hw, ++ sensor->batch_addr, ++ sensor->batch_mask, data); ++} ++ ++static u16 st_asm330lhh_ts_odr(struct st_asm330lhh_hw *hw) ++{ ++ struct st_asm330lhh_sensor *sensor; ++ u16 odr = 0; ++ u8 i; ++ ++ for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { ++ if (!hw->iio_devs[i]) ++ continue; ++ ++ sensor = iio_priv(hw->iio_devs[i]); ++ if (hw->enable_mask & BIT(sensor->id)) ++ odr = max_t(u16, odr, sensor->odr); ++ } ++ ++ return odr; ++} ++ ++static int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor, ++ u16 watermark) ++{ ++ u16 fifo_watermark = ST_ASM330LHH_MAX_FIFO_DEPTH, cur_watermark = 0; ++ struct st_asm330lhh_hw *hw = sensor->hw; ++ struct st_asm330lhh_sensor *cur_sensor; ++ __le16 wdata; ++ int i, err; ++ u8 data; ++ ++ for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { ++ cur_sensor = iio_priv(hw->iio_devs[i]); ++ ++ if (!(hw->enable_mask & BIT(cur_sensor->id))) ++ continue; ++ ++ cur_watermark = (cur_sensor == sensor) ? watermark ++ : cur_sensor->watermark; ++ ++ fifo_watermark = min_t(u16, fifo_watermark, cur_watermark); ++ } ++ ++ fifo_watermark = max_t(u16, fifo_watermark, 2); ++ mutex_lock(&hw->lock); ++ ++ err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_THL_ADDR + 1, ++ sizeof(data), &data); ++ if (err < 0) ++ goto out; ++ ++ fifo_watermark = ((data << 8) & ~ST_ASM330LHH_REG_FIFO_LEN_MASK) | ++ (fifo_watermark & ST_ASM330LHH_REG_FIFO_LEN_MASK); ++ wdata = cpu_to_le16(fifo_watermark); ++ err = hw->tf->write(hw->dev, ST_ASM330LHH_REG_FIFO_THL_ADDR, ++ sizeof(wdata), (u8 *)&wdata); ++ ++out: ++ mutex_unlock(&hw->lock); ++ ++ return err < 0 ? err : 0; ++} ++ ++static inline void st_asm330lhh_sync_hw_ts(struct st_asm330lhh_hw *hw, s64 ts) ++{ ++ s64 delta = ts - hw->hw_ts; ++ ++ hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, delta, ++ ST_ASM330LHH_EWMA_LEVEL); ++} ++ ++static struct iio_dev *st_asm330lhh_get_iiodev_from_tag(struct st_asm330lhh_hw *hw, ++ u8 tag) ++{ ++ struct iio_dev *iio_dev; ++ ++ switch (tag) { ++ case ST_ASM330LHH_GYRO_TAG: ++ iio_dev = hw->iio_devs[ST_ASM330LHH_ID_GYRO]; ++ break; ++ case ST_ASM330LHH_ACC_TAG: ++ iio_dev = hw->iio_devs[ST_ASM330LHH_ID_ACC]; ++ break; ++ default: ++ iio_dev = NULL; ++ break; ++ } ++ ++ return iio_dev; ++} ++ ++static int st_asm330lhh_read_fifo(struct st_asm330lhh_hw *hw) ++{ ++ u8 iio_buf[ALIGN(ST_ASM330LHH_SAMPLE_SIZE, sizeof(s64)) + sizeof(s64)]; ++ u8 buf[6 * ST_ASM330LHH_FIFO_SAMPLE_SIZE], tag, *ptr; ++ s64 ts_delta_hw_ts = 0, ts_irq; ++ s64 ts_delta_offs; ++ int i, err, read_len, word_len, fifo_len; ++ struct st_asm330lhh_sensor *sensor; ++ struct iio_dev *iio_dev; ++ __le16 fifo_status; ++ u16 fifo_depth; ++ int ts_processed = 0; ++ s64 hw_ts = 0ull, delta_hw_ts, cpu_timestamp; ++ ++ ts_irq = hw->ts - hw->delta_ts; ++ ++ do { ++ err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_DIFFL_ADDR, ++ sizeof(fifo_status), (u8 *)&fifo_status); ++ if (err < 0) ++ return err; ++ ++ fifo_depth = le16_to_cpu(fifo_status) & ST_ASM330LHH_REG_FIFO_LEN_MASK; ++ if (!fifo_depth) ++ return 0; ++ ++ read_len = 0; ++ fifo_len = fifo_depth * ST_ASM330LHH_FIFO_SAMPLE_SIZE; ++ while (read_len < fifo_len) { ++ word_len = min_t(int, fifo_len - read_len, sizeof(buf)); ++ err = hw->tf->read(hw->dev, ++ ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR, ++ word_len, buf); ++ if (err < 0) ++ return err; ++ ++ for (i = 0; i < word_len; i += ST_ASM330LHH_FIFO_SAMPLE_SIZE) { ++ ptr = &buf[i + ST_ASM330LHH_TAG_SIZE]; ++ tag = buf[i] >> 3; ++ ++ if (tag == ST_ASM330LHH_TS_TAG) { ++ hw->hw_val = get_unaligned_le32(ptr); ++ ++ /* check for timer rollover */ ++ if (hw->hw_val < hw->hw_val_old) { ++ hw->hw_ts_high++; ++ } ++ ++ hw->hw_ts = (hw->hw_val + (hw->hw_ts_high << 32)) * ST_ASM330LHH_TS_DELTA_NS; ++ ts_delta_hw_ts = hw->hw_ts - hw->hw_ts_old; ++ hw_ts += ts_delta_hw_ts; ++ ts_delta_offs = ++ div_s64(hw->delta_hw_ts * ST_ASM330LHH_MAX_ODR, hw->odr); ++ ++ hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, ts_irq - ++ hw->hw_ts + ts_delta_offs, ST_ASM330LHH_EWMA_LEVEL); ++ ++ ts_irq += (hw->hw_ts + ts_delta_offs); ++ hw->hw_ts_old = hw->hw_ts; ++ hw->hw_val_old = hw->hw_val; ++ ts_processed++; ++ ++ if (!hw->tsample) ++ hw->tsample = ++ hw->ts_offset + (hw->hw_ts + ts_delta_offs); ++ else ++ hw->tsample = ++ hw->tsample + (ts_delta_hw_ts + ts_delta_offs); ++ } else { ++ iio_dev = st_asm330lhh_get_iiodev_from_tag(hw, tag); ++ if (!iio_dev) ++ continue; ++ ++ sensor = iio_priv(iio_dev); ++ if (sensor->std_samples < sensor->std_level) { ++ sensor->std_samples++; ++ continue; ++ } ++ ++ sensor = iio_priv(iio_dev); ++ ++ /* Check if timestamp is in the future. */ ++ cpu_timestamp = st_asm330lhh_get_time_ns(); ++ ++ /* Avoid samples in the future. */ ++ if (hw->tsample > cpu_timestamp) ++ hw->tsample = cpu_timestamp; ++ ++ memcpy(iio_buf, ptr, ST_ASM330LHH_SAMPLE_SIZE); ++ iio_push_to_buffers_with_timestamp(iio_dev, ++ iio_buf, ++ hw->tsample); ++ } ++ } ++ read_len += word_len; ++ } ++ ++ delta_hw_ts = div_s64(hw->delta_ts - hw_ts, ts_processed); ++ delta_hw_ts = div_s64(delta_hw_ts * hw->odr, ST_ASM330LHH_MAX_ODR); ++ hw->delta_hw_ts = st_asm330lhh_ewma(hw->delta_hw_ts, ++ delta_hw_ts, ++ ST_ASM330LHH_EWMA_LEVEL); ++ } while(read_len); ++ ++ return read_len; ++} ++ ++ssize_t st_asm330lhh_get_max_watermark(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%d\n", ST_ASM330LHH_MAX_FIFO_DEPTH); ++} ++ ++ssize_t st_asm330lhh_get_watermark(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct iio_dev *iio_dev = dev_get_drvdata(dev); ++ struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev); ++ ++ return sprintf(buf, "%d\n", sensor->watermark); ++} ++ ++ssize_t st_asm330lhh_set_watermark(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct iio_dev *iio_dev = dev_get_drvdata(dev); ++ struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev); ++ int err, val; ++ ++ mutex_lock(&iio_dev->mlock); ++ if (iio_buffer_enabled(iio_dev)) { ++ err = -EBUSY; ++ goto out; ++ } ++ ++ err = kstrtoint(buf, 10, &val); ++ if (err < 0) ++ goto out; ++ ++ err = st_asm330lhh_update_watermark(sensor, val); ++ if (err < 0) ++ goto out; ++ ++ sensor->watermark = val; ++ ++out: ++ mutex_unlock(&iio_dev->mlock); ++ ++ return err < 0 ? err : size; ++} ++ ++ssize_t st_asm330lhh_flush_fifo(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct iio_dev *iio_dev = dev_get_drvdata(dev); ++ struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev); ++ struct st_asm330lhh_hw *hw = sensor->hw; ++ s64 type, event; ++ int count; ++ s64 ts; ++ ++ mutex_lock(&hw->fifo_lock); ++ ts = st_asm330lhh_get_time_ns(); ++ hw->delta_ts = ts - hw->ts; ++ hw->ts = ts; ++ set_bit(ST_ASM330LHH_HW_FLUSH, &hw->state); ++ ++ count = st_asm330lhh_read_fifo(hw); ++ ++ mutex_unlock(&hw->fifo_lock); ++ ++ type = count > 0 ? CUSTOM_IIO_EV_DIR_FIFO_DATA : CUSTOM_IIO_EV_DIR_FIFO_EMPTY; ++ event = IIO_UNMOD_EVENT_CODE(iio_dev->channels[0].type, -1, ++ CUSTOM_IIO_EV_TYPE_FIFO_FLUSH, type); ++ iio_push_event(iio_dev, event, st_asm330lhh_get_time_ns()); ++ ++ return size; ++} ++ ++int st_asm330lhh_suspend_fifo(struct st_asm330lhh_hw *hw) ++{ ++ int err; ++ ++ mutex_lock(&hw->fifo_lock); ++ ++ st_asm330lhh_read_fifo(hw); ++ err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_BYPASS); ++ ++ mutex_unlock(&hw->fifo_lock); ++ ++ return err; ++} ++ ++static int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable) ++{ ++ struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev); ++ struct st_asm330lhh_hw *hw = sensor->hw; ++ int err; ++ ++ mutex_lock(&hw->fifo_lock); ++ ++ err = st_asm330lhh_sensor_set_enable(sensor, enable); ++ if (err < 0) ++ goto out; ++ ++ err = st_asm330lhh_set_sensor_batching_odr(sensor, enable); ++ if (err < 0) ++ goto out; ++ ++ err = st_asm330lhh_update_watermark(sensor, sensor->watermark); ++ if (err < 0) ++ goto out; ++ ++ hw->odr = st_asm330lhh_ts_odr(hw); ++ ++ if (enable && hw->fifo_mode == ST_ASM330LHH_FIFO_BYPASS) { ++ st_asm330lhh_reset_hwts(hw); ++ err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_CONT); ++ } else if (!hw->enable_mask) { ++ err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_BYPASS); ++ } ++ ++out: ++ mutex_unlock(&hw->fifo_lock); ++ ++ return err; ++} ++ ++static irqreturn_t st_asm330lhh_handler_irq(int irq, void *private) ++{ ++ struct st_asm330lhh_hw *hw = (struct st_asm330lhh_hw *)private; ++ s64 ts = st_asm330lhh_get_time_ns(); ++ ++ hw->delta_ts = ts - hw->ts; ++ hw->ts = ts; ++ ++ return IRQ_WAKE_THREAD; ++} ++ ++static irqreturn_t st_asm330lhh_handler_thread(int irq, void *private) ++{ ++ struct st_asm330lhh_hw *hw = (struct st_asm330lhh_hw *)private; ++ ++ mutex_lock(&hw->fifo_lock); ++ ++ st_asm330lhh_read_fifo(hw); ++ clear_bit(ST_ASM330LHH_HW_FLUSH, &hw->state); ++ ++ mutex_unlock(&hw->fifo_lock); ++ ++ return IRQ_HANDLED; ++} ++ ++static int st_asm330lhh_buffer_preenable(struct iio_dev *iio_dev) ++{ ++ return st_asm330lhh_update_fifo(iio_dev, true); ++} ++ ++static int st_asm330lhh_buffer_postdisable(struct iio_dev *iio_dev) ++{ ++ return st_asm330lhh_update_fifo(iio_dev, false); ++} ++ ++static const struct iio_buffer_setup_ops st_asm330lhh_buffer_ops = { ++ .preenable = st_asm330lhh_buffer_preenable, ++ .postdisable = st_asm330lhh_buffer_postdisable, ++}; ++ ++static int st_asm330lhh_fifo_init(struct st_asm330lhh_hw *hw) ++{ ++ return st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_FIFO_CTRL4_ADDR, ++ ST_ASM330LHH_REG_DEC_TS_MASK, 1); ++} ++ ++int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw) ++{ ++ struct device_node *np = hw->dev->of_node; ++ struct iio_buffer *buffer; ++ unsigned long irq_type; ++ bool irq_active_low; ++ int i, err; ++ ++ irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); ++ ++ switch (irq_type) { ++ case IRQF_TRIGGER_HIGH: ++ case IRQF_TRIGGER_RISING: ++ irq_active_low = false; ++ break; ++ case IRQF_TRIGGER_LOW: ++ case IRQF_TRIGGER_FALLING: ++ irq_active_low = true; ++ break; ++ default: ++ dev_info(hw->dev, "mode %lx unsupported\n", irq_type); ++ return -EINVAL; ++ } ++ ++ err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_HLACTIVE_ADDR, ++ ST_ASM330LHH_REG_HLACTIVE_MASK, ++ irq_active_low); ++ if (err < 0) ++ return err; ++ ++ if (np && of_property_read_bool(np, "drive-open-drain")) { ++ err = st_asm330lhh_write_with_mask(hw, ++ ST_ASM330LHH_REG_PP_OD_ADDR, ++ ST_ASM330LHH_REG_PP_OD_MASK, 1); ++ if (err < 0) ++ return err; ++ ++ irq_type |= IRQF_SHARED; ++ } ++ ++ err = devm_request_threaded_irq(hw->dev, hw->irq, ++ st_asm330lhh_handler_irq, ++ st_asm330lhh_handler_thread, ++ irq_type | IRQF_ONESHOT, ++ "asm330lhh", hw); ++ if (err) { ++ dev_err(hw->dev, "failed to request trigger irq %d\n", ++ hw->irq); ++ return err; ++ } ++ ++ for (i = ST_ASM330LHH_ID_ACC; i < ST_ASM330LHH_ID_MAX; i++) { ++ if (!hw->iio_devs[i]) ++ continue; ++ ++ buffer = devm_iio_kfifo_allocate(hw->dev); ++ if (!buffer) ++ return -ENOMEM; ++ ++ iio_device_attach_buffer(hw->iio_devs[i], buffer); ++ hw->iio_devs[i]->modes |= INDIO_BUFFER_SOFTWARE; ++ hw->iio_devs[i]->setup_ops = &st_asm330lhh_buffer_ops; ++ } ++ ++ return st_asm330lhh_fifo_init(hw); ++} ++ +diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c +new file mode 100644 +index 0000000..9d9ee20 +--- /dev/null ++++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c +@@ -0,0 +1,824 @@ ++/* ++ * STMicroelectronics st_asm330lhh sensor driver ++ * ++ * Copyright 2018 STMicroelectronics Inc. ++ * ++ * Lorenzo Bianconi ++ * ++ * Licensed under the GPL-2. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "st_asm330lhh.h" ++ ++#define ST_ASM330LHH_REG_INT1_ADDR 0x0d ++#define ST_ASM330LHH_REG_INT2_ADDR 0x0e ++#define ST_ASM330LHH_REG_FIFO_CTRL4_ADDR 0x0a ++#define ST_ASM330LHH_REG_FIFO_FTH_IRQ_MASK BIT(3) ++#define ST_ASM330LHH_REG_WHOAMI_ADDR 0x0f ++#define ST_ASM330LHH_WHOAMI_VAL 0x6b ++#define ST_ASM330LHH_REG_CTRL1_XL_ADDR 0x10 ++#define ST_ASM330LHH_REG_CTRL2_G_ADDR 0x11 ++#define ST_ASM330LHH_REG_RESET_ADDR 0x12 ++#define ST_ASM330LHH_REG_RESET_MASK BIT(0) ++#define ST_ASM330LHH_REG_BDU_ADDR 0x12 ++#define ST_ASM330LHH_REG_BDU_MASK BIT(6) ++#define ST_ASM330LHH_REG_INT2_ON_INT1_ADDR 0x13 ++#define ST_ASM330LHH_REG_INT2_ON_INT1_MASK BIT(5) ++#define ST_ASM330LHH_REG_ROUNDING_ADDR 0x14 ++#define ST_ASM330LHH_REG_ROUNDING_MASK GENMASK(6, 5) ++#define ST_ASM330LHH_REG_TIMESTAMP_EN_ADDR 0x19 ++#define ST_ASM330LHH_REG_TIMESTAMP_EN_MASK BIT(5) ++ ++#define ST_ASM330LHH_REG_GYRO_OUT_X_L_ADDR 0x22 ++#define ST_ASM330LHH_REG_GYRO_OUT_Y_L_ADDR 0x24 ++#define ST_ASM330LHH_REG_GYRO_OUT_Z_L_ADDR 0x26 ++ ++#define ST_ASM330LHH_REG_ACC_OUT_X_L_ADDR 0x28 ++#define ST_ASM330LHH_REG_ACC_OUT_Y_L_ADDR 0x2a ++#define ST_ASM330LHH_REG_ACC_OUT_Z_L_ADDR 0x2c ++ ++#define ST_ASM330LHH_REG_LIR_ADDR 0x56 ++#define ST_ASM330LHH_REG_LIR_MASK BIT(0) ++ ++#define ST_ASM330LHH_ACC_FS_2G_GAIN IIO_G_TO_M_S_2(61) ++#define ST_ASM330LHH_ACC_FS_4G_GAIN IIO_G_TO_M_S_2(122) ++#define ST_ASM330LHH_ACC_FS_8G_GAIN IIO_G_TO_M_S_2(244) ++#define ST_ASM330LHH_ACC_FS_16G_GAIN IIO_G_TO_M_S_2(488) ++ ++#define ST_ASM330LHH_GYRO_FS_125_GAIN IIO_DEGREE_TO_RAD(4375) ++#define ST_ASM330LHH_GYRO_FS_250_GAIN IIO_DEGREE_TO_RAD(8750) ++#define ST_ASM330LHH_GYRO_FS_500_GAIN IIO_DEGREE_TO_RAD(17500) ++#define ST_ASM330LHH_GYRO_FS_1000_GAIN IIO_DEGREE_TO_RAD(35000) ++#define ST_ASM330LHH_GYRO_FS_2000_GAIN IIO_DEGREE_TO_RAD(70000) ++#define ST_ASM330LHH_GYRO_FS_4000_GAIN IIO_DEGREE_TO_RAD(140000) ++ ++/* Temperature in uC */ ++#define ST_ASM330LHH_TEMP_GAIN 256 ++#define ST_ASM330LHH_TEMP_FS_GAIN (1000000 / ST_ASM330LHH_TEMP_GAIN) ++#define ST_ASM330LHH_OFFSET (6400) ++ ++struct st_asm330lhh_std_entry { ++ u16 odr; ++ u8 val; ++}; ++ ++/* Minimal number of sample to be discarded */ ++struct st_asm330lhh_std_entry st_asm330lhh_std_table[] = { ++ { 13, 2 }, ++ { 26, 3 }, ++ { 52, 4 }, ++ { 104, 6 }, ++ { 208, 8 }, ++ { 416, 18 }, ++}; ++ ++static const struct st_asm330lhh_odr_table_entry st_asm330lhh_odr_table[] = { ++ [ST_ASM330LHH_ID_ACC] = { ++ .reg = { ++ .addr = ST_ASM330LHH_REG_CTRL1_XL_ADDR, ++ .mask = GENMASK(7, 4), ++ }, ++ .odr_avl[0] = { 0, 0x00 }, ++ .odr_avl[1] = { 13, 0x01 }, ++ .odr_avl[2] = { 26, 0x02 }, ++ .odr_avl[3] = { 52, 0x03 }, ++ .odr_avl[4] = { 104, 0x04 }, ++ .odr_avl[5] = { 208, 0x05 }, ++ .odr_avl[6] = { 416, 0x06 }, ++ }, ++ [ST_ASM330LHH_ID_GYRO] = { ++ .reg = { ++ .addr = ST_ASM330LHH_REG_CTRL2_G_ADDR, ++ .mask = GENMASK(7, 4), ++ }, ++ .odr_avl[0] = { 0, 0x00 }, ++ .odr_avl[1] = { 13, 0x01 }, ++ .odr_avl[2] = { 26, 0x02 }, ++ .odr_avl[3] = { 52, 0x03 }, ++ .odr_avl[4] = { 104, 0x04 }, ++ .odr_avl[5] = { 208, 0x05 }, ++ .odr_avl[6] = { 416, 0x06 }, ++ }, ++ [ST_ASM330LHH_ID_TEMP] = { ++ .odr_avl[0] = { 0, 0x00 }, ++ .odr_avl[1] = { 52, 0x01 }, ++ } ++}; ++ ++static const struct st_asm330lhh_fs_table_entry st_asm330lhh_fs_table[] = { ++ [ST_ASM330LHH_ID_ACC] = { ++ .reg = { ++ .addr = ST_ASM330LHH_REG_CTRL1_XL_ADDR, ++ .mask = GENMASK(3, 2), ++ }, ++ .size = ST_ASM330LHH_FS_ACC_LIST_SIZE, ++ .fs_avl[0] = { ST_ASM330LHH_ACC_FS_2G_GAIN, 0x0 }, ++ .fs_avl[1] = { ST_ASM330LHH_ACC_FS_4G_GAIN, 0x2 }, ++ .fs_avl[2] = { ST_ASM330LHH_ACC_FS_8G_GAIN, 0x3 }, ++ .fs_avl[3] = { ST_ASM330LHH_ACC_FS_16G_GAIN, 0x1 }, ++ }, ++ [ST_ASM330LHH_ID_GYRO] = { ++ .reg = { ++ .addr = ST_ASM330LHH_REG_CTRL2_G_ADDR, ++ .mask = GENMASK(3, 0), ++ }, ++ .size = ST_ASM330LHH_FS_GYRO_LIST_SIZE, ++ .fs_avl[0] = { ST_ASM330LHH_GYRO_FS_125_GAIN, 0x2 }, ++ .fs_avl[1] = { ST_ASM330LHH_GYRO_FS_250_GAIN, 0x0 }, ++ .fs_avl[2] = { ST_ASM330LHH_GYRO_FS_500_GAIN, 0x4 }, ++ .fs_avl[3] = { ST_ASM330LHH_GYRO_FS_1000_GAIN, 0x8 }, ++ .fs_avl[4] = { ST_ASM330LHH_GYRO_FS_2000_GAIN, 0xC }, ++ .fs_avl[5] = { ST_ASM330LHH_GYRO_FS_4000_GAIN, 0x1 }, ++ }, ++ [ST_ASM330LHH_ID_TEMP] = { ++ .size = ST_ASM330LHH_FS_TEMP_LIST_SIZE, ++ .fs_avl[0] = { ST_ASM330LHH_TEMP_FS_GAIN, 0x0 }, ++ } ++}; ++ ++static const struct iio_chan_spec st_asm330lhh_acc_channels[] = { ++ ST_ASM330LHH_CHANNEL(IIO_ACCEL, ST_ASM330LHH_REG_ACC_OUT_X_L_ADDR, ++ 1, IIO_MOD_X, 0, 16, 16, 's'), ++ ST_ASM330LHH_CHANNEL(IIO_ACCEL, ST_ASM330LHH_REG_ACC_OUT_Y_L_ADDR, ++ 1, IIO_MOD_Y, 1, 16, 16, 's'), ++ ST_ASM330LHH_CHANNEL(IIO_ACCEL, ST_ASM330LHH_REG_ACC_OUT_Z_L_ADDR, ++ 1, IIO_MOD_Z, 2, 16, 16, 's'), ++ ST_ASM330LHH_FLUSH_CHANNEL(IIO_ACCEL), ++ IIO_CHAN_SOFT_TIMESTAMP(3), ++}; ++ ++static const struct iio_chan_spec st_asm330lhh_gyro_channels[] = { ++ ST_ASM330LHH_CHANNEL(IIO_ANGL_VEL, ST_ASM330LHH_REG_GYRO_OUT_X_L_ADDR, ++ 1, IIO_MOD_X, 0, 16, 16, 's'), ++ ST_ASM330LHH_CHANNEL(IIO_ANGL_VEL, ST_ASM330LHH_REG_GYRO_OUT_Y_L_ADDR, ++ 1, IIO_MOD_Y, 1, 16, 16, 's'), ++ ST_ASM330LHH_CHANNEL(IIO_ANGL_VEL, ST_ASM330LHH_REG_GYRO_OUT_Z_L_ADDR, ++ 1, IIO_MOD_Z, 2, 16, 16, 's'), ++ ST_ASM330LHH_FLUSH_CHANNEL(IIO_ANGL_VEL), ++ IIO_CHAN_SOFT_TIMESTAMP(3), ++}; ++ ++static const struct iio_chan_spec st_asm330lhh_temp_channels[] = { ++ { ++ .type = IIO_TEMP, ++ .address = ST_ASM330LHH_REG_OUT_TEMP_L_ADDR, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) ++ | BIT(IIO_CHAN_INFO_OFFSET) ++ | BIT(IIO_CHAN_INFO_SCALE), ++ .scan_index = -1, ++ }, ++}; ++ ++int st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw, u8 addr, u8 mask, ++ u8 val) ++{ ++ u8 data; ++ int err; ++ ++ mutex_lock(&hw->lock); ++ ++ err = hw->tf->read(hw->dev, addr, sizeof(data), &data); ++ if (err < 0) { ++ dev_err(hw->dev, "failed to read %02x register\n", addr); ++ goto out; ++ } ++ ++ data = (data & ~mask) | ((val << __ffs(mask)) & mask); ++ ++ err = hw->tf->write(hw->dev, addr, sizeof(data), &data); ++ if (err < 0) ++ dev_err(hw->dev, "failed to write %02x register\n", addr); ++ ++out: ++ mutex_unlock(&hw->lock); ++ ++ return err; ++} ++ ++static int st_asm330lhh_check_whoami(struct st_asm330lhh_hw *hw) ++{ ++ int err; ++ u8 data; ++ ++ err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_WHOAMI_ADDR, sizeof(data), ++ &data); ++ if (err < 0) { ++ dev_err(hw->dev, "failed to read whoami register\n"); ++ return err; ++ } ++ ++ if (data != ST_ASM330LHH_WHOAMI_VAL) { ++ dev_err(hw->dev, "unsupported whoami [%02x]\n", data); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static int st_asm330lhh_set_full_scale(struct st_asm330lhh_sensor *sensor, ++ u32 gain) ++{ ++ enum st_asm330lhh_sensor_id id = sensor->id; ++ int i, err; ++ u8 val; ++ ++ for (i = 0; i < st_asm330lhh_fs_table[id].size; i++) ++ if (st_asm330lhh_fs_table[id].fs_avl[i].gain == gain) ++ break; ++ ++ if (i == st_asm330lhh_fs_table[id].size) ++ return -EINVAL; ++ ++ val = st_asm330lhh_fs_table[id].fs_avl[i].val; ++ err = st_asm330lhh_write_with_mask(sensor->hw, ++ st_asm330lhh_fs_table[id].reg.addr, ++ st_asm330lhh_fs_table[id].reg.mask, ++ val); ++ if (err < 0) ++ return err; ++ ++ sensor->gain = gain; ++ ++ return 0; ++} ++ ++int st_asm330lhh_get_odr_val(enum st_asm330lhh_sensor_id id, u16 odr, u8 *val) ++{ ++ int i; ++ ++ for (i = 0; i < ST_ASM330LHH_ODR_LIST_SIZE; i++) ++ if (st_asm330lhh_odr_table[id].odr_avl[i].hz >= odr) ++ break; ++ ++ if (i == ST_ASM330LHH_ODR_LIST_SIZE) ++ return -EINVAL; ++ ++ *val = st_asm330lhh_odr_table[id].odr_avl[i].val; ++ ++ return 0; ++} ++ ++static int st_asm330lhh_set_std_level(struct st_asm330lhh_sensor *sensor, ++ u16 odr) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(st_asm330lhh_std_table); i++) ++ if (st_asm330lhh_std_table[i].odr == odr) ++ break; ++ ++ if (i == ARRAY_SIZE(st_asm330lhh_std_table)) ++ return -EINVAL; ++ ++ sensor->std_level = st_asm330lhh_std_table[i].val; ++ sensor->std_samples = 0; ++ ++ return 0; ++} ++ ++static int st_asm330lhh_set_odr(struct st_asm330lhh_sensor *sensor, u16 odr) ++{ ++ struct st_asm330lhh_hw *hw = sensor->hw; ++ u8 val; ++ ++ if (st_asm330lhh_get_odr_val(sensor->id, odr, &val) < 0) ++ return -EINVAL; ++ ++ return st_asm330lhh_write_with_mask(hw, ++ st_asm330lhh_odr_table[sensor->id].reg.addr, ++ st_asm330lhh_odr_table[sensor->id].reg.mask, val); ++} ++ ++int st_asm330lhh_sensor_set_enable(struct st_asm330lhh_sensor *sensor, ++ bool enable) ++{ ++ u16 odr = enable ? sensor->odr : 0; ++ int err; ++ ++ if (sensor->id != ST_ASM330LHH_ID_TEMP) { ++ err = st_asm330lhh_set_odr(sensor, odr); ++ if (err < 0) ++ return err; ++ } ++ ++ if (enable) ++ sensor->hw->enable_mask |= BIT(sensor->id); ++ else ++ sensor->hw->enable_mask &= ~BIT(sensor->id); ++ ++ return 0; ++} ++ ++static int st_asm330lhh_read_oneshot(struct st_asm330lhh_sensor *sensor, ++ u8 addr, int *val) ++{ ++ int err, delay; ++ __le16 data; ++ ++ if (sensor->id == ST_ASM330LHH_ID_TEMP) { ++ u8 status; ++ ++ mutex_lock(&sensor->hw->fifo_lock); ++ err = sensor->hw->tf->read(sensor->hw->dev, ++ ST_ASM330LHH_REG_STATUS_ADDR, sizeof(status), &status); ++ if (err < 0) ++ goto unlock; ++ ++ if (status & ST_ASM330LHH_REG_STATUS_TDA) { ++ err = sensor->hw->tf->read(sensor->hw->dev, addr, sizeof(data), ++ (u8 *)&data); ++ if (err < 0) ++ goto unlock; ++ ++ sensor->old_data = data; ++ } else ++ data = sensor->old_data; ++unlock: ++ mutex_unlock(&sensor->hw->fifo_lock); ++ ++ } else { ++ err = st_asm330lhh_sensor_set_enable(sensor, true); ++ if (err < 0) ++ return err; ++ ++ delay = 1000000 / sensor->odr; ++ usleep_range(delay, 2 * delay); ++ ++ err = sensor->hw->tf->read(sensor->hw->dev, addr, sizeof(data), ++ (u8 *)&data); ++ if (err < 0) ++ return err; ++ ++ st_asm330lhh_sensor_set_enable(sensor, false); ++ } ++ ++ *val = (s16)data; ++ ++ return IIO_VAL_INT; ++} ++ ++static int st_asm330lhh_read_raw(struct iio_dev *iio_dev, ++ struct iio_chan_spec const *ch, ++ int *val, int *val2, long mask) ++{ ++ struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev); ++ int ret; ++ ++ switch (mask) { ++ case IIO_CHAN_INFO_RAW: ++ mutex_lock(&iio_dev->mlock); ++ if (iio_buffer_enabled(iio_dev)) { ++ ret = -EBUSY; ++ mutex_unlock(&iio_dev->mlock); ++ break; ++ } ++ ret = st_asm330lhh_read_oneshot(sensor, ch->address, val); ++ mutex_unlock(&iio_dev->mlock); ++ break; ++ case IIO_CHAN_INFO_OFFSET: ++ switch (ch->type) { ++ case IIO_TEMP: ++ *val = sensor->offset; ++ ret = IIO_VAL_INT; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case IIO_CHAN_INFO_SAMP_FREQ: ++ *val = sensor->odr; ++ ret = IIO_VAL_INT; ++ break; ++ case IIO_CHAN_INFO_SCALE: ++ switch (ch->type) { ++ case IIO_TEMP: ++ *val = 1; ++ *val2 = ST_ASM330LHH_TEMP_GAIN; ++ ret = IIO_VAL_FRACTIONAL; ++ break; ++ case IIO_ACCEL: ++ case IIO_ANGL_VEL: ++ *val = 0; ++ *val2 = sensor->gain; ++ ret = IIO_VAL_INT_PLUS_MICRO; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++static int st_asm330lhh_write_raw(struct iio_dev *iio_dev, ++ struct iio_chan_spec const *chan, ++ int val, int val2, long mask) ++{ ++ struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev); ++ int err; ++ ++ mutex_lock(&iio_dev->mlock); ++ ++ switch (mask) { ++ case IIO_CHAN_INFO_SCALE: ++ err = st_asm330lhh_set_full_scale(sensor, val2); ++ break; ++ case IIO_CHAN_INFO_SAMP_FREQ: { ++ u8 data; ++ ++ err = st_asm330lhh_set_std_level(sensor, val); ++ if (err < 0) ++ break; ++ ++ err = st_asm330lhh_get_odr_val(sensor->id, val, &data); ++ if (!err) ++ sensor->odr = val; ++ ++ err = st_asm330lhh_set_odr(sensor, sensor->odr); ++ break; ++ } ++ default: ++ err = -EINVAL; ++ break; ++ } ++ ++ mutex_unlock(&iio_dev->mlock); ++ ++ return err; ++} ++ ++static ssize_t ++st_asm330lhh_sysfs_sampling_frequency_avail(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct st_asm330lhh_sensor *sensor = iio_priv(dev_get_drvdata(dev)); ++ enum st_asm330lhh_sensor_id id = sensor->id; ++ int i, len = 0; ++ ++ for (i = 1; i < ST_ASM330LHH_ODR_LIST_SIZE; i++) ++ len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", ++ st_asm330lhh_odr_table[id].odr_avl[i].hz); ++ buf[len - 1] = '\n'; ++ ++ return len; ++} ++ ++static ssize_t st_asm330lhh_sysfs_scale_avail(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct st_asm330lhh_sensor *sensor = iio_priv(dev_get_drvdata(dev)); ++ enum st_asm330lhh_sensor_id id = sensor->id; ++ int i, len = 0; ++ ++ for (i = 0; i < st_asm330lhh_fs_table[id].size; i++) ++ len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", ++ st_asm330lhh_fs_table[id].fs_avl[i].gain); ++ buf[len - 1] = '\n'; ++ ++ return len; ++} ++ ++static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_asm330lhh_sysfs_sampling_frequency_avail); ++static IIO_DEVICE_ATTR(in_accel_scale_available, 0444, ++ st_asm330lhh_sysfs_scale_avail, NULL, 0); ++static IIO_DEVICE_ATTR(in_anglvel_scale_available, 0444, ++ st_asm330lhh_sysfs_scale_avail, NULL, 0); ++static IIO_DEVICE_ATTR(in_temp_scale_available, 0444, ++ st_asm330lhh_sysfs_scale_avail, NULL, 0); ++static IIO_DEVICE_ATTR(hwfifo_watermark_max, 0444, ++ st_asm330lhh_get_max_watermark, NULL, 0); ++static IIO_DEVICE_ATTR(hwfifo_flush, 0200, NULL, st_asm330lhh_flush_fifo, 0); ++static IIO_DEVICE_ATTR(hwfifo_watermark, 0644, st_asm330lhh_get_watermark, ++ st_asm330lhh_set_watermark, 0); ++ ++static struct attribute *st_asm330lhh_acc_attributes[] = { ++ &iio_dev_attr_sampling_frequency_available.dev_attr.attr, ++ &iio_dev_attr_in_accel_scale_available.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark.dev_attr.attr, ++ &iio_dev_attr_hwfifo_flush.dev_attr.attr, ++ NULL, ++}; ++ ++static const struct attribute_group st_asm330lhh_acc_attribute_group = { ++ .attrs = st_asm330lhh_acc_attributes, ++}; ++ ++static const struct iio_info st_asm330lhh_acc_info = { ++ .driver_module = THIS_MODULE, ++ .attrs = &st_asm330lhh_acc_attribute_group, ++ .read_raw = st_asm330lhh_read_raw, ++ .write_raw = st_asm330lhh_write_raw, ++}; ++ ++static struct attribute *st_asm330lhh_gyro_attributes[] = { ++ &iio_dev_attr_sampling_frequency_available.dev_attr.attr, ++ &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark.dev_attr.attr, ++ &iio_dev_attr_hwfifo_flush.dev_attr.attr, ++ NULL, ++}; ++ ++static const struct attribute_group st_asm330lhh_gyro_attribute_group = { ++ .attrs = st_asm330lhh_gyro_attributes, ++}; ++ ++static const struct iio_info st_asm330lhh_gyro_info = { ++ .driver_module = THIS_MODULE, ++ .attrs = &st_asm330lhh_gyro_attribute_group, ++ .read_raw = st_asm330lhh_read_raw, ++ .write_raw = st_asm330lhh_write_raw, ++}; ++ ++static struct attribute *st_asm330lhh_temp_attributes[] = { ++ &iio_dev_attr_sampling_frequency_available.dev_attr.attr, ++ &iio_dev_attr_in_temp_scale_available.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark.dev_attr.attr, ++ &iio_dev_attr_hwfifo_flush.dev_attr.attr, ++ NULL, ++}; ++ ++static const struct attribute_group st_asm330lhh_temp_attribute_group = { ++ .attrs = st_asm330lhh_temp_attributes, ++}; ++ ++static const struct iio_info st_asm330lhh_temp_info = { ++ .driver_module = THIS_MODULE, ++ .attrs = &st_asm330lhh_temp_attribute_group, ++ .read_raw = st_asm330lhh_read_raw, ++ .write_raw = st_asm330lhh_write_raw, ++}; ++ ++static const unsigned long st_asm330lhh_available_scan_masks[] = { 0x7, 0x0 }; ++ ++static int st_asm330lhh_of_get_drdy_pin(struct st_asm330lhh_hw *hw, int *drdy_pin) ++{ ++ struct device_node *np = hw->dev->of_node; ++ ++ if (!np) ++ return -EINVAL; ++ ++ return of_property_read_u32(np, "st,drdy-int-pin", drdy_pin); ++} ++ ++static int st_asm330lhh_get_drdy_reg(struct st_asm330lhh_hw *hw, u8 *drdy_reg) ++{ ++ int err = 0, drdy_pin; ++ ++ if (st_asm330lhh_of_get_drdy_pin(hw, &drdy_pin) < 0) { ++ struct st_sensors_platform_data *pdata; ++ struct device *dev = hw->dev; ++ ++ pdata = (struct st_sensors_platform_data *)dev->platform_data; ++ drdy_pin = pdata ? pdata->drdy_int_pin : 1; ++ } ++ ++ switch (drdy_pin) { ++ case 1: ++ *drdy_reg = ST_ASM330LHH_REG_INT1_ADDR; ++ break; ++ case 2: ++ *drdy_reg = ST_ASM330LHH_REG_INT2_ADDR; ++ break; ++ default: ++ dev_err(hw->dev, "unsupported data ready pin\n"); ++ err = -EINVAL; ++ break; ++ } ++ ++ return err; ++} ++ ++static int st_asm330lhh_init_device(struct st_asm330lhh_hw *hw) ++{ ++ u8 drdy_int_reg; ++ int err; ++ ++ err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_RESET_ADDR, ++ ST_ASM330LHH_REG_RESET_MASK, 1); ++ if (err < 0) ++ return err; ++ ++ msleep(200); ++ ++ /* latch interrupts */ ++ err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_LIR_ADDR, ++ ST_ASM330LHH_REG_LIR_MASK, 1); ++ if (err < 0) ++ return err; ++ ++ /* enable Block Data Update */ ++ err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_BDU_ADDR, ++ ST_ASM330LHH_REG_BDU_MASK, 1); ++ if (err < 0) ++ return err; ++ ++ err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_ROUNDING_ADDR, ++ ST_ASM330LHH_REG_ROUNDING_MASK, 3); ++ if (err < 0) ++ return err; ++ ++ /* init timestamp engine */ ++ err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_TIMESTAMP_EN_ADDR, ++ ST_ASM330LHH_REG_TIMESTAMP_EN_MASK, 1); ++ if (err < 0) ++ return err; ++ ++ /* enable FIFO watermak interrupt */ ++ err = st_asm330lhh_get_drdy_reg(hw, &drdy_int_reg); ++ if (err < 0) ++ return err; ++ ++ return st_asm330lhh_write_with_mask(hw, drdy_int_reg, ++ ST_ASM330LHH_REG_FIFO_FTH_IRQ_MASK, 1); ++} ++ ++static struct iio_dev *st_asm330lhh_alloc_iiodev(struct st_asm330lhh_hw *hw, ++ enum st_asm330lhh_sensor_id id) ++{ ++ struct st_asm330lhh_sensor *sensor; ++ struct iio_dev *iio_dev; ++ ++ iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor)); ++ if (!iio_dev) ++ return NULL; ++ ++ iio_dev->modes = INDIO_DIRECT_MODE; ++ iio_dev->dev.parent = hw->dev; ++ iio_dev->available_scan_masks = st_asm330lhh_available_scan_masks; ++ ++ sensor = iio_priv(iio_dev); ++ sensor->id = id; ++ sensor->hw = hw; ++ sensor->odr = st_asm330lhh_odr_table[id].odr_avl[1].hz; ++ sensor->gain = st_asm330lhh_fs_table[id].fs_avl[0].gain; ++ sensor->watermark = 1; ++ sensor->old_data = 0; ++ ++ switch (id) { ++ case ST_ASM330LHH_ID_ACC: ++ iio_dev->channels = st_asm330lhh_acc_channels; ++ iio_dev->num_channels = ARRAY_SIZE(st_asm330lhh_acc_channels); ++ iio_dev->name = "asm330lhh_accel"; ++ iio_dev->info = &st_asm330lhh_acc_info; ++ sensor->batch_addr = ST_ASM330LHH_REG_FIFO_BATCH_ADDR; ++ sensor->batch_mask = GENMASK(3, 0); ++ sensor->offset = 0; ++ break; ++ case ST_ASM330LHH_ID_GYRO: ++ iio_dev->channels = st_asm330lhh_gyro_channels; ++ iio_dev->num_channels = ARRAY_SIZE(st_asm330lhh_gyro_channels); ++ iio_dev->name = "asm330lhh_gyro"; ++ iio_dev->info = &st_asm330lhh_gyro_info; ++ sensor->batch_addr = ST_ASM330LHH_REG_FIFO_BATCH_ADDR; ++ sensor->batch_mask = GENMASK(7, 4); ++ sensor->offset = 0; ++ break; ++ case ST_ASM330LHH_ID_TEMP: ++ iio_dev->channels = st_asm330lhh_temp_channels; ++ iio_dev->num_channels = ARRAY_SIZE(st_asm330lhh_temp_channels); ++ iio_dev->name = "asm330lhh_temp"; ++ iio_dev->info = &st_asm330lhh_temp_info; ++ sensor->offset = ST_ASM330LHH_OFFSET; ++ break; ++ default: ++ return NULL; ++ } ++ ++ return iio_dev; ++} ++ ++int st_asm330lhh_probe(struct device *dev, int irq, ++ const struct st_asm330lhh_transfer_function *tf_ops) ++{ ++ struct st_asm330lhh_hw *hw; ++ int i, err; ++ ++ hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); ++ if (!hw) ++ return -ENOMEM; ++ ++ dev_set_drvdata(dev, (void *)hw); ++ ++ mutex_init(&hw->lock); ++ mutex_init(&hw->fifo_lock); ++ ++ hw->dev = dev; ++ hw->irq = irq; ++ hw->tf = tf_ops; ++ ++ dev_info(hw->dev, "Ver: %s\n", ST_ASM330LHH_VERSION); ++ err = st_asm330lhh_check_whoami(hw); ++ if (err < 0) ++ return err; ++ ++ err = st_asm330lhh_init_device(hw); ++ if (err < 0) ++ return err; ++ ++ for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { ++ hw->iio_devs[i] = st_asm330lhh_alloc_iiodev(hw, i); ++ if (!hw->iio_devs[i]) ++ return -ENOMEM; ++ } ++ ++ if (hw->irq > 0) { ++ err = st_asm330lhh_fifo_setup(hw); ++ if (err < 0) ++ return err; ++ } ++ ++ for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { ++ if (!hw->iio_devs[i]) ++ continue; ++ ++ err = devm_iio_device_register(hw->dev, hw->iio_devs[i]); ++ if (err) ++ return err; ++ } ++ ++ dev_info(hw->dev, "probe ok\n"); ++ ++ return 0; ++} ++EXPORT_SYMBOL(st_asm330lhh_probe); ++ ++static int __maybe_unused st_asm330lhh_suspend(struct device *dev) ++{ ++ struct st_asm330lhh_hw *hw = dev_get_drvdata(dev); ++ struct st_asm330lhh_sensor *sensor; ++ int i, err = 0; ++ ++ for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { ++ if (!hw->iio_devs[i]) ++ continue; ++ ++ sensor = iio_priv(hw->iio_devs[i]); ++ ++ if (!(hw->enable_mask & BIT(sensor->id))) ++ continue; ++ ++ err = st_asm330lhh_set_odr(sensor, 0); ++ if (err < 0) ++ return err; ++ } ++ ++ if (hw->enable_mask) ++ err = st_asm330lhh_suspend_fifo(hw); ++ ++ return err; ++} ++ ++static int __maybe_unused st_asm330lhh_resume(struct device *dev) ++{ ++ struct st_asm330lhh_hw *hw = dev_get_drvdata(dev); ++ struct st_asm330lhh_sensor *sensor; ++ int i, err = 0; ++ ++ for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { ++ if (!hw->iio_devs[i]) ++ continue; ++ ++ sensor = iio_priv(hw->iio_devs[i]); ++ if (!(hw->enable_mask & BIT(sensor->id))) ++ continue; ++ ++ err = st_asm330lhh_set_odr(sensor, sensor->odr); ++ if (err < 0) ++ return err; ++ } ++ ++ if (hw->enable_mask) ++ err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_CONT); ++ ++ return err; ++} ++ ++const struct dev_pm_ops st_asm330lhh_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(st_asm330lhh_suspend, st_asm330lhh_resume) ++}; ++EXPORT_SYMBOL(st_asm330lhh_pm_ops); ++ ++MODULE_AUTHOR("Lorenzo Bianconi "); ++MODULE_DESCRIPTION("STMicroelectronics st_asm330lhh driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(ST_ASM330LHH_VERSION); +diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_i2c.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_i2c.c +new file mode 100644 +index 0000000..4875097 +--- /dev/null ++++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_i2c.c +@@ -0,0 +1,94 @@ ++/* ++ * STMicroelectronics st_asm330lhh i2c driver ++ * ++ * Copyright 2018 STMicroelectronics Inc. ++ * ++ * Lorenzo Bianconi ++ * ++ * Licensed under the GPL-2. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "st_asm330lhh.h" ++ ++static int st_asm330lhh_i2c_read(struct device *dev, u8 addr, int len, u8 *data) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct i2c_msg msg[2]; ++ ++ msg[0].addr = client->addr; ++ msg[0].flags = client->flags; ++ msg[0].len = 1; ++ msg[0].buf = &addr; ++ ++ msg[1].addr = client->addr; ++ msg[1].flags = client->flags | I2C_M_RD; ++ msg[1].len = len; ++ msg[1].buf = data; ++ ++ return i2c_transfer(client->adapter, msg, 2); ++} ++ ++static int st_asm330lhh_i2c_write(struct device *dev, u8 addr, int len, u8 *data) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct i2c_msg msg; ++ u8 send[len + 1]; ++ ++ send[0] = addr; ++ memcpy(&send[1], data, len * sizeof(u8)); ++ ++ msg.addr = client->addr; ++ msg.flags = client->flags; ++ msg.len = len + 1; ++ msg.buf = send; ++ ++ return i2c_transfer(client->adapter, &msg, 1); ++} ++ ++static const struct st_asm330lhh_transfer_function st_asm330lhh_transfer_fn = { ++ .read = st_asm330lhh_i2c_read, ++ .write = st_asm330lhh_i2c_write, ++}; ++ ++static int st_asm330lhh_i2c_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ return st_asm330lhh_probe(&client->dev, client->irq, ++ &st_asm330lhh_transfer_fn); ++} ++ ++static const struct of_device_id st_asm330lhh_i2c_of_match[] = { ++ { ++ .compatible = "st,asm330lhh", ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, st_asm330lhh_i2c_of_match); ++ ++static const struct i2c_device_id st_asm330lhh_i2c_id_table[] = { ++ { ST_ASM330LHH_DEV_NAME }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(i2c, st_asm330lhh_i2c_id_table); ++ ++static struct i2c_driver st_asm330lhh_driver = { ++ .driver = { ++ .name = "st_asm330lhh_i2c", ++ .pm = &st_asm330lhh_pm_ops, ++ .of_match_table = of_match_ptr(st_asm330lhh_i2c_of_match), ++ }, ++ .probe = st_asm330lhh_i2c_probe, ++ .id_table = st_asm330lhh_i2c_id_table, ++}; ++module_i2c_driver(st_asm330lhh_driver); ++ ++MODULE_AUTHOR("Lorenzo Bianconi "); ++MODULE_DESCRIPTION("STMicroelectronics st_asm330lhh i2c driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(ST_ASM330LHH_VERSION); +diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_spi.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_spi.c +new file mode 100644 +index 0000000..07b8400 +--- /dev/null ++++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_spi.c +@@ -0,0 +1,109 @@ ++/* ++ * STMicroelectronics st_asm330lhh spi driver ++ * ++ * Copyright 2018 STMicroelectronics Inc. ++ * ++ * Lorenzo Bianconi ++ * ++ * Licensed under the GPL-2. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "st_asm330lhh.h" ++ ++#define SENSORS_SPI_READ BIT(7) ++ ++static int st_asm330lhh_spi_read(struct device *dev, u8 addr, int len, ++ u8 *data) ++{ ++ struct spi_device *spi = to_spi_device(dev); ++ struct st_asm330lhh_hw *hw = spi_get_drvdata(spi); ++ int err; ++ ++ struct spi_transfer xfers[] = { ++ { ++ .tx_buf = hw->tb.tx_buf, ++ .bits_per_word = 8, ++ .len = 1, ++ }, ++ { ++ .rx_buf = hw->tb.rx_buf, ++ .bits_per_word = 8, ++ .len = len, ++ } ++ }; ++ ++ hw->tb.tx_buf[0] = addr | SENSORS_SPI_READ; ++ ++ err = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); ++ if (err < 0) ++ return err; ++ ++ memcpy(data, hw->tb.rx_buf, len * sizeof(u8)); ++ ++ return len; ++} ++ ++static int st_asm330lhh_spi_write(struct device *dev, u8 addr, int len, ++ u8 *data) ++{ ++ struct st_asm330lhh_hw *hw; ++ struct spi_device *spi; ++ ++ if (len >= ST_ASM330LHH_TX_MAX_LENGTH) ++ return -ENOMEM; ++ ++ spi = to_spi_device(dev); ++ hw = spi_get_drvdata(spi); ++ ++ hw->tb.tx_buf[0] = addr; ++ memcpy(&hw->tb.tx_buf[1], data, len); ++ ++ return spi_write(spi, hw->tb.tx_buf, len + 1); ++} ++ ++static const struct st_asm330lhh_transfer_function st_asm330lhh_transfer_fn = { ++ .read = st_asm330lhh_spi_read, ++ .write = st_asm330lhh_spi_write, ++}; ++ ++static int st_asm330lhh_spi_probe(struct spi_device *spi) ++{ ++ return st_asm330lhh_probe(&spi->dev, spi->irq, ++ &st_asm330lhh_transfer_fn); ++} ++ ++static const struct of_device_id st_asm330lhh_spi_of_match[] = { ++ { ++ .compatible = "st,asm330lhh", ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, st_asm330lhh_spi_of_match); ++ ++static const struct spi_device_id st_asm330lhh_spi_id_table[] = { ++ { ST_ASM330LHH_DEV_NAME }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(spi, st_asm330lhh_spi_id_table); ++ ++static struct spi_driver st_asm330lhh_driver = { ++ .driver = { ++ .name = "st_asm330lhh_spi", ++ .pm = &st_asm330lhh_pm_ops, ++ .of_match_table = of_match_ptr(st_asm330lhh_spi_of_match), ++ }, ++ .probe = st_asm330lhh_spi_probe, ++ .id_table = st_asm330lhh_spi_id_table, ++}; ++module_spi_driver(st_asm330lhh_driver); ++ ++MODULE_AUTHOR("Lorenzo Bianconi "); ++MODULE_DESCRIPTION("STMicroelectronics st_asm330lhh spi driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(ST_ASM330LHH_VERSION); +-- +2.7.4 + diff --git a/meta-agl-refhw-gen3/recipes-kernel/linux/files/0002-agl-reference-hardware-sample-bsp.patch b/meta-agl-refhw-gen3/recipes-kernel/linux/files/0002-agl-reference-hardware-sample-bsp.patch deleted file mode 100644 index 6763558..0000000 --- a/meta-agl-refhw-gen3/recipes-kernel/linux/files/0002-agl-reference-hardware-sample-bsp.patch +++ /dev/null @@ -1,846 +0,0 @@ ---- - .../arm64/boot/dts/renesas/r8a7795-salvator-xs.dts | 10 - - arch/arm64/boot/dts/renesas/salvator-common.dtsi | 431 ++++++++++----------- - drivers/iio/imu/Kconfig | 1 + - drivers/iio/imu/Makefile | 1 + - drivers/media/i2c/adv748x/adv748x-core.c | 48 ++- - drivers/media/i2c/adv748x/adv748x.h | 12 + - drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 6 +- - 7 files changed, 260 insertions(+), 249 deletions(-) - -diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts -index 498f788..b4236a5 100644 ---- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts -+++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts -@@ -166,16 +166,6 @@ - remote-endpoint = <&rcar_dw_hdmi1_out>; - }; - --&lvds0 { -- ports { -- port@1 { -- lvds0_out: endpoint { -- remote-endpoint = <&lvds_in>; -- }; -- }; -- }; --}; -- - &ohci2 { - status = "okay"; - }; -diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi -index 878ed7c..32d19d9 100644 ---- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi -+++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi -@@ -34,6 +34,10 @@ - aliases { - serial0 = &scif2; - serial1 = &scif1; -+ serial2 = &scif5; -+ serial3 = &hscif1; -+ serial4 = &hscif0; -+ serial5 = &hscif2; - ethernet0 = &avb; - }; - -@@ -62,65 +66,26 @@ - resets = <&cpg 922>; - }; - -- backlight: backlight { -- compatible = "pwm-backlight"; -- pwms = <&pwm1 0 50000>; -- -- brightness-levels = <256 128 64 16 8 4 0>; -- default-brightness-level = <6>; -- -- power-supply = <®_12v>; -- enable-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>; -- }; -- -- cvbs-in { -- compatible = "composite-video-connector"; -- label = "CVBS IN"; -- -- port { -- cvbs_con: endpoint { -- remote-endpoint = <&adv7482_ain7>; -- }; -- }; -- }; -- -- hdmi-in { -+ hdmi0-in { - compatible = "hdmi-connector"; -- label = "HDMI IN"; -+ label = "HDMI0 IN"; - type = "a"; - - port { - hdmi_in_con: endpoint { -- remote-endpoint = <&adv7482_hdmi>; -+ remote-endpoint = <&adv7481_hdmi>; - }; - }; - }; - -- lvds { -- compatible = "panel-lvds"; -- -- width-mm = <210>; -- height-mm = <158>; -- -- data-mapping = "jeida-24"; -- enable-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>; -- -- panel-timing { -- /* 1024x768 @60Hz */ -- clock-frequency = <65000000>; -- hactive = <1024>; -- vactive = <768>; -- hsync-len = <136>; -- hfront-porch = <20>; -- hback-porch = <160>; -- vfront-porch = <3>; -- vback-porch = <29>; -- vsync-len = <6>; -- }; -+ hdmi2-in { -+ compatible = "hdmi-connector"; -+ label = "HDMI2 IN"; -+ type = "a"; - - port { -- lvds_in: endpoint { -- remote-endpoint = <&lvds0_out>; -+ hdmi_in_con2: endpoint { -+ remote-endpoint = <&adv7481_hdmi2>; - }; - }; - }; -@@ -160,17 +125,6 @@ - dais = <&rsnd_port0>; - }; - -- vbus0_usb2: regulator-vbus0-usb2 { -- compatible = "regulator-fixed"; -- -- regulator-name = "USB20_VBUS0"; -- regulator-min-microvolt = <5000000>; -- regulator-max-microvolt = <5000000>; -- -- gpio = <&gpio6 16 GPIO_ACTIVE_HIGH>; -- enable-active-high; -- }; -- - vcc_sdhi0: regulator-vcc-sdhi0 { - compatible = "regulator-fixed"; - -@@ -241,40 +195,6 @@ - }; - }; - -- vga { -- compatible = "vga-connector"; -- no-use-ddc; -- max-pixelclock = <100000>; -- -- port { -- vga_in: endpoint { -- remote-endpoint = <&adv7123_out>; -- }; -- }; -- }; -- -- vga-encoder { -- compatible = "adi,adv7123"; -- -- ports { -- #address-cells = <1>; -- #size-cells = <0>; -- -- port@0 { -- reg = <0>; -- adv7123_in: endpoint { -- remote-endpoint = <&du_out_rgb>; -- }; -- }; -- port@1 { -- reg = <1>; -- adv7123_out: endpoint { -- remote-endpoint = <&vga_in>; -- }; -- }; -- }; -- }; -- - x12_clk: x12 { - compatible = "fixed-clock"; - #clock-cells = <0>; -@@ -325,49 +245,41 @@ - }; - }; - --&csi20 { -+&csi40 { - status = "okay"; - - ports { - port@0 { - reg = <0>; -- csi20_in: endpoint { -+ -+ csi40_in: endpoint { - clock-lanes = <0>; -- data-lanes = <1>; -- remote-endpoint = <&adv7482_txb>; -+ data-lanes = <1 2 3 4>; -+ remote-endpoint = <&adv7481_txa>; - }; - }; - }; - }; - --&csi40 { -+&csi41 { - status = "okay"; - - ports { - port@0 { - reg = <0>; - -- csi40_in: endpoint { -+ csi41_in: endpoint { - clock-lanes = <0>; - data-lanes = <1 2 3 4>; -- remote-endpoint = <&adv7482_txa>; -+ remote-endpoint = <&adv7481_txa2>; - }; - }; - }; - }; - - &du { -- pinctrl-0 = <&du_pins>; -- pinctrl-names = "default"; - status = "okay"; - -- ports { -- port@0 { -- endpoint { -- remote-endpoint = <&adv7123_in>; -- }; -- }; -- }; - }; - - &ehci0 { -@@ -383,12 +295,27 @@ - clock-frequency = <32768>; - }; - -+&hscif0 { -+ pinctrl-0 = <&hscif0_pins>; -+ pinctrl-names = "default"; -+ uart-has-rtscts; -+ -+ status = "okay"; -+}; -+ - &hscif1 { - pinctrl-0 = <&hscif1_pins>; - pinctrl-names = "default"; - - /* Please use exclusively to the scif1 node */ -- /* status = "okay"; */ -+ status = "okay"; -+}; -+ -+&hscif2 { -+ pinctrl-0 = <&hscif2_pins>; -+ pinctrl-names = "default"; -+ -+ status = "okay"; - }; - - &hsusb { -@@ -404,24 +331,65 @@ - - clock-frequency = <100000>; - -- ak4613: codec@10 { -- compatible = "asahi-kasei,ak4613"; -- #sound-dai-cells = <0>; -- reg = <0x10>; -- clocks = <&rcar_sound 3>; -+ video-receiver@70 { -+ compatible = "adi,adv7481"; -+ reg = <0x70>; - -- asahi-kasei,in1-single-end; -- asahi-kasei,in2-single-end; -- asahi-kasei,out1-single-end; -- asahi-kasei,out2-single-end; -- asahi-kasei,out3-single-end; -- asahi-kasei,out4-single-end; -- asahi-kasei,out5-single-end; -- asahi-kasei,out6-single-end; -+ #address-cells = <1>; -+ #size-cells = <0>; - -- port { -- ak4613_endpoint: endpoint { -- remote-endpoint = <&rsnd_endpoint0>; -+ interrupt-parent = <&gpio0>; -+ interrupt-names = "intrq1", "intrq3"; -+ interrupts = <4 IRQ_TYPE_LEVEL_LOW>, -+ <5 IRQ_TYPE_LEVEL_LOW>; -+ -+ port@8 { -+ reg = <8>; -+ -+ adv7481_hdmi: endpoint { -+ remote-endpoint = <&hdmi_in_con>; -+ }; -+ }; -+ -+ port@a { -+ reg = <10>; -+ -+ adv7481_txa: endpoint { -+ clock-lanes = <0>; -+ data-lanes = <1 2 3 4>; -+ remote-endpoint = <&csi40_in>; -+ }; -+ }; -+ -+ }; -+ -+ video-receiver@71 { -+ compatible = "adi,adv7481"; -+ reg = <0x71>; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ interrupt-parent = <&gpio6>; -+ interrupt-names = "intrq1", "intrq3"; -+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>, -+ <1 IRQ_TYPE_LEVEL_LOW>; -+ -+ port@8 { -+ reg = <8>; -+ -+ adv7481_hdmi2: endpoint { -+ remote-endpoint = <&hdmi_in_con2>; -+ }; -+ }; -+ -+ port@a { -+ reg = <10>; -+ -+ adv7481_txa2: endpoint { -+ clock-lanes = <0>; -+ data-lanes = <1 2 3 4>; -+ remote-endpoint = <&csi41_in>; - }; - }; - }; -@@ -438,75 +406,62 @@ - }; - }; - --&i2c4 { -+&i2c3 { -+ pinctrl-0 = <&i2c3_pins>; -+ pinctrl-names = "default"; -+ - status = "okay"; - -- pca9654: gpio@20 { -- compatible = "onnn,pca9654"; -- reg = <0x20>; -- gpio-controller; -- #gpio-cells = <2>; -- }; -+ clock-frequency = <100000>; - -- csa_vdd: adc@7c { -- compatible = "maxim,max9611"; -- reg = <0x7c>; -+ asm330lhh@6a { -+ compatible = "st,asm330lhh"; -+ reg = <0x6a>; - -- shunt-resistor-micro-ohms = <5000>; -+ interrupt-names = "int1", "int2"; -+ interrupts = <&gpio6 23 IRQ_TYPE_EDGE_RISING>, -+ <&gpio2 6 IRQ_TYPE_EDGE_RISING>; - }; -+}; - -- csa_dvfs: adc@7f { -- compatible = "maxim,max9611"; -- reg = <0x7f>; -+&i2c4 { -+ status = "okay"; - -- shunt-resistor-micro-ohms = <5000>; -+ versaclock5: clock-generator@68 { -+ compatible = "idt,9fgv0841"; -+ reg = <0x68>; -+ #clock-cells = <1>; -+ clocks = <&x23_clk>; -+ clock-names = "xin"; - }; -+}; - -- video-receiver@70 { -- compatible = "adi,adv7482"; -- reg = <0x70>; -- -- #address-cells = <1>; -- #size-cells = <0>; -- -- interrupt-parent = <&gpio6>; -- interrupt-names = "intrq1", "intrq2"; -- interrupts = <30 IRQ_TYPE_LEVEL_LOW>, -- <31 IRQ_TYPE_LEVEL_LOW>; -- -- port@7 { -- reg = <7>; -- -- adv7482_ain7: endpoint { -- remote-endpoint = <&cvbs_con>; -- }; -- }; -- -- port@8 { -- reg = <8>; -+&i2c5 { -+ pinctrl-0 = <&i2c5_pins>; -+ pinctrl-names = "default"; - -- adv7482_hdmi: endpoint { -- remote-endpoint = <&hdmi_in_con>; -- }; -- }; -+ status = "okay"; - -- port@a { -- reg = <10>; -+ clock-frequency = <100000>; - -- adv7482_txa: endpoint { -- clock-lanes = <0>; -- data-lanes = <1 2 3 4>; -- remote-endpoint = <&csi40_in>; -- }; -- }; -+ ak4613: codec@10 { -+ compatible = "asahi-kasei,ak4613"; -+ #sound-dai-cells = <0>; -+ reg = <0x10>; -+ clocks = <&rcar_sound 3>; - -- port@b { -- reg = <11>; -+ asahi-kasei,in1-single-end; -+ asahi-kasei,in2-single-end; -+ asahi-kasei,out1-single-end; -+ asahi-kasei,out2-single-end; -+ asahi-kasei,out3-single-end; -+ asahi-kasei,out4-single-end; -+ asahi-kasei,out5-single-end; -+ asahi-kasei,out6-single-end; - -- adv7482_txb: endpoint { -- clock-lanes = <0>; -- data-lanes = <1>; -- remote-endpoint = <&csi20_in>; -+ port { -+ ak4613_endpoint: endpoint { -+ remote-endpoint = <&rsnd_endpoint0>; - }; - }; - }; -@@ -550,10 +505,6 @@ - }; - }; - --&lvds0 { -- status = "okay"; --}; -- - &ohci0 { - dr_mode = "otg"; - status = "okay"; -@@ -565,6 +516,7 @@ - - &pcie_bus_clk { - clock-frequency = <100000000>; -+ status = "okay"; - }; - - &pciec0 { -@@ -575,6 +527,21 @@ - status = "okay"; - }; - -+&canfd { -+ pinctrl-0 = <&canfd0_pins &canfd1_pins>; -+ pinctrl-names = "default"; -+ -+ status = "okay"; -+ -+ channel0 { -+ status = "okay"; -+ }; -+ -+ channel1 { -+ status = "okay"; -+ }; -+}; -+ - &pfc { - pinctrl-0 = <&scif_clk_pins>; - pinctrl-names = "default"; -@@ -597,38 +564,43 @@ - }; - }; - -- du_pins: du { -- groups = "du_rgb888", "du_sync", "du_oddf", "du_clk_out_0"; -- function = "du"; -+ hscif0_pins: hscif0 { -+ groups = "hscif0_data", "hscif0_ctrl"; -+ function = "hscif0"; - }; - - hscif1_pins: hscif1 { -- groups = "hscif1_data_a", "hscif1_ctrl_a"; -+ groups = "hscif1_data_a"; - function = "hscif1"; - }; - -+ hscif2_pins: hscif2 { -+ groups = "hscif2_data_c"; -+ function = "hscif2"; -+ }; -+ - i2c2_pins: i2c2 { - groups = "i2c2_a"; - function = "i2c2"; - }; - -- irq0_pins: irq0 { -- groups = "intc_ex_irq0"; -- function = "intc_ex"; -+ i2c3_pins: i2c3 { -+ groups = "i2c3"; -+ function = "i2c3"; - }; - -- pwm1_pins: pwm1 { -- groups = "pwm1_a"; -- function = "pwm1"; -+ i2c5_pins: i2c5 { -+ groups = "i2c5"; -+ function = "i2c5"; - }; - -- pwm2_pins: pwm2 { -- groups = "pwm2_a"; -- function = "pwm2"; -+ irq0_pins: irq0 { -+ groups = "intc_ex_irq0"; -+ function = "intc_ex"; - }; - - scif1_pins: scif1 { -- groups = "scif1_data_a", "scif1_ctrl"; -+ groups = "scif1_data_b"; - function = "scif1"; - }; - -@@ -637,6 +609,11 @@ - function = "scif2"; - }; - -+ scif5_pins: scif5 { -+ groups = "scif5_data_a"; -+ function = "scif5"; -+ }; -+ - scif_clk_pins: scif_clk { - groups = "scif_clk_a"; - function = "scif_clk"; -@@ -679,13 +656,13 @@ - }; - - sound_pins: sound { -- groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; -+ groups = "ssi349_ctrl", "ssi3_data", "ssi4_data"; - function = "ssi"; - }; - - sound_clk_pins: sound_clk { -- groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a", -- "audio_clkout_a", "audio_clkout3_a"; -+ groups = "audio_clk_a_a", "audio_clk_b_a", -+ "audio_clkout_a", "audio_clkout3_b"; - function = "audio_clk"; - }; - -@@ -695,40 +672,24 @@ - }; - - usb1_pins: usb1 { -- mux { -- groups = "usb1"; -- function = "usb1"; -- }; -- -- ovc { -- pins = "GP_6_27"; -- bias-pull-up; -- }; -- -- pwen { -- pins = "GP_6_26"; -- bias-pull-down; -- }; -+ groups = "usb1"; -+ function = "usb1"; - }; - - usb30_pins: usb30 { - groups = "usb30"; - function = "usb30"; - }; --}; -- --&pwm1 { -- pinctrl-0 = <&pwm1_pins>; -- pinctrl-names = "default"; -- -- status = "okay"; --}; - --&pwm2 { -- pinctrl-0 = <&pwm2_pins>; -- pinctrl-names = "default"; -+ canfd0_pins: canfd0 { -+ groups = "canfd0_data_a"; -+ function = "canfd0"; -+ }; - -- status = "okay"; -+ canfd1_pins: canfd1 { -+ groups = "canfd1_data"; -+ function = "canfd1"; -+ }; - }; - - &rcar_sound { -@@ -775,8 +736,8 @@ - bitclock-master = <&rsnd_endpoint0>; - frame-master = <&rsnd_endpoint0>; - -- playback = <&ssi0 &src0 &dvc0>; -- capture = <&ssi1 &src1 &dvc1>; -+ playback = <&ssi3>; //ssi0 -> ssi3 -+ capture = <&ssi4>; //ssi1 -> ssi4 - }; - }; - }; -@@ -803,6 +764,13 @@ - status = "okay"; - }; - -+&scif5 { -+ pinctrl-0 = <&scif5_pins>; -+ pinctrl-names = "default"; -+ -+ status = "okay"; -+}; -+ - &scif_clk { - clock-frequency = <14745600>; - }; -@@ -857,7 +825,7 @@ - status = "okay"; - }; - --&ssi1 { -+&ssi4 { - shared-pin; - }; - -@@ -869,7 +837,6 @@ - pinctrl-0 = <&usb0_pins>; - pinctrl-names = "default"; - -- vbus-supply = <&vbus0_usb2>; - status = "okay"; - }; - -diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig -index 156630a..463210d 100644 ---- a/drivers/iio/imu/Kconfig -+++ b/drivers/iio/imu/Kconfig -@@ -40,6 +40,7 @@ config KMX61 - - source "drivers/iio/imu/inv_mpu6050/Kconfig" - source "drivers/iio/imu/st_lsm6dsx/Kconfig" -+source "drivers/iio/imu/st_asm330lhh/Kconfig" - - endmenu - -diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile -index 68629c68..349a7de 100644 ---- a/drivers/iio/imu/Makefile -+++ b/drivers/iio/imu/Makefile -@@ -20,3 +20,4 @@ obj-y += inv_mpu6050/ - obj-$(CONFIG_KMX61) += kmx61.o - - obj-y += st_lsm6dsx/ -+obj-y += st_asm330lhh/ -diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c -index da8f062..c2b37f7 100644 ---- a/drivers/media/i2c/adv748x/adv748x-core.c -+++ b/drivers/media/i2c/adv748x/adv748x-core.c -@@ -165,6 +165,21 @@ static int adv748x_i2c_addresses[ADV748X_PAGE_MAX] = { - ADV748X_I2C_TXA, - }; - -+/* Default addresses for the I2C pages 0x71*/ -+static int adv748x_i2c_addresses2[ADV748X_PAGE_MAX] = { -+ ADV748X_I2C_IO2, -+ ADV748X_I2C_DPLL2, -+ ADV748X_I2C_CP2, -+ ADV748X_I2C_HDMI2, -+ ADV748X_I2C_EDID2, -+ ADV748X_I2C_REPEATER2, -+ ADV748X_I2C_INFOFRAME2, -+ ADV748X_I2C_CEC2, -+ ADV748X_I2C_SDP2, -+ ADV748X_I2C_TXB2, -+ ADV748X_I2C_TXA2, -+}; -+ - static int adv748x_read_check(struct adv748x_state *state, - int client_page, u8 reg) - { -@@ -238,9 +253,16 @@ static int adv748x_initialise_clients(struct adv748x_state *state) - int ret; - - for (i = ADV748X_PAGE_DPLL; i < ADV748X_PAGE_MAX; ++i) { -- state->i2c_clients[i] = -- adv748x_dummy_client(state, adv748x_i2c_addresses[i], -- ADV748X_IO_SLAVE_ADDR_BASE + i); -+ if((state->client->addr << 1) == 0xe0) { -+ state->i2c_clients[i] = -+ adv748x_dummy_client(state, adv748x_i2c_addresses[i], -+ ADV748X_IO_SLAVE_ADDR_BASE + i); -+ } else { -+ state->i2c_clients[i] = -+ adv748x_dummy_client(state, adv748x_i2c_addresses2[i], -+ ADV748X_IO_SLAVE_ADDR_BASE + i); -+ } -+ - if (state->i2c_clients[i] == NULL) { - adv_err(state, "failed to create i2c client %u\n", i); - return -ENOMEM; -@@ -508,6 +530,20 @@ static const struct adv748x_reg_value adv748x_set_slave_address[] = { - {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ - }; - -+static const struct adv748x_reg_value adv748x_set_slave_address2[] = { -+ {ADV748X_PAGE_IO, 0xf3, ADV748X_I2C_DPLL2 << 1}, -+ {ADV748X_PAGE_IO, 0xf4, ADV748X_I2C_CP2 << 1}, -+ {ADV748X_PAGE_IO, 0xf5, ADV748X_I2C_HDMI2 << 1}, -+ {ADV748X_PAGE_IO, 0xf6, ADV748X_I2C_EDID2 << 1}, -+ {ADV748X_PAGE_IO, 0xf7, ADV748X_I2C_REPEATER2 << 1}, -+ {ADV748X_PAGE_IO, 0xf8, ADV748X_I2C_INFOFRAME2 << 1}, -+ {ADV748X_PAGE_IO, 0xfa, ADV748X_I2C_CEC2 << 1}, -+ {ADV748X_PAGE_IO, 0xfb, ADV748X_I2C_SDP2 << 1}, -+ {ADV748X_PAGE_IO, 0xfc, ADV748X_I2C_TXB2 << 1}, -+ {ADV748X_PAGE_IO, 0xfd, ADV748X_I2C_TXA2 << 1}, -+ {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ -+}; -+ - /* Supported Formats For Script Below */ - /* - 01-29 HDMI to MIPI TxA CSI 4-Lane - RGB888: */ - static const struct adv748x_reg_value adv748x_init_txa_4lane[] = { -@@ -683,7 +719,11 @@ static int adv748x_reset(struct adv748x_state *state) - if (ret < 0) - return ret; - -- ret = adv748x_write_regs(state, adv748x_set_slave_address); -+ if((state->client->addr << 1) == 0xe0) { -+ ret = adv748x_write_regs(state, adv748x_set_slave_address); //i2c address 0x70 -+ } else { -+ ret = adv748x_write_regs(state, adv748x_set_slave_address2); //i2c address 0x71 -+ } - if (ret < 0) - return ret; - -diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h -index fb30bfa..ac50a9e 100644 ---- a/drivers/media/i2c/adv748x/adv748x.h -+++ b/drivers/media/i2c/adv748x/adv748x.h -@@ -40,6 +40,18 @@ - #define ADV748X_I2C_TXB 0x48 /* CSI-TXB Map */ - #define ADV748X_I2C_TXA 0x4a /* CSI-TXA Map */ - -+#define ADV748X_I2C_IO2 0x71 /* IO Map */ -+#define ADV748X_I2C_DPLL2 0x27 /* DPLL Map */ -+#define ADV748X_I2C_CP2 0x23 /* CP Map */ -+#define ADV748X_I2C_HDMI2 0x35 /* HDMI Map */ -+#define ADV748X_I2C_EDID2 0x37 /* EDID Map */ -+#define ADV748X_I2C_REPEATER2 0x33 /* HDMI RX Repeater Map */ -+#define ADV748X_I2C_INFOFRAME2 0x30 /* HDMI RX InfoFrame Map */ -+#define ADV748X_I2C_CEC2 0x42 /* CEC Map */ -+#define ADV748X_I2C_SDP2 0x78 /* SDP Map */ -+#define ADV748X_I2C_TXB2 0x49 /* CSI-TXB Map */ -+#define ADV748X_I2C_TXA2 0x4b /* CSI-TXA Map */ -+ - enum adv748x_page { - ADV748X_PAGE_IO, - ADV748X_PAGE_DPLL, -diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c -index 3ebe8de..546761c 100644 ---- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c -+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c -@@ -3912,7 +3912,7 @@ static const unsigned int tmu_tclk2_b_mux[] = { - /* - USB0 ------------------------------------------------------------------- */ - static const unsigned int usb0_pins[] = { - /* PWEN, OVC */ -- RCAR_GP_PIN(6, 24), RCAR_GP_PIN(6, 25), -+ RCAR_GP_PIN(6, 24), - }; - static const unsigned int usb0_mux[] = { - USB0_PWEN_MARK, USB0_OVC_MARK, -@@ -3920,7 +3920,7 @@ static const unsigned int usb0_mux[] = { - /* - USB1 ------------------------------------------------------------------- */ - static const unsigned int usb1_pins[] = { - /* PWEN, OVC */ -- RCAR_GP_PIN(6, 26), RCAR_GP_PIN(6, 27), -+ RCAR_GP_PIN(6, 27), - }; - static const unsigned int usb1_mux[] = { - USB1_PWEN_MARK, USB1_OVC_MARK, -@@ -3936,7 +3936,7 @@ static const unsigned int usb2_mux[] = { - /* - USB2_CH3 --------------------------------------------------------------- */ - static const unsigned int usb2_ch3_pins[] = { - /* PWEN, OVC */ -- RCAR_GP_PIN(6, 30), RCAR_GP_PIN(6, 31), -+ RCAR_GP_PIN(6, 30), - }; - static const unsigned int usb2_ch3_mux[] = { - USB2_CH3_PWEN_MARK, USB2_CH3_OVC_MARK, --- -2.7.4 - diff --git a/meta-agl-refhw-gen3/recipes-kernel/linux/linux-renesas_%.bbappend b/meta-agl-refhw-gen3/recipes-kernel/linux/linux-renesas_%.bbappend index 3a77619..a9cdd0c 100644 --- a/meta-agl-refhw-gen3/recipes-kernel/linux/linux-renesas_%.bbappend +++ b/meta-agl-refhw-gen3/recipes-kernel/linux/linux-renesas_%.bbappend @@ -1,12 +1,10 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" SRC_URI_append = " \ - file://0002-Introduce-dts-file-for-refhw-r-car-board.patch \ - file://0001-add-st_asm330lhh-driver.patch \ - file://0002-agl-reference-hardware-sample-bsp.patch \ + file://0001-create-r8a7795-usb-ovc-pinmux-groups.patch \ + file://0001-add-agl-refhw.patch \ + file://0002-add-st_asm330lhh-driver.patch \ file://refhw-rcar.cfg \ " -KERNEL_CONFIG_FRAGMENTS_append = " ${WORKDIR}/refhw-rcar.cfg " - -KERNEL_DEVICETREE_refhw = "renesas/r8a7795-refhw.dtb" +KERNEL_CONFIG_FRAGMENTS_append = " ${WORKDIR}/refhw-rcar.cfg" -- cgit 1.2.3-korg