Merge tag 'dey-2.6-r1.3' into dey-2.6/master
Digi Embedded Yocto 2.6-r1.3 Manually changed recipes to use the master branches instead of the fixed SHA1 from the last release. Signed-off-by: Arturo Buzarra <arturo.buzarra@digi.com>
This commit is contained in:
commit
21b09d616d
116
README.md
116
README.md
|
|
@ -1,10 +1,10 @@
|
|||
# Digi Embedded Yocto (DEY) 2.4
|
||||
## Release 2.4-r2.2
|
||||
# Digi Embedded Yocto (DEY) 2.6
|
||||
## Release 2.6-r1.3
|
||||
|
||||
This document provides information about Digi Embedded Yocto,
|
||||
Digi International's professional embedded Yocto development environment.
|
||||
|
||||
Digi Embedded Yocto 2.4 is based on the Yocto Project(TM) 2.4 (Rocko) release.
|
||||
Digi Embedded Yocto 2.6 is based on the Yocto Project(TM) 2.6 (Thud) release.
|
||||
|
||||
For a full list of supported features and interfaces please refer to the
|
||||
online documentation.
|
||||
|
|
@ -32,32 +32,6 @@ Software for the following hardware platforms is in production support:
|
|||
* [CC-WMX6UL-KIT](https://www.digi.com/products/models/cc-wmx6ul-kit) ([Get Started](https://www.digi.com/resources/documentation/digidocs/90001547/default.htm#concept/yocto/c_get_started_with_yocto.htm))
|
||||
* [CC-SBP-WMX-JN58](https://www.digi.com/products/models/cc-sbp-wmx-jn58)
|
||||
|
||||
## ConnectCore 6
|
||||
* ConnectCore 6 System-on-Module (SOM)
|
||||
* [CC-WMX-J97C-TN](https://www.digi.com/products/models/cc-wmx-j97c-tn)
|
||||
* [CC-WMX-L96C-TE](https://www.digi.com/products/models/cc-wmx-l96c-te)
|
||||
* [CC-WMX-L87C-TE](https://www.digi.com/products/models/cc-wmx-l87c-te)
|
||||
* [CC-MX-L76C-Z1](https://www.digi.com/products/models/cc-mx-l76c-z1)
|
||||
* [CC-MX-L86C-Z1](https://www.digi.com/products/models/cc-mx-l86c-z1)
|
||||
* [CC-MX-L96C-Z1](https://www.digi.com/products/models/cc-mx-l96c-z1)
|
||||
* [CC-WMX-L76C-TE](https://www.digi.com/products/models/cc-wmx-l76c-te)
|
||||
* CC-WMX-K87C-FJA
|
||||
* CC-WMX-K77C-TE
|
||||
* CC-WMX-L97D-TN
|
||||
* CC-WMX-J98C-FJA
|
||||
* CC-WMX-J98C-FJA-1
|
||||
* ConnectCore 6 SBC
|
||||
* [CC-WMX6-KIT](https://www.digi.com/products/models/cc-wmx6-kit) ([Get Started](https://www.digi.com/resources/documentation/digidocs/90001546/default.htm#concept/yocto/c_get_started_with_yocto.htm))
|
||||
* [CC-SB-WMX-J97C-1](https://www.digi.com/products/models/cc-sb-wmx-j97c-1)
|
||||
* [CC-SB-WMX-L87C-1](https://www.digi.com/products/models/cc-sb-wmx-l87c-1)
|
||||
* [CC-SB-WMX-L76C-1](https://www.digi.com/products/models/cc-sb-wmx-l76c-1)
|
||||
|
||||
## ConnectCore 6 Plus
|
||||
* ConnectCore 6 Plus System-on-Module (SOM)
|
||||
* CC-WMX-KK8D-TN
|
||||
* ConnectCore 6 Plus SBC
|
||||
* CC-SB-WMX-KK8D
|
||||
|
||||
## ConnectCore 8X
|
||||
* ConnectCore 8X System-on-Module (SOM)
|
||||
* [CC-WMX-JM7D-NN](https://www.digi.com/cc8x)
|
||||
|
|
@ -76,7 +50,7 @@ hardware.
|
|||
# Installation
|
||||
|
||||
Digi Embedded Yocto is composed of a set of different Yocto layers that work in
|
||||
parallel. The layers are specified on a [manifest](https://github.com/digi-embedded/dey-manifest/blob/rocko/default.xml) file.
|
||||
parallel. The layers are specified on a [manifest](https://github.com/digi-embedded/dey-manifest/blob/thud/default.xml) file.
|
||||
|
||||
To install, please follow the instructions at the dey-manifest [README](https://github.com/digi-embedded/dey-manifest)
|
||||
|
||||
|
|
@ -86,42 +60,34 @@ Documentation is available online at https://www.digi.com/resources/documentatio
|
|||
|
||||
# Downloads
|
||||
|
||||
* Demo images: ftp://ftp1.digi.com/support/digiembeddedyocto/2.4/r2/images/
|
||||
* Software Development Kit (SDK): ftp://ftp1.digi.com/support/digiembeddedyocto/2.4/r2/sdk/
|
||||
* Demo images: ftp://ftp1.digi.com/support/digiembeddedyocto/2.6/r1/images/
|
||||
* Software Development Kit (SDK): ftp://ftp1.digi.com/support/digiembeddedyocto/2.6/r1/sdk/
|
||||
|
||||
# Release Changelog
|
||||
|
||||
## 2.4-r2.1
|
||||
## 2.6-r1
|
||||
|
||||
* Added support for ConnectCore 8X platform. Supported features:
|
||||
* Bluetooth and Wireless interfaces (STA, SoftAP, P2P, Concurrence)
|
||||
* MCA: Reset, Watchdog, RTC, GPIOs and ADCs
|
||||
* Updated U-Boot to version 2017.03-r2
|
||||
* Fixed XBee RESET_N polarity assertion. Requires updating polarity of the
|
||||
``digi,reset-gpio`` property of node ``xbee`` on device tree files derived from
|
||||
ConnectCore 6UL SBC Pro to use polarity **GPIO_ACTIVE_LOW**
|
||||
* Updated AWS Greengrass core to version 1.7.0
|
||||
* Updated kernel version to v4.9.135 for i.MX6 and i.MX6UL platforms.
|
||||
|
||||
## 2.4-r1
|
||||
|
||||
* Release based on [Yocto 2.4 (Rocko)](https://www.yoctoproject.org/downloads/core/rocko24) including:
|
||||
* New toolchain based on GCC-7.2.0 and GLIBC-2.26
|
||||
* Updated Qt 5.9.4
|
||||
* Release based on [Yocto 2.6 (Thud)](https://www.yoctoproject.org/software-overview/downloads) including:
|
||||
* New toolchain based on GLIBC-2.28
|
||||
* Updated Qt 5.11.3
|
||||
* Updated NetworkManager to v1.14.4
|
||||
* Updated Wpa-supplicant to v2.6
|
||||
* Updated gstreamer1.0 to v1.14.0
|
||||
* Updated busybox to v1.29.2
|
||||
* Updated bluez5 to v5.50
|
||||
* Updated OpenSSL to v1.1.1a
|
||||
* Package upgrades and security fixes
|
||||
* Updated kernel version to v4.9 for ConnectCore 6 platform
|
||||
* Updated U-Boot to version 2015.04-r12
|
||||
* Updated Cryptoauthlib version to v3.0
|
||||
* Added support for Goodix 10" display
|
||||
* Updated documentation
|
||||
* Updated kernel version to v4.14.111 for i.MX8X and i.MX6UL platforms
|
||||
* Updated U-Boot to version 2018.03-r1 for i.MX8X platform
|
||||
* Updated AWS Greengrass core to version 1.8.0
|
||||
* Added support for Code Signing Tool 3.1.0
|
||||
* Changed initialization manager in ConnectCore 8X platforms to systemd
|
||||
|
||||
# Known Issues and Limitations
|
||||
|
||||
This is a list of known issues and limitations at the time of release. An
|
||||
updated list can be found on the online documentation.
|
||||
|
||||
* If TrustFence (TM) image encryption support is enabled, the uSD image will
|
||||
boot a signed U-Boot only.
|
||||
* Firmware update
|
||||
* The software update package must be located in the root level of the
|
||||
update media (subfolders are not yet supported).
|
||||
|
|
@ -129,9 +95,9 @@ boot a signed U-Boot only.
|
|||
* Remote file system management fails with long file names and paths
|
||||
(over 255 characters).
|
||||
* For P2P connections Digi recommends "Negotiated GO" modes. The QCA6564
|
||||
devices (ConnectCore 6UL and ConnectCore 6 Plus) running a 4.9 kernel
|
||||
version fail to join to autonomous groups.
|
||||
* Trustfence secure console is not supported on U-Boot v2017.03. In order to use this functionality, U-Boot v2015.04 will be required.
|
||||
devices (ConnectCore 6UL) running a 4.14 kernel version fail to join to
|
||||
autonomous groups.
|
||||
* Trustfence is not yet supported on U-Boot v2018.03.
|
||||
|
||||
## ConnectCore 6UL
|
||||
|
||||
|
|
@ -152,39 +118,9 @@ boot a signed U-Boot only.
|
|||
currently supported.
|
||||
* The QCA6564 wireless chip does not support Wake On Wireless LAN.
|
||||
|
||||
## ConnectCore 6
|
||||
|
||||
* ConnectCore 6 System-on-Module (SOM)
|
||||
* NXP i.MX6 processor has a documented errata (ERR004512) whereby the maximum
|
||||
performance of the Gigabit FEC is limited to 400Mbps (total for Tx and Rx).
|
||||
* When using softAP mode on Band A on the Qualcomm AR6233, channels used for
|
||||
Dynamic Frequency Selection (DFS) are not supported.
|
||||
* The Qualcomm AR6233 firmware does not support the following configuration
|
||||
modes:
|
||||
* Concurrent modes involving P2P mode, such as P2P + softAP or P2P + STA.
|
||||
* Bluetooth + softAP + STA concurrent mode.
|
||||
* A maximum of five clients are supported when using Qualcomm's AR6233 in
|
||||
softAP mode.
|
||||
* A maximum of ten connected devices are supported when using Qualcomm's AR6233
|
||||
Bluetooth Low Energy mode.
|
||||
* ConnectCore 6 SBC
|
||||
* The Micrel PHY KSZ9031 may take between five and six seconds to
|
||||
auto-negotiate with Gigabit switches.
|
||||
|
||||
## ConnectCore 6 Plus
|
||||
|
||||
* ConnectCore 6 Plus System-on-Module (SOM)
|
||||
* NXP i.MX6QP processor has a documented errata (ERR004512) whereby the maximum
|
||||
performance of the Gigabit FEC is limited to 400Mbps (total for Tx and Rx).
|
||||
* ConnectCore 6 Plus SBC
|
||||
* The Micrel PHY KSZ9031 may take between five and six seconds to
|
||||
auto-negotiate with Gigabit switches.
|
||||
|
||||
## ConnectCore 8X
|
||||
|
||||
* i.MX8QXP Processor
|
||||
* The following processor features are not supported in this BSP release:
|
||||
Power Management, PWM, ADC, RS485. They will be implemented in future releases.
|
||||
* GPU maximum performance reduced. The maximum frequency targets are 850 MHz
|
||||
for the shaders and 700 MHz for the core. However, in this hardware release
|
||||
the maximum frequency is limited to 650 MHz for the shaders and 600 MHz for
|
||||
|
|
@ -192,10 +128,8 @@ boot a signed U-Boot only.
|
|||
be met in future releases of the hardware.
|
||||
* BSDL operation is not supported. It will be available in future releases
|
||||
of the hardware.
|
||||
* ConnectCore 8X SBC Pro
|
||||
* USB 3.0 not supported.
|
||||
* Digi Embedded Yocto
|
||||
* The following features are not supported in this release for the ConnectCore 8X plaform:
|
||||
* The following features are not supported in this release for the ConnectCore 8X platform:
|
||||
* Trustfence (TM)
|
||||
* Digi Remote Manager
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ KERNEL_DEVICETREE ?= " \
|
|||
KERNEL_DEVICETREE_use-mainline-bsp ?= "imx6ul-ccimx6ulsbcpro.dtb"
|
||||
|
||||
KERNEL_DEFCONFIG ?= "arch/arm/configs/ccimx6ul_defconfig"
|
||||
KERNEL_DEFCONFIG_use-mainline-bsp ?= "arch/arm/configs/imx_v6_v7_defconfig"
|
||||
|
||||
SERIAL_CONSOLES ?= "115200;ttymxc4"
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ KERNEL_DEVICETREE ?= " \
|
|||
KERNEL_DEVICETREE_use-mainline-bsp ?= "imx6ul-ccimx6ulsbcexpress.dtb"
|
||||
|
||||
KERNEL_DEFCONFIG ?= "arch/arm/configs/ccimx6ul_defconfig"
|
||||
KERNEL_DEFCONFIG_use-mainline-bsp ?= "arch/arm/configs/imx_v6_v7_defconfig"
|
||||
|
||||
SERIAL_CONSOLES ?= "115200;ttymxc4"
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ SERIAL_CONSOLES ?= "115200;ttyLP2"
|
|||
# Bluetooth tty
|
||||
BT_TTY ?= "ttyLP1"
|
||||
|
||||
# XBee
|
||||
XBEE_RESET_N_GPIO ?= "397"
|
||||
XBEE_SLEEP_RQ_GPIO ?= "400"
|
||||
|
||||
# U-Boot script to be copied to the boot image
|
||||
BOOT_SCRIPTS = "boot.scr:boot.scr"
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ SERIAL_CONSOLES ?= "115200;ttyLP2"
|
|||
# Bluetooth tty
|
||||
BT_TTY ?= "ttyLP1"
|
||||
|
||||
# XBee
|
||||
XBEE_RESET_N_GPIO ?= "220"
|
||||
XBEE_SLEEP_RQ_GPIO ?= "216"
|
||||
|
||||
# U-Boot script to be copied to the boot image
|
||||
BOOT_SCRIPTS = "boot.scr:boot.scr"
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ MACHINE_EXTRA_RDEPENDS += " \
|
|||
mca-tool \
|
||||
parted \
|
||||
u-boot-fw-utils \
|
||||
xbee-init \
|
||||
"
|
||||
|
||||
MACHINE_EXTRA_RRECOMMENDS += " \
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ PREFERRED_PROVIDER_jpeg-native ?= "jpeg-native"
|
|||
PREFERRED_PROVIDER_u-boot ??= "u-boot-dey"
|
||||
PREFERRED_PROVIDER_virtual/bootloader ??= "u-boot-dey"
|
||||
PREFERRED_PROVIDER_virtual/kernel ??= "linux-dey"
|
||||
PREFERRED_PROVIDER_virtual/kernel_use-mainline-bsp ??= "linux-4.20.y"
|
||||
PREFERRED_PROVIDER_virtual/kernel_use-mainline-bsp ??= "linux-fslc"
|
||||
PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg"
|
||||
|
||||
#
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ IMX_M4_DEMOS = "imx-m4-demos"
|
|||
# so set the appropriate dependencies
|
||||
do_compile[depends] += " \
|
||||
${@' '.join('%s:do_deploy' % r for r in '${IMX_M4_DEMOS}'.split() )} \
|
||||
firmware-imx:do_deploy \
|
||||
"
|
||||
|
||||
# This package aggregates dependencies with other packages,
|
||||
|
|
@ -23,6 +24,7 @@ do_populate_lic[depends] += " \
|
|||
${@' '.join('%s:do_populate_lic' % r for r in '${IMX_EXTRA_FIRMWARE}'.split() )} \
|
||||
imx-atf:do_populate_lic \
|
||||
${@' '.join('%s:do_populate_lic' % r for r in '${IMX_M4_DEMOS}'.split() )} \
|
||||
firmware-imx:do_populate_lic \
|
||||
"
|
||||
|
||||
UBOOT_NAME = "u-boot-${MACHINE}.bin"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ else
|
|||
#
|
||||
# Set device tree filename depending on the hardware variant
|
||||
#
|
||||
if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x04"; then
|
||||
if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x04" || test "${module_variant}" = "0x06"; then
|
||||
setenv fdt_file imx6ul-ccimx6ulsbc-wb.dtb
|
||||
elif test "${module_variant}" = "0x03" || test "${module_variant}" = "0x05"; then
|
||||
setenv fdt_file imx6ul-ccimx6ulsbc.dtb
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ fi
|
|||
|
||||
# Determine U-Boot file to program basing on module variant
|
||||
if test -n "${module_variant}"; then
|
||||
if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x03"; then
|
||||
if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x03" || test "${module_variant}" = "0x06"; then
|
||||
setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6ulsbc.imx;
|
||||
elif test "${module_variant}" = "0x04" || test "${module_variant}" = "0x05"; then
|
||||
setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6ulsbc1GB.imx;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ else
|
|||
#
|
||||
# Set device tree filename depending on the hardware variant
|
||||
#
|
||||
if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x04"; then
|
||||
if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x04" || test "${module_variant}" = "0x06"; then
|
||||
setenv fdt_file imx6ul-ccimx6ulstarter-wb.dtb
|
||||
elif test "${module_variant}" = "0x03" || test "${module_variant}" = "0x05"; then
|
||||
setenv fdt_file imx6ul-ccimx6ulstarter.dtb
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ fi
|
|||
|
||||
# Determine U-Boot file to program basing on module variant
|
||||
if test -n "${module_variant}"; then
|
||||
if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x03"; then
|
||||
if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x03" || test "${module_variant}" = "0x06"; then
|
||||
setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6ulstarter.imx;
|
||||
elif test "${module_variant}" = "0x04" || test "${module_variant}" = "0x05"; then
|
||||
setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6ulstarter1GB.imx;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
# Copyright (C) 2019 Digi International.
|
||||
|
||||
# The most recent version of this tool is unable to boot closed devices.
|
||||
# Revert to the version that was used in DEY 2.4.
|
||||
SRCREV = "349286e25c3fd9b2d31b31e962340123bbc62d44"
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# Copyright (C) 2019 Digi International
|
||||
|
||||
require recipes-kernel/linux/linux-dey.inc
|
||||
|
||||
SRCBRANCH = "v4.20.y"
|
||||
SRCREV = "${AUTOREV}"
|
||||
|
||||
DEPENDS += "openssl-native"
|
||||
HOST_EXTRACFLAGS += "-I${STAGING_INCDIR_NATIVE}"
|
||||
|
||||
COMPATIBLE_MACHINE = "(ccimx6ul)"
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
SUMMARY = "Linux kernel for Digi boards"
|
||||
LICENSE = "GPLv2"
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"
|
||||
LIC_FILES_CHKSUM_use-mainline-bsp = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
|
||||
|
||||
DEPENDS += "lzop-native bc-native"
|
||||
DEPENDS += "${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', 'trustfence-sign-tools-native', '', d)}"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,167 @@
|
|||
From 2313935f3b195aa7d930961bcd44a5fac61a945e Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Fri, 20 Apr 2018 19:13:02 +0200
|
||||
Subject: [PATCH] ARM: Add support for the ConnectCore 6UL System-On-Module
|
||||
|
||||
* Getter functions for hwid information
|
||||
* Define "digi,ccimx6ul" in the compatible property so the MCA can be
|
||||
managed using the available tools.
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts | 2 +-
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts | 3 +-
|
||||
arch/arm/configs/imx_v6_v7_defconfig | 2 +-
|
||||
arch/arm/mach-imx/Kconfig | 8 +++
|
||||
arch/arm/mach-imx/Makefile | 2 +-
|
||||
arch/arm/mach-imx/som-ccimx6ul.c | 69 +++++++++++++++++++++++++
|
||||
6 files changed, 82 insertions(+), 4 deletions(-)
|
||||
create mode 100644 arch/arm/mach-imx/som-ccimx6ul.c
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts
|
||||
index 3792679c0c90..dc773f350999 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts
|
||||
@@ -15,7 +15,7 @@
|
||||
/ {
|
||||
model = "Digi International ConnectCore 6UL SBC Express.";
|
||||
compatible = "digi,ccimx6ulsbcexpress", "digi,ccimx6ulsom",
|
||||
- "fsl,imx6ul";
|
||||
+ "digi,ccimx6ul", "fsl,imx6ul";
|
||||
};
|
||||
|
||||
&adc1 {
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
index 3749fdda3611..aed1db57ed3b 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
/ {
|
||||
model = "Digi International ConnectCore 6UL SBC Pro.";
|
||||
- compatible = "digi,ccimx6ulsbcpro", "digi,ccimx6ulsom", "fsl,imx6ul";
|
||||
+ compatible = "digi,ccimx6ulsbcpro", "digi,ccimx6ulsom",
|
||||
+ "digi,ccimx6ul", "fsl,imx6ul";
|
||||
|
||||
lcd_backlight: backlight {
|
||||
compatible = "pwm-backlight";
|
||||
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
index 6985d61eddb3..2d32ab117fb5 100644
|
||||
--- a/arch/arm/configs/imx_v6_v7_defconfig
|
||||
+++ b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
@@ -36,7 +36,7 @@ CONFIG_SOC_IMX6Q=y
|
||||
CONFIG_SOC_IMX6SL=y
|
||||
CONFIG_SOC_IMX6SLL=y
|
||||
CONFIG_SOC_IMX6SX=y
|
||||
-CONFIG_SOC_IMX6UL=y
|
||||
+CONFIG_SOM_CC6UL=y
|
||||
CONFIG_SOC_IMX7D=y
|
||||
CONFIG_SOC_VF610=y
|
||||
CONFIG_PCI=y
|
||||
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
|
||||
index abc337111eff..2451ee423496 100644
|
||||
--- a/arch/arm/mach-imx/Kconfig
|
||||
+++ b/arch/arm/mach-imx/Kconfig
|
||||
@@ -523,6 +523,14 @@ config SOC_IMX6UL
|
||||
help
|
||||
This enables support for Freescale i.MX6 UltraLite processor.
|
||||
|
||||
+config SOM_CC6UL
|
||||
+ bool "Digi ConnectCore 6UL System-On-Module support"
|
||||
+ select SOC_IMX6UL
|
||||
+ select SOC_IMX6
|
||||
+
|
||||
+ help
|
||||
+ This enables support for Digi ConnectCore 6UL System-On-Module.
|
||||
+
|
||||
config SOC_LS1021A
|
||||
bool "Freescale LS1021A support"
|
||||
select ARM_GIC
|
||||
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
|
||||
index bae179af21f6..0cd7cdfc5e49 100644
|
||||
--- a/arch/arm/mach-imx/Makefile
|
||||
+++ b/arch/arm/mach-imx/Makefile
|
||||
@@ -83,7 +83,7 @@ obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
|
||||
obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o
|
||||
obj-$(CONFIG_SOC_IMX7D_CA7) += mach-imx7d.o
|
||||
obj-$(CONFIG_SOC_IMX7D_CM4) += mach-imx7d-cm4.o
|
||||
-
|
||||
+obj-$(CONFIG_SOM_CC6UL) += som-ccimx6ul.o
|
||||
ifeq ($(CONFIG_SUSPEND),y)
|
||||
AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
|
||||
obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
|
||||
diff --git a/arch/arm/mach-imx/som-ccimx6ul.c b/arch/arm/mach-imx/som-ccimx6ul.c
|
||||
new file mode 100644
|
||||
index 000000000000..269b526ee020
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-imx/som-ccimx6ul.c
|
||||
@@ -0,0 +1,69 @@
|
||||
+/*
|
||||
+ * Copyright 2018 Digi International Inc
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/export.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/string.h>
|
||||
+
|
||||
+static int digi_board_version = -EINVAL;
|
||||
+
|
||||
+int digi_get_board_version(void)
|
||||
+{
|
||||
+ struct device_node *np = NULL;
|
||||
+ const char *boardver_str;
|
||||
+ char buf[4];
|
||||
+
|
||||
+ /* Only need to read the carrier board once */
|
||||
+ if (digi_board_version > 0)
|
||||
+ return digi_board_version;
|
||||
+
|
||||
+ np = of_find_node_by_path("/");
|
||||
+ if (!np)
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ if (!of_property_read_string(np, "digi,carrierboard,version",
|
||||
+ &boardver_str)) {
|
||||
+ strncpy(buf, boardver_str, sizeof(buf));
|
||||
+ if (!kstrtoint(boardver_str, 10, &digi_board_version))
|
||||
+ pr_debug("Board version: %d\n", digi_board_version);
|
||||
+ }
|
||||
+ of_node_put(np);
|
||||
+
|
||||
+ return digi_board_version;
|
||||
+}
|
||||
+EXPORT_SYMBOL(digi_get_board_version);
|
||||
+
|
||||
+static int digi_som_hv = -EINVAL;
|
||||
+
|
||||
+int digi_get_som_hv(void)
|
||||
+{
|
||||
+ struct device_node *np = NULL;
|
||||
+ const char *som_hv_str;
|
||||
+ char buf[4];
|
||||
+
|
||||
+ /* Only need to read the HV once */
|
||||
+ if (digi_som_hv > 0)
|
||||
+ return digi_som_hv;
|
||||
+
|
||||
+ np = of_find_node_by_path("/");
|
||||
+ if (!np)
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ if (!of_property_read_string(np, "digi,hwid,hv", &som_hv_str)) {
|
||||
+ strncpy(buf, som_hv_str, sizeof(buf));
|
||||
+ if (!kstrtoint(som_hv_str, 16, &digi_som_hv))
|
||||
+ pr_debug("SOM HV: %d\n", digi_som_hv);
|
||||
+ }
|
||||
+ of_node_put(np);
|
||||
+
|
||||
+ return digi_som_hv;
|
||||
+}
|
||||
+EXPORT_SYMBOL(digi_get_som_hv);
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
From d0520a166cdeccf2821a45483602fc24a1772569 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Fri, 20 Apr 2018 20:20:30 +0200
|
||||
Subject: [PATCH] mach-imx: pm-imx6: Add hooks for board specific
|
||||
implementation
|
||||
|
||||
This commit implements two new pm hooks in pm_imx6.c (begin & end) that,
|
||||
optionally, can be implemented by the platform code.
|
||||
This is needed on platforms like the CC6UL where the i.MX6UL has to
|
||||
notify the MCA when suspending the system or resuming from suspend.
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Signed-off-by: Pedro Perez de Heredia <pedro.perez@digi.com>
|
||||
---
|
||||
arch/arm/mach-imx/pm-imx6.c | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
|
||||
index 87f45b926c78..1a4d1ea92687 100644
|
||||
--- a/arch/arm/mach-imx/pm-imx6.c
|
||||
+++ b/arch/arm/mach-imx/pm-imx6.c
|
||||
@@ -69,6 +69,14 @@ static void __iomem *suspend_ocram_base;
|
||||
static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
|
||||
|
||||
/*
|
||||
+ * Function pointers to optional board pm functions
|
||||
+ */
|
||||
+int (*imx6_board_pm_begin)(suspend_state_t);
|
||||
+void (*imx6_board_pm_end)(void);
|
||||
+EXPORT_SYMBOL(imx6_board_pm_begin);
|
||||
+EXPORT_SYMBOL(imx6_board_pm_end);
|
||||
+
|
||||
+/*
|
||||
* suspend ocram space layout:
|
||||
* ======================== high address ======================
|
||||
* .
|
||||
@@ -427,12 +435,28 @@ static int imx6q_pm_enter(suspend_state_t state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int imx6q_pm_begin(suspend_state_t state)
|
||||
+{
|
||||
+ if (imx6_board_pm_begin)
|
||||
+ return imx6_board_pm_begin(state);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void imx6q_pm_end(void)
|
||||
+{
|
||||
+ if (imx6_board_pm_end)
|
||||
+ imx6_board_pm_end();
|
||||
+}
|
||||
+
|
||||
static int imx6q_pm_valid(suspend_state_t state)
|
||||
{
|
||||
return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops imx6q_pm_ops = {
|
||||
+ .begin = imx6q_pm_begin,
|
||||
+ .end = imx6q_pm_end,
|
||||
.enter = imx6q_pm_enter,
|
||||
.valid = imx6q_pm_valid,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,701 @@
|
|||
From a2b055852d963729002f48155d8bbee7e2858e0a Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Mon, 23 Apr 2018 11:37:46 +0200
|
||||
Subject: [PATCH] imx6ul: Add MCA GPIO support for the ConnectCore 6UL SOM
|
||||
|
||||
Synched with v4.14.78/master at:
|
||||
3f8b03950b323db4ca89b1cdc1c2288f79facaa3
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts | 2 +
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts | 2 +
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi | 11 +
|
||||
arch/arm/configs/imx_v6_v7_defconfig | 1 +
|
||||
drivers/gpio/Kconfig | 9 +
|
||||
drivers/gpio/Makefile | 1 +
|
||||
drivers/gpio/gpio-mca.c | 583 ++++++++++++++++++++++++
|
||||
7 files changed, 609 insertions(+)
|
||||
create mode 100644 drivers/gpio/gpio-mca.c
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts
|
||||
index 3792679c0c90..148f1b95e46d 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts
|
||||
@@ -43,6 +43,8 @@
|
||||
pinctrl-0 = <&pinctrl_enet1>;
|
||||
phy-mode = "rmii";
|
||||
phy-handle = <ðphy0>;
|
||||
+ phy-reset-gpios = <&mca_gpio 7 GPIO_ACTIVE_LOW>;
|
||||
+ phy-reset-duration = <26>;
|
||||
status = "okay";
|
||||
|
||||
mdio {
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
index 3749fdda3611..5ad2c61276bc 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
@@ -79,6 +79,8 @@
|
||||
pinctrl-0 = <&pinctrl_enet1>;
|
||||
phy-mode = "rmii";
|
||||
phy-handle = <ðphy0>;
|
||||
+ phy-reset-gpios = <&mca_gpio 7 GPIO_ACTIVE_LOW>;
|
||||
+ phy-reset-duration = <26>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
index 03c62926ca2b..8d475051acf2 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
@@ -58,6 +58,17 @@
|
||||
fw-update-gpio = <&gpio4 14 GPIO_ACTIVE_LOW>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_mca_cc6ul>;
|
||||
+
|
||||
+ mca_gpio: gpio {
|
||||
+ compatible = "digi,mca-cc6ul-gpio";
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+
|
||||
+ interrupt-parent = <&mca_cc6ul>;
|
||||
+ interrupt-controller;
|
||||
+ #interrupt-cells = <2>;
|
||||
+ };
|
||||
+
|
||||
};
|
||||
|
||||
pfuze3000: pmic@8 {
|
||||
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
index 6985d61eddb3..6c3ede35e643 100644
|
||||
--- a/arch/arm/configs/imx_v6_v7_defconfig
|
||||
+++ b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
@@ -207,6 +207,7 @@ CONFIG_SPI_GPIO=y
|
||||
CONFIG_SPI_IMX=y
|
||||
CONFIG_SPI_FSL_DSPI=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
+CONFIG_GPIO_MCA=y
|
||||
CONFIG_GPIO_MAX732X=y
|
||||
CONFIG_GPIO_MC9S08DZ60=y
|
||||
CONFIG_GPIO_PCA953X=y
|
||||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
|
||||
index 833a1b51c948..f7daae95b2a7 100644
|
||||
--- a/drivers/gpio/Kconfig
|
||||
+++ b/drivers/gpio/Kconfig
|
||||
@@ -305,6 +305,15 @@ config GPIO_MB86S7X
|
||||
help
|
||||
Say yes here to support the GPIO controller in Fujitsu MB86S70 SoCs.
|
||||
|
||||
+config GPIO_MCA
|
||||
+ tristate "Digi ConnectCore SOMs Micro Controller Assist GPIO support"
|
||||
+ select MFD_MCA_CC6UL if SOC_IMX6UL
|
||||
+ select MFD_MCA_CC8X if ARCH_FSL_IMX8QXP
|
||||
+ select GPIOLIB_IRQCHIP
|
||||
+ help
|
||||
+ If you say yes here you will get support for the GPIOs in the
|
||||
+ Micro Controller Assist of Digi ConnectCore system-on-modules.
|
||||
+
|
||||
config GPIO_MENZ127
|
||||
tristate "MEN 16Z127 GPIO support"
|
||||
depends on MCB
|
||||
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
|
||||
index 671c4477c951..481b23e8c27e 100644
|
||||
--- a/drivers/gpio/Makefile
|
||||
+++ b/drivers/gpio/Makefile
|
||||
@@ -82,6 +82,7 @@ obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o
|
||||
obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o
|
||||
obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
|
||||
obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
|
||||
+obj-$(CONFIG_GPIO_MCA) += gpio-mca.o
|
||||
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
|
||||
obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
|
||||
obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
|
||||
diff --git a/drivers/gpio/gpio-mca.c b/drivers/gpio/gpio-mca.c
|
||||
new file mode 100644
|
||||
index 000000000000..75dd8af9f76e
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpio/gpio-mca.c
|
||||
@@ -0,0 +1,583 @@
|
||||
+/* gpio-mca.c - GPIO driver for MCA devices.
|
||||
+ *
|
||||
+ * Copyright (C) 2017 - 2019 Digi International Inc
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Library General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * Library General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Library General Public
|
||||
+ * License along with this library; if not, write to the
|
||||
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
+ * Boston, MA 02110-1301, USA.
|
||||
+ */
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
+#include <linux/irqdomain.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/regulator/consumer.h>
|
||||
+
|
||||
+#include <linux/mfd/mca-common/core.h>
|
||||
+#include <linux/mfd/mca-common/registers.h>
|
||||
+
|
||||
+#define MCA_DRVNAME_GPIO "mca-gpio"
|
||||
+
|
||||
+/*
|
||||
+ * The following macros return the register address to read/write for a given
|
||||
+ * gpio number.
|
||||
+ */
|
||||
+#define GPIO_DIR_REG(x) (MCA_GPIO_DIR_0 + ((x) / 8))
|
||||
+#define GPIO_DATA_REG(x) (MCA_GPIO_DATA_0 + ((x) / 8))
|
||||
+#define GPIO_SET_REG(x) (MCA_GPIO_SET_0 + ((x) / 8))
|
||||
+#define GPIO_CLEAR_REG(x) (MCA_GPIO_CLEAR_0 + ((x) / 8))
|
||||
+#define GPIO_TOGGLE_REG(x) (MCA_GPIO_TOGGLE_0 + ((x) / 8))
|
||||
+#define GPIO_IRQ_STATUS_REG(x) (MCA_GPIO_IRQ_STATUS_0 + (x))
|
||||
+#define GPIO_IRQ_CFG_REG(x) (MCA_GPIO_IRQ_CFG_0 + (x))
|
||||
+#define GPIO_DEB_CFG_REG(x) (MCA_GPIO_DEB_CFG_0 + ((x) / 8))
|
||||
+#define GPIO_DEB_CNT_REG(x) (MCA_GPIO_DEB_CNT_0 + (x))
|
||||
+
|
||||
+#define GPIO_CFG_UPDATE BIT(6)
|
||||
+#define GPIO_BYTE(i) ((i) / 8)
|
||||
+#define BYTE_OFFSET(i) ((i) % 8)
|
||||
+#define BIT_OFFSET(i) ((i) % 8)
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+enum mca_gpio_type {
|
||||
+ CC6UL_MCA_GPIO,
|
||||
+ CC8X_MCA_GPIO,
|
||||
+ IOEXP_MCA_GPIO,
|
||||
+};
|
||||
+
|
||||
+struct mca_gpio_data {
|
||||
+ enum mca_gpio_type devtype;
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+struct mca_gpio {
|
||||
+ void * parent;
|
||||
+ struct regmap *regmap;
|
||||
+ struct device *dev;
|
||||
+ struct gpio_chip gc;
|
||||
+ struct mutex irq_lock;
|
||||
+ uint8_t irq_cfg[MCA_MAX_IOS];
|
||||
+ uint8_t irq_capable[MCA_MAX_IO_BYTES];
|
||||
+ int irq[MCA_MAX_GPIO_IRQ_BANKS];
|
||||
+ uint8_t deb_timer_cfg[MCA_MAX_GPIO_IRQ_BANKS];
|
||||
+};
|
||||
+
|
||||
+static char const *const irq_gpio_bank_name[] = {
|
||||
+ MCA_IRQ_GPIO_BANK_0_NAME,
|
||||
+ MCA_IRQ_GPIO_BANK_1_NAME,
|
||||
+ MCA_IRQ_GPIO_BANK_2_NAME,
|
||||
+ MCA_IRQ_GPIO_BANK_3_NAME,
|
||||
+ MCA_IRQ_GPIO_BANK_4_NAME,
|
||||
+ MCA_IRQ_GPIO_BANK_5_NAME,
|
||||
+};
|
||||
+
|
||||
+static inline struct mca_gpio *to_mca_gpio(struct gpio_chip *chip)
|
||||
+{
|
||||
+ return gpiochip_get_data(chip);
|
||||
+}
|
||||
+
|
||||
+static inline bool mca_gpio_is_irq_capable(struct mca_gpio *gpio,
|
||||
+ u32 offset)
|
||||
+{
|
||||
+ return ((gpio->irq_capable[GPIO_BYTE(offset)] &
|
||||
+ (1 << BYTE_OFFSET(offset))) != 0);
|
||||
+}
|
||||
+
|
||||
+static int mca_gpio_get(struct gpio_chip *gc, unsigned num)
|
||||
+{
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+ unsigned int val;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = regmap_read(gpio->regmap, GPIO_DATA_REG(num), &val);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return (val & (1 << BIT_OFFSET(num)) ? 1 : 0);
|
||||
+}
|
||||
+
|
||||
+static void mca_gpio_set(struct gpio_chip *gc, unsigned num, int val)
|
||||
+{
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+ unsigned int reg = val ? GPIO_SET_REG(num) : GPIO_CLEAR_REG(num);
|
||||
+
|
||||
+ regmap_write(gpio->regmap, reg, 1 << BIT_OFFSET(num));
|
||||
+}
|
||||
+
|
||||
+static int mca_gpio_direction_input(struct gpio_chip *gc, unsigned num)
|
||||
+{
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+
|
||||
+ return regmap_update_bits(gpio->regmap, GPIO_DIR_REG(num),
|
||||
+ 1 << BIT_OFFSET(num), 0);
|
||||
+}
|
||||
+
|
||||
+static int mca_gpio_direction_output(struct gpio_chip *gc, unsigned num,
|
||||
+ int val)
|
||||
+{
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Set value before setting direction */
|
||||
+ mca_gpio_set(gc, num, val);
|
||||
+
|
||||
+ ret = regmap_update_bits(gpio->regmap, GPIO_DIR_REG(num),
|
||||
+ 1 << BIT_OFFSET(num), 1 << BIT_OFFSET(num));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define MCA_GPIO_MAX_DEB_VAL_TIMER_50MS (50 * 1000 * 255)
|
||||
+#define MCA_GPIO_MAX_DEB_VAL_TIMER_1MS (255 * 1000)
|
||||
+
|
||||
+static int mca_gpio_set_debounce(struct gpio_chip *gc, unsigned int usecs,
|
||||
+ unsigned int debounce)
|
||||
+{
|
||||
+ struct mca_gpio *mca_gc = to_mca_gpio(gc);
|
||||
+ u8 deb_cnt;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (debounce > MCA_GPIO_MAX_DEB_VAL_TIMER_50MS) {
|
||||
+ dev_warn(mca_gc->dev, "Value out of range %u, setting %u instead\n",
|
||||
+ debounce, MCA_GPIO_MAX_DEB_VAL_TIMER_50MS);
|
||||
+ debounce = MCA_GPIO_MAX_DEB_VAL_TIMER_50MS;
|
||||
+ }
|
||||
+
|
||||
+ if (debounce > MCA_GPIO_MAX_DEB_VAL_TIMER_1MS) {
|
||||
+ /* Set timer cfg period to 50ms */
|
||||
+ mca_gc->deb_timer_cfg[GPIO_BYTE(usecs)] |= 1 << BIT_OFFSET(usecs);
|
||||
+ deb_cnt = (debounce + 49999) / 50000;
|
||||
+ } else {
|
||||
+ /* Set timer cfg period to 1ms */
|
||||
+ mca_gc->deb_timer_cfg[GPIO_BYTE(usecs)] &= ~(1 << BIT_OFFSET(usecs));
|
||||
+ deb_cnt = (debounce + 999) / 1000;
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_write(mca_gc->regmap, GPIO_DEB_CFG_REG(usecs),
|
||||
+ mca_gc->deb_timer_cfg[GPIO_BYTE(usecs)]);
|
||||
+ if (ret) {
|
||||
+ dev_err(mca_gc->dev, "Failed to write GPIO_DEB_CFG_REG(%d) (%d)\n",
|
||||
+ usecs, ret);
|
||||
+ } else {
|
||||
+ ret = regmap_write(mca_gc->regmap, GPIO_DEB_CNT_REG(usecs), deb_cnt);
|
||||
+ if (ret)
|
||||
+ dev_err(mca_gc->dev,
|
||||
+ "Failed to write GPIO_DEB_CNT_REG(%d) (%d)\n",
|
||||
+ usecs, ret);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_gpio_set_config(struct gpio_chip *gc, unsigned int num,
|
||||
+ unsigned long config)
|
||||
+{
|
||||
+ enum pin_config_param param = pinconf_to_config_param(config);
|
||||
+ u32 arg = pinconf_to_config_argument(config);
|
||||
+
|
||||
+ if (param != PIN_CONFIG_INPUT_DEBOUNCE)
|
||||
+ return -ENOTSUPP;
|
||||
+
|
||||
+ return mca_gpio_set_debounce(gc, num, arg);
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t mca_gpio_irq_handler(int irq, void *data)
|
||||
+{
|
||||
+ struct mca_gpio *gpio = data;
|
||||
+ unsigned int pending_irqs, mask, this_irq;
|
||||
+ int ret, i, j;
|
||||
+
|
||||
+ for (i = 0; i < (gpio->gc.ngpio + 7) / 8; i++) {
|
||||
+ ret = regmap_read(gpio->regmap, GPIO_IRQ_STATUS_REG(i), &pending_irqs);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(gpio->dev,
|
||||
+ "IRQ %d: Failed to read GPIO_IRQ_STATUS_REG (%d)\n",
|
||||
+ irq, ret);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ for (j = 0; j < 8; j++) {
|
||||
+ mask = 1 << j;
|
||||
+ if (pending_irqs & mask) {
|
||||
+ /* Ack the irq and call the handler */
|
||||
+ this_irq = irq_find_mapping(gpio->gc.irq.domain, j + i * 8);
|
||||
+ ret = regmap_write(gpio->regmap,
|
||||
+ GPIO_IRQ_STATUS_REG(i),
|
||||
+ mask);
|
||||
+ if (ret) {
|
||||
+ dev_err(gpio->dev,
|
||||
+ "Failed to ack IRQ %d (%d)\n",
|
||||
+ this_irq, ret);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ handle_nested_irq(this_irq);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static void mca_gpio_irq_disable(struct irq_data *d)
|
||||
+{
|
||||
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+
|
||||
+ /*
|
||||
+ * Update the IRQ_EN bit and also set the CFG_UPDATE flag to mark what
|
||||
+ * registers have to be written later to the MCA, once we are out of
|
||||
+ * atomic context. Note that this flag is not cleared before writing
|
||||
+ * the MCA regsister.
|
||||
+ */
|
||||
+ gpio->irq_cfg[d->hwirq] |= GPIO_CFG_UPDATE;
|
||||
+ gpio->irq_cfg[d->hwirq] &= ~MCA_GPIO_IRQ_EN;
|
||||
+}
|
||||
+
|
||||
+static void mca_gpio_irq_enable(struct irq_data *d)
|
||||
+{
|
||||
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+
|
||||
+ /*
|
||||
+ * Update the IRQ_EN bit and also set the CFG_UPDATE flag to mark what
|
||||
+ * registers have to be written later to the MCA, once we are out of
|
||||
+ * atomic context. Note that this flag is not cleared before writing
|
||||
+ * the MCA regsister.
|
||||
+ */
|
||||
+ gpio->irq_cfg[d->hwirq] |= GPIO_CFG_UPDATE | MCA_GPIO_IRQ_EN;
|
||||
+}
|
||||
+
|
||||
+static void mca_gpio_irq_bus_lock(struct irq_data *d)
|
||||
+{
|
||||
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+
|
||||
+ mutex_lock(&gpio->irq_lock);
|
||||
+}
|
||||
+
|
||||
+static void mca_gpio_irq_bus_sync_unlock(struct irq_data *d)
|
||||
+{
|
||||
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+ int i, ret;
|
||||
+
|
||||
+ for (i = 0; i < gc->ngpio; i++) {
|
||||
+ /* Update only those registers that were flagged (modified) */
|
||||
+ if (!(gpio->irq_cfg[i] & GPIO_CFG_UPDATE))
|
||||
+ continue;
|
||||
+
|
||||
+ gpio->irq_cfg[i] &= ~GPIO_CFG_UPDATE;
|
||||
+
|
||||
+ ret = regmap_write(gpio->regmap,
|
||||
+ GPIO_IRQ_CFG_REG(i),
|
||||
+ gpio->irq_cfg[i]);
|
||||
+ if (ret) {
|
||||
+ dev_err(gpio->dev,
|
||||
+ "Failed to configure IRQ %d\n", d->irq);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ mutex_unlock(&gpio->irq_lock);
|
||||
+}
|
||||
+
|
||||
+static int mca_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
+{
|
||||
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+ u32 gpio_idx = d->hwirq;
|
||||
+
|
||||
+ if ((type & IRQ_TYPE_LEVEL_HIGH) || (type & IRQ_TYPE_LEVEL_LOW)) {
|
||||
+ dev_err(gpio->dev,
|
||||
+ "IRQ %d: level IRQs are not supported\n", d->irq);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Update the edge flags based on type and set CFG_UPDATE to note that
|
||||
+ * the register was modified and has to be written back to the MCA in
|
||||
+ * mca_gpio_irq_bus_sync_unlock().
|
||||
+ */
|
||||
+ gpio->irq_cfg[gpio_idx] &= ~MCA_M_GPIO_IRQ_CFG;
|
||||
+ gpio->irq_cfg[gpio_idx] |= GPIO_CFG_UPDATE;
|
||||
+
|
||||
+ if (type & IRQ_TYPE_EDGE_RISING)
|
||||
+ gpio->irq_cfg[gpio_idx] |= MCA_GPIO_IRQ_EDGE_RISE;
|
||||
+
|
||||
+ if (type & IRQ_TYPE_EDGE_FALLING)
|
||||
+ gpio->irq_cfg[gpio_idx] |= MCA_GPIO_IRQ_EDGE_FALL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mca_gpio_to_irq(struct gpio_chip *gc, u32 offset)
|
||||
+{
|
||||
+ struct mca_gpio *gpio = to_mca_gpio(gc);
|
||||
+
|
||||
+ if (GPIO_BYTE(offset) >= MCA_MAX_IO_BYTES)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Discard non irq capable gpios */
|
||||
+ if (!mca_gpio_is_irq_capable(gpio, offset))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return irq_create_mapping(gc->irq.domain, offset);
|
||||
+}
|
||||
+
|
||||
+static struct irq_chip mca_gpio_irq_chip = {
|
||||
+ .name = "mca-gpio-irq",
|
||||
+ .irq_disable = mca_gpio_irq_disable,
|
||||
+ .irq_enable = mca_gpio_irq_enable,
|
||||
+ .irq_bus_lock = mca_gpio_irq_bus_lock,
|
||||
+ .irq_bus_sync_unlock = mca_gpio_irq_bus_sync_unlock,
|
||||
+ .irq_set_type = mca_gpio_irq_set_type,
|
||||
+};
|
||||
+
|
||||
+static int mca_gpio_irq_setup(struct mca_gpio *gpio)
|
||||
+{
|
||||
+ unsigned int val;
|
||||
+ int ret, i;
|
||||
+
|
||||
+ mutex_init(&gpio->irq_lock);
|
||||
+
|
||||
+ for (i = 0; i < gpio->gc.ngpio; i++) {
|
||||
+ gpio->irq_cfg[i] = 0;
|
||||
+
|
||||
+ ret = regmap_read(gpio->regmap, GPIO_IRQ_CFG_REG(i), &val);
|
||||
+ if (ret) {
|
||||
+ dev_err(gpio->dev,
|
||||
+ "Failed to read GPIO[%d] irq config (%d)\n",
|
||||
+ i, ret);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (val & MCA_GPIO_IRQ_CAPABLE)
|
||||
+ gpio->irq_capable[GPIO_BYTE(i)] |= 1 << BYTE_OFFSET(i);
|
||||
+ else
|
||||
+ gpio->irq_capable[GPIO_BYTE(i)] &= ~(1 << BYTE_OFFSET(i));
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < MCA_MAX_GPIO_IRQ_BANKS; i++) {
|
||||
+ if (gpio->irq[i] < 0)
|
||||
+ continue;
|
||||
+ ret = devm_request_threaded_irq(gpio->dev, gpio->irq[i],
|
||||
+ NULL, mca_gpio_irq_handler,
|
||||
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
+ mca_gpio_irq_chip.name,
|
||||
+ gpio);
|
||||
+ if (ret) {
|
||||
+ dev_err(gpio->dev, "Failed to request %s IRQ (%d)\n",
|
||||
+ irq_gpio_bank_name[i], gpio->irq[i]);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = gpiochip_irqchip_add_nested(&gpio->gc,
|
||||
+ &mca_gpio_irq_chip,
|
||||
+ 0,
|
||||
+ handle_edge_irq,
|
||||
+ IRQ_TYPE_NONE);
|
||||
+ if (ret) {
|
||||
+ dev_err(gpio->dev,
|
||||
+ "Failed to connect irqchip to gpiochip (%d)\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * gpiochip_irqchip_add_nested() sets .to_irq with its own implementation but
|
||||
+ * we have to use our own version because not all GPIOs are irq capable.
|
||||
+ * Therefore, we overwrite it.
|
||||
+ */
|
||||
+ gpio->gc.to_irq = mca_gpio_to_irq;
|
||||
+
|
||||
+ for (i = 0; i < MCA_MAX_GPIO_IRQ_BANKS; i++) {
|
||||
+ if (gpio->irq[i] < 0)
|
||||
+ continue;
|
||||
+ gpiochip_set_nested_irqchip(&gpio->gc,
|
||||
+ &mca_gpio_irq_chip,
|
||||
+ gpio->irq[i]);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct gpio_chip reference_gc = {
|
||||
+ .label = "mca-gpio",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .get = mca_gpio_get,
|
||||
+ .set = mca_gpio_set,
|
||||
+ .direction_input = mca_gpio_direction_input,
|
||||
+ .direction_output = mca_gpio_direction_output,
|
||||
+ .to_irq = mca_gpio_to_irq,
|
||||
+ .set_config = mca_gpio_set_config,
|
||||
+ .can_sleep = 1,
|
||||
+ .base = -1,
|
||||
+};
|
||||
+
|
||||
+static int mca_gpio_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_drv *mca = dev_get_drvdata(pdev->dev.parent);
|
||||
+ struct device *mca_dev = mca->dev;
|
||||
+ struct regmap *regmap = mca->regmap;
|
||||
+ int *gpio_base = &mca->gpio_base;
|
||||
+ struct mca_gpio *gpio;
|
||||
+ struct device_node *np;
|
||||
+ unsigned int val;
|
||||
+ int ret, i;
|
||||
+
|
||||
+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
|
||||
+ if (!gpio) {
|
||||
+ dev_err(mca_dev, "Failed to allocate GPIO device\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ if (!mca_dev)
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
+ gpio->dev = mca_dev;
|
||||
+ gpio->regmap = regmap;
|
||||
+
|
||||
+ for (i = 0; i < MCA_MAX_GPIO_IRQ_BANKS; i++) {
|
||||
+ gpio->irq[i] = platform_get_irq_byname(pdev,
|
||||
+ irq_gpio_bank_name[i]);
|
||||
+ }
|
||||
+ gpio->gc = reference_gc;
|
||||
+ gpio->gc.of_node = pdev->dev.of_node;
|
||||
+ gpio->gc.parent = &pdev->dev;
|
||||
+ platform_set_drvdata(pdev, gpio);
|
||||
+
|
||||
+ /* Find entry in device-tree */
|
||||
+ if (mca_dev->of_node) {
|
||||
+ const struct mca_gpio_data *devdata =
|
||||
+ of_device_get_match_data(&pdev->dev);
|
||||
+ const char * compatible = pdev->dev.driver->
|
||||
+ of_match_table[devdata->devtype].compatible;
|
||||
+
|
||||
+ /* Return if node does not exist or if it is disabled */
|
||||
+ np = of_find_compatible_node(mca_dev->of_node, NULL, compatible);
|
||||
+ if (!np) {
|
||||
+ ret = -ENODEV;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ if (!of_device_is_available(np)) {
|
||||
+ ret = -ENODEV;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Get number of GPIOs from MCA firmware */
|
||||
+ if (regmap_read(regmap, MCA_GPIO_NUM, &val)) {
|
||||
+ ret = -EINVAL;
|
||||
+ dev_err(mca_dev, "Could not read number of gpios.\n");
|
||||
+ goto err;
|
||||
+ }
|
||||
+ gpio->gc.ngpio = val & MCA_GPIO_NUM_MASK;
|
||||
+ if (gpio->gc.ngpio < 1 || gpio->gc.ngpio > MCA_MAX_IOS) {
|
||||
+ ret = -EINVAL;
|
||||
+ dev_err(mca_dev, "Read invalid number of gpios (%d). "
|
||||
+ "Valid range is 1..%d.\n", gpio->gc.ngpio,
|
||||
+ MCA_MAX_IOS);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = gpiochip_add_data(&gpio->gc, gpio);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = mca_gpio_irq_setup(gpio);
|
||||
+ if (ret) {
|
||||
+ gpiochip_remove(&gpio->gc);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (gpio_base)
|
||||
+ *gpio_base = gpio->gc.base;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ gpio = NULL;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_gpio_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_gpio *gpio = platform_get_drvdata(pdev);
|
||||
+ struct mca_drv *mca = (struct mca_drv *)gpio->parent; /* TODO */
|
||||
+
|
||||
+ mca->gpio_base = -1;
|
||||
+ gpiochip_remove(&gpio->gc);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static struct mca_gpio_data mca_gpio_devdata[] = {
|
||||
+ [CC6UL_MCA_GPIO] = {
|
||||
+ .devtype = CC6UL_MCA_GPIO,
|
||||
+ },
|
||||
+ [CC8X_MCA_GPIO] = {
|
||||
+ .devtype = CC8X_MCA_GPIO,
|
||||
+ },
|
||||
+ [IOEXP_MCA_GPIO] = {
|
||||
+ .devtype = IOEXP_MCA_GPIO,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id mca_gpio_dt_ids[] = {
|
||||
+ { .compatible = "digi,mca-cc6ul-gpio",
|
||||
+ .data = &mca_gpio_devdata[CC6UL_MCA_GPIO]},
|
||||
+ { .compatible = "digi,mca-cc8x-gpio",
|
||||
+ .data = &mca_gpio_devdata[CC8X_MCA_GPIO]},
|
||||
+ { .compatible = "digi,mca-ioexp-gpio",
|
||||
+ .data = &mca_gpio_devdata[IOEXP_MCA_GPIO]},
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, mca_gpio_dt_ids);
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver mca_gpio_driver = {
|
||||
+ .probe = mca_gpio_probe,
|
||||
+ .remove = mca_gpio_remove,
|
||||
+ .driver = {
|
||||
+ .name = MCA_DRVNAME_GPIO,
|
||||
+ .owner = THIS_MODULE,
|
||||
+#ifdef CONFIG_OF
|
||||
+ .of_match_table = mca_gpio_dt_ids,
|
||||
+#endif
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init mca_gpio_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&mca_gpio_driver);
|
||||
+}
|
||||
+module_init(mca_gpio_init);
|
||||
+
|
||||
+static void __exit mca_gpio_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&mca_gpio_driver);
|
||||
+}
|
||||
+module_exit(mca_gpio_exit);
|
||||
+
|
||||
+/* Module information */
|
||||
+MODULE_AUTHOR("Digi International Inc.");
|
||||
+MODULE_DESCRIPTION("GPIO device driver for MCA of ConnectCore Modules");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_ALIAS("platform:" MCA_DRVNAME_GPIO);
|
||||
+
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
From 7350cbc80f98eacb84a67049c2181f758ca3add6 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Fri, 15 Jun 2018 09:18:15 +0200
|
||||
Subject: [PATCH] imx6ul: Add MCA IOMUX support to the ConnectCore 6UL SOM
|
||||
|
||||
Synched with v4.14.78/master at.
|
||||
3f8b03950b323db4ca89b1cdc1c2288f79facaa3
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
index 8d475051acf2..b96a0873cd88 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
@@ -286,6 +286,15 @@
|
||||
MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x3000
|
||||
>;
|
||||
};
|
||||
+
|
||||
+ pinctrl_mca_cc6ul: mcagrp {
|
||||
+ fsl,pins = <
|
||||
+ /* MCA_nINT */
|
||||
+ MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0xb0b1
|
||||
+ /* MCA_FW_UPDATE */
|
||||
+ MX6UL_PAD_NAND_CE1_B__GPIO4_IO14 0x30
|
||||
+ >;
|
||||
+ };
|
||||
};
|
||||
|
||||
®_arm {
|
||||
|
|
@ -0,0 +1,467 @@
|
|||
From 1440e9a7f2812ebe7ac1d74e8a3c7515bcd67fa8 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Mon, 23 Apr 2018 11:39:40 +0200
|
||||
Subject: [PATCH] imx6ul: Add MCA watchdog support for the ConnectCore 6UL SOM
|
||||
|
||||
Synched with v4.14.78/master at:
|
||||
3f8b03950b323db4ca89b1cdc1c2288f79facaa3
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
.../devicetree/bindings/watchdog/mca-cc6ul-wdt.txt | 22 ++
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi | 5 +
|
||||
arch/arm/configs/imx_v6_v7_defconfig | 1 +
|
||||
drivers/watchdog/Kconfig | 8 +
|
||||
drivers/watchdog/Makefile | 1 +
|
||||
drivers/watchdog/mca_wdt.c | 354 +++++++++++++++++++++
|
||||
6 files changed, 391 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/watchdog/mca-cc6ul-wdt.txt
|
||||
create mode 100644 drivers/watchdog/mca_wdt.c
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/watchdog/mca-cc6ul-wdt.txt b/Documentation/devicetree/bindings/watchdog/mca-cc6ul-wdt.txt
|
||||
new file mode 100644
|
||||
index 000000000000..c6dd2cfdd316
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/watchdog/mca-cc6ul-wdt.txt
|
||||
@@ -0,0 +1,22 @@
|
||||
+* Digi Watchdog Timer for MCA of ConnectCore 6UL
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: must be "digi,mca-cc6ul-wdt".
|
||||
+
|
||||
+Optional properties:
|
||||
+- digi,timeout-sec: contains the watchdog timeout in seconds.
|
||||
+- digi,irq-no-reset: if present, the watchdog will generate an interrupt instead
|
||||
+ of a system reset.
|
||||
+- digi,full-reset: if present, the watchdog will perform a full system reset,
|
||||
+ including the MCA. Otherwise, only the microprocessor is reset. Note
|
||||
+ that this option requires the system to be configured to generate a
|
||||
+ reset and not an interrupt.
|
||||
+
|
||||
+Example:
|
||||
+ mca: mca-cc6ul@7e {
|
||||
+ watchdog {
|
||||
+ compatible = "digi,mca-cc6ul-wdt";
|
||||
+ digi,timeout-sec = <15>;
|
||||
+ digi,irq-no-reset;
|
||||
+ };
|
||||
+ };
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
index b96a0873cd88..848bf78dfceb 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
@@ -69,6 +69,11 @@
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
+ watchdog {
|
||||
+ compatible = "digi,mca-cc6ul-wdt";
|
||||
+ digi,full-reset;
|
||||
+ };
|
||||
+
|
||||
};
|
||||
|
||||
pfuze3000: pmic@8 {
|
||||
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
index 6c3ede35e643..9c693c7778a4 100644
|
||||
--- a/arch/arm/configs/imx_v6_v7_defconfig
|
||||
+++ b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
@@ -226,6 +226,7 @@ CONFIG_IMX_THERMAL=y
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_DA9062_WATCHDOG=y
|
||||
CONFIG_RN5T618_WATCHDOG=y
|
||||
+CONFIG_MCA_WATCHDOG=y
|
||||
CONFIG_IMX2_WDT=y
|
||||
CONFIG_MFD_DA9052_I2C=y
|
||||
CONFIG_MFD_DA9062=y
|
||||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
|
||||
index 2d64333f4782..800821bfdd7d 100644
|
||||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -171,6 +171,14 @@ config MENZ069_WATCHDOG
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called menz069_wdt.
|
||||
|
||||
+config MCA_WATCHDOG
|
||||
+ tristate "Digi ConnectCore SOMs Micro Controller Assist Watchdog"
|
||||
+ select WATCHDOG_CORE
|
||||
+ select MFD_MCA_CC6UL if SOC_IMX6UL
|
||||
+ select MFD_MCA_CC8X if ARCH_FSL_IMX8QXP
|
||||
+ help
|
||||
+ If you say yes here you will get support for the watchdog in the Micro Controller Assist of Digi ConnectCore system-on-modules.
|
||||
+
|
||||
config TANGOX_WATCHDOG
|
||||
tristate "Sigma Designs SMP86xx/SMP87xx watchdog"
|
||||
select WATCHDOG_CORE
|
||||
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
|
||||
index f69cdff5ad7f..36a275937216 100644
|
||||
--- a/drivers/watchdog/Makefile
|
||||
+++ b/drivers/watchdog/Makefile
|
||||
@@ -80,6 +80,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
|
||||
obj-$(CONFIG_MESON_GXBB_WATCHDOG) += meson_gxbb_wdt.o
|
||||
obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
|
||||
obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
|
||||
+obj-$(CONFIG_MCA_WATCHDOG) += mca_wdt.o
|
||||
obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
|
||||
obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
|
||||
obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
|
||||
diff --git a/drivers/watchdog/mca_wdt.c b/drivers/watchdog/mca_wdt.c
|
||||
new file mode 100644
|
||||
index 000000000000..7d5e8b303ed5
|
||||
--- /dev/null
|
||||
+++ b/drivers/watchdog/mca_wdt.c
|
||||
@@ -0,0 +1,354 @@
|
||||
+/*
|
||||
+ * Watchdog driver for MCA on ConnectCore modules
|
||||
+ *
|
||||
+ * Copyright(c) 2016 - 2018 Digi International Inc.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/watchdog.h>
|
||||
+
|
||||
+#include <linux/mfd/mca-common/core.h>
|
||||
+
|
||||
+#define MCA_DRVNAME_WATCHDOG "mca-watchdog"
|
||||
+
|
||||
+#define WDT_REFRESH_LEN (MCA_WDT_REFRESH_3 - \
|
||||
+ MCA_WDT_REFRESH_0 + 1)
|
||||
+#define WDT_REFRESH_PATTERN "WDTP"
|
||||
+#define WATCHDOG_NAME "MCA Watchdog"
|
||||
+#define DEFAULT_TIMEOUT 30 /* 30 sec default timeout */
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+enum mca_wdt_type {
|
||||
+ CC6UL_MCA_WDT,
|
||||
+ CC8X_MCA_WDT,
|
||||
+};
|
||||
+
|
||||
+struct mca_wdt_data {
|
||||
+ enum mca_wdt_type devtype;
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+struct mca_wdt {
|
||||
+ struct watchdog_device wdd;
|
||||
+ struct mca_drv *mca;
|
||||
+ struct kref kref;
|
||||
+ unsigned int default_timeout;
|
||||
+ bool irqnoreset;
|
||||
+ bool nowayout;
|
||||
+ bool fullreset;
|
||||
+ unsigned int irq_timeout;
|
||||
+};
|
||||
+
|
||||
+static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
+module_param(nowayout, bool, 0);
|
||||
+MODULE_PARM_DESC(nowayout,
|
||||
+ "Watchdog cannot be stopped once started (default="
|
||||
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
+
|
||||
+static int mca_wdt_set_timeout(struct watchdog_device *wdd,
|
||||
+ unsigned int timeout)
|
||||
+{
|
||||
+ struct mca_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mca_drv *mca = wdt->mca;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (timeout < wdt->wdd.min_timeout ||
|
||||
+ timeout > wdt->wdd.max_timeout) {
|
||||
+ ret = -EINVAL;
|
||||
+ } else {
|
||||
+ ret = regmap_write(mca->regmap, MCA_WDT_TIMEOUT, timeout);
|
||||
+ }
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(mca->dev, "Failed to set timeout, %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ wdd->timeout = timeout;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mca_config_options(struct mca_wdt *wdt)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ u8 control = 0;
|
||||
+
|
||||
+ control |= wdt->nowayout ? MCA_WDT_NOWAYOUT : 0;
|
||||
+ control |= wdt->irqnoreset ? MCA_WDT_IRQNORESET : 0;
|
||||
+ control |= wdt->fullreset ? MCA_WDT_FULLRESET : 0;
|
||||
+
|
||||
+ ret = regmap_update_bits(wdt->mca->regmap, MCA_WDT_CONTROL,
|
||||
+ MCA_WDT_NOWAYOUT | MCA_WDT_IRQNORESET |
|
||||
+ MCA_WDT_FULLRESET, control);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+
|
||||
+ /* Set timeout */
|
||||
+ ret = mca_wdt_set_timeout(&wdt->wdd, wdt->default_timeout);
|
||||
+ if (ret) {
|
||||
+ dev_err(wdt->mca->dev, "Could not set watchdog timeout (%d)\n",
|
||||
+ ret);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_wdt_ping(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mca_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mca_drv *mca = wdt->mca;
|
||||
+ const char *pattern = WDT_REFRESH_PATTERN;
|
||||
+
|
||||
+ /*
|
||||
+ * Refresh the watchdog timer by writing refresh pattern to REFRESH_x
|
||||
+ * registers
|
||||
+ */
|
||||
+ return regmap_bulk_write(mca->regmap, MCA_WDT_REFRESH_0,
|
||||
+ pattern, WDT_REFRESH_LEN);
|
||||
+}
|
||||
+
|
||||
+static void mca_wdt_release_resources(struct kref *r)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static int mca_wdt_start(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mca_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /* Enable watchdog */
|
||||
+ ret = regmap_update_bits(wdt->mca->regmap, MCA_WDT_CONTROL,
|
||||
+ MCA_WDT_ENABLE, MCA_WDT_ENABLE);
|
||||
+ if (ret) {
|
||||
+ dev_err(wdt->mca->dev, "Could not enable watchdog (%d)\n", ret);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_wdt_stop(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mca_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+
|
||||
+ /* Disable watchdog */
|
||||
+ return regmap_update_bits(wdt->mca->regmap, MCA_WDT_CONTROL,
|
||||
+ MCA_WDT_ENABLE, 0);
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t mca_wdt_timeout_event(int irq, void *data)
|
||||
+{
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static struct watchdog_info mca_wdt_info = {
|
||||
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | \
|
||||
+ WDIOF_MAGICCLOSE,
|
||||
+ .identity = WATCHDOG_NAME,
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_ops mca_wdt_ops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .start = mca_wdt_start,
|
||||
+ .stop = mca_wdt_stop,
|
||||
+ .ping = mca_wdt_ping,
|
||||
+ .set_timeout = mca_wdt_set_timeout,
|
||||
+};
|
||||
+
|
||||
+static int of_mca_wdt_init(struct device_node *np,
|
||||
+ struct mca_wdt *wdt)
|
||||
+{
|
||||
+ unsigned int timeout;
|
||||
+
|
||||
+ /* parse options */
|
||||
+ wdt->irqnoreset = of_property_read_bool(np, "digi,irq-no-reset");
|
||||
+ wdt->fullreset = of_property_read_bool(np, "digi,full-reset");
|
||||
+
|
||||
+ if (!of_property_read_u32_index(np, "digi,timeout-sec", 0, &timeout)) {
|
||||
+ if (timeout < wdt->wdd.min_timeout ||
|
||||
+ timeout > wdt->wdd.max_timeout)
|
||||
+ dev_warn(wdt->mca->dev,
|
||||
+ "Invalid timeout-sec value. Using default.\n");
|
||||
+ else
|
||||
+ wdt->default_timeout = timeout;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mca_wdt_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_drv *mca = dev_get_drvdata(pdev->dev.parent);
|
||||
+ struct mca_wdt *wdt;
|
||||
+ const struct mca_wdt_data *devdata = (struct mca_wdt_data *)pdev->id_entry->driver_data;
|
||||
+ struct device_node *np;
|
||||
+ int ret;
|
||||
+
|
||||
+ wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
|
||||
+ if (!wdt) {
|
||||
+ dev_err(mca->dev, "Failed to allocate watchdog device\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ wdt->mca = mca;
|
||||
+ wdt->default_timeout = DEFAULT_TIMEOUT;
|
||||
+ wdt->nowayout = nowayout;
|
||||
+ wdt->wdd.min_timeout = 0;
|
||||
+ wdt->wdd.max_timeout = 0xff;
|
||||
+ wdt->wdd.info = &mca_wdt_info;
|
||||
+ wdt->wdd.ops = &mca_wdt_ops;
|
||||
+ wdt->wdd.parent = &pdev->dev;
|
||||
+
|
||||
+ watchdog_set_drvdata(&wdt->wdd, wdt);
|
||||
+ kref_init(&wdt->kref);
|
||||
+ platform_set_drvdata(pdev, wdt);
|
||||
+
|
||||
+ /* Find entry in device-tree */
|
||||
+ if (mca->dev->of_node) {
|
||||
+ const char * compatible = pdev->dev.driver->
|
||||
+ of_match_table[devdata->devtype].compatible;
|
||||
+
|
||||
+ /*
|
||||
+ * Return silently if watchdog node does not exist
|
||||
+ * or if it is disabled
|
||||
+ */
|
||||
+ np = of_find_compatible_node(mca->dev->of_node, NULL, compatible);
|
||||
+ if (!np) {
|
||||
+ ret = -ENODEV;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ if (!of_device_is_available(np)) {
|
||||
+ ret = -ENODEV;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Parse DT properties */
|
||||
+ ret = of_mca_wdt_init(np, wdt);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Configure WDT options */
|
||||
+ ret = mca_config_options(wdt);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Failed to configure WDT options\n");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Set nowayout option into watchdog device */
|
||||
+ watchdog_set_nowayout(&wdt->wdd, nowayout);
|
||||
+
|
||||
+ /* Register interrupt if so configured */
|
||||
+ if (wdt->irqnoreset) {
|
||||
+ wdt->irq_timeout = platform_get_irq_byname(pdev,
|
||||
+ MCA_IRQ_WATCHDOG_NAME);
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev, wdt->irq_timeout,
|
||||
+ NULL, mca_wdt_timeout_event,
|
||||
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
+ MCA_IRQ_WATCHDOG_NAME, wdt);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "Failed to request %s IRQ. (%d)\n",
|
||||
+ MCA_IRQ_WATCHDOG_NAME, wdt->irq_timeout);
|
||||
+ wdt->irq_timeout = -ENXIO;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = watchdog_register_device(&wdt->wdd);
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(wdt->mca->dev,
|
||||
+ "watchdog_register_device() failed: %d\n", ret);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ pr_info("Watchdog driver for MCA (timeout=%d sec, nowayout=%d, %s%s)\n",
|
||||
+ wdt->default_timeout, nowayout,
|
||||
+ wdt->irqnoreset ? "interrupt (no reset)" : "reset",
|
||||
+ wdt->irqnoreset ? "" : wdt->fullreset ? " (full)" : " (MPU only)");
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ wdt = NULL;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_wdt_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_wdt *wdt = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ if(wdt->irq_timeout)
|
||||
+ devm_free_irq(&pdev->dev, wdt->irq_timeout, wdt);
|
||||
+ watchdog_unregister_device(&wdt->wdd);
|
||||
+ kref_put(&wdt->kref, mca_wdt_release_resources);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static struct mca_wdt_data mca_wdt_devdata[] = {
|
||||
+ [CC6UL_MCA_WDT] = {
|
||||
+ .devtype = CC6UL_MCA_WDT,
|
||||
+ },
|
||||
+ [CC8X_MCA_WDT] = {
|
||||
+ .devtype = CC8X_MCA_WDT,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct platform_device_id mca_wdt_devtype[] = {
|
||||
+ {
|
||||
+ .name = "mca-cc6ul-watchdog",
|
||||
+ .driver_data = (kernel_ulong_t)&mca_wdt_devdata[CC6UL_MCA_WDT],
|
||||
+ }, {
|
||||
+ .name = "mca-cc8x-watchdog",
|
||||
+ .driver_data = (kernel_ulong_t)&mca_wdt_devdata[CC8X_MCA_WDT],
|
||||
+ }, {
|
||||
+ /* sentinel */
|
||||
+ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(platform, mca_wdt_devtype);
|
||||
+
|
||||
+static const struct of_device_id mca_wdt_match[] = {
|
||||
+ { .compatible = "digi,mca-cc6ul-wdt",
|
||||
+ .data = &mca_wdt_devdata[CC6UL_MCA_WDT]},
|
||||
+ { .compatible = "digi,mca-cc8x-wdt",
|
||||
+ .data = &mca_wdt_devdata[CC8X_MCA_WDT]},
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, mca_wdt_match);
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver mca_wdt_driver = {
|
||||
+ .probe = mca_wdt_probe,
|
||||
+ .remove = mca_wdt_remove,
|
||||
+ .id_table = mca_wdt_devtype,
|
||||
+ .driver = {
|
||||
+ .name = MCA_DRVNAME_WATCHDOG,
|
||||
+ .of_match_table = of_match_ptr(mca_wdt_match),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(mca_wdt_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Digi International Inc.");
|
||||
+MODULE_DESCRIPTION("Watchdog device driver for MCA of ConnectCore Modules");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_ALIAS("platform:" MCA_DRVNAME_WATCHDOG);
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,937 @@
|
|||
From bfc63af24c96ca3206e3f8e6b0fd437944e6519e Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Mon, 23 Apr 2018 11:42:42 +0200
|
||||
Subject: [PATCH] imx6ul: Add MCA tamper support for ConnectCore 6UL SOM and
|
||||
SBCs
|
||||
|
||||
Synched with v4.14.78/master at:
|
||||
3f8b03950b323db4ca89b1cdc1c2288f79facaa3
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts | 7 +
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi | 4 +
|
||||
arch/arm/configs/imx_v6_v7_defconfig | 1 +
|
||||
drivers/iio/Kconfig | 1 +
|
||||
drivers/iio/Makefile | 1 +
|
||||
drivers/iio/tamper/Kconfig | 20 +
|
||||
drivers/iio/tamper/Makefile | 6 +
|
||||
drivers/iio/tamper/mca_tamper.c | 801 ++++++++++++++++++++++++++++
|
||||
8 files changed, 841 insertions(+)
|
||||
create mode 100644 drivers/iio/tamper/Kconfig
|
||||
create mode 100644 drivers/iio/tamper/Makefile
|
||||
create mode 100644 drivers/iio/tamper/mca_tamper.c
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
index acea9a56971e..7cbc14d56680 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
@@ -162,6 +162,13 @@
|
||||
digi,adc-vref = <3000000>;
|
||||
};
|
||||
|
||||
+/* Enable Tamper detection. There are 2 digital (0 and 1) and 2
|
||||
+ * analog (2 and 3) tamper interfaces.
|
||||
+ */
|
||||
+&mca_tamper {
|
||||
+ digi,tamper-if-list = <0 1 2 3>;
|
||||
+};
|
||||
+
|
||||
&pwm1 {
|
||||
status = "okay";
|
||||
};
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
index b5efc58d362d..a20fb5ffc98b 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
@@ -79,6 +79,10 @@
|
||||
digi,adc-vref = <3000000>;
|
||||
};
|
||||
|
||||
+ mca_tamper: tamper {
|
||||
+ compatible = "digi,mca-cc6ul-tamper";
|
||||
+ };
|
||||
+
|
||||
};
|
||||
|
||||
pfuze3000: pmic@8 {
|
||||
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
index 060c1de356ca..188fb4309851 100644
|
||||
--- a/arch/arm/configs/imx_v6_v7_defconfig
|
||||
+++ b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
@@ -390,6 +390,7 @@ CONFIG_VF610_ADC=y
|
||||
CONFIG_SENSORS_ISL29018=y
|
||||
CONFIG_MAG3110=y
|
||||
CONFIG_MPL3115=y
|
||||
+CONFIG_TAMPER_MCA=y
|
||||
CONFIG_PWM=y
|
||||
CONFIG_PWM_FSL_FTM=y
|
||||
CONFIG_PWM_IMX=y
|
||||
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
|
||||
index d08aeb41cd07..e4c3fd62ca92 100644
|
||||
--- a/drivers/iio/Kconfig
|
||||
+++ b/drivers/iio/Kconfig
|
||||
@@ -94,6 +94,7 @@ source "drivers/iio/potentiostat/Kconfig"
|
||||
source "drivers/iio/pressure/Kconfig"
|
||||
source "drivers/iio/proximity/Kconfig"
|
||||
source "drivers/iio/resolver/Kconfig"
|
||||
+source "drivers/iio/tamper/Kconfig"
|
||||
source "drivers/iio/temperature/Kconfig"
|
||||
|
||||
endif # IIO
|
||||
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
|
||||
index cb5993251381..004de1adaf82 100644
|
||||
--- a/drivers/iio/Makefile
|
||||
+++ b/drivers/iio/Makefile
|
||||
@@ -37,5 +37,6 @@ obj-y += potentiostat/
|
||||
obj-y += pressure/
|
||||
obj-y += proximity/
|
||||
obj-y += resolver/
|
||||
+obj-y += tamper/
|
||||
obj-y += temperature/
|
||||
obj-y += trigger/
|
||||
diff --git a/drivers/iio/tamper/Kconfig b/drivers/iio/tamper/Kconfig
|
||||
new file mode 100644
|
||||
index 000000000000..2a9a395becf4
|
||||
--- /dev/null
|
||||
+++ b/drivers/iio/tamper/Kconfig
|
||||
@@ -0,0 +1,20 @@
|
||||
+#
|
||||
+# Tamper Devices
|
||||
+#
|
||||
+
|
||||
+menu "Tamper devices"
|
||||
+
|
||||
+config TAMPER_MCA
|
||||
+ tristate "Tamper support for MCA on Digi ConnectCore SOMs"
|
||||
+ select MFD_MCA_CC6UL if SOC_IMX6UL
|
||||
+ select MFD_MCA_CC8X if ARCH_FSL_IMX8QXP
|
||||
+
|
||||
+ help
|
||||
+ Say Y here to build the tamper driver on the MCA of the
|
||||
+ ConnectCore system-on-modules.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called mca_tamper
|
||||
+
|
||||
+endmenu
|
||||
+
|
||||
diff --git a/drivers/iio/tamper/Makefile b/drivers/iio/tamper/Makefile
|
||||
new file mode 100644
|
||||
index 000000000000..9f422a829081
|
||||
--- /dev/null
|
||||
+++ b/drivers/iio/tamper/Makefile
|
||||
@@ -0,0 +1,6 @@
|
||||
+#
|
||||
+# Makefile for IIO Tamper devices
|
||||
+#
|
||||
+
|
||||
+# When adding new entries keep the list in alphabetical order
|
||||
+obj-$(CONFIG_TAMPER_MCA) += mca_tamper.o
|
||||
diff --git a/drivers/iio/tamper/mca_tamper.c b/drivers/iio/tamper/mca_tamper.c
|
||||
new file mode 100644
|
||||
index 000000000000..2c92624aed18
|
||||
--- /dev/null
|
||||
+++ b/drivers/iio/tamper/mca_tamper.c
|
||||
@@ -0,0 +1,801 @@
|
||||
+/* mca_tamper.c - Tamper driver for MCA on ConnectCore modules
|
||||
+ *
|
||||
+ * Copyright (C) 2016 - 2018 Digi International Inc
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Library General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * Library General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Library General Public
|
||||
+ * License along with this library; if not, write to the
|
||||
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
+ * Boston, MA 02110-1301, USA.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/acpi.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/iio/events.h>
|
||||
+#include <linux/iio/iio.h>
|
||||
+#include <linux/iio/sysfs.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/mfd/mca-common/core.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/rtc.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#define MCA_DRVNAME_TAMPER "mca-tamper"
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+enum mca_tamper_type {
|
||||
+ CC6UL_MCA_TAMPER,
|
||||
+ CC8X_MCA_TAMPER,
|
||||
+};
|
||||
+
|
||||
+struct mca_tamper_data {
|
||||
+ enum mca_tamper_type devtype;
|
||||
+ u16 num_tamper_ifaces;
|
||||
+ u16 digital_tamper_cnt;
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+struct mca_tamper {
|
||||
+ struct mca_drv *mca;
|
||||
+ struct iio_dev *iio;
|
||||
+ char name[10];
|
||||
+ uint8_t config0;
|
||||
+ uint8_t config1;
|
||||
+ uint8_t io_in;
|
||||
+ uint8_t io_out;
|
||||
+ uint8_t pwroff_delay_ms;
|
||||
+ uint8_t event;
|
||||
+ int irq;
|
||||
+ int iface;
|
||||
+};
|
||||
+
|
||||
+/* Tamper register offsets */
|
||||
+enum {
|
||||
+ CFG0 = 0,
|
||||
+ CFG1 = MCA_TAMPER0_CFG1 - MCA_TAMPER0_CFG0,
|
||||
+ IO_IN = MCA_TAMPER0_IO_IN - MCA_TAMPER0_CFG0,
|
||||
+ IO_OUT = MCA_TAMPER0_IO_OUT - MCA_TAMPER0_CFG0,
|
||||
+ DELAY_PWROFF = MCA_TAMPER0_DELAY_PWROFF - MCA_TAMPER0_CFG0,
|
||||
+ DATE_YEAR_L = MCA_TAMPER0_DATE_START - MCA_TAMPER0_CFG0,
|
||||
+ DATE_YEAR_H,
|
||||
+ DATE_MONTH,
|
||||
+ DATE_DAY,
|
||||
+ DATE_HOUR,
|
||||
+ DATE_MIN,
|
||||
+ DATE_SEC,
|
||||
+ EVENT = MCA_TAMPER0_EVENT - MCA_TAMPER0_CFG0,
|
||||
+ TICKS = MCA_TAMPER2_TICKS_L - MCA_TAMPER2_CFG0,
|
||||
+ THR_L = MCA_TAMPER2_THRESH_LO_L - MCA_TAMPER2_CFG0,
|
||||
+ THR_H = MCA_TAMPER2_THRESH_HI_L - MCA_TAMPER2_CFG0,
|
||||
+};
|
||||
+
|
||||
+static int mca_tamper_read_raw(struct iio_dev *iio,
|
||||
+ struct iio_chan_spec const *ch,
|
||||
+ int *val, int *val2, long mask)
|
||||
+{
|
||||
+ struct mca_tamper *tp = iio_priv(iio);
|
||||
+ u32 value;
|
||||
+ int ret;
|
||||
+ unsigned int event_reg;
|
||||
+
|
||||
+ switch (tp->iface) {
|
||||
+ case 0:
|
||||
+ event_reg = MCA_TAMPER0_EVENT;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ event_reg = MCA_TAMPER1_EVENT;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ event_reg = MCA_TAMPER2_EVENT;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ event_reg = MCA_TAMPER3_EVENT;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ switch (mask) {
|
||||
+ case IIO_CHAN_INFO_RAW:
|
||||
+ ret = regmap_read(tp->mca->regmap, event_reg, &value);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(tp->mca->dev,
|
||||
+ "Error reading Tamper%d event register (%d)\n",
|
||||
+ ch->channel, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ *val = value;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return IIO_VAL_INT;
|
||||
+}
|
||||
+
|
||||
+static const struct iio_event_spec mca_tamper_events[] = {
|
||||
+ {
|
||||
+ .type = IIO_EV_TYPE_CHANGE,
|
||||
+ .dir = IIO_EV_DIR_NONE,
|
||||
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void mca_tamper_get_time(u8 *data, struct rtc_time *tm)
|
||||
+{
|
||||
+ tm->tm_year = ((data[DATE_YEAR_H] << 8) | data[DATE_YEAR_L]) - 1900;
|
||||
+ tm->tm_mon = (data[DATE_MONTH] & MCA_RTC_MONTH_MASK) - 1;
|
||||
+ tm->tm_mday = (data[DATE_DAY] & MCA_RTC_DAY_MASK);
|
||||
+ tm->tm_hour = (data[DATE_HOUR] & MCA_RTC_HOUR_MASK);
|
||||
+ tm->tm_min = (data[DATE_MIN] & MCA_RTC_MIN_MASK);
|
||||
+ tm->tm_sec = (data[DATE_SEC] & MCA_RTC_SEC_MASK);
|
||||
+}
|
||||
+
|
||||
+static unsigned int get_tamper_base_reg(unsigned int iface)
|
||||
+{
|
||||
+ switch (iface) {
|
||||
+ case 0:
|
||||
+ return MCA_TAMPER0_CFG0;
|
||||
+ case 1:
|
||||
+ return MCA_TAMPER1_CFG0;
|
||||
+ case 2:
|
||||
+ return MCA_TAMPER2_CFG0;
|
||||
+ case 3:
|
||||
+ return MCA_TAMPER3_CFG0;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return ~0;
|
||||
+}
|
||||
+
|
||||
+/* Sysfs interface */
|
||||
+#define TAMPER_SYSFS_SHOW_REG(reg, addr, type) \
|
||||
+static ssize_t show_##reg(struct device *dev, \
|
||||
+ struct device_attribute *attr, char *buf) \
|
||||
+{ \
|
||||
+ struct iio_dev *iio = dev_to_iio_dev(dev); \
|
||||
+ struct mca_tamper *tp = iio_priv(iio); \
|
||||
+ int ret; \
|
||||
+ type val; \
|
||||
+ unsigned int tamper_base_reg = get_tamper_base_reg(tp->iface); \
|
||||
+ \
|
||||
+ if (tamper_base_reg == ~0) \
|
||||
+ return -1; \
|
||||
+ \
|
||||
+ ret = regmap_bulk_read(tp->mca->regmap, \
|
||||
+ tamper_base_reg + addr, \
|
||||
+ &val, sizeof(val)); \
|
||||
+ if (ret != 0) { \
|
||||
+ dev_err(tp->mca->dev, \
|
||||
+ "Failed reading Tamper%d #reg register (%d)\n", \
|
||||
+ tp->iface, ret); \
|
||||
+ return 0; \
|
||||
+ } \
|
||||
+ return sprintf(buf, "0x%04x\n", (type)val); \
|
||||
+}
|
||||
+
|
||||
+#define TAMPER_SYSFS_STORE_REG(reg, addr, type) \
|
||||
+static ssize_t store_##reg(struct device *dev, \
|
||||
+ struct device_attribute *attr, \
|
||||
+ const char *buf, size_t count) \
|
||||
+{ \
|
||||
+ struct iio_dev *iio = dev_to_iio_dev(dev); \
|
||||
+ struct mca_tamper *tp = iio_priv(iio); \
|
||||
+ int ret; \
|
||||
+ unsigned long val; \
|
||||
+ unsigned int tamper_base_reg = get_tamper_base_reg(tp->iface); \
|
||||
+ \
|
||||
+ if (tamper_base_reg == ~0) \
|
||||
+ return -1; \
|
||||
+ \
|
||||
+ ret = kstrtoul(buf, 0, &val); \
|
||||
+ if (ret) { \
|
||||
+ dev_err(tp->mca->dev, \
|
||||
+ "%s: error parsing input (%s)\n", \
|
||||
+ __func__, buf); \
|
||||
+ return ret; \
|
||||
+ } \
|
||||
+ ret = regmap_bulk_write(tp->mca->regmap, \
|
||||
+ tamper_base_reg + addr, \
|
||||
+ &val, sizeof(type)); \
|
||||
+ if (ret != 0) { \
|
||||
+ dev_err(tp->mca->dev, \
|
||||
+ "Failed write Tamper%d #reg register (%d)\n", \
|
||||
+ tp->iface, ret); \
|
||||
+ return 0; \
|
||||
+ } \
|
||||
+ return count; \
|
||||
+}
|
||||
+
|
||||
+#define MCA_TAMPER_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
|
||||
+
|
||||
+static ssize_t show_tp_events(struct device *dev, struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct iio_dev *iio = dev_to_iio_dev(dev);
|
||||
+ struct mca_tamper *tp = iio_priv(iio);
|
||||
+ int ret;
|
||||
+ unsigned int val;
|
||||
+ unsigned int tamper_base_reg = get_tamper_base_reg(tp->iface);
|
||||
+
|
||||
+ if (tamper_base_reg == ~0)
|
||||
+ return -1;
|
||||
+
|
||||
+ ret = regmap_read(tp->mca->regmap, tamper_base_reg + EVENT, &val);
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(tp->mca->dev,
|
||||
+ "Failed reading Tamper%d #reg register (%d)\n",
|
||||
+ tp->iface, ret);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ switch (val) {
|
||||
+ case 0x00:
|
||||
+ ret = sprintf(buf, "none\n");
|
||||
+ break;
|
||||
+ case MCA_TAMPER_SIGNALED:
|
||||
+ ret = sprintf(buf, "signaled\n");
|
||||
+ break;
|
||||
+ case (MCA_TAMPER_ACKED | MCA_TAMPER_SIGNALED):
|
||||
+ ret = sprintf(buf, "signaled+acked\n");
|
||||
+ break;
|
||||
+ default:
|
||||
+ ret = sprintf(buf, "unknown (0x%04x)\n", (u8)val);
|
||||
+ break;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_tp_events(struct device *dev, struct device_attribute *attr,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ struct iio_dev *iio = dev_to_iio_dev(dev);
|
||||
+ struct mca_tamper *tp = iio_priv(iio);
|
||||
+ int ret;
|
||||
+ unsigned long val;
|
||||
+ unsigned int tamper_base_reg = get_tamper_base_reg(tp->iface);
|
||||
+
|
||||
+ if (tamper_base_reg == ~0)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (!strncmp(buf, "ack", strlen("ack")))
|
||||
+ val = MCA_TAMPER_ACKED;
|
||||
+ else if (!strncmp(buf, "clear", strlen("clear")))
|
||||
+ val = MCA_TAMPER_CLEAR;
|
||||
+ else {
|
||||
+ /* Check if string is a raw value */
|
||||
+ ret = kstrtoul(buf, 0, &val);
|
||||
+ if (ret || (val != MCA_TAMPER_CLEAR &&
|
||||
+ val != MCA_TAMPER_ACKED)) {
|
||||
+ dev_err(tp->mca->dev,
|
||||
+ "%s: error parsing input (%s)\n",
|
||||
+ __func__, buf);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_write(tp->mca->regmap, tamper_base_reg + EVENT, val);
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(tp->mca->dev,
|
||||
+ "Failed write Tamper%d #reg register (%d)\n",
|
||||
+ tp->iface, ret);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t show_timestamp(struct device *dev, struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct iio_dev *iio = dev_to_iio_dev(dev);
|
||||
+ struct mca_tamper *tp = iio_priv(iio);
|
||||
+ unsigned int tamper_base_reg = get_tamper_base_reg(tp->iface);
|
||||
+ time64_t tamper_t64 = -1;
|
||||
+ struct rtc_time tm;
|
||||
+ u8 data[MCA_TAMPER_REGS_LEN];
|
||||
+ int ret;
|
||||
+
|
||||
+ if (tamper_base_reg == ~0)
|
||||
+ return -1;
|
||||
+
|
||||
+ ret = regmap_bulk_read(tp->mca->regmap, tamper_base_reg, data,
|
||||
+ sizeof(data));
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(tp->mca->dev, "Failed reading Tamper%d registers (%d)\n",
|
||||
+ tp->iface, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Confirm the event and get the timestamp */
|
||||
+ if (data[EVENT] & MCA_TAMPER_SIGNALED) {
|
||||
+ mca_tamper_get_time(data, &tm);
|
||||
+ tamper_t64 = rtc_tm_to_time64(&tm);
|
||||
+ }
|
||||
+
|
||||
+ return sprintf(buf, "%lld\n", tamper_t64);
|
||||
+}
|
||||
+
|
||||
+static IIO_DEVICE_ATTR(tamper_events, S_IRUGO | S_IWUSR, show_tp_events, store_tp_events, 0);
|
||||
+static IIO_DEVICE_ATTR(timestamp, S_IRUGO, show_timestamp, NULL, 0);
|
||||
+
|
||||
+#ifdef MCA_TAMPER_HAS_EXTRA_SYSFS_ENTRIES
|
||||
+TAMPER_SYSFS_SHOW_REG(config0, CFG0, u8)
|
||||
+TAMPER_SYSFS_SHOW_REG(config1, CFG1, u8)
|
||||
+TAMPER_SYSFS_SHOW_REG(io_in, IO_IN, u8)
|
||||
+TAMPER_SYSFS_SHOW_REG(io_out, IO_OUT, u8)
|
||||
+TAMPER_SYSFS_SHOW_REG(pwroff_delay_ms, DELAY_PWROFF, u8)
|
||||
+TAMPER_SYSFS_SHOW_REG(srate, TICKS, u16)
|
||||
+TAMPER_SYSFS_SHOW_REG(thr_l, THR_L, u16)
|
||||
+TAMPER_SYSFS_SHOW_REG(thr_h, THR_H, u16)
|
||||
+
|
||||
+TAMPER_SYSFS_STORE_REG(config0, CFG0, u8)
|
||||
+TAMPER_SYSFS_STORE_REG(config1, CFG1, u8)
|
||||
+TAMPER_SYSFS_STORE_REG(io_in, IO_IN, u8)
|
||||
+TAMPER_SYSFS_STORE_REG(io_out, IO_OUT, u8)
|
||||
+TAMPER_SYSFS_STORE_REG(pwroff_delay_ms, DELAY_PWROFF, u8)
|
||||
+TAMPER_SYSFS_STORE_REG(srate, TICKS, u16)
|
||||
+TAMPER_SYSFS_STORE_REG(thr_l, THR_L, u16)
|
||||
+TAMPER_SYSFS_STORE_REG(thr_h, THR_H, u16)
|
||||
+
|
||||
+static IIO_DEVICE_ATTR(config0, S_IRUGO | S_IWUSR, show_config0, store_config0, 0);
|
||||
+static IIO_DEVICE_ATTR(config1, S_IRUGO | S_IWUSR, show_config1, store_config1, 0);
|
||||
+static IIO_DEVICE_ATTR(io_in, S_IRUGO | S_IWUSR, show_io_in, store_io_in, 0);
|
||||
+static IIO_DEVICE_ATTR(io_out, S_IRUGO | S_IWUSR, show_io_out, store_io_out, 0);
|
||||
+static IIO_DEVICE_ATTR(pwroff_delay_ms, S_IRUGO | S_IWUSR, show_pwroff_delay_ms, store_pwroff_delay_ms, 0);
|
||||
+static IIO_DEVICE_ATTR(srate, S_IRUGO | S_IWUSR, show_srate, store_srate, 0);
|
||||
+static IIO_DEVICE_ATTR(thr_l, S_IRUGO | S_IWUSR, show_thr_l, store_thr_l, 0);
|
||||
+static IIO_DEVICE_ATTR(thr_h, S_IRUGO | S_IWUSR, show_thr_h, store_thr_h, 0);
|
||||
+
|
||||
+static struct attribute *mca_tamper_attributes[] = {
|
||||
+ MCA_TAMPER_DEV_ATTR(config0),
|
||||
+ MCA_TAMPER_DEV_ATTR(io_in),
|
||||
+ MCA_TAMPER_DEV_ATTR(io_out),
|
||||
+ MCA_TAMPER_DEV_ATTR(pwroff_delay_ms),
|
||||
+ MCA_TAMPER_DEV_ATTR(tamper_events),
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static struct attribute *mca_tamper_analog_attributes[] = {
|
||||
+ MCA_TAMPER_DEV_ATTR(config0),
|
||||
+ MCA_TAMPER_DEV_ATTR(config1),
|
||||
+ MCA_TAMPER_DEV_ATTR(io_in),
|
||||
+ MCA_TAMPER_DEV_ATTR(io_out),
|
||||
+ MCA_TAMPER_DEV_ATTR(pwroff_delay_ms),
|
||||
+ MCA_TAMPER_DEV_ATTR(tamper_events),
|
||||
+ MCA_TAMPER_DEV_ATTR(timestamp),
|
||||
+ MCA_TAMPER_DEV_ATTR(srate),
|
||||
+ MCA_TAMPER_DEV_ATTR(thr_l),
|
||||
+ MCA_TAMPER_DEV_ATTR(thr_h),
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const struct attribute_group mca_tamper_analog_attribute_group = {
|
||||
+ .name = "tamper_analog",
|
||||
+ .attrs = mca_tamper_analog_attributes,
|
||||
+};
|
||||
+
|
||||
+static const struct iio_info mca_tamper_analog_info = {
|
||||
+ .attrs = &mca_tamper_analog_attribute_group,
|
||||
+ .read_raw = &mca_tamper_read_raw,
|
||||
+};
|
||||
+
|
||||
+#else
|
||||
+static struct attribute *mca_tamper_attributes[] = {
|
||||
+ MCA_TAMPER_DEV_ATTR(tamper_events),
|
||||
+ MCA_TAMPER_DEV_ATTR(timestamp),
|
||||
+ NULL,
|
||||
+};
|
||||
+#endif /* MCA_TAMPER_HAS_EXTRA_SYSFS_ENTRIES */
|
||||
+
|
||||
+static const struct attribute_group mca_tamper_attribute_group = {
|
||||
+ .name = "tamper",
|
||||
+ .attrs = mca_tamper_attributes,
|
||||
+};
|
||||
+
|
||||
+static const struct iio_info mca_tamper_info = {
|
||||
+ .attrs = &mca_tamper_attribute_group,
|
||||
+ .read_raw = &mca_tamper_read_raw,
|
||||
+};
|
||||
+
|
||||
+#ifdef MCA_TAMPER_DUMP_REGISTERS
|
||||
+static void mca_tamper_regs_dump(u8 *data)
|
||||
+{
|
||||
+ printk("Tamper CFG0 = 0x%02x\n", data[CFG0]);
|
||||
+ printk("Tamper CFG1 = 0x%02x\n", data[CFG1]);
|
||||
+ printk("Tamper IO_IN = 0x%02x\n", data[IO_IN]);
|
||||
+ printk("Tamper IO_OUT = 0x%02x\n", data[IO_OUT]);
|
||||
+ printk("Tamper DELAY_PWROFF = 0x%02x\n", data[DELAY_PWROFF]);
|
||||
+ printk("Tamper DATE_YEAR_L = 0x%02x\n", data[DATE_YEAR_L]);
|
||||
+ printk("Tamper DATE_YEAR_H = 0x%02x\n", data[DATE_YEAR_H]);
|
||||
+ printk("Tamper DATE_MONTH = 0x%02x\n", data[DATE_MONTH]);
|
||||
+ printk("Tamper DATE_DAY = 0x%02x\n", data[DATE_DAY]);
|
||||
+ printk("Tamper DATE_HOUR = 0x%02x\n", data[DATE_HOUR]);
|
||||
+ printk("Tamper DATE_MIN = 0x%02x\n", data[DATE_MIN]);
|
||||
+ printk("Tamper DATE_SEC = 0x%02x\n", data[DATE_SEC]);
|
||||
+ printk("Tamper EVENT = 0x%02x\n", data[EVENT]);
|
||||
+}
|
||||
+#else
|
||||
+static void mca_tamper_regs_dump(u8 *data) {}
|
||||
+#endif
|
||||
+
|
||||
+static irqreturn_t mca_tamper_irq_handler(int irq, void *private)
|
||||
+{
|
||||
+ struct iio_dev *iio = private;
|
||||
+ struct mca_tamper *tp = iio_priv(iio);
|
||||
+ struct rtc_time tm;
|
||||
+ u8 data[MCA_TAMPER_REGS_LEN];
|
||||
+ time64_t tamper_t64;
|
||||
+ u64 event;
|
||||
+ int ret;
|
||||
+ unsigned int tamper_base_reg = get_tamper_base_reg(tp->iface);
|
||||
+
|
||||
+ if (tamper_base_reg == ~0)
|
||||
+ goto irq_out;
|
||||
+
|
||||
+ dev_dbg(tp->mca->dev, "Tamper %d IRQ (%d)\n", tp->iface, irq);
|
||||
+
|
||||
+ ret = regmap_bulk_read(tp->mca->regmap, tamper_base_reg, data,
|
||||
+ sizeof(data));
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(tp->mca->dev, "Failed reading Tamper%d registers (%d)\n",
|
||||
+ tp->iface, ret);
|
||||
+ goto irq_out;
|
||||
+ }
|
||||
+
|
||||
+ /* Confirm the event and get the timestamp */
|
||||
+ if (!(data[EVENT] & MCA_TAMPER_SIGNALED))
|
||||
+ goto irq_out;
|
||||
+
|
||||
+ if (data[EVENT] & MCA_TAMPER_ACKED)
|
||||
+ goto irq_out;
|
||||
+
|
||||
+ mca_tamper_regs_dump(data);
|
||||
+ mca_tamper_get_time(data, &tm);
|
||||
+ tamper_t64 = rtc_tm_to_time64(&tm);
|
||||
+
|
||||
+ /* Notify the event... */
|
||||
+ event = IIO_MOD_EVENT_CODE(IIO_ACTIVITY, tp->iface, IIO_NO_MOD,
|
||||
+ IIO_EV_TYPE_CHANGE, IIO_EV_DIR_NONE);
|
||||
+ iio_push_event(iio, event, tamper_t64);
|
||||
+
|
||||
+irq_out:
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int mca_tamper_is_enabled(struct mca_drv *mca, int iface)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 data[MCA_TAMPER_REGS_LEN];
|
||||
+ unsigned int tamper_base_reg = get_tamper_base_reg(iface);
|
||||
+
|
||||
+ /* Get tamper configuration registers */
|
||||
+ ret = regmap_bulk_read(mca->regmap,
|
||||
+ tamper_base_reg,
|
||||
+ data, sizeof(data));
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(mca->dev,
|
||||
+ "Failed reading tamper%d registers (%d)\n",
|
||||
+ iface, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Verify if the tamper interface is enabled */
|
||||
+ if (!(data[CFG0] & MCA_TAMPER_DET_EN))
|
||||
+ return -1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mca_init_hardware(struct mca_tamper *tp)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 data[MCA_TAMPER_REGS_LEN];
|
||||
+ unsigned int tamper_base_reg = get_tamper_base_reg(tp->iface);
|
||||
+
|
||||
+ /* Verify if the tamper interface is enabled */
|
||||
+ ret = regmap_bulk_read(tp->mca->regmap,
|
||||
+ tamper_base_reg,
|
||||
+ data, sizeof(data));
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(tp->mca->dev,
|
||||
+ "Failed reading tamper%d registers (%d)\n",
|
||||
+ tp->iface, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ tp->config0 = data[CFG0];
|
||||
+ tp->config1 = data[CFG1];
|
||||
+ tp->io_in = data[IO_IN];
|
||||
+ tp->io_out = data[IO_OUT];
|
||||
+ tp->pwroff_delay_ms = data[DELAY_PWROFF];
|
||||
+
|
||||
+ if (!(data[CFG0] & MCA_TAMPER_DET_EN))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (tp->mca->gpio_base >= 0) {
|
||||
+ ret = devm_gpio_request(tp->mca->dev,
|
||||
+ tp->mca->gpio_base + tp->io_in,
|
||||
+ "TAMPER IN");
|
||||
+ if (ret != 0) {
|
||||
+ dev_warn(tp->mca->dev,
|
||||
+ "Error requesting GPIO %d for tamper %d input. It might be in use by other device.\n",
|
||||
+ tp->mca->gpio_base + tp->io_in, tp->iface);
|
||||
+ }
|
||||
+
|
||||
+ if (data[CFG0] & MCA_TAMPER_OUT_EN) {
|
||||
+ ret = devm_gpio_request(tp->mca->dev,
|
||||
+ tp->mca->gpio_base + tp->io_out,
|
||||
+ "TAMPER OUT");
|
||||
+ if (ret != 0) {
|
||||
+ dev_warn(tp->mca->dev,
|
||||
+ "Error requesting GPIO %d for tamper %d output. It might be in use by other device.\n",
|
||||
+ tp->mca->gpio_base + tp->io_out,
|
||||
+ tp->iface);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mca_init_channel(struct iio_chan_spec *chan, int idx)
|
||||
+{
|
||||
+ chan->type = IIO_ACTIVITY;
|
||||
+ chan->indexed = 1;
|
||||
+ chan->channel = idx;
|
||||
+ chan->scan_index = idx;
|
||||
+ chan->scan_type.sign = 'u';
|
||||
+ chan->scan_type.realbits = 1;
|
||||
+ chan->scan_type.storagebits = 32;
|
||||
+ chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
|
||||
+ chan->event_spec = mca_tamper_events;
|
||||
+ chan->num_event_specs = ARRAY_SIZE(mca_tamper_events);
|
||||
+}
|
||||
+
|
||||
+static int mca_tamper_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_drv *mca = dev_get_drvdata(pdev->dev.parent);
|
||||
+ struct mca_tamper **mca_tamper = NULL;
|
||||
+ const struct mca_tamper_data *devdata = of_device_get_match_data(&pdev->dev);
|
||||
+ struct device_node *np;
|
||||
+ struct property *prop;
|
||||
+ const __be32 *cur;
|
||||
+ u32 iface;
|
||||
+ int ret = 0;
|
||||
+ u16 num_tamper_ifaces;
|
||||
+ u16 digital_tamper_cnt;
|
||||
+
|
||||
+ if (!mca || !mca->dev || !mca->dev->of_node || !devdata)
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
+ pr_info("Tamper driver for MCA\n");
|
||||
+
|
||||
+ num_tamper_ifaces = devdata->num_tamper_ifaces;
|
||||
+ digital_tamper_cnt = devdata->digital_tamper_cnt;
|
||||
+
|
||||
+ mca_tamper = devm_kzalloc(&pdev->dev,
|
||||
+ sizeof(*mca_tamper) * num_tamper_ifaces,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!mca_tamper) {
|
||||
+ dev_err(&pdev->dev, "Failed to allocate memory for mca_tamper\n");
|
||||
+ ret = -ENOMEM;
|
||||
+ goto exit_error;
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(pdev, mca_tamper);
|
||||
+
|
||||
+ for (iface = 0; iface < num_tamper_ifaces; iface++)
|
||||
+ mca_tamper[iface] = NULL;
|
||||
+
|
||||
+ /* Return silently if RTC node does not exist or if it is disabled */
|
||||
+ {
|
||||
+ const char * compatible = pdev->dev.driver->
|
||||
+ of_match_table[devdata->devtype].compatible;
|
||||
+ np = of_find_compatible_node(mca->dev->of_node, NULL, compatible);
|
||||
+ }
|
||||
+ if (!np || !of_device_is_available(np)) {
|
||||
+ ret = -ENODEV;
|
||||
+ goto exit_error;
|
||||
+ }
|
||||
+
|
||||
+ of_property_for_each_u32(np, "digi,tamper-if-list",
|
||||
+ prop, cur, iface) {
|
||||
+ struct iio_chan_spec *channels;
|
||||
+ struct iio_dev *iiod = NULL;
|
||||
+
|
||||
+ if (iface >= num_tamper_ifaces)
|
||||
+ continue;
|
||||
+
|
||||
+ if (mca_tamper_is_enabled(mca, iface) != 0) {
|
||||
+ dev_info(&pdev->dev, "Tamper %d disabled\n", iface);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ iiod = devm_iio_device_alloc(&pdev->dev,
|
||||
+ sizeof(*mca_tamper));
|
||||
+ if (!iiod) {
|
||||
+ dev_err(&pdev->dev, "Failed to allocate iio device\n");
|
||||
+ ret = -ENOMEM;
|
||||
+ goto exit_error;
|
||||
+ }
|
||||
+ mca_tamper[iface] = iio_priv(iiod);
|
||||
+ mca_tamper[iface]->mca = mca;
|
||||
+ mca_tamper[iface]->iface = iface;
|
||||
+ mca_tamper[iface]->iio = iiod;
|
||||
+
|
||||
+ iiod->dev.parent = &pdev->dev;
|
||||
+ sprintf(mca_tamper[iface]->name, "TAMPER%d", iface);
|
||||
+ iiod->name = mca_tamper[iface]->name;
|
||||
+ iiod->modes = INDIO_DIRECT_MODE;
|
||||
+ channels = devm_kzalloc(&pdev->dev,
|
||||
+ sizeof(struct iio_chan_spec),
|
||||
+ GFP_KERNEL);
|
||||
+ iiod->channels = channels;
|
||||
+ if (!iiod->channels) {
|
||||
+ dev_err(&pdev->dev, "Failed to allocate iio channels\n");
|
||||
+ ret = -ENOMEM;
|
||||
+ goto exit_error;
|
||||
+ }
|
||||
+
|
||||
+#ifdef MCA_TAMPER_HAS_EXTRA_SYSFS_ENTRIES
|
||||
+ if (iface < digital_tamper_cnt)
|
||||
+ iiod->info = &mca_tamper_info;
|
||||
+ else
|
||||
+ iiod->info = &mca_tamper_analog_info;
|
||||
+#else
|
||||
+ iiod->info = &mca_tamper_info;
|
||||
+#endif
|
||||
+ iiod->num_channels = 1;
|
||||
+ mca_init_channel(channels, iface);
|
||||
+
|
||||
+ ret = mca_init_hardware(mca_tamper[iface]);
|
||||
+ if (ret != 0) {
|
||||
+ /* Skip the error msg if interface is not enabled */
|
||||
+ if (ret != -ENODEV)
|
||||
+ dev_err(&pdev->dev, "Failed to init Tamper %d\n",
|
||||
+ iface);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ mca_tamper[iface]->irq = platform_get_irq_byname(pdev,
|
||||
+ mca_tamper[iface]->name);
|
||||
+ if (mca_tamper[iface]->irq) {
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev,
|
||||
+ mca_tamper[iface]->irq,
|
||||
+ NULL, mca_tamper_irq_handler,
|
||||
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
+ mca_tamper[iface]->name,
|
||||
+ iiod);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "Requested TAMPER %d IRQ (%d).\n",
|
||||
+ iface, mca_tamper[iface]->irq);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = iio_device_register(iiod);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "Failed to register mca tamper iio device\n");
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(&pdev->dev, "Tamper %d enabled\n", iface);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+exit_error:
|
||||
+ for (iface = 0; iface < num_tamper_ifaces; iface++) {
|
||||
+ if (mca_tamper[iface]) {
|
||||
+ if (mca_tamper[iface]->iio)
|
||||
+ kfree(mca_tamper[iface]->iio->channels);
|
||||
+ kfree(mca_tamper[iface]->iio);
|
||||
+ }
|
||||
+ }
|
||||
+ kfree(mca_tamper);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_tamper_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_tamper **mca_tamper = dev_get_drvdata(pdev->dev.parent);
|
||||
+ struct mca_drv *mca;
|
||||
+ const struct mca_tamper_data *devdata = of_device_get_match_data(&pdev->dev);
|
||||
+ u16 num_tamper_ifaces = devdata->num_tamper_ifaces;
|
||||
+ u32 iface;
|
||||
+
|
||||
+ for (iface = 0; iface < num_tamper_ifaces; iface++) {
|
||||
+ if (mca_tamper[iface] == NULL)
|
||||
+ continue;
|
||||
+ /* Release the resources allocated */
|
||||
+ mca = mca_tamper[iface]->mca;
|
||||
+ if (mca->gpio_base >= 0) {
|
||||
+ devm_gpio_free(&pdev->dev,
|
||||
+ mca->gpio_base + mca_tamper[iface]->io_in);
|
||||
+ if (mca_tamper[iface]->config0 & MCA_TAMPER_OUT_EN)
|
||||
+ devm_gpio_free(&pdev->dev,
|
||||
+ mca->gpio_base + mca_tamper[iface]->io_out);
|
||||
+ }
|
||||
+ devm_kfree(&pdev->dev, (void *)mca_tamper[iface]->iio->channels);
|
||||
+ if (mca_tamper[iface]->irq)
|
||||
+ devm_free_irq(&pdev->dev, mca_tamper[iface]->irq,
|
||||
+ mca_tamper[iface]->iio);
|
||||
+ iio_device_unregister(mca_tamper[iface]->iio);
|
||||
+ devm_iio_device_free(&pdev->dev, mca_tamper[iface]->iio);
|
||||
+ }
|
||||
+ kfree(mca_tamper);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static struct mca_tamper_data mca_tamper_devdata[] = {
|
||||
+ [CC6UL_MCA_TAMPER] = {
|
||||
+ .devtype = CC6UL_MCA_TAMPER,
|
||||
+ .num_tamper_ifaces = 4,
|
||||
+ .digital_tamper_cnt = 2
|
||||
+ },
|
||||
+ [CC8X_MCA_TAMPER] = {
|
||||
+ .devtype = CC8X_MCA_TAMPER,
|
||||
+ .num_tamper_ifaces = 4,
|
||||
+ .digital_tamper_cnt = 2
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id mca_tamper_ids[] = {
|
||||
+ { .compatible = "digi,mca-cc6ul-tamper",
|
||||
+ .data = &mca_tamper_devdata[CC6UL_MCA_TAMPER]},
|
||||
+ { .compatible = "digi,mca-cc8x-tamper",
|
||||
+ .data = &mca_tamper_devdata[CC8X_MCA_TAMPER]},
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, mca_tamper_ids);
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver mca_tamper_driver = {
|
||||
+ .probe = mca_tamper_probe,
|
||||
+ .remove = mca_tamper_remove,
|
||||
+ .driver = {
|
||||
+ .name = MCA_DRVNAME_TAMPER,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = of_match_ptr(mca_tamper_ids),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init mca_tamper_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&mca_tamper_driver);
|
||||
+}
|
||||
+module_init(mca_tamper_init);
|
||||
+
|
||||
+static void __exit mca_tamper_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&mca_tamper_driver);
|
||||
+}
|
||||
+module_exit(mca_tamper_exit);
|
||||
+
|
||||
+MODULE_AUTHOR("Digi International Inc");
|
||||
+MODULE_DESCRIPTION("Tamper driver for MCA of ConnectCore Modules");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_ALIAS("platform:" MCA_DRVNAME_TAMPER);
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,540 @@
|
|||
From 33fb650af68bcc05f59181ae7a4f8424a0949f91 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Mon, 23 Apr 2018 11:44:37 +0200
|
||||
Subject: [PATCH] imx6ul: Add RTC MCA support for ConnectCore 6UL SOM
|
||||
|
||||
Synched with v4.14.78/master at:
|
||||
3f8b03950b323db4ca89b1cdc1c2288f79facaa3
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi | 4 +
|
||||
arch/arm/configs/imx_v6_v7_defconfig | 1 +
|
||||
drivers/rtc/Kconfig | 12 +
|
||||
drivers/rtc/Makefile | 1 +
|
||||
drivers/rtc/rtc-mca.c | 454 ++++++++++++++++++++++++++++++
|
||||
5 files changed, 472 insertions(+)
|
||||
create mode 100644 drivers/rtc/rtc-mca.c
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
index c721320a4117..8163533c83b0 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
@@ -69,6 +69,10 @@
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
+ rtc {
|
||||
+ compatible = "digi,mca-cc6ul-rtc";
|
||||
+ };
|
||||
+
|
||||
watchdog {
|
||||
compatible = "digi,mca-cc6ul-wdt";
|
||||
digi,full-reset;
|
||||
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
index 0a07b13ce593..8a763ab6a365 100644
|
||||
--- a/arch/arm/configs/imx_v6_v7_defconfig
|
||||
+++ b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
@@ -370,6 +370,7 @@ CONFIG_RTC_DRV_PCF8523=y
|
||||
CONFIG_RTC_DRV_PCF8563=y
|
||||
CONFIG_RTC_DRV_M41T80=y
|
||||
CONFIG_RTC_DRV_DA9063=y
|
||||
+CONFIG_RTC_DRV_MCA=y
|
||||
CONFIG_RTC_DRV_MC13XXX=y
|
||||
CONFIG_RTC_DRV_MXC=y
|
||||
CONFIG_RTC_DRV_MXC_V2=y
|
||||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
|
||||
index a819ef07b7ec..303c17e8a909 100644
|
||||
--- a/drivers/rtc/Kconfig
|
||||
+++ b/drivers/rtc/Kconfig
|
||||
@@ -1106,6 +1106,18 @@ config RTC_DRV_M48T59
|
||||
This driver can also be built as a module, if so, the module
|
||||
will be called "rtc-m48t59".
|
||||
|
||||
+config RTC_DRV_MCA
|
||||
+ tristate "Digi ConnectCore SOMs Micro Controller Assist RTC"
|
||||
+ select MFD_MCA_CC6UL if SOC_IMX6UL
|
||||
+ select MFD_MCA_CC8X if ARCH_FSL_IMX8QXP
|
||||
+
|
||||
+ help
|
||||
+ If you say Y here you will get support for the RTC in the
|
||||
+ Micro Controller Assist of Digi ConnectCore system-on-modules.
|
||||
+
|
||||
+ This driver can also be built as a module, if so, the module
|
||||
+ will be called "rtc-mca".
|
||||
+
|
||||
config RTC_DRV_MSM6242
|
||||
tristate "Oki MSM6242"
|
||||
depends on HAS_IOMEM
|
||||
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
|
||||
index 290c1730fb0a..cd1b13723479 100644
|
||||
--- a/drivers/rtc/Makefile
|
||||
+++ b/drivers/rtc/Makefile
|
||||
@@ -98,6 +98,7 @@ obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
|
||||
obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o
|
||||
obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
|
||||
obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o
|
||||
+obj-$(CONFIG_RTC_DRV_MCA) += rtc-mca.o
|
||||
obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o
|
||||
obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
|
||||
obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o
|
||||
diff --git a/drivers/rtc/rtc-mca.c b/drivers/rtc/rtc-mca.c
|
||||
new file mode 100644
|
||||
index 000000000000..b0e3d17aa995
|
||||
--- /dev/null
|
||||
+++ b/drivers/rtc/rtc-mca.c
|
||||
@@ -0,0 +1,454 @@
|
||||
+/* rtc-mca.c - Real time clock device driver for MCA on ConnectCore modules
|
||||
+ * Copyright (C) 2016 - 2018 Digi International
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Library General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * Library General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Library General Public
|
||||
+ * License along with this library; if not, write to the
|
||||
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
+ * Boston, MA 02110-1301, USA.
|
||||
+ */
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/rtc.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/mfd/mca-common/core.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/of_irq.h>
|
||||
+#include <linux/regmap.h>
|
||||
+
|
||||
+#define MCA_DRVNAME_RTC "mca-rtc"
|
||||
+
|
||||
+#define CLOCK_DATA_LEN (MCA_RTC_COUNT_SEC - MCA_RTC_COUNT_YEAR_L + 1)
|
||||
+#define ALARM_DATA_LEN (MCA_RTC_ALARM_SEC - MCA_RTC_ALARM_YEAR_L + 1)
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+enum mca_rtc_type {
|
||||
+ CC6UL_MCA_RTC,
|
||||
+ CC8X_MCA_RTC,
|
||||
+};
|
||||
+
|
||||
+struct mca_rtc_data {
|
||||
+ enum mca_rtc_type devtype;
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+struct mca_rtc {
|
||||
+ struct rtc_device *rtc_dev;
|
||||
+ struct mca_drv *mca;
|
||||
+ int irq_alarm;
|
||||
+ bool alarm_enabled;
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ DATA_YEAR_L,
|
||||
+ DATA_YEAR_H,
|
||||
+ DATA_MONTH,
|
||||
+ DATA_DAY,
|
||||
+ DATA_HOUR,
|
||||
+ DATA_MIN,
|
||||
+ DATA_SEC,
|
||||
+};
|
||||
+
|
||||
+static void mca_data_to_tm(u8 *data, struct rtc_time *tm)
|
||||
+{
|
||||
+ /* conversion from MCA RTC to struct time is month-1 and year-1900 */
|
||||
+ tm->tm_year = (((data[DATA_YEAR_H] &
|
||||
+ MCA_RTC_YEAR_H_MASK) << 8) |
|
||||
+ (data[DATA_YEAR_L] & MCA_RTC_YEAR_L_MASK)) -
|
||||
+ 1900;
|
||||
+ tm->tm_mon = (data[DATA_MONTH] & MCA_RTC_MONTH_MASK) - 1;
|
||||
+ tm->tm_mday = (data[DATA_DAY] & MCA_RTC_DAY_MASK);
|
||||
+ tm->tm_hour = (data[DATA_HOUR] & MCA_RTC_HOUR_MASK);
|
||||
+ tm->tm_min = (data[DATA_MIN] & MCA_RTC_MIN_MASK);
|
||||
+ tm->tm_sec = (data[DATA_SEC] & MCA_RTC_SEC_MASK);
|
||||
+}
|
||||
+
|
||||
+static void mca_tm_to_data(struct rtc_time *tm, u8 *data)
|
||||
+{
|
||||
+ /* conversion from struct time to MCA RTC is year+1900 */
|
||||
+ data[DATA_YEAR_L] &= (u8)~MCA_RTC_YEAR_L_MASK;
|
||||
+ data[DATA_YEAR_H] &= (u8)~MCA_RTC_YEAR_H_MASK;
|
||||
+ data[DATA_YEAR_L] |= (tm->tm_year + 1900) &
|
||||
+ MCA_RTC_YEAR_L_MASK;
|
||||
+ data[DATA_YEAR_H] |= ((tm->tm_year + 1900) >> 8) &
|
||||
+ MCA_RTC_YEAR_H_MASK;
|
||||
+
|
||||
+ /* conversion from struct time to MCA RTC is month+1 */
|
||||
+ data[DATA_MONTH] &= ~MCA_RTC_MONTH_MASK;
|
||||
+ data[DATA_MONTH] |= (tm->tm_mon + 1) & MCA_RTC_MONTH_MASK;
|
||||
+
|
||||
+ data[DATA_DAY] &= ~MCA_RTC_DAY_MASK;
|
||||
+ data[DATA_DAY] |= tm->tm_mday & MCA_RTC_DAY_MASK;
|
||||
+
|
||||
+ data[DATA_HOUR] &= ~MCA_RTC_HOUR_MASK;
|
||||
+ data[DATA_HOUR] |= tm->tm_hour & MCA_RTC_HOUR_MASK;
|
||||
+
|
||||
+ data[DATA_MIN] &= ~MCA_RTC_MIN_MASK;
|
||||
+ data[DATA_MIN] |= tm->tm_min & MCA_RTC_MIN_MASK;
|
||||
+
|
||||
+ data[DATA_SEC] &= ~MCA_RTC_SEC_MASK;
|
||||
+ data[DATA_SEC] |= tm->tm_sec & MCA_RTC_SEC_MASK;
|
||||
+}
|
||||
+
|
||||
+static int mca_rtc_stop_alarm(struct device *dev)
|
||||
+{
|
||||
+ struct mca_rtc *rtc = dev_get_drvdata(dev);
|
||||
+
|
||||
+ return regmap_update_bits(rtc->mca->regmap, MCA_RTC_CONTROL,
|
||||
+ MCA_RTC_ALARM_EN, 0);
|
||||
+}
|
||||
+
|
||||
+static int mca_rtc_start_alarm(struct device *dev)
|
||||
+{
|
||||
+ struct mca_rtc *rtc = dev_get_drvdata(dev);
|
||||
+
|
||||
+ return regmap_update_bits(rtc->mca->regmap, MCA_RTC_CONTROL,
|
||||
+ MCA_RTC_ALARM_EN,
|
||||
+ MCA_RTC_ALARM_EN);
|
||||
+}
|
||||
+
|
||||
+static int mca_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
+{
|
||||
+ struct mca_rtc *rtc = dev_get_drvdata(dev);
|
||||
+ u8 data[CLOCK_DATA_LEN] = { [0 ... (CLOCK_DATA_LEN - 1)] = 0 };
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = regmap_bulk_read(rtc->mca->regmap, MCA_RTC_COUNT_YEAR_L,
|
||||
+ data, CLOCK_DATA_LEN);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "Failed to read RTC time data: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ mca_data_to_tm(data, tm);
|
||||
+ return rtc_valid_tm(tm);
|
||||
+}
|
||||
+
|
||||
+static int mca_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
+{
|
||||
+ struct mca_rtc *rtc = dev_get_drvdata(dev);
|
||||
+ u8 data[CLOCK_DATA_LEN] = { [0 ... (CLOCK_DATA_LEN - 1)] = 0 };
|
||||
+ int ret;
|
||||
+
|
||||
+ mca_tm_to_data(tm, data);
|
||||
+
|
||||
+ ret = regmap_bulk_write(rtc->mca->regmap, MCA_RTC_COUNT_YEAR_L,
|
||||
+ data, CLOCK_DATA_LEN);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "Failed to set RTC time data: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * The MCA RTC alarm expires (triggers the irq) when the RTC time matches the
|
||||
+ * value programmed in the alarm register and the RTC counter increments.
|
||||
+ * This means, one second after the programmed value. To correct this, the
|
||||
+ * alarm value is adjusted when it is being written/read, decrementing/incremen-
|
||||
+ * ting the value by 1 second.
|
||||
+ */
|
||||
+static void mca_rtc_adjust_alarm_time(struct rtc_wkalrm *alrm, bool inc)
|
||||
+{
|
||||
+ unsigned long time;
|
||||
+
|
||||
+ rtc_tm_to_time(&alrm->time, &time);
|
||||
+ time = inc ? time + 1 : time - 1;
|
||||
+ rtc_time_to_tm(time, &alrm->time);
|
||||
+}
|
||||
+
|
||||
+static int mca_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
+{
|
||||
+ struct mca_rtc *rtc = dev_get_drvdata(dev);
|
||||
+ u8 data[CLOCK_DATA_LEN] = { [0 ... (CLOCK_DATA_LEN - 1)] = 0 };
|
||||
+ int ret;
|
||||
+ unsigned int val;
|
||||
+
|
||||
+ ret = regmap_bulk_read(rtc->mca->regmap, MCA_RTC_ALARM_YEAR_L,
|
||||
+ data, ALARM_DATA_LEN);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ mca_data_to_tm(data, &alrm->time);
|
||||
+ mca_rtc_adjust_alarm_time(alrm, true);
|
||||
+
|
||||
+ /* Enable status */
|
||||
+ ret = regmap_read(rtc->mca->regmap, MCA_RTC_CONTROL, &val);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Pending status */
|
||||
+ ret = regmap_read(rtc->mca->regmap, MCA_IRQ_STATUS_0, &val);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ alrm->pending = (val & MCA_RTC_ALARM) ? 1 : 0;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mca_rtc_alarm_irq_enable(struct device *dev,
|
||||
+ unsigned int enabled)
|
||||
+{
|
||||
+ struct mca_rtc *rtc = dev_get_drvdata(dev);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (enabled) {
|
||||
+ ret = mca_rtc_start_alarm(dev);
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(dev, "Failed to enable alarm IRQ (%d)\n", ret);
|
||||
+ goto exit_alarm_irq;
|
||||
+ }
|
||||
+ rtc->alarm_enabled = 1;
|
||||
+ } else {
|
||||
+ ret = mca_rtc_stop_alarm(dev);
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(dev, "Failed to disable alarm IRQ (%d)\n", ret);
|
||||
+ goto exit_alarm_irq;
|
||||
+ }
|
||||
+ rtc->alarm_enabled = 0;
|
||||
+ }
|
||||
+
|
||||
+exit_alarm_irq:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
+{
|
||||
+ struct mca_rtc *rtc = dev_get_drvdata(dev);
|
||||
+ u8 data[CLOCK_DATA_LEN] = { [0 ... (CLOCK_DATA_LEN - 1)] = 0 };
|
||||
+ int ret;
|
||||
+
|
||||
+ mca_rtc_adjust_alarm_time(alrm, false);
|
||||
+ mca_tm_to_data(&alrm->time, data);
|
||||
+
|
||||
+ ret = regmap_bulk_write(rtc->mca->regmap, MCA_RTC_ALARM_YEAR_L,
|
||||
+ data, ALARM_DATA_LEN);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return mca_rtc_alarm_irq_enable(dev, alrm->enabled);
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t mca_alarm_event(int irq, void *data)
|
||||
+{
|
||||
+ struct mca_rtc *rtc = data;
|
||||
+
|
||||
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static const struct rtc_class_ops mca_rtc_ops = {
|
||||
+ .read_time = mca_rtc_read_time,
|
||||
+ .set_time = mca_rtc_set_time,
|
||||
+ .read_alarm = mca_rtc_read_alarm,
|
||||
+ .set_alarm = mca_rtc_set_alarm,
|
||||
+ .alarm_irq_enable = mca_rtc_alarm_irq_enable,
|
||||
+};
|
||||
+
|
||||
+static int mca_rtc_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_drv *mca = dev_get_drvdata(pdev->dev.parent);
|
||||
+ struct mca_rtc *rtc;
|
||||
+ const struct mca_rtc_data *devdata =
|
||||
+ of_device_get_match_data(&pdev->dev);
|
||||
+ struct device_node *np = NULL;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (!mca || !mca->dev->parent->of_node)
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
+ rtc = devm_kzalloc(&pdev->dev, sizeof *rtc, GFP_KERNEL);
|
||||
+ if (!rtc)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, rtc);
|
||||
+ device_init_wakeup(&pdev->dev, 1);
|
||||
+ rtc->mca = mca;
|
||||
+
|
||||
+ /* Find entry in device-tree */
|
||||
+ if (mca->dev->of_node) {
|
||||
+ const char * compatible = pdev->dev.driver->
|
||||
+ of_match_table[devdata->devtype].compatible;
|
||||
+
|
||||
+ /*
|
||||
+ * Return silently if RTC node does not exist
|
||||
+ * or if it is disabled
|
||||
+ */
|
||||
+ np = of_find_compatible_node(mca->dev->of_node, NULL, compatible);
|
||||
+ if (!np) {
|
||||
+ ret = -ENODEV;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ if (!of_device_is_available(np)) {
|
||||
+ ret = -ENODEV;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Enable RTC hardware */
|
||||
+ ret = regmap_update_bits(mca->regmap, MCA_RTC_CONTROL,
|
||||
+ MCA_RTC_EN, MCA_RTC_EN);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&pdev->dev, "Failed to enable RTC.\n");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Register RTC device */
|
||||
+ rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
|
||||
+
|
||||
+ if (IS_ERR(rtc->rtc_dev)) {
|
||||
+ dev_err(&pdev->dev, "Failed to allocate RTC device: %ld\n",
|
||||
+ PTR_ERR(rtc->rtc_dev));
|
||||
+ ret = PTR_ERR(rtc->rtc_dev);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ rtc->rtc_dev->ops = &mca_rtc_ops;
|
||||
+ ret = rtc_register_device(rtc->rtc_dev);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&pdev->dev, "Failed to register RTC device.\n");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /*
|
||||
+ * Register interrupts. Complain on errors but let device
|
||||
+ * to be registered at least for date/time.
|
||||
+ */
|
||||
+ rtc->irq_alarm = platform_get_irq_byname(pdev,
|
||||
+ MCA_IRQ_RTC_ALARM_NAME);
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev, rtc->irq_alarm, NULL,
|
||||
+ mca_alarm_event,
|
||||
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
+ MCA_IRQ_RTC_ALARM_NAME, rtc);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Failed to request %s IRQ. (%d)\n",
|
||||
+ MCA_IRQ_RTC_ALARM_NAME, rtc->irq_alarm);
|
||||
+ rtc->irq_alarm = -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ rtc = NULL;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_rtc_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_rtc *rtc = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ if (rtc->irq_alarm >= 0)
|
||||
+ devm_free_irq(&pdev->dev, rtc->irq_alarm, rtc);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM
|
||||
+static int mca_rtc_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct platform_device *pdev = to_platform_device(dev);
|
||||
+ struct mca_rtc *rtc = platform_get_drvdata(pdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!device_may_wakeup(&pdev->dev) && rtc->alarm_enabled) {
|
||||
+ /* Disable the alarm irq to avoid unwanted wakeups */
|
||||
+ ret = mca_rtc_stop_alarm(&pdev->dev);
|
||||
+ if (ret < 0)
|
||||
+ dev_err(&pdev->dev, "Failed to disable RTC Alarm\n");
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mca_rtc_resume(struct device *dev)
|
||||
+{
|
||||
+ struct platform_device *pdev = to_platform_device(dev);
|
||||
+ struct mca_rtc *rtc = platform_get_drvdata(pdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!device_may_wakeup(&pdev->dev) && rtc->alarm_enabled) {
|
||||
+ /* Enable the alarm irq, just in case it was disabled suspending */
|
||||
+ ret = mca_rtc_start_alarm(&pdev->dev);
|
||||
+ if (ret < 0)
|
||||
+ dev_err(&pdev->dev, "Failed to restart RTC Alarm\n");
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct dev_pm_ops mca_rtc_pm_ops = {
|
||||
+ .suspend = mca_rtc_suspend,
|
||||
+ .resume = mca_rtc_resume,
|
||||
+ .poweroff = mca_rtc_suspend,
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static struct mca_rtc_data mca_rtc_devdata[] = {
|
||||
+ [CC6UL_MCA_RTC] = {
|
||||
+ .devtype = CC6UL_MCA_RTC,
|
||||
+ },
|
||||
+ [CC8X_MCA_RTC] = {
|
||||
+ .devtype = CC8X_MCA_RTC,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id mca_rtc_dt_ids[] = {
|
||||
+ { .compatible = "digi,mca-cc6ul-rtc",
|
||||
+ .data = &mca_rtc_devdata[CC6UL_MCA_RTC]},
|
||||
+ { .compatible = "digi,mca-cc8x-rtc",
|
||||
+ .data = &mca_rtc_devdata[CC8X_MCA_RTC]},
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, mca_rtc_dt_ids);
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver mca_rtc_driver = {
|
||||
+ .probe = mca_rtc_probe,
|
||||
+ .remove = mca_rtc_remove,
|
||||
+ .driver = {
|
||||
+ .name = MCA_DRVNAME_RTC,
|
||||
+ .owner = THIS_MODULE,
|
||||
+#ifdef CONFIG_PM
|
||||
+ .pm = &mca_rtc_pm_ops,
|
||||
+#endif
|
||||
+#ifdef CONFIG_OF
|
||||
+ .of_match_table = mca_rtc_dt_ids,
|
||||
+#endif
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init mca_rtc_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&mca_rtc_driver);
|
||||
+}
|
||||
+module_init(mca_rtc_init);
|
||||
+
|
||||
+static void __exit mca_rtc_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&mca_rtc_driver);
|
||||
+}
|
||||
+module_exit(mca_rtc_exit);
|
||||
+
|
||||
+/* Module information */
|
||||
+MODULE_AUTHOR("Digi International Inc.");
|
||||
+MODULE_DESCRIPTION("Real time clock device driver for MCA of ConnectCore Modules");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_ALIAS("platform:" MCA_DRVNAME_RTC);
|
||||
|
|
@ -0,0 +1,490 @@
|
|||
From 052464d671eb993264a78b3e35170c1d9fd44268 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Mon, 23 Apr 2018 11:45:16 +0200
|
||||
Subject: [PATCH] imx6ul: Add MCA power key support for ConnectCore 6UL SOM
|
||||
|
||||
Synched with v4.14.78/master at:
|
||||
3f8b03950b323db4ca89b1cdc1c2288f79facaa3
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi | 9 +
|
||||
arch/arm/configs/imx_v6_v7_defconfig | 1 +
|
||||
drivers/input/misc/Kconfig | 12 +
|
||||
drivers/input/misc/Makefile | 1 +
|
||||
drivers/input/misc/pwrkey-mca.c | 401 ++++++++++++++++++++++++++++++
|
||||
5 files changed, 424 insertions(+)
|
||||
create mode 100644 drivers/input/misc/pwrkey-mca.c
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
index 8163533c83b0..f2a17f9b88d1 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
|
||||
@@ -78,6 +78,15 @@
|
||||
digi,full-reset;
|
||||
};
|
||||
|
||||
+ pwrkey {
|
||||
+ compatible = "digi,mca-cc6ul-pwrkey";
|
||||
+ digi,key-power;
|
||||
+ digi,key-sleep;
|
||||
+ digi,debounce-ms = <100>;
|
||||
+ digi,pwroff-delay-sec = <6>;
|
||||
+ digi,pwroff-guard-sec = <30>;
|
||||
+ };
|
||||
+
|
||||
mca_adc: adc {
|
||||
compatible = "digi,mca-cc6ul-adc";
|
||||
digi,adc-vref = <3000000>;
|
||||
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
index 8a763ab6a365..31d02719c51e 100644
|
||||
--- a/arch/arm/configs/imx_v6_v7_defconfig
|
||||
+++ b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
@@ -186,6 +186,7 @@ CONFIG_TOUCHSCREEN_SX8654=y
|
||||
CONFIG_TOUCHSCREEN_COLIBRI_VF50=y
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_MMA8450=y
|
||||
+CONFIG_INPUT_MCA_PWRKEY=y
|
||||
CONFIG_SERIO_SERPORT=m
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
CONFIG_SERIAL_IMX=y
|
||||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
|
||||
index ca59a2be9bc5..cef9795466f7 100644
|
||||
--- a/drivers/input/misc/Kconfig
|
||||
+++ b/drivers/input/misc/Kconfig
|
||||
@@ -851,4 +851,16 @@ config INPUT_SC27XX_VIBRA
|
||||
To compile this driver as a module, choose M here. The module will
|
||||
be called sc27xx_vibra.
|
||||
|
||||
+config INPUT_MCA_PWRKEY
|
||||
+ tristate "Digi ConnectCore SOMs Micro Controller Assist Power key"
|
||||
+ select MFD_MCA_CC6UL if SOC_IMX6UL
|
||||
+ select MFD_MCA_CC8X if ARCH_FSL_IMX8QXP
|
||||
+ help
|
||||
+ If you say Y here you will get support for the Power Key in the
|
||||
+ Micro Controller Assist of Digi ConnectCore system-on-modules,
|
||||
+ as an input device, reporting the power input/button status.
|
||||
+
|
||||
+ This driver can also be built as a module, if so, the module
|
||||
+ will be called "pwrkey-mca".
|
||||
+
|
||||
endif
|
||||
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
|
||||
index 9d0f9d1ff68f..1ed17d1b0c68 100644
|
||||
--- a/drivers/input/misc/Makefile
|
||||
+++ b/drivers/input/misc/Makefile
|
||||
@@ -47,6 +47,7 @@ obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o
|
||||
obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
|
||||
obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o
|
||||
obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o
|
||||
+obj-$(CONFIG_INPUT_MCA_PWRKEY) += pwrkey-mca.o
|
||||
obj-$(CONFIG_INPUT_MMA8450) += mma8450.o
|
||||
obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
|
||||
diff --git a/drivers/input/misc/pwrkey-mca.c b/drivers/input/misc/pwrkey-mca.c
|
||||
new file mode 100644
|
||||
index 000000000000..ddb83ef77045
|
||||
--- /dev/null
|
||||
+++ b/drivers/input/misc/pwrkey-mca.c
|
||||
@@ -0,0 +1,401 @@
|
||||
+/* pwrkey-mca.c - Power Key device driver for MCA on ConnectCore modules
|
||||
+ * Copyright (C) 2016 - 2018 Digi International Inc
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Library General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * Library General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Library General Public
|
||||
+ * License along with this library; if not, write to the
|
||||
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
+ * Boston, MA 02110-1301, USA.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/input.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/workqueue.h>
|
||||
+#include <linux/mfd/mca-common/core.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/of_irq.h>
|
||||
+#include <linux/regmap.h>
|
||||
+
|
||||
+#define MCA_DRVNAME_PWRKEY "mca-pwrkey"
|
||||
+
|
||||
+#define DEFAULT_PWR_KEY_DEBOUNCE 150 /* 150 ms */
|
||||
+#define DEFAULT_PWR_KEY_DELAY 4 /* 4 seconds */
|
||||
+#define DEFAULT_PWR_KEY_GUARD 25 /* 25 seconds */
|
||||
+#define MAX_PWR_KEY_DEBOUNCE 255
|
||||
+#define MAX_PWR_KEY_DELAY 255
|
||||
+#define MAX_PWR_KEY_GUARD 255
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+enum mca_pwrkey_type {
|
||||
+ CC6UL_MCA_PWRKEY,
|
||||
+ CC8X_MCA_PWRKEY,
|
||||
+};
|
||||
+
|
||||
+struct mca_pwrkey_data {
|
||||
+ enum mca_pwrkey_type devtype;
|
||||
+ char drv_name_phys[40];
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+struct mca_pwrkey {
|
||||
+ struct mca_drv *mca;
|
||||
+ struct input_dev *input;
|
||||
+ int irq_power;
|
||||
+ int irq_sleep;
|
||||
+ bool key_power;
|
||||
+ bool key_sleep;
|
||||
+ bool suspended;
|
||||
+ uint32_t debounce_ms;
|
||||
+ uint32_t pwroff_delay_sec;
|
||||
+ uint32_t pwroff_guard_sec;
|
||||
+};
|
||||
+
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
+static DEFINE_SPINLOCK(lock);
|
||||
+#endif
|
||||
+
|
||||
+static irqreturn_t mca_pwrkey_power_off_irq_handler(int irq, void *data)
|
||||
+{
|
||||
+ struct mca_pwrkey *pwrkey = data;
|
||||
+
|
||||
+ dev_notice(&pwrkey->input->dev, "Power Button - KEY_POWER\n");
|
||||
+
|
||||
+ input_report_key(pwrkey->input, KEY_POWER, 1);
|
||||
+ input_sync(pwrkey->input);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t mca_pwrkey_sleep_irq_handler(int irq, void *data)
|
||||
+{
|
||||
+ struct mca_pwrkey *pwrkey = data;
|
||||
+
|
||||
+ /* Report the event only if not coming from suspend */
|
||||
+ if (!pwrkey->suspended) {
|
||||
+ dev_notice(&pwrkey->input->dev, "Power button - KEY_SLEEP\n");
|
||||
+
|
||||
+ input_report_key(pwrkey->input, KEY_SLEEP, 1);
|
||||
+ input_report_key(pwrkey->input, KEY_SLEEP, 0);
|
||||
+ input_sync(pwrkey->input);
|
||||
+ }
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int mca_pwrkey_initialize(struct mca_pwrkey *pwrkey)
|
||||
+{
|
||||
+ int ret;
|
||||
+ uint8_t pwrctrl0 = 0;
|
||||
+
|
||||
+ ret = regmap_write(pwrkey->mca->regmap, MCA_PWR_KEY_DEBOUNCE,
|
||||
+ (uint8_t)pwrkey->debounce_ms);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(pwrkey->mca->dev,
|
||||
+ "Failed to set debounce time 0x%02x, %d\n",
|
||||
+ (uint8_t)pwrkey->debounce_ms, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_write(pwrkey->mca->regmap, MCA_PWR_KEY_DELAY,
|
||||
+ (uint8_t)pwrkey->pwroff_delay_sec);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(pwrkey->mca->dev,
|
||||
+ "Failed to set delay time 0x%02x, %d\n",
|
||||
+ (uint8_t)pwrkey->pwroff_delay_sec, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_write(pwrkey->mca->regmap, MCA_PWR_KEY_GUARD,
|
||||
+ (uint8_t)pwrkey->pwroff_guard_sec);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(pwrkey->mca->dev,
|
||||
+ "Failed to set guard time 0x%02x, %d\n",
|
||||
+ (uint8_t)pwrkey->pwroff_guard_sec, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (pwrkey->key_power)
|
||||
+ pwrctrl0 |= MCA_PWR_KEY_OFF_EN;
|
||||
+
|
||||
+ if (pwrkey->key_sleep)
|
||||
+ pwrctrl0 |= MCA_PWR_KEY_SLEEP_EN;
|
||||
+
|
||||
+ if (pwrkey->pwroff_guard_sec != 0)
|
||||
+ pwrctrl0 |= MCA_PWR_GUARD_EN;
|
||||
+
|
||||
+ ret = regmap_write(pwrkey->mca->regmap, MCA_PWR_CTRL_0, pwrctrl0);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(pwrkey->mca->dev,
|
||||
+ "Failed to set PWR_CTRL_0 0x%02x, %d\n",
|
||||
+ pwrctrl0, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int of_mca_pwrkey_read_settings(struct device_node *np,
|
||||
+ struct mca_pwrkey *pwrkey)
|
||||
+{
|
||||
+ uint32_t val;
|
||||
+
|
||||
+ /* Get driver configuration data from device tree */
|
||||
+ pwrkey->debounce_ms = DEFAULT_PWR_KEY_DEBOUNCE;
|
||||
+ pwrkey->pwroff_delay_sec = DEFAULT_PWR_KEY_DEBOUNCE;
|
||||
+ pwrkey->pwroff_guard_sec = DEFAULT_PWR_KEY_GUARD;
|
||||
+
|
||||
+ pwrkey->key_power = of_property_read_bool(np, "digi,key-power");
|
||||
+ pwrkey->key_sleep = of_property_read_bool(np, "digi,key-sleep");
|
||||
+
|
||||
+ if (!of_property_read_u32(np, "digi,debounce-ms", &val)) {
|
||||
+ if (val <= MAX_PWR_KEY_DEBOUNCE)
|
||||
+ pwrkey->debounce_ms = val;
|
||||
+ else
|
||||
+ dev_warn(pwrkey->mca->dev,
|
||||
+ "Invalid debounce-ms value. Using default.\n");
|
||||
+ }
|
||||
+
|
||||
+ if (!of_property_read_u32(np, "digi,pwroff-delay-sec", &val)) {
|
||||
+ if (val <= MAX_PWR_KEY_DELAY)
|
||||
+ pwrkey->pwroff_delay_sec = val;
|
||||
+ else
|
||||
+ dev_warn(pwrkey->mca->dev,
|
||||
+ "Invalid pwroff-delay-sec value. Using default.\n");
|
||||
+ }
|
||||
+
|
||||
+ if (!of_property_read_u32(np, "digi,pwroff-guard-sec", &val)) {
|
||||
+ if (val <= MAX_PWR_KEY_GUARD)
|
||||
+ pwrkey->pwroff_guard_sec = val;
|
||||
+ else
|
||||
+ dev_warn(pwrkey->mca->dev,
|
||||
+ "Invalid pwroff-guard-sec value. Using default.\n");
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mca_pwrkey_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_drv *mca = dev_get_drvdata(pdev->dev.parent);
|
||||
+ struct mca_pwrkey *pwrkey;
|
||||
+ const struct mca_pwrkey_data *devdata =
|
||||
+ of_device_get_match_data(&pdev->dev);
|
||||
+ struct device_node *np = NULL;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (!mca || !mca->dev || !mca->dev->parent ||
|
||||
+ !mca->dev->parent->of_node)
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
+ /* Find entry in device-tree */
|
||||
+ if (mca->dev->of_node) {
|
||||
+ const char * compatible = pdev->dev.driver->
|
||||
+ of_match_table[devdata->devtype].compatible;
|
||||
+
|
||||
+ /* Return if pwrkey node does not exist or if it is disabled */
|
||||
+ np = of_find_compatible_node(mca->dev->of_node, NULL, compatible);
|
||||
+ if (!np || !of_device_is_available(np))
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ pwrkey = devm_kzalloc(&pdev->dev, sizeof(struct mca_pwrkey),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!pwrkey) {
|
||||
+ dev_err(&pdev->dev, "Failed to allocate memory.\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ pwrkey->input = input_allocate_device();
|
||||
+ if (!pwrkey->input) {
|
||||
+ dev_err(&pdev->dev, "Failed to allocated input device.\n");
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_free;
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(pdev, pwrkey);
|
||||
+ pwrkey->mca = mca;
|
||||
+ pwrkey->irq_power = platform_get_irq_byname(pdev,
|
||||
+ MCA_IRQ_PWR_OFF_NAME);
|
||||
+ pwrkey->irq_sleep = platform_get_irq_byname(pdev,
|
||||
+ MCA_IRQ_PWR_SLEEP_NAME);
|
||||
+ pwrkey->input->name = dev_name(&pdev->dev);
|
||||
+ pwrkey->input->phys = devdata->drv_name_phys;
|
||||
+ pwrkey->input->dev.parent = &pdev->dev;
|
||||
+
|
||||
+ input_set_capability(pwrkey->input, EV_KEY, KEY_POWER);
|
||||
+ input_set_capability(pwrkey->input, EV_KEY, KEY_SLEEP);
|
||||
+
|
||||
+ /* Initialize driver settings from device tree */
|
||||
+ ret = of_mca_pwrkey_read_settings(np, pwrkey);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Failed to get %s dtb settings\n",
|
||||
+ dev_name(&pdev->dev));
|
||||
+ goto err_free_inputdev;
|
||||
+ }
|
||||
+
|
||||
+ ret = mca_pwrkey_initialize(pwrkey);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Failed to initilize pwrkey registers\n");
|
||||
+ goto err_free_inputdev;
|
||||
+ }
|
||||
+
|
||||
+ if (pwrkey->key_power) {
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev, pwrkey->irq_power, NULL,
|
||||
+ mca_pwrkey_power_off_irq_handler,
|
||||
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
+ MCA_IRQ_PWR_OFF_NAME, pwrkey);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Failed to request %s IRQ (%d).\n",
|
||||
+ MCA_IRQ_PWR_OFF_NAME, pwrkey->irq_power);
|
||||
+ goto err_free_inputdev;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (pwrkey->key_sleep) {
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev, pwrkey->irq_sleep, NULL,
|
||||
+ mca_pwrkey_sleep_irq_handler,
|
||||
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
+ MCA_IRQ_PWR_SLEEP_NAME, pwrkey);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Failed to request %s IRQ (%d).\n",
|
||||
+ MCA_IRQ_PWR_SLEEP_NAME, pwrkey->irq_sleep);
|
||||
+ goto err_irq1;
|
||||
+ }
|
||||
+ enable_irq_wake(pwrkey->irq_sleep);
|
||||
+ }
|
||||
+
|
||||
+ ret = input_register_device(pwrkey->input);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Failed to register input device (%d).\n",
|
||||
+ ret);
|
||||
+ goto err_irq2;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_irq2:
|
||||
+ if (pwrkey->key_sleep)
|
||||
+ free_irq(pwrkey->mca->irq_base + pwrkey->irq_sleep, pwrkey);
|
||||
+err_irq1:
|
||||
+ if (pwrkey->key_power)
|
||||
+ free_irq(pwrkey->mca->irq_base + pwrkey->irq_power, pwrkey);
|
||||
+err_free_inputdev:
|
||||
+ input_free_device(pwrkey->input);
|
||||
+err_free:
|
||||
+ kfree(pwrkey);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_pwrkey_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mca_pwrkey *pwrkey = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ if (pwrkey->key_power)
|
||||
+ free_irq(pwrkey->irq_power, pwrkey);
|
||||
+ if (pwrkey->key_sleep)
|
||||
+ free_irq(pwrkey->irq_sleep, pwrkey);
|
||||
+ input_unregister_device(pwrkey->input);
|
||||
+ kfree(pwrkey);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
+static int __maybe_unused mca_pwrkey_resume(struct device *dev)
|
||||
+{
|
||||
+ struct platform_device *pdev = to_platform_device(dev);
|
||||
+ struct mca_pwrkey *pwrkey = platform_get_drvdata(pdev);
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&lock, flags);
|
||||
+ pwrkey->suspended = false;
|
||||
+ spin_unlock_irqrestore(&lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __maybe_unused mca_pwrkey_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct platform_device *pdev = to_platform_device(dev);
|
||||
+ struct mca_pwrkey *pwrkey = platform_get_drvdata(pdev);
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&lock, flags);
|
||||
+ pwrkey->suspended = true;
|
||||
+ spin_unlock_irqrestore(&lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+SIMPLE_DEV_PM_OPS(mca_pwrkey_pm_ops, mca_pwrkey_suspend, mca_pwrkey_resume);
|
||||
+#endif /* CONFIG_PM_SLEEP */
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static struct mca_pwrkey_data mca_pwrkey_devdata[] = {
|
||||
+ [CC6UL_MCA_PWRKEY] = {
|
||||
+ .devtype = CC6UL_MCA_PWRKEY,
|
||||
+ .drv_name_phys= "mca-cc6ul-pwrkey/input0"
|
||||
+ },
|
||||
+ [CC8X_MCA_PWRKEY] = {
|
||||
+ .devtype = CC8X_MCA_PWRKEY,
|
||||
+ .drv_name_phys= "mca-cc8x-pwrkey/input0"
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id mca_pwrkey_ids[] = {
|
||||
+ { .compatible = "digi,mca-cc6ul-pwrkey",
|
||||
+ .data = &mca_pwrkey_devdata[CC6UL_MCA_PWRKEY]},
|
||||
+ { .compatible = "digi,mca-cc8x-pwrkey",
|
||||
+ .data = &mca_pwrkey_devdata[CC8X_MCA_PWRKEY]},
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, mca_pwrkey_ids);
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver mca_pwrkey_driver = {
|
||||
+ .probe = mca_pwrkey_probe,
|
||||
+ .remove = mca_pwrkey_remove,
|
||||
+ .driver = {
|
||||
+ .name = MCA_DRVNAME_PWRKEY,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = of_match_ptr(mca_pwrkey_ids),
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
+ .pm = &mca_pwrkey_pm_ops,
|
||||
+#endif
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init mca_pwrkey_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&mca_pwrkey_driver);
|
||||
+}
|
||||
+module_init(mca_pwrkey_init);
|
||||
+
|
||||
+static void __exit mca_pwrkey_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&mca_pwrkey_driver);
|
||||
+}
|
||||
+module_exit(mca_pwrkey_exit);
|
||||
+
|
||||
+MODULE_AUTHOR("Digi International Inc");
|
||||
+MODULE_DESCRIPTION("pwrkey device driver for MCA of ConnectCore Modules");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_ALIAS("platform:" MCA_DRVNAME_PWRKEY);
|
||||
|
|
@ -0,0 +1,892 @@
|
|||
From f56dbb1e8b6a501e84d69ac5f18ec7a66cb4faa7 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Mon, 23 Apr 2018 11:46:52 +0200
|
||||
Subject: [PATCH] ccimx6ulsbcpro: Add IOEXP core I2C support
|
||||
|
||||
Synched with v4.14.78/master at:
|
||||
3f8b03950b323db4ca89b1cdc1c2288f79facaa3
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/configs/imx_v6_v7_defconfig | 1 +
|
||||
drivers/mfd/Kconfig | 10 +
|
||||
drivers/mfd/Makefile | 4 +-
|
||||
drivers/mfd/mca-ioexp-core.c | 415 ++++++++++++++++++++++++++++++++
|
||||
drivers/mfd/mca-ioexp-i2c.c | 186 ++++++++++++++
|
||||
drivers/mfd/mca-ioexp-irq.c | 89 +++++++
|
||||
include/linux/mfd/mca-ioexp/core.h | 87 +++++++
|
||||
include/linux/mfd/mca-ioexp/registers.h | 15 ++
|
||||
8 files changed, 805 insertions(+), 2 deletions(-)
|
||||
create mode 100644 drivers/mfd/mca-ioexp-core.c
|
||||
create mode 100644 drivers/mfd/mca-ioexp-i2c.c
|
||||
create mode 100644 drivers/mfd/mca-ioexp-irq.c
|
||||
create mode 100644 include/linux/mfd/mca-ioexp/core.h
|
||||
create mode 100644 include/linux/mfd/mca-ioexp/registers.h
|
||||
|
||||
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
index ed31623082ac..a269983e3cba 100644
|
||||
--- a/arch/arm/configs/imx_v6_v7_defconfig
|
||||
+++ b/arch/arm/configs/imx_v6_v7_defconfig
|
||||
@@ -242,6 +242,7 @@ CONFIG_MFD_DA9063=y
|
||||
CONFIG_MFD_MC13XXX_SPI=y
|
||||
CONFIG_MFD_MC13XXX_I2C=y
|
||||
CONFIG_MFD_RN5T618=y
|
||||
+CONFIG_MFD_MCA_IOEXP=y
|
||||
CONFIG_MFD_STMPE=y
|
||||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
|
||||
index 42c72334d645..5b87d592aece 100644
|
||||
--- a/drivers/mfd/Kconfig
|
||||
+++ b/drivers/mfd/Kconfig
|
||||
@@ -458,6 +458,16 @@ config MFD_MCA_CC8X
|
||||
Additional drivers must be enabled in order to use the functionality
|
||||
of the device (RTC, watchdog, ...).
|
||||
|
||||
+config MFD_MCA_IOEXP
|
||||
+ bool "Digi IO Expander"
|
||||
+ select MFD_CORE
|
||||
+ select REGMAP_I2C
|
||||
+ select REGMAP_IRQ
|
||||
+ depends on I2C=y
|
||||
+ help
|
||||
+ Select this option to enable support for the Digi IO Expander.
|
||||
+ This includes the GPIO and ADC drivers.
|
||||
+
|
||||
config MFD_MX25_TSADC
|
||||
tristate "Freescale i.MX25 integrated Touchscreen and ADC unit"
|
||||
select REGMAP_MMIO
|
||||
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
|
||||
index 28443313ba92..bfbaaba0d74f 100644
|
||||
--- a/drivers/mfd/Makefile
|
||||
+++ b/drivers/mfd/Makefile
|
||||
@@ -249,5 +249,5 @@ obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
|
||||
|
||||
mca-cc6ul-objs := mca-cc6ul-core.o mca-cc6ul-irq.o mca-cc6ul-i2c.o
|
||||
obj-$(CONFIG_MFD_MCA_CC6UL) += mca-cc6ul.o
|
||||
-mca-cc8x-objs := mca-cc8x-core.o mca-cc8x-irq.o mca-cc8x-i2c.o
|
||||
-obj-$(CONFIG_MFD_MCA_CC8X) += mca-cc8x.o
|
||||
+mca-ioexp-objs := mca-ioexp-core.o mca-ioexp-irq.o mca-ioexp-i2c.o
|
||||
+obj-$(CONFIG_MFD_MCA_IOEXP) += mca-ioexp.o
|
||||
diff --git a/drivers/mfd/mca-ioexp-core.c b/drivers/mfd/mca-ioexp-core.c
|
||||
new file mode 100644
|
||||
index 000000000000..19b3c7f2b4be
|
||||
--- /dev/null
|
||||
+++ b/drivers/mfd/mca-ioexp-core.c
|
||||
@@ -0,0 +1,415 @@
|
||||
+/*
|
||||
+ * Copyright 2017 - 2019 Digi International Inc
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/sysfs.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/mfd/core.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/suspend.h>
|
||||
+#include <linux/proc_fs.h>
|
||||
+#include <linux/kthread.h>
|
||||
+#include <linux/uaccess.h>
|
||||
+#include <linux/reboot.h>
|
||||
+
|
||||
+#include <linux/mfd/mca-common/core.h>
|
||||
+#include <linux/mfd/mca-ioexp/core.h>
|
||||
+
|
||||
+#include <asm/unaligned.h>
|
||||
+
|
||||
+static struct resource mca_ioexp_gpios_resources[] = {
|
||||
+ {
|
||||
+ .name = MCA_IRQ_GPIO_BANK_0_NAME,
|
||||
+ .start = MCA_IOEXP_IRQ_GPIO_BANK_0,
|
||||
+ .end = MCA_IOEXP_IRQ_GPIO_BANK_0,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = MCA_IRQ_GPIO_BANK_1_NAME,
|
||||
+ .start = MCA_IOEXP_IRQ_GPIO_BANK_1,
|
||||
+ .end = MCA_IOEXP_IRQ_GPIO_BANK_1,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = MCA_IRQ_GPIO_BANK_2_NAME,
|
||||
+ .start = MCA_IOEXP_IRQ_GPIO_BANK_2,
|
||||
+ .end = MCA_IOEXP_IRQ_GPIO_BANK_2,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = MCA_IRQ_GPIO_BANK_3_NAME,
|
||||
+ .start = MCA_IOEXP_IRQ_GPIO_BANK_3,
|
||||
+ .end = MCA_IOEXP_IRQ_GPIO_BANK_3,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = MCA_IRQ_GPIO_BANK_4_NAME,
|
||||
+ .start = MCA_IOEXP_IRQ_GPIO_BANK_4,
|
||||
+ .end = MCA_IOEXP_IRQ_GPIO_BANK_4,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = MCA_IRQ_GPIO_BANK_5_NAME,
|
||||
+ .start = MCA_IOEXP_IRQ_GPIO_BANK_5,
|
||||
+ .end = MCA_IOEXP_IRQ_GPIO_BANK_5,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct mfd_cell mca_ioexp_devs[] = {
|
||||
+ {
|
||||
+ .name = MCA_IOEXP_DRVNAME_GPIO,
|
||||
+ .num_resources = ARRAY_SIZE(mca_ioexp_gpios_resources),
|
||||
+ .resources = mca_ioexp_gpios_resources,
|
||||
+ .of_compatible = "digi,mca-ioexp-gpio",
|
||||
+ },
|
||||
+ {
|
||||
+ .name = MCA_IOEXP_DRVNAME_ADC,
|
||||
+ .of_compatible = "digi,mca-ioexp-adc",
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static ssize_t hwver_show(struct device *dev, struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct mca_ioexp *ioexp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ return sprintf(buf, "%d\n", ioexp->hw_version);
|
||||
+}
|
||||
+static DEVICE_ATTR(hw_version, S_IRUGO, hwver_show, NULL);
|
||||
+
|
||||
+static ssize_t fwver_show(struct device *dev, struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct mca_ioexp *ioexp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ return sprintf(buf, "%d.%02d %s\n", MCA_FW_VER_MAJOR(ioexp->fw_version),
|
||||
+ MCA_FW_VER_MINOR(ioexp->fw_version),
|
||||
+ ioexp->fw_is_alpha ? "(alpha)" : "");
|
||||
+}
|
||||
+static DEVICE_ATTR(fw_version, S_IRUGO, fwver_show, NULL);
|
||||
+
|
||||
+static struct attribute *mca_ioexp_sysfs_entries[] = {
|
||||
+ &dev_attr_hw_version.attr,
|
||||
+ &dev_attr_fw_version.attr,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static struct attribute_group mca_ioexp_attr_group = {
|
||||
+ .name = NULL, /* put in device directory */
|
||||
+ .attrs = mca_ioexp_sysfs_entries,
|
||||
+};
|
||||
+
|
||||
+static int read_reg_group(struct mca_ioexp *ioexp,
|
||||
+ unsigned int start_addr,
|
||||
+ unsigned int count,
|
||||
+ uint8_t *dest)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ unsigned int error;
|
||||
+
|
||||
+ if (count == 0 || !dest)
|
||||
+ return -1;
|
||||
+
|
||||
+ for (i = 0; i < count; i++) {
|
||||
+ const unsigned int reg_addr = start_addr + i;
|
||||
+ unsigned int value;
|
||||
+
|
||||
+ error = regmap_read(ioexp->regmap, reg_addr, &value);
|
||||
+ if (error) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Error reading register %02X (%d)\n",
|
||||
+ reg_addr, error);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ dest[i] = value;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int mca_ioexp_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct mca_ioexp *ioexp = dev_get_drvdata(dev);
|
||||
+ int error;
|
||||
+
|
||||
+ if (!ioexp->preserved_regs)
|
||||
+ return 0;
|
||||
+
|
||||
+
|
||||
+ error = read_reg_group(ioexp, MCA_GPIO_DIR_0,
|
||||
+ ioexp->preserved_regs->gpio_dir.cnt,
|
||||
+ ioexp->preserved_regs->gpio_dir.values);
|
||||
+ if (error) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to preserve MCA_GPIO_DIR registers.\n");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ error = read_reg_group(ioexp, MCA_GPIO_DATA_0,
|
||||
+ ioexp->preserved_regs->gpio_data.cnt,
|
||||
+ ioexp->preserved_regs->gpio_data.values);
|
||||
+ if (error) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to preserve MCA_GPIO_DATA registers.\n");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ error = read_reg_group(ioexp, MCA_GPIO_IRQ_CFG_0,
|
||||
+ ioexp->preserved_regs->irq_cfg.cnt,
|
||||
+ ioexp->preserved_regs->irq_cfg.values);
|
||||
+ if (error) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to preserve MCA_GPIO_IRQ_CFG registers.\n");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ error = read_reg_group(ioexp, MCA_IRQ_MASK_0,
|
||||
+ ioexp->preserved_regs->irq_mask.cnt,
|
||||
+ ioexp->preserved_regs->irq_mask.values);
|
||||
+ if (error) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to preserve MCA_IRQ_MASK registers.\n");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ error = read_reg_group(ioexp, MCA_REG_ADC_CFG0_0,
|
||||
+ ioexp->preserved_regs->adc_cfg.cnt,
|
||||
+ ioexp->preserved_regs->adc_cfg.values);
|
||||
+ if (error) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to preserve MCA_REG_ADC_CFG registers.\n");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ disable_irq(ioexp->chip_irq);
|
||||
+ return 0;
|
||||
+
|
||||
+exit:
|
||||
+ if (error)
|
||||
+ dev_err(ioexp->dev, "Configuration will be lost on resume. The IOs in use might need to be reconfigured in order to work properly.\n");
|
||||
+
|
||||
+ disable_irq(ioexp->chip_irq);
|
||||
+
|
||||
+ /* Do not return errors or the device will not go to sleep. */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int write_reg_group(struct mca_ioexp *ioexp,
|
||||
+ unsigned int start_addr,
|
||||
+ unsigned int count,
|
||||
+ uint8_t *values)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ unsigned int error;
|
||||
+
|
||||
+ if (count == 0 || !values)
|
||||
+ return -1;
|
||||
+
|
||||
+ for (i = 0; i < count; i++) {
|
||||
+ const unsigned int reg_addr = start_addr + i;
|
||||
+ const unsigned int value = values[i];
|
||||
+
|
||||
+ error = regmap_write(ioexp->regmap, reg_addr, value);
|
||||
+ if (error) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Error writing register %02X (%d)\n",
|
||||
+ reg_addr, error);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+int mca_ioexp_resume(struct device *dev)
|
||||
+{
|
||||
+ struct mca_ioexp *ioexp = dev_get_drvdata(dev);
|
||||
+ int error;
|
||||
+
|
||||
+ if (!ioexp->preserved_regs)
|
||||
+ return 0;
|
||||
+
|
||||
+ error = write_reg_group(ioexp, MCA_GPIO_DIR_0,
|
||||
+ ioexp->preserved_regs->gpio_dir.cnt,
|
||||
+ ioexp->preserved_regs->gpio_dir.values);
|
||||
+ if (error)
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to restore MCA_GPIO_DIR registers.\n");
|
||||
+
|
||||
+ error = write_reg_group(ioexp, MCA_GPIO_DATA_0,
|
||||
+ ioexp->preserved_regs->gpio_data.cnt,
|
||||
+ ioexp->preserved_regs->gpio_data.values);
|
||||
+ if (error)
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to restore MCA_GPIO_DATA registers.\n");
|
||||
+
|
||||
+ error = write_reg_group(ioexp, MCA_GPIO_IRQ_CFG_0,
|
||||
+ ioexp->preserved_regs->irq_cfg.cnt,
|
||||
+ ioexp->preserved_regs->irq_cfg.values);
|
||||
+ if (error)
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to restore MCA_GPIO_IRQ_CFG registers.\n");
|
||||
+
|
||||
+ error = write_reg_group(ioexp, MCA_IRQ_MASK_0,
|
||||
+ ioexp->preserved_regs->irq_mask.cnt,
|
||||
+ ioexp->preserved_regs->irq_mask.values);
|
||||
+ if (error)
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to restore MCA_IRQ_MASK registers.\n");
|
||||
+
|
||||
+ error = write_reg_group(ioexp, MCA_REG_ADC_CFG0_0,
|
||||
+ ioexp->preserved_regs->adc_cfg.cnt,
|
||||
+ ioexp->preserved_regs->adc_cfg.values);
|
||||
+ if (error)
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to restore MCA_REG_ADC_CFG registers.\n");
|
||||
+
|
||||
+ enable_irq(ioexp->chip_irq);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int mca_ioexp_device_init(struct mca_ioexp *ioexp, u32 irq)
|
||||
+{
|
||||
+ int ret;
|
||||
+ unsigned int val;
|
||||
+
|
||||
+ ret = regmap_read(ioexp->regmap, MCA_DEVICE_ID, &val);
|
||||
+ if (ret) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Cannot read MCA IO Expander Device ID (%d)\n",
|
||||
+ ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ioexp->dev_id = (u8)val;
|
||||
+
|
||||
+ if (ioexp->dev_id != MCA_IOEXP_DEVICE_ID_VAL) {
|
||||
+ dev_err(ioexp->dev, "Invalid MCA IO Expander Device ID (%x)\n",
|
||||
+ ioexp->dev_id);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_read(ioexp->regmap, MCA_HW_VER, &val);
|
||||
+ if (ret) {
|
||||
+ dev_err(ioexp->dev, "Cannot read MCA Hardware Version (%d)\n",
|
||||
+ ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ioexp->hw_version = (u8)val;
|
||||
+
|
||||
+ ret = regmap_bulk_read(ioexp->regmap, MCA_FW_VER_L, &val, 2);
|
||||
+ if (ret) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Cannot read MCA IO Expander Firmware Version (%d)\n",
|
||||
+ ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ioexp->fw_version = (u16)(val & ~MCA_FW_VER_ALPHA_MASK);
|
||||
+ ioexp->fw_is_alpha = val & MCA_FW_VER_ALPHA_MASK ? true : false;
|
||||
+
|
||||
+ ioexp->chip_irq = irq;
|
||||
+ ioexp->gpio_base = -1;
|
||||
+
|
||||
+ if (of_find_property(ioexp->dev->of_node, "restore-config-on-resume",
|
||||
+ NULL)) {
|
||||
+ unsigned int gpio_num;
|
||||
+
|
||||
+ ioexp->preserved_regs = kzalloc(sizeof *ioexp->preserved_regs,
|
||||
+ GFP_KERNEL | GFP_DMA);
|
||||
+ if (!ioexp->preserved_regs) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Failed to allocate memory for preserved registers.\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_read(ioexp->regmap, MCA_GPIO_NUM, &gpio_num);
|
||||
+ if (ret) {
|
||||
+ dev_err(ioexp->dev,
|
||||
+ "Error reading MCA_GPIO_NUM (%d)\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ioexp->preserved_regs->gpio_dir.cnt = (gpio_num + 7) / 8;
|
||||
+ ioexp->preserved_regs->gpio_dir.values =
|
||||
+ kzalloc(ioexp->preserved_regs->gpio_dir.cnt,
|
||||
+ GFP_KERNEL | GFP_DMA);
|
||||
+ ioexp->preserved_regs->gpio_data.cnt = (gpio_num + 7) / 8;
|
||||
+ ioexp->preserved_regs->gpio_data.values =
|
||||
+ kzalloc(ioexp->preserved_regs->gpio_data.cnt,
|
||||
+ GFP_KERNEL | GFP_DMA);
|
||||
+ ioexp->preserved_regs->irq_cfg.cnt = gpio_num;
|
||||
+ ioexp->preserved_regs->irq_cfg.values =
|
||||
+ kzalloc(ioexp->preserved_regs->irq_cfg.cnt,
|
||||
+ GFP_KERNEL | GFP_DMA);
|
||||
+ ioexp->preserved_regs->irq_mask.cnt = 4;
|
||||
+ ioexp->preserved_regs->irq_mask.values =
|
||||
+ kzalloc(ioexp->preserved_regs->irq_mask.cnt,
|
||||
+ GFP_KERNEL | GFP_DMA);
|
||||
+ ioexp->preserved_regs->adc_cfg.cnt = gpio_num;
|
||||
+ ioexp->preserved_regs->adc_cfg.values =
|
||||
+ kzalloc(ioexp->preserved_regs->adc_cfg.cnt,
|
||||
+ GFP_KERNEL | GFP_DMA);
|
||||
+
|
||||
+ } else {
|
||||
+ ioexp->preserved_regs = NULL;
|
||||
+ }
|
||||
+ ret = mca_ioexp_irq_init(ioexp);
|
||||
+ if (ret) {
|
||||
+ dev_err(ioexp->dev, "Cannot initialize interrupts (%d)\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = mfd_add_devices(ioexp->dev, -1, mca_ioexp_devs,
|
||||
+ ARRAY_SIZE(mca_ioexp_devs), NULL, ioexp->irq_base,
|
||||
+ regmap_irq_get_domain(ioexp->regmap_irq));
|
||||
+
|
||||
+ if (ret) {
|
||||
+ dev_err(ioexp->dev, "Cannot add MFD cells (%d)\n", ret);
|
||||
+ goto out_irq;
|
||||
+ }
|
||||
+
|
||||
+ ret = sysfs_create_group(&ioexp->dev->kobj, &mca_ioexp_attr_group);
|
||||
+ if (ret) {
|
||||
+ dev_err(ioexp->dev, "Cannot create sysfs entries (%d)\n", ret);
|
||||
+ goto out_dev;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+out_dev:
|
||||
+ mfd_remove_devices(ioexp->dev);
|
||||
+out_irq:
|
||||
+ mca_ioexp_irq_exit(ioexp);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void mca_ioexp_device_exit(struct mca_ioexp *ioexp)
|
||||
+{
|
||||
+ sysfs_remove_group(&ioexp->dev->kobj, &mca_ioexp_attr_group);
|
||||
+ mfd_remove_devices(ioexp->dev);
|
||||
+ mca_ioexp_irq_exit(ioexp);
|
||||
+
|
||||
+ if (!ioexp->preserved_regs) {
|
||||
+ kfree(ioexp->preserved_regs->gpio_dir.values);
|
||||
+ kfree(ioexp->preserved_regs->gpio_data.values);
|
||||
+ kfree(ioexp->preserved_regs->irq_cfg.values);
|
||||
+ kfree(ioexp->preserved_regs->irq_mask.values);
|
||||
+ kfree(ioexp->preserved_regs->adc_cfg.values);
|
||||
+ kfree(ioexp->preserved_regs);
|
||||
+
|
||||
+ ioexp->preserved_regs = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+MODULE_AUTHOR("Digi International Inc");
|
||||
+MODULE_DESCRIPTION("MCA IO Expander driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
diff --git a/drivers/mfd/mca-ioexp-i2c.c b/drivers/mfd/mca-ioexp-i2c.c
|
||||
new file mode 100644
|
||||
index 000000000000..29a5587ce683
|
||||
--- /dev/null
|
||||
+++ b/drivers/mfd/mca-ioexp-i2c.c
|
||||
@@ -0,0 +1,186 @@
|
||||
+/*
|
||||
+ * Copyright 2017 - 2019 Digi International Inc
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/of.h>
|
||||
+
|
||||
+#include <linux/mfd/core.h>
|
||||
+#include <linux/mfd/mca-common/core.h>
|
||||
+#include <linux/mfd/mca-ioexp/core.h>
|
||||
+
|
||||
+static const struct regmap_range mca_ioexp_readable_ranges[] = {
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_range mca_ioexp_writeable_ranges[] = {
|
||||
+ regmap_reg_range(MCA_IRQ_STATUS_0, MCA_IRQ_MASK_3),
|
||||
+ regmap_reg_range(MCA_GPIO_DIR_0, MCA_GPIO_IRQ_CFG_63),
|
||||
+ regmap_reg_range(MCA_REG_ADC_CFG0_0, MCA_REG_ADC_CFG0_31),
|
||||
+ regmap_reg_range(MCA_REG_ADC_CFG1_0, MCA_REG_ADC_CFG1_31),
|
||||
+ regmap_reg_range(MCA_REG_ADC_CFG2_0, MCA_REG_ADC_CFG2_31),
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_range mca_ioexp_volatile_ranges[] = {
|
||||
+ /* Real volatile registers */
|
||||
+ regmap_reg_range(MCA_IRQ_STATUS_0, MCA_IRQ_STATUS_3),
|
||||
+ regmap_reg_range(MCA_GPIO_DATA_0, MCA_GPIO_DATA_7),
|
||||
+ regmap_reg_range(MCA_GPIO_IRQ_STATUS_0, MCA_GPIO_IRQ_STATUS_7),
|
||||
+ regmap_reg_range(MCA_REG_ADC_VAL_L_0, MCA_REG_ADC_VAL_H_31),
|
||||
+
|
||||
+ /*
|
||||
+ * Fake volatile registers.
|
||||
+ *
|
||||
+ * These registers could be cached but non-volatile registers makes
|
||||
+ * regmap access each register one by one which has some drawbacks:
|
||||
+ * - Breaks CRC in the protocol.
|
||||
+ * - Requires the MCA firmware to process each access as a separate
|
||||
+ * access, even when the data requested must be returned in bulk.
|
||||
+ *
|
||||
+ * For this reasons we will consider all registers volatile.
|
||||
+ */
|
||||
+ regmap_reg_range(MCA_DEVICE_ID, MCA_UID_9),
|
||||
+ regmap_reg_range(MCA_IRQ_MASK_0, MCA_IRQ_MASK_3),
|
||||
+ regmap_reg_range(MCA_GPIO_NUM, MCA_GPIO_DIR_7),
|
||||
+ regmap_reg_range(MCA_GPIO_IRQ_CFG_0, MCA_GPIO_IRQ_CFG_63),
|
||||
+ regmap_reg_range(MCA_REG_ADC_NUM_CH, MCA_REG_ADC_NUM_BYTES),
|
||||
+ regmap_reg_range(MCA_REG_ADC_CFG0_0, MCA_REG_ADC_CFG0_31),
|
||||
+ regmap_reg_range(MCA_REG_ADC_CFG1_0, MCA_REG_ADC_CFG1_31),
|
||||
+ regmap_reg_range(MCA_REG_ADC_CFG2_0, MCA_REG_ADC_CFG2_31),
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_access_table mca_ioexp_readable_table = {
|
||||
+ .yes_ranges = mca_ioexp_readable_ranges,
|
||||
+ .n_yes_ranges = ARRAY_SIZE(mca_ioexp_readable_ranges),
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_access_table mca_ioexp_writeable_table = {
|
||||
+ .yes_ranges = mca_ioexp_writeable_ranges,
|
||||
+ .n_yes_ranges = ARRAY_SIZE(mca_ioexp_writeable_ranges),
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_access_table mca_ioexp_volatile_table = {
|
||||
+ .yes_ranges = mca_ioexp_volatile_ranges,
|
||||
+ .n_yes_ranges = ARRAY_SIZE(mca_ioexp_volatile_ranges),
|
||||
+};
|
||||
+
|
||||
+static struct regmap_config mca_ioexp_regmap_config = {
|
||||
+ .reg_bits = 16,
|
||||
+ .val_bits = 8,
|
||||
+ .max_register = 0xFFFF,
|
||||
+
|
||||
+ .rd_table = &mca_ioexp_readable_table,
|
||||
+ .wr_table = &mca_ioexp_writeable_table,
|
||||
+ .volatile_table = &mca_ioexp_volatile_table,
|
||||
+
|
||||
+ .cache_type = REGCACHE_RBTREE,
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id mca_ioexp_dt_ids[] = {
|
||||
+ { .compatible = "digi,mca_ioexp", },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, mca_ioexp_dt_ids);
|
||||
+
|
||||
+static int mca_ioexp_i2c_probe(struct i2c_client *i2c,
|
||||
+ const struct i2c_device_id *id)
|
||||
+{
|
||||
+ struct mca_ioexp *ioexp;
|
||||
+ int ret;
|
||||
+
|
||||
+ ioexp = devm_kzalloc(&i2c->dev, sizeof(struct mca_ioexp), GFP_KERNEL);
|
||||
+ if (ioexp == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ i2c_set_clientdata(i2c, ioexp);
|
||||
+ ioexp->dev = &i2c->dev;
|
||||
+ ioexp->chip_irq = i2c->irq;
|
||||
+ ioexp->regmap = devm_regmap_init_i2c(i2c, &mca_ioexp_regmap_config);
|
||||
+ if (IS_ERR(ioexp->regmap)) {
|
||||
+ ret = PTR_ERR(ioexp->regmap);
|
||||
+ dev_err(ioexp->dev, "Failed to allocate register map (%d)\n", ret);
|
||||
+ goto err_regmap;
|
||||
+ }
|
||||
+
|
||||
+ ret = mca_ioexp_device_init(ioexp, i2c->irq);
|
||||
+ if (ret) {
|
||||
+ dev_err(ioexp->dev, "Failed to init i2c device (%d)\n", ret);
|
||||
+ goto err_regmap;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_regmap:
|
||||
+ devm_kfree(ioexp->dev, ioexp);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mca_ioexp_i2c_remove(struct i2c_client *i2c)
|
||||
+{
|
||||
+ struct mca_ioexp *ioexp = i2c_get_clientdata(i2c);
|
||||
+
|
||||
+ mca_ioexp_device_exit(ioexp);
|
||||
+ devm_kfree(ioexp->dev, ioexp);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mca_ioexp_i2c_shutdown(struct i2c_client *i2c)
|
||||
+{
|
||||
+ struct mca_ioexp *ioexp = i2c_get_clientdata(i2c);
|
||||
+
|
||||
+ /*
|
||||
+ * Disable the IRQ so that the I/O Expander does not wake-up the MCA
|
||||
+ * when powered off.
|
||||
+ */
|
||||
+ disable_irq(ioexp->chip_irq);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM
|
||||
+static int mca_ioexp_i2c_suspend(struct device *dev)
|
||||
+{
|
||||
+ return mca_ioexp_suspend(dev);
|
||||
+}
|
||||
+
|
||||
+static int mca_ioexp_i2c_resume(struct device *dev)
|
||||
+{
|
||||
+ return mca_ioexp_resume(dev);
|
||||
+}
|
||||
+
|
||||
+static SIMPLE_DEV_PM_OPS(mca_ioexp_i2c_pm_ops,
|
||||
+ mca_ioexp_i2c_suspend,
|
||||
+ mca_ioexp_i2c_resume);
|
||||
+#endif
|
||||
+
|
||||
+static const struct i2c_device_id mca_ioexp_i2c_id[] = {
|
||||
+ {"mca_ioexp", 0},
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(i2c, mca_ioexp_i2c_id);
|
||||
+
|
||||
+static struct i2c_driver mca_ioexp_i2c_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "mca_ioexp",
|
||||
+ .of_match_table = of_match_ptr(mca_ioexp_dt_ids),
|
||||
+#ifdef CONFIG_PM
|
||||
+ .pm = &mca_ioexp_i2c_pm_ops,
|
||||
+#endif
|
||||
+ },
|
||||
+ .probe = mca_ioexp_i2c_probe,
|
||||
+ .remove = mca_ioexp_i2c_remove,
|
||||
+ .shutdown = mca_ioexp_i2c_shutdown,
|
||||
+ .id_table = mca_ioexp_i2c_id,
|
||||
+};
|
||||
+
|
||||
+module_i2c_driver(mca_ioexp_i2c_driver);
|
||||
diff --git a/drivers/mfd/mca-ioexp-irq.c b/drivers/mfd/mca-ioexp-irq.c
|
||||
new file mode 100644
|
||||
index 000000000000..439149765dd0
|
||||
--- /dev/null
|
||||
+++ b/drivers/mfd/mca-ioexp-irq.c
|
||||
@@ -0,0 +1,89 @@
|
||||
+/*
|
||||
+ * Copyright 2017 - 2019 Digi International Inc
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/mfd/core.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/mfd/mca-ioexp/core.h>
|
||||
+#include <linux/mfd/mca-common/core.h>
|
||||
+
|
||||
+#define MCA_IOEXP_IRQ_0_OFFSET 0
|
||||
+#define MCA_IOEXP_IRQ_1_OFFSET 1
|
||||
+#define MCA_IOEXP_IRQ_2_OFFSET 2
|
||||
+#define MCA_IOEXP_IRQ_3_OFFSET 3
|
||||
+
|
||||
+static const struct regmap_irq mca_ioexp_irqs[] = {
|
||||
+ [MCA_IOEXP_IRQ_GPIO_BANK_0] = {
|
||||
+ .reg_offset = MCA_IOEXP_IRQ_1_OFFSET,
|
||||
+ .mask = MCA_GPIO_BANK_0,
|
||||
+ },
|
||||
+ [MCA_IOEXP_IRQ_GPIO_BANK_1] = {
|
||||
+ .reg_offset = MCA_IOEXP_IRQ_1_OFFSET,
|
||||
+ .mask = MCA_GPIO_BANK_1,
|
||||
+ },
|
||||
+ [MCA_IOEXP_IRQ_GPIO_BANK_2] = {
|
||||
+ .reg_offset = MCA_IOEXP_IRQ_1_OFFSET,
|
||||
+ .mask = MCA_GPIO_BANK_2,
|
||||
+ },
|
||||
+ [MCA_IOEXP_IRQ_GPIO_BANK_3] = {
|
||||
+ .reg_offset = MCA_IOEXP_IRQ_1_OFFSET,
|
||||
+ .mask = MCA_GPIO_BANK_3,
|
||||
+ },
|
||||
+ [MCA_IOEXP_IRQ_GPIO_BANK_4] = {
|
||||
+ .reg_offset = MCA_IOEXP_IRQ_1_OFFSET,
|
||||
+ .mask = MCA_GPIO_BANK_4,
|
||||
+ },
|
||||
+ [MCA_IOEXP_IRQ_GPIO_BANK_5] = {
|
||||
+ .reg_offset = MCA_IOEXP_IRQ_1_OFFSET,
|
||||
+ .mask = MCA_GPIO_BANK_5,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_irq_chip mca_ioexp_irq_chip = {
|
||||
+ .name = "mca-ioexp-irq",
|
||||
+ .irqs = mca_ioexp_irqs,
|
||||
+ .num_irqs = ARRAY_SIZE(mca_ioexp_irqs),
|
||||
+ .num_regs = MCA_IOEXP_NUM_IRQ_REGS,
|
||||
+ .status_base = MCA_IRQ_STATUS_0,
|
||||
+ .mask_base = MCA_IRQ_MASK_0,
|
||||
+ .ack_base = MCA_IRQ_STATUS_0,
|
||||
+ .init_ack_masked = true,
|
||||
+};
|
||||
+
|
||||
+int mca_ioexp_irq_init(struct mca_ioexp *ioexp)
|
||||
+{
|
||||
+ int ret;
|
||||
+ const int irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED;
|
||||
+
|
||||
+ if (!ioexp->chip_irq) {
|
||||
+ dev_err(ioexp->dev, "No IRQ configured\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ioexp->irq_base = -1;
|
||||
+ ret = regmap_add_irq_chip(ioexp->regmap, ioexp->chip_irq,
|
||||
+ irq_flags,
|
||||
+ ioexp->irq_base, &mca_ioexp_irq_chip,
|
||||
+ &ioexp->regmap_irq);
|
||||
+ if (ret) {
|
||||
+ dev_err(ioexp->dev, "Failed to request IRQ %d (%d)\n",
|
||||
+ ioexp->chip_irq, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void mca_ioexp_irq_exit(struct mca_ioexp *ioexp)
|
||||
+{
|
||||
+ regmap_del_irq_chip(ioexp->chip_irq, ioexp->regmap_irq);
|
||||
+}
|
||||
diff --git a/include/linux/mfd/mca-ioexp/core.h b/include/linux/mfd/mca-ioexp/core.h
|
||||
new file mode 100644
|
||||
index 000000000000..cb9969262da5
|
||||
--- /dev/null
|
||||
+++ b/include/linux/mfd/mca-ioexp/core.h
|
||||
@@ -0,0 +1,87 @@
|
||||
+/*
|
||||
+ * Copyright 2017 - 2019 Digi International Inc
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#ifndef MFD_MCA_IOEXP_CORE_H_
|
||||
+#define MFD_MCA_IOEXP_CORE_H_
|
||||
+
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/mfd/mca-ioexp/registers.h>
|
||||
+
|
||||
+#define MCA_IOEXP_DRVNAME_ADC "mca-ioexp-adc"
|
||||
+#define MCA_IOEXP_DRVNAME_GPIO "mca-ioexp-gpio"
|
||||
+
|
||||
+#define MCA_IOEXP_DEVICE_ID_VAL 0x37
|
||||
+#define MCA_IOEXP_ADDR_LEN 2
|
||||
+#define MCA_IOEXP_MAX_FRAME_DATA_LEN 256
|
||||
+
|
||||
+/* Interrupts */
|
||||
+enum mca_ioexp_irqs {
|
||||
+ MCA_IOEXP_IRQ_GPIO_BANK_0,
|
||||
+ MCA_IOEXP_IRQ_GPIO_BANK_1,
|
||||
+ MCA_IOEXP_IRQ_GPIO_BANK_2,
|
||||
+ MCA_IOEXP_IRQ_GPIO_BANK_3,
|
||||
+ MCA_IOEXP_IRQ_GPIO_BANK_4,
|
||||
+ MCA_IOEXP_IRQ_GPIO_BANK_5,
|
||||
+ /* ... */
|
||||
+
|
||||
+ MCA_IOEXP_NUM_IRQS,
|
||||
+};
|
||||
+
|
||||
+/* Number of interrupt registers */
|
||||
+#define MCA_IOEXP_NUM_IRQ_REGS 4
|
||||
+
|
||||
+struct mca_ioexp {
|
||||
+ struct device *dev;
|
||||
+ u8 dev_id;
|
||||
+ u8 hw_version;
|
||||
+ bool fw_is_alpha;
|
||||
+ u16 fw_version;
|
||||
+ u32 flags;
|
||||
+ struct regmap *regmap;
|
||||
+ struct regmap_irq_chip_data *regmap_irq;
|
||||
+ int chip_irq;
|
||||
+ u32 irq_base;
|
||||
+ int gpio_base;
|
||||
+
|
||||
+ struct {
|
||||
+ struct {
|
||||
+ uint8_t *values;
|
||||
+ uint8_t cnt;
|
||||
+ } gpio_dir;
|
||||
+
|
||||
+ struct {
|
||||
+ uint8_t *values;
|
||||
+ uint8_t cnt;
|
||||
+ } gpio_data;
|
||||
+
|
||||
+ struct {
|
||||
+ uint8_t *values;
|
||||
+ uint8_t cnt;
|
||||
+ } irq_cfg;
|
||||
+
|
||||
+ struct {
|
||||
+ uint8_t *values;
|
||||
+ uint8_t cnt;
|
||||
+ } irq_mask;
|
||||
+
|
||||
+ struct {
|
||||
+ uint8_t *values;
|
||||
+ uint8_t cnt;
|
||||
+ } adc_cfg;
|
||||
+ } *preserved_regs;
|
||||
+};
|
||||
+
|
||||
+int mca_ioexp_device_init(struct mca_ioexp *ioexp, u32 irq);
|
||||
+int mca_ioexp_irq_init(struct mca_ioexp *ioexp);
|
||||
+void mca_ioexp_device_exit(struct mca_ioexp *ioexp);
|
||||
+void mca_ioexp_irq_exit(struct mca_ioexp *ioexp);
|
||||
+int mca_ioexp_suspend(struct device *dev);
|
||||
+int mca_ioexp_resume(struct device *dev);
|
||||
+
|
||||
+#endif /* MFD_MCA_IOEXP_CORE_H_ */
|
||||
diff --git a/include/linux/mfd/mca-ioexp/registers.h b/include/linux/mfd/mca-ioexp/registers.h
|
||||
new file mode 100644
|
||||
index 000000000000..9359c9953e0d
|
||||
--- /dev/null
|
||||
+++ b/include/linux/mfd/mca-ioexp/registers.h
|
||||
@@ -0,0 +1,15 @@
|
||||
+/*
|
||||
+ * Copyright 2017 - 2019 Digi International Inc
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#ifndef MCA_IOEXP_REGISTERS_H_
|
||||
+#define MCA_IOEXP_REGISTERS_H_
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+
|
||||
+#endif /* MCA_IOEXP_REGISTERS_H_ */
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
From 4a2907834799eda9bd681ccd85557d6433666903 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Mon, 23 Apr 2018 11:47:38 +0200
|
||||
Subject: [PATCH] ccimx6ulsbcpro: Add IOEXP GPIO support
|
||||
|
||||
Synched with v4.14.78/master at:
|
||||
3f8b03950b323db4ca89b1cdc1c2288f79facaa3
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts | 23 +++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
index afc87b34f441..a818aec68959 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
@@ -130,6 +130,29 @@
|
||||
irq-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ mca_ioexp: mca_io@6e {
|
||||
+ compatible = "digi,mca_ioexp";
|
||||
+ reg = <0x6e>;
|
||||
+ interrupt-parent = <&mca_gpio>;
|
||||
+ interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
|
||||
+ restore-config-on-resume;
|
||||
+ status = "okay";
|
||||
+
|
||||
+ interrupt-controller;
|
||||
+ #interrupt-cells = <2>;
|
||||
+ pinctrl-names = "default";
|
||||
+
|
||||
+ mca_ioexp_gpio: gpio {
|
||||
+ compatible = "digi,mca-ioexp-gpio";
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+
|
||||
+ interrupt-parent = <&mca_ioexp>;
|
||||
+ interrupt-controller;
|
||||
+ #interrupt-cells = <2>;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
&lcdif {
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
From d39028a304c0059ee16c65462e3e653670482aca Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Mon, 23 Apr 2018 11:48:15 +0200
|
||||
Subject: [PATCH] ccimx6ulsbcpro: Add IOEXP ADC support
|
||||
|
||||
Synched with v4.14.78/master at:
|
||||
3f8b03950b323db4ca89b1cdc1c2288f79facaa3
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
index 7df31112cabf..b2b6a49391f4 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
@@ -153,6 +153,12 @@
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
+
|
||||
+ mca_ioexp_adc: adc {
|
||||
+ compatible = "digi,mca-ioexp-adc";
|
||||
+ digi,adc-ch-list = <3 4 5>;
|
||||
+ digi,adc-vref = <3300000>;
|
||||
+ };
|
||||
};
|
||||
};
|
||||
|
||||
@@ -482,4 +488,3 @@
|
||||
>;
|
||||
};
|
||||
};
|
||||
-
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
From ac65a7be2a14e2c5f90319674527257a53e59402 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
Date: Tue, 8 Jan 2019 16:42:40 +0100
|
||||
Subject: [PATCH] ARM: dts: ccimx6ulsbcpro: Configure touch GPIO reset line
|
||||
|
||||
The Goodix touch requires both the INT and reset lines in order to fix
|
||||
an I2C address at startup.
|
||||
|
||||
This commit uses the IOEXP GPIO29 to control the DISP_5V supply which
|
||||
controls the voltage source for the reset line pull-up. It also sets the
|
||||
internal pull-up on the INT line so the line is not left floating.
|
||||
|
||||
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
|
||||
---
|
||||
arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
index 14274a0d6435..62133ede2736 100644
|
||||
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts
|
||||
@@ -128,6 +128,7 @@
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_RISING>;
|
||||
irq-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
|
||||
+ reset-gpios = <&mca_ioexp_gpio 29 GPIO_ACTIVE_HIGH>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -366,7 +367,7 @@
|
||||
|
||||
pinctrl_goodix_touch: goodixgrp{
|
||||
fsl,pins = <
|
||||
- MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1020
|
||||
+ MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b0b0
|
||||
>;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,452 @@
|
|||
CONFIG_KERNEL_LZO=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_PREEMPT_VOLUNTARY=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
CONFIG_LOG_BUF_SHIFT=18
|
||||
CONFIG_CGROUPS=y
|
||||
CONFIG_RELAY=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_EXPERT=y
|
||||
CONFIG_PERF_EVENTS=y
|
||||
# CONFIG_SLUB_DEBUG is not set
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_ARCH_MULTI_V6=y
|
||||
CONFIG_ARCH_MXC=y
|
||||
CONFIG_MACH_MX31LILLY=y
|
||||
CONFIG_MACH_MX31LITE=y
|
||||
CONFIG_MACH_PCM037=y
|
||||
CONFIG_MACH_PCM037_EET=y
|
||||
CONFIG_MACH_MX31_3DS=y
|
||||
CONFIG_MACH_MX31MOBOARD=y
|
||||
CONFIG_MACH_QONG=y
|
||||
CONFIG_MACH_ARMADILLO5X0=y
|
||||
CONFIG_MACH_KZM_ARM11_01=y
|
||||
CONFIG_MACH_IMX31_DT=y
|
||||
CONFIG_MACH_IMX35_DT=y
|
||||
CONFIG_MACH_PCM043=y
|
||||
CONFIG_MACH_MX35_3DS=y
|
||||
CONFIG_MACH_VPR200=y
|
||||
CONFIG_SOC_IMX50=y
|
||||
CONFIG_SOC_IMX51=y
|
||||
CONFIG_SOC_IMX53=y
|
||||
CONFIG_SOC_IMX6Q=y
|
||||
CONFIG_SOC_IMX6SL=y
|
||||
CONFIG_SOC_IMX6SLL=y
|
||||
CONFIG_SOC_IMX6SX=y
|
||||
CONFIG_SOM_CC6UL=y
|
||||
CONFIG_SOC_IMX7D=y
|
||||
CONFIG_SOC_VF610=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_PCI_IMX6=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_ARM_PSCI=y
|
||||
CONFIG_HIGHMEM=y
|
||||
CONFIG_FORCE_MAX_ZONEORDER=14
|
||||
CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_CPU_FREQ=y
|
||||
CONFIG_CPU_FREQ_STAT=y
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
|
||||
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
|
||||
CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
|
||||
CONFIG_CPUFREQ_DT=y
|
||||
CONFIG_ARM_IMX6Q_CPUFREQ=y
|
||||
CONFIG_CPU_IDLE=y
|
||||
CONFIG_ARM_CPUIDLE=y
|
||||
CONFIG_VFP=y
|
||||
CONFIG_NEON=y
|
||||
CONFIG_PM_DEBUG=y
|
||||
CONFIG_PM_TEST_SUSPEND=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_MODVERSIONS=y
|
||||
CONFIG_MODULE_SRCVERSION_ALL=y
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
|
||||
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
|
||||
# CONFIG_INET_XFRM_MODE_BEET is not set
|
||||
CONFIG_NETFILTER=y
|
||||
CONFIG_CAN=y
|
||||
CONFIG_CAN_FLEXCAN=y
|
||||
CONFIG_BT=y
|
||||
CONFIG_BT_HCIUART=y
|
||||
CONFIG_BT_HCIUART_LL=y
|
||||
CONFIG_CFG80211=y
|
||||
CONFIG_CFG80211_WEXT=y
|
||||
CONFIG_MAC80211=y
|
||||
CONFIG_RFKILL=y
|
||||
CONFIG_RFKILL_INPUT=y
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
# CONFIG_STANDALONE is not set
|
||||
CONFIG_FW_LOADER_USER_HELPER=y
|
||||
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
|
||||
CONFIG_CMA_SIZE_MBYTES=64
|
||||
CONFIG_IMX_WEIM=y
|
||||
CONFIG_CONNECTOR=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_CMDLINE_PARTS=y
|
||||
CONFIG_MTD_BLOCK=y
|
||||
CONFIG_MTD_CFI=y
|
||||
CONFIG_MTD_JEDECPROBE=y
|
||||
CONFIG_MTD_CFI_INTELEXT=y
|
||||
CONFIG_MTD_CFI_AMDSTD=y
|
||||
CONFIG_MTD_CFI_STAA=y
|
||||
CONFIG_MTD_PHYSMAP_OF=y
|
||||
CONFIG_MTD_DATAFLASH=y
|
||||
CONFIG_MTD_M25P80=y
|
||||
CONFIG_MTD_SST25L=y
|
||||
CONFIG_MTD_NAND=y
|
||||
CONFIG_MTD_NAND_GPMI_NAND=y
|
||||
CONFIG_MTD_NAND_VF610_NFC=y
|
||||
CONFIG_MTD_NAND_MXC=y
|
||||
CONFIG_MTD_SPI_NOR=y
|
||||
CONFIG_SPI_FSL_QUADSPI=y
|
||||
CONFIG_MTD_UBI=y
|
||||
CONFIG_MTD_UBI_FASTMAP=y
|
||||
CONFIG_MTD_UBI_BLOCK=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=65536
|
||||
CONFIG_EEPROM_AT24=y
|
||||
CONFIG_EEPROM_AT25=y
|
||||
# CONFIG_SCSI_PROC_FS is not set
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_SCSI_CONSTANTS=y
|
||||
CONFIG_SCSI_LOGGING=y
|
||||
CONFIG_SCSI_SCAN_ASYNC=y
|
||||
# CONFIG_SCSI_LOWLEVEL is not set
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_AHCI_PLATFORM=y
|
||||
CONFIG_AHCI_IMX=y
|
||||
CONFIG_PATA_IMX=y
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_NET_VENDOR_BROADCOM is not set
|
||||
CONFIG_CS89x0=y
|
||||
CONFIG_CS89x0_PLATFORM=y
|
||||
# CONFIG_NET_VENDOR_FARADAY is not set
|
||||
# CONFIG_NET_VENDOR_INTEL is not set
|
||||
# CONFIG_NET_VENDOR_MARVELL is not set
|
||||
# CONFIG_NET_VENDOR_MICREL is not set
|
||||
# CONFIG_NET_VENDOR_MICROCHIP is not set
|
||||
# CONFIG_NET_VENDOR_NATSEMI is not set
|
||||
# CONFIG_NET_VENDOR_SEEQ is not set
|
||||
CONFIG_SMC91X=y
|
||||
CONFIG_SMC911X=y
|
||||
CONFIG_SMSC911X=y
|
||||
# CONFIG_NET_VENDOR_STMICRO is not set
|
||||
CONFIG_AT803X_PHY=y
|
||||
CONFIG_MICREL_PHY=y
|
||||
CONFIG_SMSC_PHY=y
|
||||
CONFIG_USB_PEGASUS=m
|
||||
CONFIG_USB_RTL8150=m
|
||||
CONFIG_USB_RTL8152=y
|
||||
CONFIG_USB_LAN78XX=y
|
||||
CONFIG_USB_USBNET=y
|
||||
CONFIG_USB_NET_CDC_EEM=m
|
||||
CONFIG_USB_NET_SMSC95XX=y
|
||||
CONFIG_USB_NET_MCS7830=y
|
||||
CONFIG_BRCMFMAC=m
|
||||
CONFIG_MWIFIEX=m
|
||||
CONFIG_MWIFIEX_SDIO=m
|
||||
CONFIG_MWIFIEX_PCIE=m
|
||||
CONFIG_WL12XX=m
|
||||
CONFIG_WL18XX=m
|
||||
CONFIG_WLCORE_SDIO=m
|
||||
# CONFIG_WILINK_PLATFORM_DATA is not set
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
CONFIG_KEYBOARD_GPIO=y
|
||||
CONFIG_KEYBOARD_SNVS_PWRKEY=y
|
||||
CONFIG_KEYBOARD_IMX=y
|
||||
CONFIG_MOUSE_PS2=m
|
||||
CONFIG_MOUSE_PS2_ELANTECH=y
|
||||
CONFIG_INPUT_TOUCHSCREEN=y
|
||||
CONFIG_TOUCHSCREEN_ADS7846=y
|
||||
CONFIG_TOUCHSCREEN_EGALAX=y
|
||||
CONFIG_TOUCHSCREEN_MAX11801=y
|
||||
CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
|
||||
CONFIG_TOUCHSCREEN_EDT_FT5X06=y
|
||||
CONFIG_TOUCHSCREEN_MC13783=y
|
||||
CONFIG_TOUCHSCREEN_TSC2004=y
|
||||
CONFIG_TOUCHSCREEN_TSC2007=y
|
||||
CONFIG_TOUCHSCREEN_STMPE=y
|
||||
CONFIG_TOUCHSCREEN_SX8654=y
|
||||
CONFIG_TOUCHSCREEN_COLIBRI_VF50=y
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_MMA8450=y
|
||||
CONFIG_INPUT_MCA_PWRKEY=y
|
||||
CONFIG_SERIO_SERPORT=m
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
CONFIG_SERIAL_IMX=y
|
||||
CONFIG_SERIAL_IMX_CONSOLE=y
|
||||
CONFIG_SERIAL_MCA_CC6UL=y
|
||||
CONFIG_SERIAL_FSL_LPUART=y
|
||||
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
|
||||
CONFIG_SERIAL_DEV_BUS=y
|
||||
# CONFIG_I2C_COMPAT is not set
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_MUX=y
|
||||
CONFIG_I2C_MUX_GPIO=y
|
||||
# CONFIG_I2C_HELPER_AUTO is not set
|
||||
CONFIG_I2C_ALGOPCF=m
|
||||
CONFIG_I2C_ALGOPCA=m
|
||||
CONFIG_I2C_GPIO=y
|
||||
CONFIG_I2C_IMX=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_GPIO=y
|
||||
CONFIG_SPI_IMX=y
|
||||
CONFIG_SPI_FSL_DSPI=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_GPIO_MCA=y
|
||||
CONFIG_GPIO_MAX732X=y
|
||||
CONFIG_GPIO_MC9S08DZ60=y
|
||||
CONFIG_GPIO_PCA953X=y
|
||||
CONFIG_GPIO_STMPE=y
|
||||
CONFIG_GPIO_74X164=y
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_POWER_RESET_SYSCON=y
|
||||
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_SENSORS_MC13783_ADC=y
|
||||
CONFIG_SENSORS_GPIO_FAN=y
|
||||
CONFIG_SENSORS_IIO_HWMON=y
|
||||
CONFIG_THERMAL_WRITABLE_TRIPS=y
|
||||
CONFIG_CPU_THERMAL=y
|
||||
CONFIG_IMX_THERMAL=y
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_DA9062_WATCHDOG=y
|
||||
CONFIG_RN5T618_WATCHDOG=y
|
||||
CONFIG_MCA_WATCHDOG=y
|
||||
CONFIG_IMX2_WDT=y
|
||||
CONFIG_MFD_DA9052_I2C=y
|
||||
CONFIG_MFD_DA9062=y
|
||||
CONFIG_MFD_MC13XXX_SPI=y
|
||||
CONFIG_MFD_MC13XXX_I2C=y
|
||||
CONFIG_MFD_RN5T618=y
|
||||
CONFIG_MFD_MCA_IOEXP=y
|
||||
CONFIG_MFD_STMPE=y
|
||||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
CONFIG_REGULATOR_ANATOP=y
|
||||
CONFIG_REGULATOR_DA9052=y
|
||||
CONFIG_REGULATOR_DA9062=y
|
||||
CONFIG_REGULATOR_GPIO=y
|
||||
CONFIG_REGULATOR_MC13783=y
|
||||
CONFIG_REGULATOR_MC13892=y
|
||||
CONFIG_REGULATOR_PFUZE100=y
|
||||
CONFIG_REGULATOR_RN5T618=y
|
||||
CONFIG_RC_CORE=y
|
||||
CONFIG_RC_DEVICES=y
|
||||
CONFIG_IR_GPIO_CIR=y
|
||||
CONFIG_MEDIA_SUPPORT=y
|
||||
CONFIG_MEDIA_CAMERA_SUPPORT=y
|
||||
CONFIG_MEDIA_CONTROLLER=y
|
||||
CONFIG_VIDEO_V4L2_SUBDEV_API=y
|
||||
CONFIG_MEDIA_USB_SUPPORT=y
|
||||
CONFIG_USB_VIDEO_CLASS=m
|
||||
CONFIG_V4L_PLATFORM_DRIVERS=y
|
||||
CONFIG_VIDEO_MUX=y
|
||||
CONFIG_SOC_CAMERA=y
|
||||
CONFIG_V4L_MEM2MEM_DRIVERS=y
|
||||
CONFIG_VIDEO_CODA=m
|
||||
# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
|
||||
CONFIG_VIDEO_ADV7180=m
|
||||
CONFIG_VIDEO_OV5640=m
|
||||
CONFIG_IMX_IPUV3_CORE=y
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_PANEL_LVDS=y
|
||||
CONFIG_DRM_PANEL_SIMPLE=y
|
||||
CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
|
||||
CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
|
||||
CONFIG_DRM_DW_HDMI_CEC=y
|
||||
CONFIG_DRM_IMX=y
|
||||
CONFIG_DRM_IMX_PARALLEL_DISPLAY=y
|
||||
CONFIG_DRM_IMX_TVE=y
|
||||
CONFIG_DRM_IMX_LDB=y
|
||||
CONFIG_DRM_IMX_HDMI=y
|
||||
CONFIG_DRM_ETNAVIV=y
|
||||
CONFIG_DRM_MXSFB=y
|
||||
CONFIG_FB_MODE_HELPERS=y
|
||||
CONFIG_LCD_CLASS_DEVICE=y
|
||||
CONFIG_LCD_L4F00242T03=y
|
||||
CONFIG_LCD_PLATFORM=y
|
||||
CONFIG_BACKLIGHT_PWM=y
|
||||
CONFIG_BACKLIGHT_GPIO=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_LOGO=y
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_SND_USB_AUDIO=m
|
||||
CONFIG_SND_SOC=y
|
||||
CONFIG_SND_SOC_FSL_ASRC=y
|
||||
CONFIG_SND_IMX_SOC=y
|
||||
CONFIG_SND_SOC_PHYCORE_AC97=y
|
||||
CONFIG_SND_SOC_EUKREA_TLV320=y
|
||||
CONFIG_SND_SOC_IMX_ES8328=y
|
||||
CONFIG_SND_SOC_IMX_SGTL5000=y
|
||||
CONFIG_SND_SOC_IMX_SPDIF=y
|
||||
CONFIG_SND_SOC_IMX_MC13783=y
|
||||
CONFIG_SND_SOC_FSL_ASOC_CARD=y
|
||||
CONFIG_SND_SOC_AC97_CODEC=y
|
||||
CONFIG_SND_SOC_CS42XX8_I2C=y
|
||||
CONFIG_SND_SOC_TLV320AIC3X=y
|
||||
CONFIG_SND_SOC_WM8960=y
|
||||
CONFIG_SND_SOC_WM8962=y
|
||||
CONFIG_SND_SIMPLE_CARD=y
|
||||
CONFIG_HID_MULTITOUCH=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_EHCI_MXC=y
|
||||
CONFIG_USB_STORAGE=y
|
||||
CONFIG_USB_CHIPIDEA=y
|
||||
CONFIG_USB_CHIPIDEA_UDC=y
|
||||
CONFIG_USB_CHIPIDEA_HOST=y
|
||||
CONFIG_USB_SERIAL=m
|
||||
CONFIG_USB_SERIAL_GENERIC=y
|
||||
CONFIG_USB_SERIAL_FTDI_SIO=m
|
||||
CONFIG_USB_SERIAL_OPTION=m
|
||||
CONFIG_USB_TEST=m
|
||||
CONFIG_USB_EHSET_TEST_FIXTURE=m
|
||||
CONFIG_NOP_USB_XCEIV=y
|
||||
CONFIG_USB_MXS_PHY=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_FSL_USB2=y
|
||||
CONFIG_USB_CONFIGFS=m
|
||||
CONFIG_USB_CONFIGFS_SERIAL=y
|
||||
CONFIG_USB_CONFIGFS_ACM=y
|
||||
CONFIG_USB_CONFIGFS_OBEX=y
|
||||
CONFIG_USB_CONFIGFS_NCM=y
|
||||
CONFIG_USB_CONFIGFS_ECM=y
|
||||
CONFIG_USB_CONFIGFS_ECM_SUBSET=y
|
||||
CONFIG_USB_CONFIGFS_RNDIS=y
|
||||
CONFIG_USB_CONFIGFS_EEM=y
|
||||
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
|
||||
CONFIG_USB_CONFIGFS_F_LB_SS=y
|
||||
CONFIG_USB_CONFIGFS_F_FS=y
|
||||
CONFIG_USB_CONFIGFS_F_UAC1=y
|
||||
CONFIG_USB_CONFIGFS_F_UAC2=y
|
||||
CONFIG_USB_CONFIGFS_F_MIDI=y
|
||||
CONFIG_USB_CONFIGFS_F_HID=y
|
||||
CONFIG_USB_CONFIGFS_F_UVC=y
|
||||
CONFIG_USB_CONFIGFS_F_PRINTER=y
|
||||
CONFIG_USB_ZERO=m
|
||||
CONFIG_USB_AUDIO=m
|
||||
CONFIG_USB_ETH=m
|
||||
CONFIG_USB_G_NCM=m
|
||||
CONFIG_USB_GADGETFS=m
|
||||
CONFIG_USB_FUNCTIONFS=m
|
||||
CONFIG_USB_MASS_STORAGE=m
|
||||
CONFIG_USB_G_SERIAL=m
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
CONFIG_MMC_SDHCI_ESDHC_IMX=y
|
||||
CONFIG_NEW_LEDS=y
|
||||
CONFIG_LEDS_CLASS=y
|
||||
CONFIG_LEDS_GPIO=y
|
||||
CONFIG_LEDS_PWM=y
|
||||
CONFIG_LEDS_TRIGGERS=y
|
||||
CONFIG_LEDS_TRIGGER_TIMER=y
|
||||
CONFIG_LEDS_TRIGGER_ONESHOT=y
|
||||
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
|
||||
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
|
||||
CONFIG_LEDS_TRIGGER_GPIO=y
|
||||
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
|
||||
CONFIG_RTC_DRV_DS1307=y
|
||||
CONFIG_RTC_DRV_ISL1208=y
|
||||
CONFIG_RTC_DRV_PCF8523=y
|
||||
CONFIG_RTC_DRV_PCF8563=y
|
||||
CONFIG_RTC_DRV_M41T80=y
|
||||
CONFIG_RTC_DRV_DA9063=y
|
||||
CONFIG_RTC_DRV_MCA=y
|
||||
CONFIG_RTC_DRV_MC13XXX=y
|
||||
CONFIG_RTC_DRV_MXC=y
|
||||
CONFIG_RTC_DRV_MXC_V2=y
|
||||
CONFIG_RTC_DRV_SNVS=y
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_FSL_EDMA=y
|
||||
CONFIG_IMX_SDMA=y
|
||||
CONFIG_MXS_DMA=y
|
||||
CONFIG_DMATEST=m
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_STAGING_MEDIA=y
|
||||
CONFIG_VIDEO_IMX_MEDIA=y
|
||||
CONFIG_COMMON_CLK_PWM=y
|
||||
CONFIG_IIO=y
|
||||
CONFIG_MMA8452=y
|
||||
CONFIG_IMX7D_ADC=y
|
||||
CONFIG_MCA_ADC=y
|
||||
CONFIG_VF610_ADC=y
|
||||
CONFIG_SENSORS_ISL29018=y
|
||||
CONFIG_MAG3110=y
|
||||
CONFIG_MPL3115=y
|
||||
CONFIG_TAMPER_MCA=y
|
||||
CONFIG_PWM=y
|
||||
CONFIG_PWM_FSL_FTM=y
|
||||
CONFIG_PWM_IMX=y
|
||||
CONFIG_NVMEM_IMX_OCOTP=y
|
||||
CONFIG_NVMEM_VF610_OCOTP=y
|
||||
CONFIG_TEE=y
|
||||
CONFIG_OPTEE=y
|
||||
CONFIG_MUX_MMIO=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
CONFIG_EXT2_FS_POSIX_ACL=y
|
||||
CONFIG_EXT2_FS_SECURITY=y
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT3_FS_POSIX_ACL=y
|
||||
CONFIG_EXT3_FS_SECURITY=y
|
||||
CONFIG_QUOTA=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
# CONFIG_PRINT_QUOTA_WARNING is not set
|
||||
CONFIG_AUTOFS4_FS=y
|
||||
CONFIG_FUSE_FS=y
|
||||
CONFIG_ISO9660_FS=m
|
||||
CONFIG_JOLIET=y
|
||||
CONFIG_ZISOFS=y
|
||||
CONFIG_UDF_FS=m
|
||||
CONFIG_MSDOS_FS=m
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_TMPFS_POSIX_ACL=y
|
||||
CONFIG_JFFS2_FS=y
|
||||
CONFIG_UBIFS_FS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NLS_DEFAULT="cp437"
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_ISO8859_15=m
|
||||
CONFIG_NLS_UTF8=y
|
||||
CONFIG_SECURITYFS=y
|
||||
CONFIG_CRYPTO_DEV_FSL_CAAM=y
|
||||
CONFIG_CRYPTO_DEV_SAHARA=y
|
||||
CONFIG_CRC_CCITT=m
|
||||
CONFIG_CRC_T10DIF=y
|
||||
CONFIG_CRC7=m
|
||||
CONFIG_LIBCRC32C=m
|
||||
CONFIG_FONTS=y
|
||||
CONFIG_FONT_8x8=y
|
||||
CONFIG_FONT_8x16=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_PROVE_LOCKING=y
|
||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||
# CONFIG_FTRACE is not set
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
|
||||
|
||||
SRC_URI_append_ccimx6ul_use-mainline-bsp = " \
|
||||
file://0001-ARM-Add-support-for-the-ConnectCore-6UL-System-On-Mo.patch \
|
||||
file://0002-mach-imx-pm-imx6-Add-hooks-for-board-specific-implem.patch \
|
||||
file://0003-imx6ul-Add-MCA-core-I2C-driver-support.patch \
|
||||
file://0004-imx6ul-Add-MCA-GPIO-support-for-the-ConnectCore-6UL-.patch \
|
||||
file://0005-imx6ul-Add-MCA-IOMUX-support-to-the-ConnectCore-6UL-.patch \
|
||||
file://0006-imx6ul-Add-MCA-watchdog-support-for-the-ConnectCore-.patch \
|
||||
file://0007-imx6ul-Add-MCA-ADC-support-for-ConnectCore-6UL-SOM-a.patch \
|
||||
file://0008-imx6ul-Add-MCA-tamper-support-for-ConnectCore-6UL-SO.patch \
|
||||
file://0009-imx6ul-Add-MCA-UART-support-for-ConnectCore-6UL-SOM-.patch \
|
||||
file://0010-imx6ul-Add-RTC-MCA-support-for-ConnectCore-6UL-SOM.patch \
|
||||
file://0011-imx6ul-Add-MCA-power-key-support-for-ConnectCore-6UL.patch \
|
||||
"
|
||||
|
||||
SRC_URI_append_ccimx6ulsbc_use-mainline-bsp = " \
|
||||
file://0001-ccimx6ulsbcpro-Add-IOEXP-core-I2C-support.patch \
|
||||
file://0002-ccimx6ulsbcpro-Add-IOEXP-GPIO-support.patch \
|
||||
file://0003-ccimx6ulsbcpro-Add-IOEXP-ADC-support.patch \
|
||||
file://0004-ARM-dts-ccimx6ulsbcpro-Configure-touch-GPIO-reset-li.patch \
|
||||
"
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
#ACTION!="add|change|move", GOTO="mm_digi_xbee_cellular_modem_end"
|
||||
ACTION!="add|change|move", GOTO="mm_digi_xbee_cellular_modem_end"
|
||||
|
||||
# By default, ModemManager expects a default baudrate of 57600bps. Different
|
||||
# baudrates may be used by setting the ID_MM_TTY_BAUDRATE udev tag.
|
||||
|
||||
# ModemManager documentation states that the best practice is to use the DEVPATH
|
||||
# this way rather than other rules such as KERNEL, so be careful when modifying
|
||||
#DEVPATH=="/devices/platform/5a060000.serial/tty/ttyLP0", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular"
|
||||
DEVPATH=="/devices/platform/5a800000.i2c/i2c-0/0-0063/mca-cc8x-uart/tty/ttyMCA0", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular"
|
||||
|
||||
#LABEL="mm_digi_xbee_cellular_modem_end"
|
||||
LABEL="mm_digi_xbee_cellular_modem_end"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
[Unit]
|
||||
Description=Late modems scan
|
||||
Requires=ModemManager.service
|
||||
After=ModemManager.service xbee-init.service time-sync.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=mmcli --scan-modems 1>/dev/null 2>&1
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
[Unit]
|
||||
Description=Late modems scan timer
|
||||
|
||||
[Timer]
|
||||
OnActiveSec=40s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
@ -5,6 +5,8 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:"
|
|||
SRC_URI += " \
|
||||
file://78-mm-digi-xbee-cellular.rules \
|
||||
file://80-mm-net-device-blacklist.rules \
|
||||
file://late-modems-scan.service \
|
||||
file://late-modems-scan.timer \
|
||||
"
|
||||
|
||||
# 'polkit' depends on 'consolekit', and this requires 'x11' distro feature. So
|
||||
|
|
@ -19,6 +21,14 @@ do_install_append() {
|
|||
|
||||
# Install udev rules for ModemManager blacklist devices
|
||||
install -m 0644 ${WORKDIR}/80-mm-net-device-blacklist.rules ${D}${nonarch_base_libdir}/udev/rules.d/
|
||||
|
||||
# Install systemd service for scanning late modems
|
||||
install -d ${D}${systemd_unitdir}/system/
|
||||
install -m 0644 ${WORKDIR}/late-modems-scan.service ${D}${systemd_unitdir}/system/
|
||||
install -m 0644 ${WORKDIR}/late-modems-scan.timer ${D}${systemd_unitdir}/system/
|
||||
}
|
||||
|
||||
SYSTEMD_SERVICE_${PN}_append = " late-modems-scan.timer"
|
||||
FILES_${PN}_append = " late-modems-scan.timer"
|
||||
|
||||
PACKAGE_ARCH = "${MACHINE_ARCH}"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright (C) 2019 Digi International Inc.
|
||||
|
||||
SUMMARY = "Digi XBee initialization"
|
||||
DESCRIPTION = "Initialization scripts for XBee hardware of Digi boards"
|
||||
SECTION = "base"
|
||||
LICENSE = "GPL-2.0"
|
||||
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
|
||||
|
||||
SRC_URI = " \
|
||||
file://xbee-init \
|
||||
file://xbee-init.service \
|
||||
"
|
||||
S = "${WORKDIR}"
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${sysconfdir}/init.d/
|
||||
install -m 0755 ${WORKDIR}/xbee-init ${D}${sysconfdir}/
|
||||
ln -sf /etc/xbee-init ${D}${sysconfdir}/init.d/xbee-init
|
||||
sed -i -e "s,##XBEE_RESET_N_GPIO##,${XBEE_RESET_N_GPIO},g" \
|
||||
-e "s,##XBEE_SLEEP_RQ_GPIO##,${XBEE_SLEEP_RQ_GPIO},g" \
|
||||
${D}${sysconfdir}/xbee-init
|
||||
|
||||
install -d ${D}${systemd_unitdir}/system/
|
||||
install -m 0644 ${WORKDIR}/xbee-init.service ${D}${systemd_unitdir}/system/
|
||||
}
|
||||
|
||||
PACKAGES =+ "${PN}-init"
|
||||
FILES_${PN}-init = " \
|
||||
${sysconfdir}/xbee-init \
|
||||
${sysconfdir}/init.d/xbee-init \
|
||||
${systemd_unitdir}/system/xbee-init.service \
|
||||
"
|
||||
INITSCRIPT_PACKAGES += "${PN}-init"
|
||||
INITSCRIPT_NAME_${PN}-init = "xbee-init"
|
||||
INITSCRIPT_PARAMS_${PN}-init = "start 19 2 3 4 5 . stop 21 0 1 6 ."
|
||||
|
||||
SYSTEMD_SERVICE_${PN}-init = "xbee-init.service"
|
||||
|
||||
PACKAGE_ARCH = "${MACHINE_ARCH}"
|
||||
COMPATIBLE_MACHINE = "(ccimx8x)"
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Linux GPIOs on XBee lines
|
||||
XBEE_RESET_N_GPIO="##XBEE_RESET_N_GPIO##"
|
||||
XBEE_SLEEP_RQ_GPIO="##XBEE_SLEEP_RQ_GPIO##"
|
||||
|
||||
# request_gpio <gpio_nr>
|
||||
request_gpio_out() {
|
||||
local SG_GPIONR="${1}"
|
||||
local SG_GPIOPATH="/sys/class/gpio/gpio${SG_GPIONR}"
|
||||
|
||||
[ -d "${SG_GPIOPATH}" ] || printf "%s" "${SG_GPIONR}" > /sys/class/gpio/export
|
||||
printf out > "${SG_GPIOPATH}/direction" && sleep .2
|
||||
}
|
||||
|
||||
# free_gpio <gpio_nr>
|
||||
free_gpio() {
|
||||
local SG_GPIONR="${1}"
|
||||
local SG_GPIOPATH="/sys/class/gpio/gpio${SG_GPIONR}"
|
||||
|
||||
[ -d "${SG_GPIOPATH}" ] && printf "%s" "${SG_GPIONR}" > /sys/class/gpio/unexport
|
||||
}
|
||||
|
||||
# set_gpio_value <gpio_nr> <value>
|
||||
set_gpio_value() {
|
||||
local SG_GPIONR="${1}"
|
||||
local SG_GPIOVAL="${2}"
|
||||
local SG_GPIOPATH="/sys/class/gpio/gpio${SG_GPIONR}"
|
||||
|
||||
printf out > "${SG_GPIOPATH}/direction" && sleep .2
|
||||
printf "${SG_GPIOVAL}" > "${SG_GPIOPATH}/value" && sleep .2
|
||||
}
|
||||
|
||||
xbee_init() {
|
||||
# Power cycle XBEE_RESET_N
|
||||
request_gpio_out ${XBEE_RESET_N_GPIO}
|
||||
set_gpio_value ${XBEE_RESET_N_GPIO} 0
|
||||
set_gpio_value ${XBEE_RESET_N_GPIO} 1
|
||||
|
||||
# Set low XBEE_SLEEP_RQ
|
||||
request_gpio_out ${XBEE_SLEEP_RQ_GPIO}
|
||||
set_gpio_value ${XBEE_SLEEP_RQ_GPIO} 0
|
||||
}
|
||||
|
||||
xbee_stop() {
|
||||
free_gpio ${XBEE_RESET_N_GPIO}
|
||||
free_gpio ${XBEE_SLEEP_RQ_GPIO}
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting XBee hardware: "
|
||||
xbee_init
|
||||
echo "done."
|
||||
;;
|
||||
stop)
|
||||
echo -n "Stopping XBee hardware: "
|
||||
xbee_stop
|
||||
echo "done."
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
sleep 1
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
[Unit]
|
||||
Description=XBee GPIOs initialization
|
||||
Before=ModemManager.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/etc/xbee-init start
|
||||
ExecStop=/etc/xbee-init stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
@ -13,9 +13,7 @@ IMAGE_FEATURES += " \
|
|||
${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'dey-wireless', '', d)} \
|
||||
"
|
||||
|
||||
IMAGE_INSTALL = " \
|
||||
dey-examples-digiapix \
|
||||
"
|
||||
CORE_IMAGE_BASE_INSTALL += "dey-examples-digiapix"
|
||||
|
||||
# SDK features (for toolchains generated from an image with populate_sdk)
|
||||
SDKIMAGE_FEATURES ?= "dev-pkgs dbg-pkgs staticdev-pkgs"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
From: Gabriel Valcazar <gabriel.valcazar@digi.com>
|
||||
Date: Thu, 28 Mar 2019 17:40:00 +0100
|
||||
Subject: [PATCH] sd-resolve: forcefully cancel worker threads during
|
||||
resolve_free
|
||||
|
||||
For services that use sd-resolve, such as timesyncd, this prevents the system
|
||||
from stalling whenever the service stops while a worker thread is busy calling
|
||||
getaddrinfo().
|
||||
|
||||
Signed-off-by: Gabriel Valcazar <gabriel.valcazar@digi.com>
|
||||
---
|
||||
src/libsystemd/sd-resolve/sd-resolve.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c
|
||||
index a189f14..571604c 100644
|
||||
--- a/src/libsystemd/sd-resolve/sd-resolve.c
|
||||
+++ b/src/libsystemd/sd-resolve/sd-resolve.c
|
||||
@@ -577,8 +577,10 @@ static void resolve_free(sd_resolve *resolve) {
|
||||
|
||||
/* Now terminate them and wait until they are gone.
|
||||
If we get an error than most likely the thread already exited. */
|
||||
- for (i = 0; i < resolve->n_valid_workers; i++)
|
||||
+ for (i = 0; i < resolve->n_valid_workers; i++) {
|
||||
+ pthread_cancel(resolve->workers[i]);
|
||||
(void) pthread_join(resolve->workers[i], NULL);
|
||||
+ }
|
||||
|
||||
/* Close all communication channels */
|
||||
close_many(resolve->fds, _FD_MAX);
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:"
|
||||
|
||||
SRC_URI += "file://0001-udev-use-the-usual-set-of-load-paths-for-udev-rules.patch"
|
||||
SRC_URI += " \
|
||||
file://0001-udev-use-the-usual-set-of-load-paths-for-udev-rules.patch \
|
||||
file://0002-sd-resolve-forcefully-cancel-worker-threads-during-r.patch \
|
||||
"
|
||||
|
||||
#FIX-it: Workaround as missing ending slash in FIRMWARE_PATH [YOCIMX-2831]
|
||||
EXTRA_OEMESON_remove = "-Dfirmware-path=${nonarch_base_libdir}/firmware "
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright (C) 2019 Digi International Inc.
|
||||
|
||||
# Re-add the base RDEPENDS to class-target since they are being overwritten in the
|
||||
# original recipe
|
||||
RDEPENDS_${PN}_class-target_append = " \
|
||||
${PYTHON_PN}-unittest \
|
||||
${PYTHON_PN}-difflib \
|
||||
${PYTHON_PN}-pprint \
|
||||
${PYTHON_PN}-pickle \
|
||||
${PYTHON_PN}-shell \
|
||||
${PYTHON_PN}-nose \
|
||||
${PYTHON_PN}-doctest \
|
||||
${PYTHON_PN}-datetime \
|
||||
${PYTHON_PN}-distutils \
|
||||
${PYTHON_PN}-misc \
|
||||
${PYTHON_PN}-mmap \
|
||||
${PYTHON_PN}-netclient \
|
||||
${PYTHON_PN}-numbers \
|
||||
${PYTHON_PN}-pydoc \
|
||||
${PYTHON_PN}-pkgutil \
|
||||
${PYTHON_PN}-email \
|
||||
${PYTHON_PN}-compression \
|
||||
${PYTHON_PN}-ctypes \
|
||||
${PYTHON_PN}-threading \
|
||||
"
|
||||
|
|
@ -14,4 +14,4 @@ do_install() {
|
|||
install -m 0755 hdp-test.py ${D}${bindir}
|
||||
}
|
||||
|
||||
RDEPENDS_${PN} = "python3 python3-argparse python3-crypt python3-dbus python3-pygobject"
|
||||
RDEPENDS_${PN} = "python3 python3-crypt python3-dbus python3-pygobject"
|
||||
|
|
|
|||
|
|
@ -19,4 +19,4 @@ SUBSYSTEM=="spidev", GROUP="digiapix", MODE="0660"
|
|||
SUBSYSTEM=="gpio", KERNEL=="gpiochip0", ACTION=="add", RUN="/etc/udev/scripts/digiapix.sh"
|
||||
SUBSYSTEM=="gpio", KERNEL!="gpiochip*", ACTION=="add", RUN="/etc/udev/scripts/digiapix.sh"
|
||||
|
||||
SUBSYSTEM=="pwm", ACTION=="add", RUN="/etc/udev/scripts/digiapix.sh"
|
||||
SUBSYSTEM=="pwm", ACTION=="add|change", RUN="/etc/udev/scripts/digiapix.sh"
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ model = Digi International ConnectCore 6 QuadPlus Single Board Computer.
|
|||
|
||||
# USER LED (RED) - GPIO02_IO02
|
||||
USER_LED = 34
|
||||
USER_LED0 = 34
|
||||
|
||||
# USER LED (ORANGE) - GPIO02_IO03
|
||||
USER_LED_2 = 35
|
||||
USER_LED1 = 35
|
||||
|
||||
# USER LED (GREEN) - GPIO02_IO04
|
||||
USER_LED_3 = 36
|
||||
USER_LED2 = 36
|
||||
|
||||
# USER BUTTON - GPIO02_IO05
|
||||
USER_BUTTON = 37
|
||||
|
|
@ -5,12 +5,13 @@ model = Digi International ConnectCore 6 Single Board Computer.
|
|||
|
||||
# USER LED (RED) - GPIO02_IO02
|
||||
USER_LED = 34
|
||||
USER_LED0 = 34
|
||||
|
||||
# USER LED (ORANGE) - GPIO02_IO03
|
||||
USER_LED_2 = 35
|
||||
USER_LED1 = 35
|
||||
|
||||
# USER LED (GREEN) - GPIO02_IO04
|
||||
USER_LED_3 = 36
|
||||
USER_LED2 = 36
|
||||
|
||||
# USER BUTTON - GPIO02_IO05
|
||||
USER_BUTTON = 37
|
||||
|
|
@ -26,5 +26,5 @@ DEFAULT_PWM = 7,0
|
|||
|
||||
[ADC]
|
||||
|
||||
# TODO: only MCA ADCs are supported at the moment, with them being disabled by default
|
||||
# ADC_IN0 on Expansion connector
|
||||
DEFAULT_ADC = 0,0
|
||||
|
|
@ -4,10 +4,14 @@ model = Digi International ConnectCore 8X SBC Pro.
|
|||
[GPIO]
|
||||
|
||||
# USER LED0 - MCA_IO18
|
||||
USER_LED = 222
|
||||
USER_LED = 223
|
||||
USER_LED0 = 223
|
||||
|
||||
# USER_LED1 - MCA_IO10
|
||||
USER_LED1 = 215
|
||||
|
||||
# USER BUTTON - MCA_IO05
|
||||
USER_BUTTON = 209
|
||||
USER_BUTTON = 210
|
||||
|
||||
[I2C]
|
||||
|
||||
|
|
@ -26,5 +30,5 @@ DEFAULT_PWM = 7,0
|
|||
|
||||
[ADC]
|
||||
|
||||
# TODO: only MCA ADCs are supported at the moment, with them being disabled by default
|
||||
# ADC_IN0 on Expansion connector
|
||||
DEFAULT_ADC = 0,0
|
||||
|
|
@ -19,13 +19,17 @@ if basename "${DEVPATH}" | grep -qs "gpiochip0$"; then
|
|||
# Use 'gpiochip0' event to set group and mode for 'export/unexport' files
|
||||
chown root:digiapix /sys/class/gpio/export /sys/class/gpio/unexport
|
||||
chmod g+w /sys/class/gpio/export /sys/class/gpio/unexport
|
||||
elif basename "${DEVPATH}" | grep -qs "pwmchip[0-9]\+$"; then
|
||||
elif basename "${DEVPATH}" | grep -qs "pwmchip[0-9]\+$" && [ "${ACTION}" = "add" ] ; then
|
||||
# Set group and mode for pwmchip's 'export/unexport' files
|
||||
chown root:digiapix /sys${DEVPATH}/export /sys${DEVPATH}/unexport
|
||||
chmod g+w /sys${DEVPATH}/export /sys${DEVPATH}/unexport
|
||||
elif basename "${DEVPATH}" | grep -qs "pwmchip[0-9]\+$" && [ "${ACTION}" = "change" ] ; then
|
||||
# Set group and mode for 'pwmX' channel and all files inside it...
|
||||
chown root:digiapix /sys${DEVPATH}/${EXPORT} /sys${DEVPATH}/${EXPORT}/*
|
||||
chmod g+w /sys${DEVPATH}/${EXPORT}/*
|
||||
else
|
||||
# Change group and mode of the sysfs files created whenever a 'gpioX'
|
||||
# or 'pwmX' is exported
|
||||
# is exported
|
||||
chown -h root:digiapix /sys${DEVPATH}/*
|
||||
chmod g+w /sys${DEVPATH}/*
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ LIBDIGIAPIX_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${LI
|
|||
SRC_URI = " \
|
||||
${LIBDIGIAPIX_GIT_URI};branch=${SRCBRANCH} \
|
||||
file://99-digiapix.rules \
|
||||
file://board.conf \
|
||||
file://libdigiapix.conf \
|
||||
file://digiapix.sh \
|
||||
"
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ do_install() {
|
|||
install -m 0755 ${WORKDIR}/digiapix.sh ${D}${sysconfdir}/udev/scripts/
|
||||
|
||||
# Install board config file
|
||||
install -m 0644 ${WORKDIR}/board.conf ${D}${sysconfdir}/libdigiapix.conf
|
||||
install -m 0644 ${WORKDIR}/libdigiapix.conf ${D}${sysconfdir}/
|
||||
}
|
||||
|
||||
USERADD_PACKAGES = "${PN}"
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ int main( int argc, char** argv )
|
|||
}
|
||||
|
||||
if( filename != NULL ) {
|
||||
if( ( fd_file = open( filename, O_RDWR | O_CREAT ) ) < 0 ) {
|
||||
if( ( fd_file = open( filename, O_RDWR | O_CREAT , 0600 ) ) < 0 ) {
|
||||
fprintf( stderr, "Error opening file: %s (%d)\n",
|
||||
filename, errno );
|
||||
release_resources_and_exit( EXIT_FAILURE );
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
set -e
|
||||
|
||||
AVAILABLE_PLATFORMS="ccimx8x-sbc-pro ccimx8x-sbc-express ccimx6qpsbc ccimx6sbc ccimx6ulsbc ccimx6ulstarter"
|
||||
AVAILABLE_PLATFORMS="ccimx8x-sbc-pro ccimx8x-sbc-express ccimx6ulsbc ccimx6ulstarter"
|
||||
|
||||
MANIFEST_URL="https://github.com/digi-embedded/dey-manifest.git"
|
||||
|
||||
|
|
@ -123,8 +123,6 @@ while read _pl _tgt; do
|
|||
done<<-_EOF_
|
||||
ccimx8x-sbc-pro dey-image-qt
|
||||
ccimx8x-sbc-express dey-image-qt
|
||||
ccimx6qpsbc dey-image-qt
|
||||
ccimx6sbc dey-image-qt
|
||||
ccimx6ulsbc dey-image-qt
|
||||
ccimx6ulstarter core-image-base
|
||||
_EOF_
|
||||
|
|
|
|||
|
|
@ -173,8 +173,6 @@ while read _pl _var _tgt; do
|
|||
done<<-_EOF_
|
||||
ccimx8x-sbc-pro DONTBUILDVARIANTS dey-image-qt,dey-image-aws
|
||||
ccimx8x-sbc-express DONTBUILDVARIANTS dey-image-qt,dey-image-aws
|
||||
ccimx6qpsbc DONTBUILDVARIANTS dey-image-qt,dey-image-aws
|
||||
ccimx6sbc DONTBUILDVARIANTS dey-image-qt,dey-image-aws
|
||||
ccimx6ulsbc DONTBUILDVARIANTS dey-image-qt,dey-image-aws
|
||||
ccimx6ulstarter DONTBUILDVARIANTS core-image-base,dey-image-aws
|
||||
ccimx6ulsom DONTBUILDVARIANTS dey-image-mft-module-min
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
|
||||
# changes incompatibly
|
||||
POKY_BBLAYERS_CONF_VERSION = "2"
|
||||
|
||||
BBPATH = "${TOPDIR}"
|
||||
BBFILES ?= ""
|
||||
|
||||
BBLAYERS ?= " \
|
||||
##OEROOT##/meta \
|
||||
##OEROOT##/meta-poky \
|
||||
##OEROOT##/meta-yocto-bsp \
|
||||
##DIGIBASE##/meta-openembedded/meta-oe \
|
||||
##DIGIBASE##/meta-openembedded/meta-python \
|
||||
##DIGIBASE##/meta-openembedded/meta-networking \
|
||||
##DIGIBASE##/meta-openembedded/meta-webserver \
|
||||
##DIGIBASE##/meta-qt5 \
|
||||
##DIGIBASE##/meta-swupdate \
|
||||
##DIGIBASE##/meta-freescale \
|
||||
##DIGIBASE##/meta-fsl-demos \
|
||||
##DIGIBASE##/meta-digi/meta-digi-arm \
|
||||
##DIGIBASE##/meta-digi/meta-digi-dey \
|
||||
"
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
Digi Embedded Yocto provides the following image recipes:
|
||||
|
||||
* dey-image-qt: graphical QT image
|
||||
|
||||
By default the image is X11-based so it provides a full SATO theme
|
||||
desktop environment.
|
||||
|
||||
To compile the image for the framebuffer (instead of X11) add the
|
||||
following line to the project's conf/local.conf:
|
||||
|
||||
DISTRO_FEATURES_remove = "x11"
|
||||
|
||||
* dey-image-aws: console-only image supporting Amazon Web Services IoT
|
||||
|
||||
This image includes the AWS Greengrass Core and an AWS IoT platform
|
||||
example application. For more information on AWS support in Digi
|
||||
Embedded Yocto see the online documentation.
|
||||
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
#
|
||||
# This file is your local configuration file and is where all local user settings
|
||||
# are placed. The comments in this file give some guide to the options a new user
|
||||
# to the system might want to change but pretty much any configuration option can
|
||||
# be set in this file. More adventurous users can look at local.conf.extended
|
||||
# which contains other examples of configuration which can be placed in this file
|
||||
# but new users likely won't need any of them initially.
|
||||
#
|
||||
# Lines starting with the '#' character are commented out and in some cases the
|
||||
# default values are provided as comments to show people example syntax. Enabling
|
||||
# the option is a question of removing the # character and making any change to the
|
||||
# variable as required.
|
||||
|
||||
#
|
||||
# Machine Selection
|
||||
#
|
||||
# You need to select a specific machine to target the build with. There are a selection
|
||||
# of emulated machines available which can boot and run in the QEMU emulator:
|
||||
#
|
||||
#MACHINE ?= "qemuarm"
|
||||
#MACHINE ?= "qemuarm64"
|
||||
#MACHINE ?= "qemumips"
|
||||
#MACHINE ?= "qemumips64"
|
||||
#MACHINE ?= "qemuppc"
|
||||
#MACHINE ?= "qemux86"
|
||||
#MACHINE ?= "qemux86-64"
|
||||
#
|
||||
# There are also the following hardware board target machines included for
|
||||
# demonstration purposes:
|
||||
#
|
||||
#MACHINE ?= "beaglebone-yocto"
|
||||
#MACHINE ?= "genericx86"
|
||||
#MACHINE ?= "genericx86-64"
|
||||
#MACHINE ?= "mpc8315e-rdb"
|
||||
#MACHINE ?= "edgerouter"
|
||||
#
|
||||
# This sets the default machine to be qemux86 if no other machine is selected:
|
||||
#MACHINE ??= "qemux86"
|
||||
|
||||
MACHINE = "ccimx6qpsbc"
|
||||
|
||||
#
|
||||
# Use Digi's internal git repositories
|
||||
#
|
||||
#DIGI_INTERNAL_GIT ?= "1"
|
||||
|
||||
#
|
||||
# Where to place downloads
|
||||
#
|
||||
# During a first build the system will download many different source code tarballs
|
||||
# from various upstream projects. This can take a while, particularly if your network
|
||||
# connection is slow. These are all stored in DL_DIR. When wiping and rebuilding you
|
||||
# can preserve this directory to speed up this part of subsequent builds. This directory
|
||||
# is safe to share between multiple builds on the same machine too.
|
||||
#
|
||||
# The default is a downloads directory under TOPDIR which is the build directory.
|
||||
#
|
||||
#DL_DIR ?= "${TOPDIR}/downloads"
|
||||
|
||||
#
|
||||
# Where to place shared-state files
|
||||
#
|
||||
# BitBake has the capability to accelerate builds based on previously built output.
|
||||
# This is done using "shared state" files which can be thought of as cache objects
|
||||
# and this option determines where those files are placed.
|
||||
#
|
||||
# You can wipe out TMPDIR leaving this directory intact and the build would regenerate
|
||||
# from these files if no changes were made to the configuration. If changes were made
|
||||
# to the configuration, only shared state files where the state was still valid would
|
||||
# be used (done using checksums).
|
||||
#
|
||||
# The default is a sstate-cache directory under TOPDIR.
|
||||
#
|
||||
#SSTATE_DIR ?= "${TOPDIR}/sstate-cache"
|
||||
|
||||
#
|
||||
# Where to place the build output
|
||||
#
|
||||
# This option specifies where the bulk of the building work should be done and
|
||||
# where BitBake should place its temporary files and output. Keep in mind that
|
||||
# this includes the extraction and compilation of many applications and the toolchain
|
||||
# which can use Gigabytes of hard disk space.
|
||||
#
|
||||
# The default is a tmp directory under TOPDIR.
|
||||
#
|
||||
#TMPDIR = "${TOPDIR}/tmp"
|
||||
|
||||
#
|
||||
# Default policy config
|
||||
#
|
||||
# The distribution setting controls which policy settings are used as defaults.
|
||||
# The default value is fine for general Yocto project use, at least initially.
|
||||
# Ultimately when creating custom policy, people will likely end up subclassing
|
||||
# these defaults.
|
||||
#
|
||||
DISTRO ?= "dey"
|
||||
# As an example of a subclass there is a "bleeding" edge policy configuration
|
||||
# where many versions are set to the absolute latest code from the upstream
|
||||
# source control systems. This is just mentioned here as an example, its not
|
||||
# useful to most new users.
|
||||
# DISTRO ?= "poky-bleeding"
|
||||
|
||||
#
|
||||
# Package Management configuration
|
||||
#
|
||||
# This variable lists which packaging formats to enable. Multiple package backends
|
||||
# can be enabled at once and the first item listed in the variable will be used
|
||||
# to generate the root filesystems.
|
||||
# Options are:
|
||||
# - 'package_deb' for debian style deb files
|
||||
# - 'package_ipk' for ipk files are used by opkg (a debian style embedded package manager)
|
||||
# - 'package_rpm' for rpm style packages
|
||||
# E.g.: PACKAGE_CLASSES ?= "package_rpm package_deb package_ipk"
|
||||
# We default to rpm:
|
||||
PACKAGE_CLASSES ?= "package_rpm"
|
||||
|
||||
#
|
||||
# SDK target architecture
|
||||
#
|
||||
# This variable specifies the architecture to build SDK items for and means
|
||||
# you can build the SDK packages for architectures other than the machine you are
|
||||
# running the build on (i.e. building i686 packages on an x86_64 host).
|
||||
# Supported values are i686 and x86_64
|
||||
#SDKMACHINE ?= "i686"
|
||||
|
||||
#
|
||||
# Extra image configuration defaults
|
||||
#
|
||||
# The EXTRA_IMAGE_FEATURES variable allows extra packages to be added to the generated
|
||||
# images. Some of these options are added to certain image types automatically. The
|
||||
# variable can contain the following options:
|
||||
# "dbg-pkgs" - add -dbg packages for all installed packages
|
||||
# (adds symbol information for debugging/profiling)
|
||||
# "dev-pkgs" - add -dev packages for all installed packages
|
||||
# (useful if you want to develop against libs in the image)
|
||||
# "ptest-pkgs" - add -ptest packages for all ptest-enabled packages
|
||||
# (useful if you want to run the package test suites)
|
||||
# "tools-sdk" - add development tools (gcc, make, pkgconfig etc.)
|
||||
# "tools-debug" - add debugging tools (gdb, strace)
|
||||
# "eclipse-debug" - add Eclipse remote debugging support
|
||||
# "tools-profile" - add profiling tools (oprofile, lttng, valgrind)
|
||||
# "tools-testapps" - add useful testing tools (ts_print, aplay, arecord etc.)
|
||||
# "debug-tweaks" - make an image suitable for development
|
||||
# e.g. ssh root access has a blank password
|
||||
# There are other application targets that can be used here too, see
|
||||
# meta/classes/image.bbclass and meta/classes/core-image.bbclass for more details.
|
||||
# We default to enabling the debugging tweaks.
|
||||
EXTRA_IMAGE_FEATURES ?= "debug-tweaks"
|
||||
|
||||
#
|
||||
# Additional image features
|
||||
#
|
||||
# The following is a list of additional classes to use when building images which
|
||||
# enable extra features. Some available options which can be included in this variable
|
||||
# are:
|
||||
# - 'buildstats' collect build statistics
|
||||
# - 'image-mklibs' to reduce shared library files size for an image
|
||||
# - 'image-prelink' in order to prelink the filesystem image
|
||||
# NOTE: if listing mklibs & prelink both, then make sure mklibs is before prelink
|
||||
# NOTE: mklibs also needs to be explicitly enabled for a given image, see local.conf.extended
|
||||
USER_CLASSES ?= "buildstats image-mklibs image-prelink"
|
||||
|
||||
#
|
||||
# Runtime testing of images
|
||||
#
|
||||
# The build system can test booting virtual machine images under qemu (an emulator)
|
||||
# after any root filesystems are created and run tests against those images. It can also
|
||||
# run tests against any SDK that are built. To enable this uncomment these lines.
|
||||
# See classes/test{image,sdk}.bbclass for further details.
|
||||
#IMAGE_CLASSES += "testimage testsdk"
|
||||
#TESTIMAGE_AUTO_qemuall = "1"
|
||||
|
||||
#
|
||||
# Interactive shell configuration
|
||||
#
|
||||
# Under certain circumstances the system may need input from you and to do this it
|
||||
# can launch an interactive shell. It needs to do this since the build is
|
||||
# multithreaded and needs to be able to handle the case where more than one parallel
|
||||
# process may require the user's attention. The default is iterate over the available
|
||||
# terminal types to find one that works.
|
||||
#
|
||||
# Examples of the occasions this may happen are when resolving patches which cannot
|
||||
# be applied, to use the devshell or the kernel menuconfig
|
||||
#
|
||||
# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none
|
||||
# Note: currently, Konsole support only works for KDE 3.x due to the way
|
||||
# newer Konsole versions behave
|
||||
#OE_TERMINAL = "auto"
|
||||
# By default disable interactive patch resolution (tasks will just fail instead):
|
||||
PATCHRESOLVE = "noop"
|
||||
|
||||
#
|
||||
# Disk Space Monitoring during the build
|
||||
#
|
||||
# Monitor the disk space during the build. If there is less that 1GB of space or less
|
||||
# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully
|
||||
# shutdown the build. If there is less that 100MB or 1K inodes, perform a hard abort
|
||||
# of the build. The reason for this is that running completely out of space can corrupt
|
||||
# files and damages the build in ways which may not be easily recoverable.
|
||||
# It's necesary to monitor /tmp, if there is no space left the build will fail
|
||||
# with very exotic errors.
|
||||
BB_DISKMON_DIRS ??= "\
|
||||
STOPTASKS,${TMPDIR},1G,100K \
|
||||
STOPTASKS,${DL_DIR},1G,100K \
|
||||
STOPTASKS,${SSTATE_DIR},1G,100K \
|
||||
STOPTASKS,/tmp,100M,100K \
|
||||
ABORT,${TMPDIR},100M,1K \
|
||||
ABORT,${DL_DIR},100M,1K \
|
||||
ABORT,${SSTATE_DIR},100M,1K \
|
||||
ABORT,/tmp,10M,1K"
|
||||
|
||||
#
|
||||
# Shared-state files from other locations
|
||||
#
|
||||
# As mentioned above, shared state files are prebuilt cache data objects which can
|
||||
# used to accelerate build time. This variable can be used to configure the system
|
||||
# to search other mirror locations for these objects before it builds the data itself.
|
||||
#
|
||||
# This can be a filesystem directory, or a remote url such as http or ftp. These
|
||||
# would contain the sstate-cache results from previous builds (possibly from other
|
||||
# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the
|
||||
# cache locations to check for the shared objects.
|
||||
# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH
|
||||
# at the end as shown in the examples below. This will be substituted with the
|
||||
# correct path within the directory structure.
|
||||
#SSTATE_MIRRORS ?= "\
|
||||
#file://.* http://someserver.tld/share/sstate/PATH;downloadfilename=PATH \n \
|
||||
#file://.* file:///some/local/dir/sstate/PATH"
|
||||
|
||||
#
|
||||
# Yocto Project SState Mirror
|
||||
#
|
||||
# The Yocto Project has prebuilt artefacts available for its releases, you can enable
|
||||
# use of these by uncommenting the following line. This will mean the build uses
|
||||
# the network to check for artefacts at the start of builds, which does slow it down
|
||||
# equally, it will also speed up the builds by not having to build things if they are
|
||||
# present in the cache. It assumes you can download something faster than you can build it
|
||||
# which will depend on your network.
|
||||
#
|
||||
#SSTATE_MIRRORS ?= "file://.* http://sstate.yoctoproject.org/2.5/PATH;downloadfilename=PATH"
|
||||
|
||||
#
|
||||
# Qemu configuration
|
||||
#
|
||||
# By default qemu will build with a builtin VNC server where graphical output can be
|
||||
# seen. The two lines below enable the SDL backend too. By default libsdl2-native will
|
||||
# be built, if you want to use your host's libSDL instead of the minimal libsdl built
|
||||
# by libsdl2-native then uncomment the ASSUME_PROVIDED line below.
|
||||
PACKAGECONFIG_append_pn-qemu-native = " sdl"
|
||||
PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl"
|
||||
#ASSUME_PROVIDED += "libsdl2-native"
|
||||
|
||||
# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to
|
||||
# track the version of this file when it was generated. This can safely be ignored if
|
||||
# this doesn't mean anything to you.
|
||||
CONF_VERSION = "1"
|
||||
|
||||
#
|
||||
# Enable local PR server
|
||||
#
|
||||
PRSERV_HOST = "localhost:0"
|
||||
|
||||
#
|
||||
# Some libraries and packages are covered by NXP EULA
|
||||
#
|
||||
#ACCEPT_FSL_EULA = "1"
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
|
||||
# changes incompatibly
|
||||
POKY_BBLAYERS_CONF_VERSION = "2"
|
||||
|
||||
BBPATH = "${TOPDIR}"
|
||||
BBFILES ?= ""
|
||||
|
||||
BBLAYERS ?= " \
|
||||
##OEROOT##/meta \
|
||||
##OEROOT##/meta-poky \
|
||||
##OEROOT##/meta-yocto-bsp \
|
||||
##DIGIBASE##/meta-openembedded/meta-oe \
|
||||
##DIGIBASE##/meta-openembedded/meta-python \
|
||||
##DIGIBASE##/meta-openembedded/meta-networking \
|
||||
##DIGIBASE##/meta-openembedded/meta-webserver \
|
||||
##DIGIBASE##/meta-qt5 \
|
||||
##DIGIBASE##/meta-swupdate \
|
||||
##DIGIBASE##/meta-freescale \
|
||||
##DIGIBASE##/meta-fsl-demos \
|
||||
##DIGIBASE##/meta-digi/meta-digi-arm \
|
||||
##DIGIBASE##/meta-digi/meta-digi-dey \
|
||||
"
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
Digi Embedded Yocto provides the following image recipes:
|
||||
|
||||
* dey-image-qt: graphical QT image
|
||||
|
||||
By default the image is X11-based so it provides a full SATO theme
|
||||
desktop environment.
|
||||
|
||||
To compile the image for the framebuffer (instead of X11) add the
|
||||
following line to the project's conf/local.conf:
|
||||
|
||||
DISTRO_FEATURES_remove = "x11"
|
||||
|
||||
* dey-image-aws: console-only image supporting Amazon Web Services IoT
|
||||
|
||||
This image includes the AWS Greengrass Core and an AWS IoT platform
|
||||
example application. For more information on AWS support in Digi
|
||||
Embedded Yocto see the online documentation.
|
||||
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
#
|
||||
# This file is your local configuration file and is where all local user settings
|
||||
# are placed. The comments in this file give some guide to the options a new user
|
||||
# to the system might want to change but pretty much any configuration option can
|
||||
# be set in this file. More adventurous users can look at local.conf.extended
|
||||
# which contains other examples of configuration which can be placed in this file
|
||||
# but new users likely won't need any of them initially.
|
||||
#
|
||||
# Lines starting with the '#' character are commented out and in some cases the
|
||||
# default values are provided as comments to show people example syntax. Enabling
|
||||
# the option is a question of removing the # character and making any change to the
|
||||
# variable as required.
|
||||
|
||||
#
|
||||
# Machine Selection
|
||||
#
|
||||
# You need to select a specific machine to target the build with. There are a selection
|
||||
# of emulated machines available which can boot and run in the QEMU emulator:
|
||||
#
|
||||
#MACHINE ?= "qemuarm"
|
||||
#MACHINE ?= "qemuarm64"
|
||||
#MACHINE ?= "qemumips"
|
||||
#MACHINE ?= "qemumips64"
|
||||
#MACHINE ?= "qemuppc"
|
||||
#MACHINE ?= "qemux86"
|
||||
#MACHINE ?= "qemux86-64"
|
||||
#
|
||||
# There are also the following hardware board target machines included for
|
||||
# demonstration purposes:
|
||||
#
|
||||
#MACHINE ?= "beaglebone-yocto"
|
||||
#MACHINE ?= "genericx86"
|
||||
#MACHINE ?= "genericx86-64"
|
||||
#MACHINE ?= "mpc8315e-rdb"
|
||||
#MACHINE ?= "edgerouter"
|
||||
#
|
||||
# This sets the default machine to be qemux86 if no other machine is selected:
|
||||
#MACHINE ??= "qemux86"
|
||||
|
||||
MACHINE = "ccimx6sbc"
|
||||
|
||||
#
|
||||
# Use Digi's internal git repositories
|
||||
#
|
||||
#DIGI_INTERNAL_GIT ?= "1"
|
||||
|
||||
#
|
||||
# Where to place downloads
|
||||
#
|
||||
# During a first build the system will download many different source code tarballs
|
||||
# from various upstream projects. This can take a while, particularly if your network
|
||||
# connection is slow. These are all stored in DL_DIR. When wiping and rebuilding you
|
||||
# can preserve this directory to speed up this part of subsequent builds. This directory
|
||||
# is safe to share between multiple builds on the same machine too.
|
||||
#
|
||||
# The default is a downloads directory under TOPDIR which is the build directory.
|
||||
#
|
||||
#DL_DIR ?= "${TOPDIR}/downloads"
|
||||
|
||||
#
|
||||
# Where to place shared-state files
|
||||
#
|
||||
# BitBake has the capability to accelerate builds based on previously built output.
|
||||
# This is done using "shared state" files which can be thought of as cache objects
|
||||
# and this option determines where those files are placed.
|
||||
#
|
||||
# You can wipe out TMPDIR leaving this directory intact and the build would regenerate
|
||||
# from these files if no changes were made to the configuration. If changes were made
|
||||
# to the configuration, only shared state files where the state was still valid would
|
||||
# be used (done using checksums).
|
||||
#
|
||||
# The default is a sstate-cache directory under TOPDIR.
|
||||
#
|
||||
#SSTATE_DIR ?= "${TOPDIR}/sstate-cache"
|
||||
|
||||
#
|
||||
# Where to place the build output
|
||||
#
|
||||
# This option specifies where the bulk of the building work should be done and
|
||||
# where BitBake should place its temporary files and output. Keep in mind that
|
||||
# this includes the extraction and compilation of many applications and the toolchain
|
||||
# which can use Gigabytes of hard disk space.
|
||||
#
|
||||
# The default is a tmp directory under TOPDIR.
|
||||
#
|
||||
#TMPDIR = "${TOPDIR}/tmp"
|
||||
|
||||
#
|
||||
# Default policy config
|
||||
#
|
||||
# The distribution setting controls which policy settings are used as defaults.
|
||||
# The default value is fine for general Yocto project use, at least initially.
|
||||
# Ultimately when creating custom policy, people will likely end up subclassing
|
||||
# these defaults.
|
||||
#
|
||||
DISTRO ?= "dey"
|
||||
# As an example of a subclass there is a "bleeding" edge policy configuration
|
||||
# where many versions are set to the absolute latest code from the upstream
|
||||
# source control systems. This is just mentioned here as an example, its not
|
||||
# useful to most new users.
|
||||
# DISTRO ?= "poky-bleeding"
|
||||
|
||||
#
|
||||
# Package Management configuration
|
||||
#
|
||||
# This variable lists which packaging formats to enable. Multiple package backends
|
||||
# can be enabled at once and the first item listed in the variable will be used
|
||||
# to generate the root filesystems.
|
||||
# Options are:
|
||||
# - 'package_deb' for debian style deb files
|
||||
# - 'package_ipk' for ipk files are used by opkg (a debian style embedded package manager)
|
||||
# - 'package_rpm' for rpm style packages
|
||||
# E.g.: PACKAGE_CLASSES ?= "package_rpm package_deb package_ipk"
|
||||
# We default to rpm:
|
||||
PACKAGE_CLASSES ?= "package_rpm"
|
||||
|
||||
#
|
||||
# SDK target architecture
|
||||
#
|
||||
# This variable specifies the architecture to build SDK items for and means
|
||||
# you can build the SDK packages for architectures other than the machine you are
|
||||
# running the build on (i.e. building i686 packages on an x86_64 host).
|
||||
# Supported values are i686 and x86_64
|
||||
#SDKMACHINE ?= "i686"
|
||||
|
||||
#
|
||||
# Extra image configuration defaults
|
||||
#
|
||||
# The EXTRA_IMAGE_FEATURES variable allows extra packages to be added to the generated
|
||||
# images. Some of these options are added to certain image types automatically. The
|
||||
# variable can contain the following options:
|
||||
# "dbg-pkgs" - add -dbg packages for all installed packages
|
||||
# (adds symbol information for debugging/profiling)
|
||||
# "dev-pkgs" - add -dev packages for all installed packages
|
||||
# (useful if you want to develop against libs in the image)
|
||||
# "ptest-pkgs" - add -ptest packages for all ptest-enabled packages
|
||||
# (useful if you want to run the package test suites)
|
||||
# "tools-sdk" - add development tools (gcc, make, pkgconfig etc.)
|
||||
# "tools-debug" - add debugging tools (gdb, strace)
|
||||
# "eclipse-debug" - add Eclipse remote debugging support
|
||||
# "tools-profile" - add profiling tools (oprofile, lttng, valgrind)
|
||||
# "tools-testapps" - add useful testing tools (ts_print, aplay, arecord etc.)
|
||||
# "debug-tweaks" - make an image suitable for development
|
||||
# e.g. ssh root access has a blank password
|
||||
# There are other application targets that can be used here too, see
|
||||
# meta/classes/image.bbclass and meta/classes/core-image.bbclass for more details.
|
||||
# We default to enabling the debugging tweaks.
|
||||
EXTRA_IMAGE_FEATURES ?= "debug-tweaks"
|
||||
|
||||
#
|
||||
# Additional image features
|
||||
#
|
||||
# The following is a list of additional classes to use when building images which
|
||||
# enable extra features. Some available options which can be included in this variable
|
||||
# are:
|
||||
# - 'buildstats' collect build statistics
|
||||
# - 'image-mklibs' to reduce shared library files size for an image
|
||||
# - 'image-prelink' in order to prelink the filesystem image
|
||||
# NOTE: if listing mklibs & prelink both, then make sure mklibs is before prelink
|
||||
# NOTE: mklibs also needs to be explicitly enabled for a given image, see local.conf.extended
|
||||
USER_CLASSES ?= "buildstats image-mklibs image-prelink"
|
||||
|
||||
#
|
||||
# Runtime testing of images
|
||||
#
|
||||
# The build system can test booting virtual machine images under qemu (an emulator)
|
||||
# after any root filesystems are created and run tests against those images. It can also
|
||||
# run tests against any SDK that are built. To enable this uncomment these lines.
|
||||
# See classes/test{image,sdk}.bbclass for further details.
|
||||
#IMAGE_CLASSES += "testimage testsdk"
|
||||
#TESTIMAGE_AUTO_qemuall = "1"
|
||||
|
||||
#
|
||||
# Interactive shell configuration
|
||||
#
|
||||
# Under certain circumstances the system may need input from you and to do this it
|
||||
# can launch an interactive shell. It needs to do this since the build is
|
||||
# multithreaded and needs to be able to handle the case where more than one parallel
|
||||
# process may require the user's attention. The default is iterate over the available
|
||||
# terminal types to find one that works.
|
||||
#
|
||||
# Examples of the occasions this may happen are when resolving patches which cannot
|
||||
# be applied, to use the devshell or the kernel menuconfig
|
||||
#
|
||||
# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none
|
||||
# Note: currently, Konsole support only works for KDE 3.x due to the way
|
||||
# newer Konsole versions behave
|
||||
#OE_TERMINAL = "auto"
|
||||
# By default disable interactive patch resolution (tasks will just fail instead):
|
||||
PATCHRESOLVE = "noop"
|
||||
|
||||
#
|
||||
# Disk Space Monitoring during the build
|
||||
#
|
||||
# Monitor the disk space during the build. If there is less that 1GB of space or less
|
||||
# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully
|
||||
# shutdown the build. If there is less that 100MB or 1K inodes, perform a hard abort
|
||||
# of the build. The reason for this is that running completely out of space can corrupt
|
||||
# files and damages the build in ways which may not be easily recoverable.
|
||||
# It's necesary to monitor /tmp, if there is no space left the build will fail
|
||||
# with very exotic errors.
|
||||
BB_DISKMON_DIRS ??= "\
|
||||
STOPTASKS,${TMPDIR},1G,100K \
|
||||
STOPTASKS,${DL_DIR},1G,100K \
|
||||
STOPTASKS,${SSTATE_DIR},1G,100K \
|
||||
STOPTASKS,/tmp,100M,100K \
|
||||
ABORT,${TMPDIR},100M,1K \
|
||||
ABORT,${DL_DIR},100M,1K \
|
||||
ABORT,${SSTATE_DIR},100M,1K \
|
||||
ABORT,/tmp,10M,1K"
|
||||
|
||||
#
|
||||
# Shared-state files from other locations
|
||||
#
|
||||
# As mentioned above, shared state files are prebuilt cache data objects which can
|
||||
# used to accelerate build time. This variable can be used to configure the system
|
||||
# to search other mirror locations for these objects before it builds the data itself.
|
||||
#
|
||||
# This can be a filesystem directory, or a remote url such as http or ftp. These
|
||||
# would contain the sstate-cache results from previous builds (possibly from other
|
||||
# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the
|
||||
# cache locations to check for the shared objects.
|
||||
# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH
|
||||
# at the end as shown in the examples below. This will be substituted with the
|
||||
# correct path within the directory structure.
|
||||
#SSTATE_MIRRORS ?= "\
|
||||
#file://.* http://someserver.tld/share/sstate/PATH;downloadfilename=PATH \n \
|
||||
#file://.* file:///some/local/dir/sstate/PATH"
|
||||
|
||||
#
|
||||
# Yocto Project SState Mirror
|
||||
#
|
||||
# The Yocto Project has prebuilt artefacts available for its releases, you can enable
|
||||
# use of these by uncommenting the following line. This will mean the build uses
|
||||
# the network to check for artefacts at the start of builds, which does slow it down
|
||||
# equally, it will also speed up the builds by not having to build things if they are
|
||||
# present in the cache. It assumes you can download something faster than you can build it
|
||||
# which will depend on your network.
|
||||
#
|
||||
#SSTATE_MIRRORS ?= "file://.* http://sstate.yoctoproject.org/2.5/PATH;downloadfilename=PATH"
|
||||
|
||||
#
|
||||
# Qemu configuration
|
||||
#
|
||||
# By default qemu will build with a builtin VNC server where graphical output can be
|
||||
# seen. The two lines below enable the SDL backend too. By default libsdl2-native will
|
||||
# be built, if you want to use your host's libSDL instead of the minimal libsdl built
|
||||
# by libsdl2-native then uncomment the ASSUME_PROVIDED line below.
|
||||
PACKAGECONFIG_append_pn-qemu-native = " sdl"
|
||||
PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl"
|
||||
#ASSUME_PROVIDED += "libsdl2-native"
|
||||
|
||||
# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to
|
||||
# track the version of this file when it was generated. This can safely be ignored if
|
||||
# this doesn't mean anything to you.
|
||||
CONF_VERSION = "1"
|
||||
|
||||
#
|
||||
# Enable local PR server
|
||||
#
|
||||
PRSERV_HOST = "localhost:0"
|
||||
|
||||
#
|
||||
# Some libraries and packages are covered by NXP EULA
|
||||
#
|
||||
#ACCEPT_FSL_EULA = "1"
|
||||
Loading…
Reference in New Issue