Add kernel for stm32mp machine
Kernel lts 4.19 Signed-off-by: Christophe Priouzeau <christophe.priouzeau@st.com>
This commit is contained in:
parent
3fef5201b0
commit
b5ef9c5a74
|
|
@ -0,0 +1,81 @@
|
||||||
|
COMPATIBLE_MACHINE = "(stm32mpcommon)"
|
||||||
|
|
||||||
|
inherit kernel
|
||||||
|
|
||||||
|
DEPENDS += "openssl-native util-linux-native"
|
||||||
|
|
||||||
|
B = "${WORKDIR}/linux-${MACHINE}-standard-build"
|
||||||
|
# Configure build dir for externalsrc class usage through devtool
|
||||||
|
EXTERNALSRC_BUILD_pn-${PN} = "${WORKDIR}/linux-${MACHINE}-standard-build"
|
||||||
|
|
||||||
|
# To share config fragments between layers
|
||||||
|
FILESEXTRAPATHS_prepend := "${THISDIR}:"
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# Do not deploy kernel module with specfic tarball
|
||||||
|
MODULE_TARBALL_DEPLOY = "0"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# Defconfig
|
||||||
|
#
|
||||||
|
#If the defconfig is contained on the kernel tree (arch/${ARCH}/configs)
|
||||||
|
#you must use the following line
|
||||||
|
do_configure_prepend() {
|
||||||
|
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS MACHINE
|
||||||
|
if [ ! -z ${KERNEL_DEFCONFIG} ];
|
||||||
|
then
|
||||||
|
bbnote "Kernel customized: configuration of linux STM by using DEFCONFIG: ${KERNEL_DEFCONFIG}"
|
||||||
|
oe_runmake ${PARALLEL_MAKE} -C ${S} O=${B} CC="${KERNEL_CC}" LD="${KERNEL_LD}" ${KERNEL_DEFCONFIG}
|
||||||
|
else
|
||||||
|
if [ ! -z ${KERNEL_EXTERNAL_DEFCONFIG} ];
|
||||||
|
then
|
||||||
|
bbnote "Kernel customized: configuration of linux STM by using external DEFCONFIG"
|
||||||
|
install -m 0644 ${WORKDIR}/${KERNEL_EXTERNAL_DEFCONFIG} ${B}/.config
|
||||||
|
oe_runmake -C ${S} O=${B} CC="${KERNEL_CC}" LD="${KERNEL_LD}" oldconfig
|
||||||
|
else
|
||||||
|
bbwarn "You must specify KERNEL_DEFCONFIG or KERNEL_EXTERNAL_DEFCONFIG"
|
||||||
|
die "NO DEFCONFIG SPECIFIED"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "${KERNEL_CONFIG_FRAGMENTS}" ]
|
||||||
|
then
|
||||||
|
for f in ${KERNEL_CONFIG_FRAGMENTS}
|
||||||
|
do
|
||||||
|
bbnote "file = $f"
|
||||||
|
# Check if the config fragment was copied into the WORKDIR from
|
||||||
|
# the OE meta data
|
||||||
|
if [ ! -e "$f" ]
|
||||||
|
then
|
||||||
|
echo "Could not find kernel config fragment $f"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
bbnote "${S}/scripts/kconfig/merge_config.sh -m -r -O ${B} ${B}/.config ${KERNEL_CONFIG_FRAGMENTS} 1>&2"
|
||||||
|
# Now that all the fragments are located merge them.
|
||||||
|
(${S}/scripts/kconfig/merge_config.sh -m -r -O ${B} ${B}/.config ${KERNEL_CONFIG_FRAGMENTS} 1>&2 )
|
||||||
|
fi
|
||||||
|
|
||||||
|
yes '' | oe_runmake -C ${S} O=${B} CC="${KERNEL_CC}" LD="${KERNEL_LD}" oldconfig
|
||||||
|
#oe_runmake -C ${S} O=${B} savedefconfig && cp ${B}/defconfig ${WORKDIR}/defconfig.saved
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
do_install_append() {
|
||||||
|
# Install KERNEL_IMAGETYPE for kernel-imagebootfs package
|
||||||
|
install -m 0644 ${KERNEL_OUTPUT_DIR}/${KERNEL_IMAGETYPE} ${D}/${KERNEL_IMAGEDEST}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# Support checking the kernel load address parameter: expecting proper value for ST kernel.
|
||||||
|
#
|
||||||
|
python do_loadaddrcheck() {
|
||||||
|
if not d.getVar('ST_KERNEL_LOADADDR'):
|
||||||
|
bb.fatal('Missing ST_KERNEL_LOADADDR value for ST kernel build: please define it in your machine.')
|
||||||
|
}
|
||||||
|
|
||||||
|
PACKAGES =+ "${KERNEL_PACKAGE_NAME}-headers ${KERNEL_PACKAGE_NAME}-imagebootfs"
|
||||||
|
FILES_${KERNEL_PACKAGE_NAME}-headers = "${exec_prefix}/src/linux*"
|
||||||
|
FILES_${KERNEL_PACKAGE_NAME}-image += "boot/ ${KERNEL_IMAGEDEST}"
|
||||||
|
FILES_${KERNEL_PACKAGE_NAME}-imagebootfs = "boot/*.dtb boot/${KERNEL_IMAGETYPE}"
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
From 07a8a17983431bcc47ef52be1370f156e56119ce Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Tue, 13 Nov 2018 12:14:29 +0100
|
||||||
|
Subject: [PATCH 01/52] ARM: stm32mp1-r0-rc1: MACHINE
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/mach-stm32/Kconfig | 5 +----
|
||||||
|
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
|
||||||
|
index 713c068..651bdf4 100644
|
||||||
|
--- a/arch/arm/mach-stm32/Kconfig
|
||||||
|
+++ b/arch/arm/mach-stm32/Kconfig
|
||||||
|
@@ -4,6 +4,7 @@ menuconfig ARCH_STM32
|
||||||
|
select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
|
||||||
|
select ARM_GIC if ARCH_MULTI_V7
|
||||||
|
select ARM_PSCI if ARCH_MULTI_V7
|
||||||
|
+ select ARM_AMBA
|
||||||
|
select ARCH_HAS_RESET_CONTROLLER
|
||||||
|
select CLKSRC_STM32
|
||||||
|
select PINCTRL
|
||||||
|
@@ -18,22 +19,18 @@ if ARM_SINGLE_ARMV7M
|
||||||
|
|
||||||
|
config MACH_STM32F429
|
||||||
|
bool "STMicroelectronics STM32F429"
|
||||||
|
- select ARM_AMBA
|
||||||
|
default y
|
||||||
|
|
||||||
|
config MACH_STM32F469
|
||||||
|
bool "STMicroelectronics STM32F469"
|
||||||
|
- select ARM_AMBA
|
||||||
|
default y
|
||||||
|
|
||||||
|
config MACH_STM32F746
|
||||||
|
bool "STMicroelectronics STM32F746"
|
||||||
|
- select ARM_AMBA
|
||||||
|
default y
|
||||||
|
|
||||||
|
config MACH_STM32F769
|
||||||
|
bool "STMicroelectronics STM32F769"
|
||||||
|
- select ARM_AMBA
|
||||||
|
default y
|
||||||
|
|
||||||
|
config MACH_STM32H743
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,638 @@
|
||||||
|
From 656c7df3520f4422b871a4e69c68e6a9daf7ba61 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Tue, 13 Nov 2018 12:18:06 +0100
|
||||||
|
Subject: [PATCH 04/52] ARM: stm32mp1-r0-rc1: I2C
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/i2c/busses/i2c-stm32f7.c | 369 +++++++++++++++++++++++++++++++++------
|
||||||
|
1 file changed, 320 insertions(+), 49 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
|
||||||
|
index 62d023e..c1cbf93 100644
|
||||||
|
--- a/drivers/i2c/busses/i2c-stm32f7.c
|
||||||
|
+++ b/drivers/i2c/busses/i2c-stm32f7.c
|
||||||
|
@@ -21,12 +21,17 @@
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/iopoll.h>
|
||||||
|
+#include <linux/mfd/syscon.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_irq.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
+#include <linux/pinctrl/consumer.h>
|
||||||
|
+#include <linux/pm_runtime.h>
|
||||||
|
+#include <linux/pm_wakeirq.h>
|
||||||
|
+#include <linux/regmap.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
@@ -46,6 +51,7 @@
|
||||||
|
|
||||||
|
/* STM32F7 I2C control 1 */
|
||||||
|
#define STM32F7_I2C_CR1_PECEN BIT(23)
|
||||||
|
+#define STM32F7_I2C_CR1_WUPEN BIT(18)
|
||||||
|
#define STM32F7_I2C_CR1_SBC BIT(16)
|
||||||
|
#define STM32F7_I2C_CR1_RXDMAEN BIT(15)
|
||||||
|
#define STM32F7_I2C_CR1_TXDMAEN BIT(14)
|
||||||
|
@@ -163,6 +169,26 @@
|
||||||
|
#define STM32F7_SCLH_MAX BIT(8)
|
||||||
|
#define STM32F7_SCLL_MAX BIT(8)
|
||||||
|
|
||||||
|
+#define STM32F7_AUTOSUSPEND_DELAY (HZ / 100)
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * struct stm32f7_i2c_regs - i2c f7 registers backup
|
||||||
|
+ * @cr1: Control register 1
|
||||||
|
+ * @cr2: Control register 2
|
||||||
|
+ * @oar1: Own address 1 register
|
||||||
|
+ * @oar2: Own address 2 register
|
||||||
|
+ * @pecr: PEC register
|
||||||
|
+ * @timingr: Timing register
|
||||||
|
+ */
|
||||||
|
+struct stm32f7_i2c_regs {
|
||||||
|
+ u32 cr1;
|
||||||
|
+ u32 cr2;
|
||||||
|
+ u32 oar1;
|
||||||
|
+ u32 oar2;
|
||||||
|
+ u32 pecr;
|
||||||
|
+ u32 tmgr;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* struct stm32f7_i2c_spec - private i2c specification timing
|
||||||
|
* @rate: I2C bus speed (Hz)
|
||||||
|
@@ -259,6 +285,8 @@ struct stm32f7_i2c_msg {
|
||||||
|
* struct stm32f7_i2c_dev - private data of the controller
|
||||||
|
* @adap: I2C adapter for this controller
|
||||||
|
* @dev: device for this controller
|
||||||
|
+ * @irq_event: interrupt event line for the controller
|
||||||
|
+ * @irq_wakeup: interrupt wakeup line for the controller
|
||||||
|
* @base: virtual memory area
|
||||||
|
* @complete: completion of I2C message
|
||||||
|
* @clk: hw i2c clock
|
||||||
|
@@ -276,11 +304,14 @@ struct stm32f7_i2c_msg {
|
||||||
|
* slave)
|
||||||
|
* @dma: dma data
|
||||||
|
* @use_dma: boolean to know if dma is used in the current transfer
|
||||||
|
+ * @regmap: holds SYSCFG phandle for Fast Mode Plus bits
|
||||||
|
*/
|
||||||
|
struct stm32f7_i2c_dev {
|
||||||
|
struct i2c_adapter adap;
|
||||||
|
struct device *dev;
|
||||||
|
void __iomem *base;
|
||||||
|
+ int irq_event;
|
||||||
|
+ int irq_wakeup;
|
||||||
|
struct completion complete;
|
||||||
|
struct clk *clk;
|
||||||
|
int speed;
|
||||||
|
@@ -292,10 +323,12 @@ struct stm32f7_i2c_dev {
|
||||||
|
struct stm32f7_i2c_timings timing;
|
||||||
|
struct i2c_client *slave[STM32F7_I2C_MAX_SLAVE];
|
||||||
|
struct i2c_client *slave_running;
|
||||||
|
+ struct stm32f7_i2c_regs regs;
|
||||||
|
u32 slave_dir;
|
||||||
|
bool master_mode;
|
||||||
|
struct stm32_i2c_dma *dma;
|
||||||
|
bool use_dma;
|
||||||
|
+ struct regmap *regmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -1545,15 +1578,13 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||||
|
i2c_dev->msg_id = 0;
|
||||||
|
f7_msg->smbus = false;
|
||||||
|
|
||||||
|
- ret = clk_enable(i2c_dev->clk);
|
||||||
|
- if (ret) {
|
||||||
|
- dev_err(i2c_dev->dev, "Failed to enable clock\n");
|
||||||
|
+ ret = pm_runtime_get_sync(i2c_dev->dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
- }
|
||||||
|
|
||||||
|
ret = stm32f7_i2c_wait_free_bus(i2c_dev);
|
||||||
|
if (ret)
|
||||||
|
- goto clk_free;
|
||||||
|
+ goto pm_free;
|
||||||
|
|
||||||
|
stm32f7_i2c_xfer_msg(i2c_dev, msgs);
|
||||||
|
|
||||||
|
@@ -1569,8 +1600,9 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
-clk_free:
|
||||||
|
- clk_disable(i2c_dev->clk);
|
||||||
|
+pm_free:
|
||||||
|
+ pm_runtime_mark_last_busy(i2c_dev->dev);
|
||||||
|
+ pm_runtime_put_autosuspend(i2c_dev->dev);
|
||||||
|
|
||||||
|
return (ret < 0) ? ret : num;
|
||||||
|
}
|
||||||
|
@@ -1592,39 +1624,37 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||||
|
f7_msg->read_write = read_write;
|
||||||
|
f7_msg->smbus = true;
|
||||||
|
|
||||||
|
- ret = clk_enable(i2c_dev->clk);
|
||||||
|
- if (ret) {
|
||||||
|
- dev_err(i2c_dev->dev, "Failed to enable clock\n");
|
||||||
|
+ ret = pm_runtime_get_sync(dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
- }
|
||||||
|
|
||||||
|
ret = stm32f7_i2c_wait_free_bus(i2c_dev);
|
||||||
|
if (ret)
|
||||||
|
- goto clk_free;
|
||||||
|
+ goto pm_free;
|
||||||
|
|
||||||
|
ret = stm32f7_i2c_smbus_xfer_msg(i2c_dev, flags, command, data);
|
||||||
|
if (ret)
|
||||||
|
- goto clk_free;
|
||||||
|
+ goto pm_free;
|
||||||
|
|
||||||
|
timeout = wait_for_completion_timeout(&i2c_dev->complete,
|
||||||
|
i2c_dev->adap.timeout);
|
||||||
|
ret = f7_msg->result;
|
||||||
|
if (ret)
|
||||||
|
- goto clk_free;
|
||||||
|
+ goto pm_free;
|
||||||
|
|
||||||
|
if (!timeout) {
|
||||||
|
dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
|
||||||
|
if (i2c_dev->use_dma)
|
||||||
|
dmaengine_terminate_all(dma->chan_using);
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
- goto clk_free;
|
||||||
|
+ goto pm_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check PEC */
|
||||||
|
if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && read_write) {
|
||||||
|
ret = stm32f7_i2c_smbus_check_pec(i2c_dev);
|
||||||
|
if (ret)
|
||||||
|
- goto clk_free;
|
||||||
|
+ goto pm_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_write && size != I2C_SMBUS_QUICK) {
|
||||||
|
@@ -1649,11 +1679,15 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-clk_free:
|
||||||
|
- clk_disable(i2c_dev->clk);
|
||||||
|
+pm_free:
|
||||||
|
+ pm_runtime_mark_last_busy(dev);
|
||||||
|
+ pm_runtime_put_autosuspend(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void stm32f7_i2c_enable_wakeup(struct stm32f7_i2c_dev *i2c_dev,
|
||||||
|
+ bool enable);
|
||||||
|
+
|
||||||
|
static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||||
|
{
|
||||||
|
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
|
||||||
|
@@ -1676,13 +1710,12 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
- if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
|
||||||
|
- ret = clk_enable(i2c_dev->clk);
|
||||||
|
- if (ret) {
|
||||||
|
- dev_err(dev, "Failed to enable clock\n");
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ ret = pm_runtime_get_sync(dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev))
|
||||||
|
+ stm32f7_i2c_enable_wakeup(i2c_dev, true);
|
||||||
|
|
||||||
|
if (id == 0) {
|
||||||
|
/* Configure Own Address 1 */
|
||||||
|
@@ -1703,7 +1736,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||||
|
oar2 &= ~STM32F7_I2C_OAR2_MASK;
|
||||||
|
if (slave->flags & I2C_CLIENT_TEN) {
|
||||||
|
ret = -EOPNOTSUPP;
|
||||||
|
- goto exit;
|
||||||
|
+ goto pm_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
oar2 |= STM32F7_I2C_OAR2_OA2_7(slave->addr);
|
||||||
|
@@ -1712,7 +1745,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||||
|
writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2);
|
||||||
|
} else {
|
||||||
|
ret = -ENODEV;
|
||||||
|
- goto exit;
|
||||||
|
+ goto pm_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable ACK */
|
||||||
|
@@ -1723,11 +1756,13 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||||
|
STM32F7_I2C_CR1_PE;
|
||||||
|
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ ret = 0;
|
||||||
|
+pm_free:
|
||||||
|
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev))
|
||||||
|
+ stm32f7_i2c_enable_wakeup(i2c_dev, false);
|
||||||
|
|
||||||
|
-exit:
|
||||||
|
- if (!(stm32f7_i2c_is_slave_registered(i2c_dev)))
|
||||||
|
- clk_disable(i2c_dev->clk);
|
||||||
|
+ pm_runtime_mark_last_busy(dev);
|
||||||
|
+ pm_runtime_put_autosuspend(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -1745,6 +1780,10 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
|
||||||
|
|
||||||
|
WARN_ON(!i2c_dev->slave[id]);
|
||||||
|
|
||||||
|
+ ret = pm_runtime_get_sync(i2c_dev->dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
if (id == 0) {
|
||||||
|
mask = STM32F7_I2C_OAR1_OA1EN;
|
||||||
|
stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask);
|
||||||
|
@@ -1755,14 +1794,56 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
|
||||||
|
|
||||||
|
i2c_dev->slave[id] = NULL;
|
||||||
|
|
||||||
|
- if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
|
||||||
|
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
|
||||||
|
stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
|
||||||
|
- clk_disable(i2c_dev->clk);
|
||||||
|
+ stm32f7_i2c_enable_wakeup(i2c_dev, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ pm_runtime_mark_last_busy(i2c_dev->dev);
|
||||||
|
+ pm_runtime_put_autosuspend(i2c_dev->dev);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int stm32f7_i2c_setup_wakeup(struct stm32f7_i2c_dev *i2c_dev)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ device_init_wakeup(i2c_dev->dev, true);
|
||||||
|
+ ret = dev_pm_set_dedicated_wake_irq(i2c_dev->dev, i2c_dev->irq_wakeup);
|
||||||
|
+ if (ret) {
|
||||||
|
+ device_init_wakeup(i2c_dev->dev, false);
|
||||||
|
+ dev_warn(i2c_dev->dev, "failed to set up wakeup irq");
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return device_set_wakeup_enable(i2c_dev->dev, false);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev,
|
||||||
|
+ struct stm32f7_i2c_dev *i2c_dev)
|
||||||
|
+{
|
||||||
|
+ struct device_node *np = pdev->dev.of_node;
|
||||||
|
+ int ret;
|
||||||
|
+ u32 reg, mask;
|
||||||
|
+
|
||||||
|
+ i2c_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg-fmp");
|
||||||
|
+ if (IS_ERR(i2c_dev->regmap)) {
|
||||||
|
+ /* Optional */
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32_index(np, "st,syscfg-fmp", 1, ®);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32_index(np, "st,syscfg-fmp", 2, &mask);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return regmap_update_bits(i2c_dev->regmap, reg, mask, mask);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
|
||||||
|
{
|
||||||
|
return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SLAVE |
|
||||||
|
@@ -1786,7 +1867,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||||
|
struct stm32f7_i2c_dev *i2c_dev;
|
||||||
|
const struct stm32f7_i2c_setup *setup;
|
||||||
|
struct resource *res;
|
||||||
|
- u32 irq_error, irq_event, clk_rate, rise_time, fall_time;
|
||||||
|
+ u32 irq_error, clk_rate, rise_time, fall_time;
|
||||||
|
struct i2c_adapter *adap;
|
||||||
|
struct reset_control *rst;
|
||||||
|
dma_addr_t phy_addr;
|
||||||
|
@@ -1802,13 +1883,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||||
|
return PTR_ERR(i2c_dev->base);
|
||||||
|
phy_addr = (dma_addr_t)res->start;
|
||||||
|
|
||||||
|
- irq_event = irq_of_parse_and_map(np, 0);
|
||||||
|
- if (!irq_event) {
|
||||||
|
+ i2c_dev->irq_event = of_irq_get_byname(np, "event");
|
||||||
|
+ if (!i2c_dev->irq_event) {
|
||||||
|
dev_err(&pdev->dev, "IRQ event missing or invalid\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- irq_error = irq_of_parse_and_map(np, 1);
|
||||||
|
+ irq_error = of_irq_get_byname(np, "error");
|
||||||
|
if (!irq_error) {
|
||||||
|
dev_err(&pdev->dev, "IRQ error missing or invalid\n");
|
||||||
|
return -EINVAL;
|
||||||
|
@@ -1819,6 +1900,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||||
|
dev_err(&pdev->dev, "Error: Missing controller clock\n");
|
||||||
|
return PTR_ERR(i2c_dev->clk);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
ret = clk_prepare_enable(i2c_dev->clk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Failed to prepare_enable clock\n");
|
||||||
|
@@ -1828,12 +1910,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||||
|
i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
|
||||||
|
ret = device_property_read_u32(&pdev->dev, "clock-frequency",
|
||||||
|
&clk_rate);
|
||||||
|
- if (!ret && clk_rate >= 1000000)
|
||||||
|
+ if (!ret && clk_rate >= 1000000) {
|
||||||
|
i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS;
|
||||||
|
- else if (!ret && clk_rate >= 400000)
|
||||||
|
+ ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto clk_free;
|
||||||
|
+ } else if (!ret && clk_rate >= 400000) {
|
||||||
|
i2c_dev->speed = STM32_I2C_SPEED_FAST;
|
||||||
|
- else if (!ret && clk_rate >= 100000)
|
||||||
|
+ } else if (!ret && clk_rate >= 100000) {
|
||||||
|
i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
rst = devm_reset_control_get(&pdev->dev, NULL);
|
||||||
|
if (IS_ERR(rst)) {
|
||||||
|
@@ -1847,14 +1933,14 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
|
i2c_dev->dev = &pdev->dev;
|
||||||
|
|
||||||
|
- ret = devm_request_threaded_irq(&pdev->dev, irq_event,
|
||||||
|
+ ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq_event,
|
||||||
|
stm32f7_i2c_isr_event,
|
||||||
|
stm32f7_i2c_isr_event_thread,
|
||||||
|
IRQF_ONESHOT,
|
||||||
|
pdev->name, i2c_dev);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Failed to request irq event %i\n",
|
||||||
|
- irq_event);
|
||||||
|
+ i2c_dev->irq_event);
|
||||||
|
goto clk_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1888,8 +1974,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||||
|
if (ret)
|
||||||
|
goto clk_free;
|
||||||
|
|
||||||
|
- stm32f7_i2c_hw_config(i2c_dev);
|
||||||
|
-
|
||||||
|
adap = &i2c_dev->adap;
|
||||||
|
i2c_set_adapdata(adap, i2c_dev);
|
||||||
|
snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)",
|
||||||
|
@@ -1908,18 +1992,45 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||||
|
STM32F7_I2C_TXDR,
|
||||||
|
STM32F7_I2C_RXDR);
|
||||||
|
|
||||||
|
- ret = i2c_add_adapter(adap);
|
||||||
|
- if (ret)
|
||||||
|
- goto clk_free;
|
||||||
|
+ i2c_dev->irq_wakeup = of_irq_get_byname(np, "wakeup");
|
||||||
|
+ if (i2c_dev->irq_wakeup > 0) {
|
||||||
|
+ ret = stm32f7_i2c_setup_wakeup(i2c_dev);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto clk_free;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, i2c_dev);
|
||||||
|
|
||||||
|
- clk_disable(i2c_dev->clk);
|
||||||
|
+ pm_runtime_set_autosuspend_delay(i2c_dev->dev,
|
||||||
|
+ STM32F7_AUTOSUSPEND_DELAY);
|
||||||
|
+ pm_runtime_use_autosuspend(i2c_dev->dev);
|
||||||
|
+ pm_runtime_set_active(i2c_dev->dev);
|
||||||
|
+ pm_runtime_enable(i2c_dev->dev);
|
||||||
|
+
|
||||||
|
+ pm_runtime_get_noresume(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ stm32f7_i2c_hw_config(i2c_dev);
|
||||||
|
+
|
||||||
|
+ ret = i2c_add_adapter(adap);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto pm_disable;
|
||||||
|
|
||||||
|
dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr);
|
||||||
|
|
||||||
|
+ pm_runtime_mark_last_busy(i2c_dev->dev);
|
||||||
|
+ pm_runtime_put_autosuspend(i2c_dev->dev);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
+pm_disable:
|
||||||
|
+ dev_pm_clear_wake_irq(i2c_dev->dev);
|
||||||
|
+ device_init_wakeup(i2c_dev->dev, false);
|
||||||
|
+
|
||||||
|
+ pm_runtime_put_noidle(i2c_dev->dev);
|
||||||
|
+ pm_runtime_disable(i2c_dev->dev);
|
||||||
|
+ pm_runtime_set_suspended(i2c_dev->dev);
|
||||||
|
+ pm_runtime_dont_use_autosuspend(i2c_dev->dev);
|
||||||
|
+
|
||||||
|
clk_free:
|
||||||
|
clk_disable_unprepare(i2c_dev->clk);
|
||||||
|
|
||||||
|
@@ -1936,11 +2047,170 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_del_adapter(&i2c_dev->adap);
|
||||||
|
+ pm_runtime_get_sync(i2c_dev->dev);
|
||||||
|
+
|
||||||
|
+ dev_pm_clear_wake_irq(i2c_dev->dev);
|
||||||
|
+ device_init_wakeup(i2c_dev->dev, false);
|
||||||
|
|
||||||
|
- clk_unprepare(i2c_dev->clk);
|
||||||
|
+ clk_disable_unprepare(i2c_dev->clk);
|
||||||
|
+
|
||||||
|
+ pm_runtime_put_noidle(i2c_dev->dev);
|
||||||
|
+ pm_runtime_disable(i2c_dev->dev);
|
||||||
|
+ pm_runtime_set_suspended(i2c_dev->dev);
|
||||||
|
+ pm_runtime_dont_use_autosuspend(i2c_dev->dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_PM
|
||||||
|
+static int stm32f7_i2c_runtime_suspend(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
|
||||||
|
+
|
||||||
|
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev))
|
||||||
|
+ clk_disable_unprepare(i2c_dev->clk);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32f7_i2c_runtime_resume(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
|
||||||
|
+ ret = clk_prepare_enable(i2c_dev->clk);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(dev, "failed to prepare_enable clock\n");
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_PM_SLEEP
|
||||||
|
+static int stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = pm_runtime_get_sync(i2c_dev->dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ i2c_dev->regs.cr1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1);
|
||||||
|
+ i2c_dev->regs.cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
|
||||||
|
+ i2c_dev->regs.oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1);
|
||||||
|
+ i2c_dev->regs.oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2);
|
||||||
|
+ i2c_dev->regs.pecr = readl_relaxed(i2c_dev->base + STM32F7_I2C_PECR);
|
||||||
|
+ i2c_dev->regs.tmgr = readl_relaxed(i2c_dev->base + STM32F7_I2C_TIMINGR);
|
||||||
|
+
|
||||||
|
+ pm_runtime_put_sync(i2c_dev->dev);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev)
|
||||||
|
+{
|
||||||
|
+ u32 cr1;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = pm_runtime_get_sync(i2c_dev->dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ cr1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1);
|
||||||
|
+ if (cr1 & STM32F7_I2C_CR1_PE)
|
||||||
|
+ stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
|
||||||
|
+ STM32F7_I2C_CR1_PE);
|
||||||
|
+
|
||||||
|
+ writel_relaxed(i2c_dev->regs.tmgr, i2c_dev->base + STM32F7_I2C_TIMINGR);
|
||||||
|
+ writel_relaxed(i2c_dev->regs.cr1 & ~STM32F7_I2C_CR1_PE,
|
||||||
|
+ i2c_dev->base + STM32F7_I2C_CR1);
|
||||||
|
+ if (i2c_dev->regs.cr1 & STM32F7_I2C_CR1_PE)
|
||||||
|
+ stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
|
||||||
|
+ STM32F7_I2C_CR1_PE);
|
||||||
|
+ writel_relaxed(i2c_dev->regs.cr2, i2c_dev->base + STM32F7_I2C_CR2);
|
||||||
|
+ writel_relaxed(i2c_dev->regs.oar1, i2c_dev->base + STM32F7_I2C_OAR1);
|
||||||
|
+ writel_relaxed(i2c_dev->regs.oar2, i2c_dev->base + STM32F7_I2C_OAR2);
|
||||||
|
+ writel_relaxed(i2c_dev->regs.pecr, i2c_dev->base + STM32F7_I2C_PECR);
|
||||||
|
+
|
||||||
|
+ pm_runtime_put_sync(i2c_dev->dev);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32f7_i2c_enable_wakeup(struct stm32f7_i2c_dev *i2c_dev,
|
||||||
|
+ bool enable)
|
||||||
|
+{
|
||||||
|
+ void __iomem *base = i2c_dev->base;
|
||||||
|
+ u32 mask = STM32F7_I2C_CR1_WUPEN;
|
||||||
|
+
|
||||||
|
+ if (i2c_dev->irq_wakeup <= 0)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (enable) {
|
||||||
|
+ device_set_wakeup_enable(i2c_dev->dev, true);
|
||||||
|
+ enable_irq_wake(i2c_dev->irq_wakeup);
|
||||||
|
+ enable_irq_wake(i2c_dev->irq_event);
|
||||||
|
+ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
|
||||||
|
+ readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1);
|
||||||
|
+ } else {
|
||||||
|
+ disable_irq_wake(i2c_dev->irq_wakeup);
|
||||||
|
+ disable_irq_wake(i2c_dev->irq_event);
|
||||||
|
+ device_set_wakeup_enable(i2c_dev->dev, false);
|
||||||
|
+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32f7_i2c_suspend(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = stm32f7_i2c_regs_backup(i2c_dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
|
||||||
|
+ pinctrl_pm_select_sleep_state(dev);
|
||||||
|
+ pm_runtime_force_suspend(dev);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32f7_i2c_resume(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
|
||||||
|
+ ret = pm_runtime_force_resume(dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+ pinctrl_pm_select_default_state(dev);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = stm32f7_i2c_regs_restore(i2c_dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+#else
|
||||||
|
+static void stm32f7_i2c_enable_wakeup(struct stm32f7_i2c_dev *i2c_dev,
|
||||||
|
+ bool enable)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+static const struct dev_pm_ops stm32f7_i2c_pm_ops = {
|
||||||
|
+ SET_RUNTIME_PM_OPS(stm32f7_i2c_runtime_suspend,
|
||||||
|
+ stm32f7_i2c_runtime_resume, NULL)
|
||||||
|
+ SET_SYSTEM_SLEEP_PM_OPS(stm32f7_i2c_suspend, stm32f7_i2c_resume)
|
||||||
|
+};
|
||||||
|
|
||||||
|
static const struct of_device_id stm32f7_i2c_match[] = {
|
||||||
|
{ .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup},
|
||||||
|
@@ -1952,6 +2222,7 @@ static struct platform_driver stm32f7_i2c_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "stm32f7-i2c",
|
||||||
|
.of_match_table = stm32f7_i2c_match,
|
||||||
|
+ .pm = &stm32f7_i2c_pm_ops,
|
||||||
|
},
|
||||||
|
.probe = stm32f7_i2c_probe,
|
||||||
|
.remove = stm32f7_i2c_remove,
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,154 @@
|
||||||
|
From 358a1325502b2362a6fb74af3027f3f165684375 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Tue, 13 Nov 2018 12:19:47 +0100
|
||||||
|
Subject: [PATCH 06/52] ARM: stm32mp1-r0-rc1: IRQ Mailbox
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/irqchip/irq-stm32-exti.c | 23 ++++++++++++++++++-----
|
||||||
|
drivers/mailbox/mailbox-test.c | 26 ++++++++++++++------------
|
||||||
|
drivers/mailbox/stm32-ipcc.c | 4 ++--
|
||||||
|
3 files changed, 34 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
index 0a2088e..e185ed8 100644
|
||||||
|
--- a/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
+++ b/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
@@ -650,11 +650,6 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||||
|
*/
|
||||||
|
writel_relaxed(0, base + stm32_bank->imr_ofst);
|
||||||
|
writel_relaxed(0, base + stm32_bank->emr_ofst);
|
||||||
|
- writel_relaxed(0, base + stm32_bank->rtsr_ofst);
|
||||||
|
- writel_relaxed(0, base + stm32_bank->ftsr_ofst);
|
||||||
|
- writel_relaxed(~0UL, base + stm32_bank->rpr_ofst);
|
||||||
|
- if (stm32_bank->fpr_ofst != UNDEF_REG)
|
||||||
|
- writel_relaxed(~0UL, base + stm32_bank->fpr_ofst);
|
||||||
|
|
||||||
|
pr_info("%s: bank%d, External IRQs available:%#x\n",
|
||||||
|
node->full_name, bank_idx, irqs_mask);
|
||||||
|
@@ -735,9 +730,27 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int stm32_exti_h_translate(struct irq_domain *d,
|
||||||
|
+ struct irq_fwspec *fwspec,
|
||||||
|
+ unsigned long *out_hwirq,
|
||||||
|
+ unsigned int *out_type)
|
||||||
|
+{
|
||||||
|
+ if (is_of_node(fwspec->fwnode)) {
|
||||||
|
+ if (fwspec->param_count != 2)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ *out_hwirq = fwspec->param[0];
|
||||||
|
+ *out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return -EINVAL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const struct irq_domain_ops stm32_exti_h_domain_ops = {
|
||||||
|
.alloc = stm32_exti_h_domain_alloc,
|
||||||
|
.free = irq_domain_free_irqs_common,
|
||||||
|
+ .translate = stm32_exti_h_translate,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c
|
||||||
|
index 58bfafc..4e4ac4b 100644
|
||||||
|
--- a/drivers/mailbox/mailbox-test.c
|
||||||
|
+++ b/drivers/mailbox/mailbox-test.c
|
||||||
|
@@ -31,7 +31,6 @@
|
||||||
|
(MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
|
||||||
|
|
||||||
|
static bool mbox_data_ready;
|
||||||
|
-static struct dentry *root_debugfs_dir;
|
||||||
|
|
||||||
|
struct mbox_test_device {
|
||||||
|
struct device *dev;
|
||||||
|
@@ -45,6 +44,7 @@ struct mbox_test_device {
|
||||||
|
spinlock_t lock;
|
||||||
|
wait_queue_head_t waitq;
|
||||||
|
struct fasync_struct *async_queue;
|
||||||
|
+ struct dentry *root_debugfs_dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t mbox_test_signal_write(struct file *filp,
|
||||||
|
@@ -262,16 +262,16 @@ static int mbox_test_add_debugfs(struct platform_device *pdev,
|
||||||
|
if (!debugfs_initialized())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- root_debugfs_dir = debugfs_create_dir("mailbox", NULL);
|
||||||
|
- if (!root_debugfs_dir) {
|
||||||
|
+ tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL);
|
||||||
|
+ if (!tdev->root_debugfs_dir) {
|
||||||
|
dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- debugfs_create_file("message", 0600, root_debugfs_dir,
|
||||||
|
+ debugfs_create_file("message", 0600, tdev->root_debugfs_dir,
|
||||||
|
tdev, &mbox_test_message_ops);
|
||||||
|
|
||||||
|
- debugfs_create_file("signal", 0200, root_debugfs_dir,
|
||||||
|
+ debugfs_create_file("signal", 0200, tdev->root_debugfs_dir,
|
||||||
|
tdev, &mbox_test_signal_ops);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -363,22 +363,24 @@ static int mbox_test_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
|
/* It's okay for MMIO to be NULL */
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
- size = resource_size(res);
|
||||||
|
tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
- if (PTR_ERR(tdev->tx_mmio) == -EBUSY)
|
||||||
|
+ if (PTR_ERR(tdev->tx_mmio) == -EBUSY) {
|
||||||
|
/* if reserved area in SRAM, try just ioremap */
|
||||||
|
+ size = resource_size(res);
|
||||||
|
tdev->tx_mmio = devm_ioremap(&pdev->dev, res->start, size);
|
||||||
|
- else if (IS_ERR(tdev->tx_mmio))
|
||||||
|
+ } else if (IS_ERR(tdev->tx_mmio)) {
|
||||||
|
tdev->tx_mmio = NULL;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* If specified, second reg entry is Rx MMIO */
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||||
|
- size = resource_size(res);
|
||||||
|
tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
- if (PTR_ERR(tdev->rx_mmio) == -EBUSY)
|
||||||
|
+ if (PTR_ERR(tdev->rx_mmio) == -EBUSY) {
|
||||||
|
+ size = resource_size(res);
|
||||||
|
tdev->rx_mmio = devm_ioremap(&pdev->dev, res->start, size);
|
||||||
|
- else if (IS_ERR(tdev->rx_mmio))
|
||||||
|
+ } else if (IS_ERR(tdev->rx_mmio)) {
|
||||||
|
tdev->rx_mmio = tdev->tx_mmio;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
|
||||||
|
tdev->rx_channel = mbox_test_request_channel(pdev, "rx");
|
||||||
|
@@ -416,7 +418,7 @@ static int mbox_test_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct mbox_test_device *tdev = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
- debugfs_remove_recursive(root_debugfs_dir);
|
||||||
|
+ debugfs_remove_recursive(tdev->root_debugfs_dir);
|
||||||
|
|
||||||
|
if (tdev->tx_channel)
|
||||||
|
mbox_free_channel(tdev->tx_channel);
|
||||||
|
diff --git a/drivers/mailbox/stm32-ipcc.c b/drivers/mailbox/stm32-ipcc.c
|
||||||
|
index 533b0da..cd5ceca 100644
|
||||||
|
--- a/drivers/mailbox/stm32-ipcc.c
|
||||||
|
+++ b/drivers/mailbox/stm32-ipcc.c
|
||||||
|
@@ -276,8 +276,8 @@ static int stm32_ipcc_probe(struct platform_device *pdev)
|
||||||
|
dev_err(dev, "Failed to set wake up irq\n");
|
||||||
|
goto err_init_wkp;
|
||||||
|
}
|
||||||
|
- } else {
|
||||||
|
- device_init_wakeup(dev, false);
|
||||||
|
+ /* disable the wakeup source, let the user enable it or not */
|
||||||
|
+ device_set_wakeup_enable(dev, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mailbox controller */
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,78 @@
|
||||||
|
From 82c6107d054adcc906e43190ef150840876c2618 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Tue, 13 Nov 2018 12:23:50 +0100
|
||||||
|
Subject: [PATCH 10/52] ARM: stm32mp1-r0-rc1: ETH
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 30 ++++++++++++++++++++++-
|
||||||
|
1 file changed, 29 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||||
|
index 7e2e79d..d1cf145 100644
|
||||||
|
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||||
|
@@ -42,6 +42,7 @@ struct stm32_dwmac {
|
||||||
|
struct clk *clk_ethstp;
|
||||||
|
struct clk *syscfg_clk;
|
||||||
|
bool int_phyclk; /* Clock from RCC to drive PHY */
|
||||||
|
+ int irq_pwr_wakeup;
|
||||||
|
u32 mode_reg; /* MAC glue-logic mode register */
|
||||||
|
struct regmap *regmap;
|
||||||
|
u32 speed;
|
||||||
|
@@ -232,7 +233,9 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
|
||||||
|
static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||||
|
struct device *dev)
|
||||||
|
{
|
||||||
|
+ struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
struct device_node *np = dev->of_node;
|
||||||
|
+ int err = 0;
|
||||||
|
|
||||||
|
dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk");
|
||||||
|
|
||||||
|
@@ -260,7 +263,26 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||||
|
return PTR_ERR(dwmac->syscfg_clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ /* Get IRQ information early to have an ability to ask for deferred
|
||||||
|
+ * probe if needed before we went too far with resource allocation.
|
||||||
|
+ */
|
||||||
|
+ dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev,
|
||||||
|
+ "stm32_pwr_wakeup");
|
||||||
|
+ if (!dwmac->int_phyclk && dwmac->irq_pwr_wakeup >= 0) {
|
||||||
|
+ err = device_init_wakeup(&pdev->dev, true);
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(&pdev->dev, "Failed to init wake up irq\n");
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+ err = dev_pm_set_dedicated_wake_irq(&pdev->dev,
|
||||||
|
+ dwmac->irq_pwr_wakeup);
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(&pdev->dev, "Failed to set wake up irq\n");
|
||||||
|
+ device_init_wakeup(&pdev->dev, false);
|
||||||
|
+ }
|
||||||
|
+ device_set_wakeup_enable(&pdev->dev, false);
|
||||||
|
+ }
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32_dwmac_probe(struct platform_device *pdev)
|
||||||
|
@@ -326,9 +348,15 @@ static int stm32_dwmac_remove(struct platform_device *pdev)
|
||||||
|
struct net_device *ndev = platform_get_drvdata(pdev);
|
||||||
|
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||||
|
int ret = stmmac_dvr_remove(&pdev->dev);
|
||||||
|
+ struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
|
||||||
|
|
||||||
|
stm32_dwmac_clk_disable(priv->plat->bsp_priv);
|
||||||
|
|
||||||
|
+ if (dwmac->irq_pwr_wakeup >= 0) {
|
||||||
|
+ dev_pm_clear_wake_irq(&pdev->dev);
|
||||||
|
+ device_init_wakeup(&pdev->dev, false);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,335 @@
|
||||||
|
From a38a0eadf1db60bd8d1ff084c2ddc8016432b4fb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Tue, 13 Nov 2018 12:25:05 +0100
|
||||||
|
Subject: [PATCH 11/52] ARM: stm32mp1-r0-rc1: NVMEM
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/nvmem/Kconfig | 10 ++
|
||||||
|
drivers/nvmem/Makefile | 2 +
|
||||||
|
drivers/nvmem/core.c | 37 ++++++++
|
||||||
|
drivers/nvmem/stm32-romem.c | 205 +++++++++++++++++++++++++++++++++++++++++
|
||||||
|
include/linux/nvmem-consumer.h | 7 ++
|
||||||
|
5 files changed, 261 insertions(+)
|
||||||
|
create mode 100644 drivers/nvmem/stm32-romem.c
|
||||||
|
|
||||||
|
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
|
||||||
|
index 0a7a470e..f398b18 100644
|
||||||
|
--- a/drivers/nvmem/Kconfig
|
||||||
|
+++ b/drivers/nvmem/Kconfig
|
||||||
|
@@ -113,6 +113,16 @@ config NVMEM_BCM_OCOTP
|
||||||
|
This driver can also be built as a module. If so, the module
|
||||||
|
will be called nvmem-bcm-ocotp.
|
||||||
|
|
||||||
|
+config NVMEM_STM32_ROMEM
|
||||||
|
+ tristate "STMicroelectronics STM32 factory-programmed memory support"
|
||||||
|
+ depends on ARCH_STM32 || COMPILE_TEST
|
||||||
|
+ help
|
||||||
|
+ Say y here to enable read-only access for STMicroelectronics STM32
|
||||||
|
+ factory-programmed memory area.
|
||||||
|
+
|
||||||
|
+ This driver can also be built as a module. If so, the module
|
||||||
|
+ will be called nvmem-stm32-romem.
|
||||||
|
+
|
||||||
|
config NVMEM_SUNXI_SID
|
||||||
|
tristate "Allwinner SoCs SID support"
|
||||||
|
depends on ARCH_SUNXI
|
||||||
|
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
|
||||||
|
index 4e8c616..e85c946 100644
|
||||||
|
--- a/drivers/nvmem/Makefile
|
||||||
|
+++ b/drivers/nvmem/Makefile
|
||||||
|
@@ -26,6 +26,8 @@ nvmem_qfprom-y := qfprom.o
|
||||||
|
obj-$(CONFIG_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
|
||||||
|
nvmem_rockchip_efuse-y := rockchip-efuse.o
|
||||||
|
obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
|
||||||
|
+nvmem_stm32_romem-y := stm32-romem.o
|
||||||
|
+obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
|
||||||
|
nvmem_sunxi_sid-y := sunxi_sid.o
|
||||||
|
obj-$(CONFIG_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o
|
||||||
|
nvmem-uniphier-efuse-y := uniphier-efuse.o
|
||||||
|
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
|
||||||
|
index 7c530c8..60dacd7 100644
|
||||||
|
--- a/drivers/nvmem/core.c
|
||||||
|
+++ b/drivers/nvmem/core.c
|
||||||
|
@@ -1234,6 +1234,43 @@ int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val)
|
||||||
|
EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * nvmem_cell_read_u16() - Read a cell value as an u16
|
||||||
|
+ *
|
||||||
|
+ * @dev: Device that requests the nvmem cell.
|
||||||
|
+ * @cell_id: Name of nvmem cell to read.
|
||||||
|
+ * @val: pointer to output value.
|
||||||
|
+ *
|
||||||
|
+ * Return: 0 on success or negative errno.
|
||||||
|
+ */
|
||||||
|
+int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
|
||||||
|
+{
|
||||||
|
+ struct nvmem_cell *cell;
|
||||||
|
+ void *buf;
|
||||||
|
+ size_t len;
|
||||||
|
+
|
||||||
|
+ cell = nvmem_cell_get(dev, cell_id);
|
||||||
|
+ if (IS_ERR(cell))
|
||||||
|
+ return PTR_ERR(cell);
|
||||||
|
+
|
||||||
|
+ buf = nvmem_cell_read(cell, &len);
|
||||||
|
+ if (IS_ERR(buf)) {
|
||||||
|
+ nvmem_cell_put(cell);
|
||||||
|
+ return PTR_ERR(buf);
|
||||||
|
+ }
|
||||||
|
+ if (len != sizeof(*val)) {
|
||||||
|
+ kfree(buf);
|
||||||
|
+ nvmem_cell_put(cell);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ memcpy(val, buf, sizeof(*val));
|
||||||
|
+ kfree(buf);
|
||||||
|
+ nvmem_cell_put(cell);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(nvmem_cell_read_u16);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* nvmem_device_cell_read() - Read a given nvmem device and cell
|
||||||
|
*
|
||||||
|
* @nvmem: nvmem device to read from.
|
||||||
|
diff --git a/drivers/nvmem/stm32-romem.c b/drivers/nvmem/stm32-romem.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..198872f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/nvmem/stm32-romem.c
|
||||||
|
@@ -0,0 +1,205 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/*
|
||||||
|
+ * STM32 Factory-programmed memory read access driver
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
|
||||||
|
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com> for STMicroelectronics.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/arm-smccc.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/nvmem-provider.h>
|
||||||
|
+#include <linux/of_device.h>
|
||||||
|
+
|
||||||
|
+/* BSEC secure service access from non-secure */
|
||||||
|
+#define STM32_SMC_BSEC 0x82001003
|
||||||
|
+#define STM32_SMC_READ_SHADOW 0x01
|
||||||
|
+#define STM32_SMC_PROG_OTP 0x02
|
||||||
|
+#define STM32_SMC_WRITE_SHADOW 0x03
|
||||||
|
+#define STM32_SMC_READ_OTP 0x04
|
||||||
|
+
|
||||||
|
+struct stm32_romem_cfg {
|
||||||
|
+ int size;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct stm32_romem_priv {
|
||||||
|
+ void __iomem *base;
|
||||||
|
+ struct nvmem_config cfg;
|
||||||
|
+ struct device *dev;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int stm32_romem_read(void *context, unsigned int offset, void *buf,
|
||||||
|
+ size_t bytes)
|
||||||
|
+{
|
||||||
|
+ struct stm32_romem_priv *priv = context;
|
||||||
|
+ u8 *buf8 = buf;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = offset; i < offset + bytes; i++)
|
||||||
|
+ *buf8++ = readb_relaxed(priv->base + i);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_bsec_smc(u8 op, u32 otp, u32 data, u32 *result)
|
||||||
|
+{
|
||||||
|
+#if IS_ENABLED(CONFIG_HAVE_ARM_SMCCC)
|
||||||
|
+ struct arm_smccc_res res;
|
||||||
|
+
|
||||||
|
+ arm_smccc_smc(STM32_SMC_BSEC, op, otp, data, 0, 0, 0, 0, &res);
|
||||||
|
+ if (res.a0)
|
||||||
|
+ return -EIO;
|
||||||
|
+
|
||||||
|
+ if (result)
|
||||||
|
+ *result = (u32)res.a1;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+#else
|
||||||
|
+ return -ENXIO;
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_bsec_read(void *context, unsigned int offset, void *buf,
|
||||||
|
+ size_t bytes)
|
||||||
|
+{
|
||||||
|
+ struct stm32_romem_priv *priv = context;
|
||||||
|
+ u32 roffset, rbytes, val;
|
||||||
|
+ u8 *buf8 = buf, *val8 = (u8 *)&val;
|
||||||
|
+ int i, j = 0, ret, skip_bytes, size;
|
||||||
|
+
|
||||||
|
+ /* Round unaligned access to 32-bits */
|
||||||
|
+ roffset = rounddown(offset, 4);
|
||||||
|
+ skip_bytes = offset & 0x3;
|
||||||
|
+ rbytes = roundup(bytes + skip_bytes, 4);
|
||||||
|
+
|
||||||
|
+ if (roffset + rbytes > priv->cfg.size)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ for (i = roffset; (i < roffset + rbytes); i += 4) {
|
||||||
|
+ ret = stm32_bsec_smc(STM32_SMC_READ_OTP, i >> 2, 0, &val);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(priv->dev, "Failed to read data%d (%d)\n",
|
||||||
|
+ i >> 2, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* skip first bytes in case of unaligned read */
|
||||||
|
+ if (skip_bytes)
|
||||||
|
+ size = min(bytes, (size_t)(4 - skip_bytes));
|
||||||
|
+ else
|
||||||
|
+ size = min(bytes, (size_t)4);
|
||||||
|
+ memcpy(&buf8[j], &val8[skip_bytes], size);
|
||||||
|
+ bytes -= size;
|
||||||
|
+ j += size;
|
||||||
|
+ skip_bytes = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_bsec_write(void *context, unsigned int offset, void *buf,
|
||||||
|
+ size_t bytes)
|
||||||
|
+{
|
||||||
|
+ struct stm32_romem_priv *priv = context;
|
||||||
|
+ u32 *buf32 = buf;
|
||||||
|
+ int ret, i;
|
||||||
|
+
|
||||||
|
+ /* Allow only writing complete 32-bits aligned words */
|
||||||
|
+ if ((bytes % 4) || (offset % 4))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ for (i = offset; i < offset + bytes; i += 4) {
|
||||||
|
+ ret = stm32_bsec_smc(STM32_SMC_PROG_OTP, i >> 2, *buf32++,
|
||||||
|
+ NULL);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(priv->dev, "Failed to write data%d (%d)\n",
|
||||||
|
+ i >> 2, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_romem_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ const struct stm32_romem_cfg *cfg;
|
||||||
|
+ struct device *dev = &pdev->dev;
|
||||||
|
+ struct stm32_romem_priv *priv;
|
||||||
|
+ struct nvmem_device *nvmem;
|
||||||
|
+ struct resource *res;
|
||||||
|
+
|
||||||
|
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
+ if (!priv)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
+ priv->base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
+ if (IS_ERR(priv->base))
|
||||||
|
+ return PTR_ERR(priv->base);
|
||||||
|
+
|
||||||
|
+ priv->dev = dev;
|
||||||
|
+ priv->cfg.name = "stm32-romem";
|
||||||
|
+ priv->cfg.word_size = 1;
|
||||||
|
+ priv->cfg.stride = 1;
|
||||||
|
+ priv->cfg.dev = &pdev->dev;
|
||||||
|
+ priv->cfg.priv = priv;
|
||||||
|
+ priv->cfg.owner = THIS_MODULE;
|
||||||
|
+
|
||||||
|
+ cfg = (const struct stm32_romem_cfg *)
|
||||||
|
+ of_match_device(dev->driver->of_match_table, dev)->data;
|
||||||
|
+ if (!cfg) {
|
||||||
|
+ priv->cfg.read_only = true;
|
||||||
|
+ priv->cfg.size = resource_size(res);
|
||||||
|
+ priv->cfg.reg_read = stm32_romem_read;
|
||||||
|
+ } else {
|
||||||
|
+ priv->cfg.read_only = false;
|
||||||
|
+ priv->cfg.size = cfg->size;
|
||||||
|
+ priv->cfg.reg_read = stm32_bsec_read;
|
||||||
|
+ priv->cfg.reg_write = stm32_bsec_write;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ nvmem = nvmem_register(&priv->cfg);
|
||||||
|
+ if (IS_ERR(nvmem))
|
||||||
|
+ return PTR_ERR(nvmem);
|
||||||
|
+
|
||||||
|
+ platform_set_drvdata(pdev, nvmem);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_romem_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct nvmem_device *nvmem = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ return nvmem_unregister(nvmem);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct stm32_romem_cfg stm32mp15_bsec_cfg = {
|
||||||
|
+ .size = 384, /* 96 x 32-bits data words */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct of_device_id stm32_romem_of_match[] = {
|
||||||
|
+ { .compatible = "st,stm32-romem", }, {
|
||||||
|
+ .compatible = "st,stm32mp15-bsec",
|
||||||
|
+ .data = (void *)&stm32mp15_bsec_cfg,
|
||||||
|
+ }, {
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, stm32_romem_of_match);
|
||||||
|
+
|
||||||
|
+static struct platform_driver stm32_romem_driver = {
|
||||||
|
+ .probe = stm32_romem_probe,
|
||||||
|
+ .remove = stm32_romem_remove,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "stm32-romem",
|
||||||
|
+ .of_match_table = of_match_ptr(stm32_romem_of_match),
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+module_platform_driver(stm32_romem_driver);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
|
||||||
|
+MODULE_DESCRIPTION("STMicroelectronics STM32 RO-MEM");
|
||||||
|
+MODULE_ALIAS("platform:nvmem-stm32-romem");
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
|
||||||
|
index 4e85447..f303008 100644
|
||||||
|
--- a/include/linux/nvmem-consumer.h
|
||||||
|
+++ b/include/linux/nvmem-consumer.h
|
||||||
|
@@ -39,6 +39,7 @@ void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
|
||||||
|
void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
|
||||||
|
int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
|
||||||
|
int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val);
|
||||||
|
+int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val);
|
||||||
|
|
||||||
|
/* direct nvmem device read/write interface */
|
||||||
|
struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
|
||||||
|
@@ -95,6 +96,12 @@ static inline int nvmem_cell_read_u32(struct device *dev,
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline int nvmem_cell_read_u16(struct device *dev,
|
||||||
|
+ const char *cell_id, u16 *val)
|
||||||
|
+{
|
||||||
|
+ return -ENOSYS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static inline struct nvmem_device *nvmem_device_get(struct device *dev,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,192 @@
|
||||||
|
From 0d162ed61018cda930bb77680ab88b63633d5ce0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Tue, 13 Nov 2018 12:29:27 +0100
|
||||||
|
Subject: [PATCH 14/52] ARM: stm32mp1-r0-rc1: WATCHDOG
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/watchdog/Kconfig | 12 ++++
|
||||||
|
drivers/watchdog/Makefile | 1 +
|
||||||
|
drivers/watchdog/stpmic1_wdt.c | 139 +++++++++++++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 152 insertions(+)
|
||||||
|
create mode 100644 drivers/watchdog/stpmic1_wdt.c
|
||||||
|
|
||||||
|
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
|
||||||
|
index 5ea8909..6d2ffef 100644
|
||||||
|
--- a/drivers/watchdog/Kconfig
|
||||||
|
+++ b/drivers/watchdog/Kconfig
|
||||||
|
@@ -806,6 +806,18 @@ config STM32_WATCHDOG
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called stm32_iwdg.
|
||||||
|
|
||||||
|
+config STPMIC1_WATCHDOG
|
||||||
|
+ tristate "STPMIC1 PMIC watchdog support"
|
||||||
|
+ depends on MFD_STPMIC1
|
||||||
|
+ select WATCHDOG_CORE
|
||||||
|
+ help
|
||||||
|
+ Say Y here to include watchdog support embedded into STPMIC1 PMIC.
|
||||||
|
+ If the watchdog timer expires, stpmic1 will shut down all its power
|
||||||
|
+ supplies.
|
||||||
|
+
|
||||||
|
+ To compile this driver as a module, choose M here: the
|
||||||
|
+ module will be called spmic1_wdt.
|
||||||
|
+
|
||||||
|
config UNIPHIER_WATCHDOG
|
||||||
|
tristate "UniPhier watchdog support"
|
||||||
|
depends on ARCH_UNIPHIER || COMPILE_TEST
|
||||||
|
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
|
||||||
|
index bf92e7b..2649cf3 100644
|
||||||
|
--- a/drivers/watchdog/Makefile
|
||||||
|
+++ b/drivers/watchdog/Makefile
|
||||||
|
@@ -217,3 +217,4 @@ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
|
||||||
|
obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
|
||||||
|
obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o
|
||||||
|
obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
|
||||||
|
+obj-$(CONFIG_STPMIC1_WATCHDOG) += stpmic1_wdt.o
|
||||||
|
diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..a6cbc27
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/watchdog/stpmic1_wdt.c
|
||||||
|
@@ -0,0 +1,139 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+// Copyright (C) STMicroelectronics 2018
|
||||||
|
+// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
|
||||||
|
+
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/mfd/stpmic1.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/regmap.h>
|
||||||
|
+#include <linux/slab.h>
|
||||||
|
+#include <linux/watchdog.h>
|
||||||
|
+
|
||||||
|
+/* WATCHDOG CONTROL REGISTER bit */
|
||||||
|
+#define WDT_START BIT(0)
|
||||||
|
+#define WDT_PING BIT(1)
|
||||||
|
+#define WDT_START_MASK BIT(0)
|
||||||
|
+#define WDT_PING_MASK BIT(1)
|
||||||
|
+#define WDT_STOP 0
|
||||||
|
+
|
||||||
|
+#define PMIC_WDT_MIN_TIMEOUT 1
|
||||||
|
+#define PMIC_WDT_MAX_TIMEOUT 256
|
||||||
|
+#define PMIC_WDT_DEFAULT_TIMEOUT 30
|
||||||
|
+
|
||||||
|
+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) ")");
|
||||||
|
+
|
||||||
|
+struct stpmic1_wdt {
|
||||||
|
+ struct stpmic1 *pmic;
|
||||||
|
+ struct watchdog_device wdtdev;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int pmic_wdt_start(struct watchdog_device *wdd)
|
||||||
|
+{
|
||||||
|
+ struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||||
|
+
|
||||||
|
+ return regmap_update_bits(wdt->pmic->regmap,
|
||||||
|
+ WCHDG_CR, WDT_START_MASK, WDT_START);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int pmic_wdt_stop(struct watchdog_device *wdd)
|
||||||
|
+{
|
||||||
|
+ struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||||
|
+
|
||||||
|
+ return regmap_update_bits(wdt->pmic->regmap,
|
||||||
|
+ WCHDG_CR, WDT_START_MASK, WDT_STOP);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int pmic_wdt_ping(struct watchdog_device *wdd)
|
||||||
|
+{
|
||||||
|
+ struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||||
|
+
|
||||||
|
+ return regmap_update_bits(wdt->pmic->regmap,
|
||||||
|
+ WCHDG_CR, WDT_PING_MASK, WDT_PING);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int pmic_wdt_set_timeout(struct watchdog_device *wdd,
|
||||||
|
+ unsigned int timeout)
|
||||||
|
+{
|
||||||
|
+ struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||||
|
+
|
||||||
|
+ wdd->timeout = timeout;
|
||||||
|
+ /* timeout is equal to register value + 1 */
|
||||||
|
+ return regmap_write(wdt->pmic->regmap, WCHDG_TIMER_CR, timeout - 1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct watchdog_info pmic_watchdog_info = {
|
||||||
|
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
|
||||||
|
+ .identity = "STPMIC1 PMIC Watchdog",
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct watchdog_ops pmic_watchdog_ops = {
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ .start = pmic_wdt_start,
|
||||||
|
+ .stop = pmic_wdt_stop,
|
||||||
|
+ .ping = pmic_wdt_ping,
|
||||||
|
+ .set_timeout = pmic_wdt_set_timeout,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int pmic_wdt_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+ struct stpmic1 *pmic;
|
||||||
|
+ struct stpmic1_wdt *wdt;
|
||||||
|
+
|
||||||
|
+ if (!pdev->dev.parent)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ pmic = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
+ if (!pmic)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ wdt = devm_kzalloc(&pdev->dev, sizeof(struct stpmic1_wdt), GFP_KERNEL);
|
||||||
|
+ if (!wdt)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ wdt->pmic = pmic;
|
||||||
|
+
|
||||||
|
+ wdt->wdtdev.info = &pmic_watchdog_info;
|
||||||
|
+ wdt->wdtdev.ops = &pmic_watchdog_ops;
|
||||||
|
+ wdt->wdtdev.min_timeout = PMIC_WDT_MIN_TIMEOUT;
|
||||||
|
+ wdt->wdtdev.max_timeout = PMIC_WDT_MAX_TIMEOUT;
|
||||||
|
+
|
||||||
|
+ wdt->wdtdev.timeout = PMIC_WDT_DEFAULT_TIMEOUT;
|
||||||
|
+ watchdog_init_timeout(&wdt->wdtdev, 0, &pdev->dev);
|
||||||
|
+
|
||||||
|
+ watchdog_set_nowayout(&wdt->wdtdev, nowayout);
|
||||||
|
+ watchdog_set_drvdata(&wdt->wdtdev, wdt);
|
||||||
|
+
|
||||||
|
+ ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ dev_dbg(wdt->pmic->dev, "PMIC Watchdog driver probed\n");
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct of_device_id of_pmic_wdt_match[] = {
|
||||||
|
+ { .compatible = "st,stpmic1-wdt" },
|
||||||
|
+ { },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+MODULE_DEVICE_TABLE(of, of_pmic_wdt_match);
|
||||||
|
+
|
||||||
|
+static struct platform_driver stpmic1_wdt_driver = {
|
||||||
|
+ .probe = pmic_wdt_probe,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "stpmic1-wdt",
|
||||||
|
+ .of_match_table = of_pmic_wdt_match,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+module_platform_driver(stpmic1_wdt_driver);
|
||||||
|
+
|
||||||
|
+MODULE_DESCRIPTION("Watchdog driver for STPMIC1 device");
|
||||||
|
+MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,901 @@
|
||||||
|
From 535343fc0142b45ec82958a4cbea41945d4d93c9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Tue, 13 Nov 2018 12:30:43 +0100
|
||||||
|
Subject: [PATCH 15/52] ARM: stm32mp1-r0-rc1: MISC
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/mach-integrator/integrator_cp.c | 2 -
|
||||||
|
arch/arm/mach-versatile/versatile_dt.c | 4 -
|
||||||
|
drivers/soc/Kconfig | 1 +
|
||||||
|
drivers/soc/Makefile | 1 +
|
||||||
|
drivers/soc/st/Kconfig | 9 +
|
||||||
|
drivers/soc/st/Makefile | 1 +
|
||||||
|
drivers/soc/st/stm32_pm_domain.c | 212 ++++++++++++
|
||||||
|
drivers/spi/Kconfig | 9 +
|
||||||
|
drivers/spi/Makefile | 1 +
|
||||||
|
drivers/spi/spi-stm32-qspi.c | 541 +++++++++++++++++++++++++++++++
|
||||||
|
10 files changed, 775 insertions(+), 6 deletions(-)
|
||||||
|
create mode 100644 drivers/soc/st/Kconfig
|
||||||
|
create mode 100644 drivers/soc/st/Makefile
|
||||||
|
create mode 100644 drivers/soc/st/stm32_pm_domain.c
|
||||||
|
create mode 100644 drivers/spi/spi-stm32-qspi.c
|
||||||
|
|
||||||
|
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
|
||||||
|
index 772a7cf..976ded5 100644
|
||||||
|
--- a/arch/arm/mach-integrator/integrator_cp.c
|
||||||
|
+++ b/arch/arm/mach-integrator/integrator_cp.c
|
||||||
|
@@ -80,8 +80,6 @@ static unsigned int mmc_status(struct device *dev)
|
||||||
|
static struct mmci_platform_data mmc_data = {
|
||||||
|
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||||
|
.status = mmc_status,
|
||||||
|
- .gpio_wp = -1,
|
||||||
|
- .gpio_cd = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static u64 notrace intcp_read_sched_clock(void)
|
||||||
|
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
|
||||||
|
index 3c8d39c..e9d6068 100644
|
||||||
|
--- a/arch/arm/mach-versatile/versatile_dt.c
|
||||||
|
+++ b/arch/arm/mach-versatile/versatile_dt.c
|
||||||
|
@@ -89,15 +89,11 @@ unsigned int mmc_status(struct device *dev)
|
||||||
|
static struct mmci_platform_data mmc0_plat_data = {
|
||||||
|
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||||
|
.status = mmc_status,
|
||||||
|
- .gpio_wp = -1,
|
||||||
|
- .gpio_cd = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mmci_platform_data mmc1_plat_data = {
|
||||||
|
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||||
|
.status = mmc_status,
|
||||||
|
- .gpio_wp = -1,
|
||||||
|
- .gpio_cd = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
|
||||||
|
index c07b4a8..f2bd1ce 100644
|
||||||
|
--- a/drivers/soc/Kconfig
|
||||||
|
+++ b/drivers/soc/Kconfig
|
||||||
|
@@ -11,6 +11,7 @@ source "drivers/soc/qcom/Kconfig"
|
||||||
|
source "drivers/soc/renesas/Kconfig"
|
||||||
|
source "drivers/soc/rockchip/Kconfig"
|
||||||
|
source "drivers/soc/samsung/Kconfig"
|
||||||
|
+source "drivers/soc/st/Kconfig"
|
||||||
|
source "drivers/soc/sunxi/Kconfig"
|
||||||
|
source "drivers/soc/tegra/Kconfig"
|
||||||
|
source "drivers/soc/ti/Kconfig"
|
||||||
|
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
|
||||||
|
index 113e884..a16f673 100644
|
||||||
|
--- a/drivers/soc/Makefile
|
||||||
|
+++ b/drivers/soc/Makefile
|
||||||
|
@@ -18,6 +18,7 @@ obj-y += qcom/
|
||||||
|
obj-y += renesas/
|
||||||
|
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
|
||||||
|
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
|
||||||
|
+obj-$(CONFIG_ARCH_STM32) += st/
|
||||||
|
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||||
|
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||||
|
obj-$(CONFIG_SOC_TI) += ti/
|
||||||
|
diff --git a/drivers/soc/st/Kconfig b/drivers/soc/st/Kconfig
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..82ee423
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/soc/st/Kconfig
|
||||||
|
@@ -0,0 +1,9 @@
|
||||||
|
+if ARCH_STM32
|
||||||
|
+
|
||||||
|
+config STM32_PM_DOMAINS
|
||||||
|
+ bool "STM32 PM domains"
|
||||||
|
+ depends on MACH_STM32MP157
|
||||||
|
+ select PM_GENERIC_DOMAINS
|
||||||
|
+ default y if MACH_STM32MP157
|
||||||
|
+
|
||||||
|
+endif # ARCH_STM32
|
||||||
|
diff --git a/drivers/soc/st/Makefile b/drivers/soc/st/Makefile
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..8d7f291
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/soc/st/Makefile
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+obj-$(CONFIG_STM32_PM_DOMAINS) += stm32_pm_domain.o
|
||||||
|
diff --git a/drivers/soc/st/stm32_pm_domain.c b/drivers/soc/st/stm32_pm_domain.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0386624
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/soc/st/stm32_pm_domain.c
|
||||||
|
@@ -0,0 +1,212 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||||
|
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
|
||||||
|
+ * Author: Olivier Bideau <olivier.bideau@st.com> for STMicroelectronics.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/arm-smccc.h>
|
||||||
|
+#include <linux/err.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/of_platform.h>
|
||||||
|
+#include <linux/pm_domain.h>
|
||||||
|
+#include <linux/printk.h>
|
||||||
|
+#include <linux/slab.h>
|
||||||
|
+
|
||||||
|
+#define SMC(domain, state) \
|
||||||
|
+{ \
|
||||||
|
+ struct arm_smccc_res res; \
|
||||||
|
+ arm_smccc_smc(0x82001008, domain, state, 0, \
|
||||||
|
+ 0, 0, 0, 0, &res); \
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#define STM32_SMC_PD_DOMAIN_ON 0
|
||||||
|
+#define STM32_SMC_PD_DOMAIN_OFF 1
|
||||||
|
+
|
||||||
|
+struct stm32_pm_domain {
|
||||||
|
+ struct device *dev;
|
||||||
|
+ struct generic_pm_domain genpd;
|
||||||
|
+ int id;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int stm32_pd_power_off(struct generic_pm_domain *domain)
|
||||||
|
+{
|
||||||
|
+ struct stm32_pm_domain *priv = container_of(domain,
|
||||||
|
+ struct stm32_pm_domain,
|
||||||
|
+ genpd);
|
||||||
|
+
|
||||||
|
+ SMC(priv->id, STM32_SMC_PD_DOMAIN_OFF);
|
||||||
|
+
|
||||||
|
+ dev_dbg(priv->dev, "%s OFF\n", domain->name);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_pd_power_on(struct generic_pm_domain *domain)
|
||||||
|
+{
|
||||||
|
+ struct stm32_pm_domain *priv = container_of(domain,
|
||||||
|
+ struct stm32_pm_domain,
|
||||||
|
+ genpd);
|
||||||
|
+
|
||||||
|
+ SMC(priv->id, STM32_SMC_PD_DOMAIN_ON);
|
||||||
|
+
|
||||||
|
+ dev_dbg(priv->dev, "%s ON\n", domain->name);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32_pm_domain_remove(struct stm32_pm_domain *domain)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = pm_genpd_remove(&domain->genpd);
|
||||||
|
+ if (ret)
|
||||||
|
+ dev_err(domain->dev, "failed to remove PM domain %s: %d\n",
|
||||||
|
+ domain->genpd.name, ret);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_pm_domain_add(struct stm32_pm_domain *domain,
|
||||||
|
+ struct device *dev,
|
||||||
|
+ struct device_node *np)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ domain->dev = dev;
|
||||||
|
+ domain->genpd.name = np->name;
|
||||||
|
+ domain->genpd.power_off = stm32_pd_power_off;
|
||||||
|
+ domain->genpd.power_on = stm32_pd_power_on;
|
||||||
|
+ domain->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32(np, "reg", &domain->id);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(domain->dev, "no domain ID\n");
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = pm_genpd_init(&domain->genpd, NULL, 0);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(domain->dev, "failed to initialise PM domain %s: %d\n",
|
||||||
|
+ np->name, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = of_genpd_add_provider_simple(np, &domain->genpd);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(domain->dev, "failed to register PM domain %s: %d\n",
|
||||||
|
+ np->name, ret);
|
||||||
|
+ stm32_pm_domain_remove(domain);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dev_info(domain->dev, "domain %s registered\n", np->name);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32_pm_subdomain_add(struct stm32_pm_domain *domain,
|
||||||
|
+ struct device *dev,
|
||||||
|
+ struct device_node *np)
|
||||||
|
+{
|
||||||
|
+ struct device_node *np_child;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ for_each_child_of_node(np, np_child) {
|
||||||
|
+ struct stm32_pm_domain *sub_domain;
|
||||||
|
+
|
||||||
|
+ sub_domain = devm_kzalloc(dev, sizeof(*sub_domain), GFP_KERNEL);
|
||||||
|
+ if (!sub_domain)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ sub_domain->dev = dev;
|
||||||
|
+ sub_domain->genpd.name = np_child->name;
|
||||||
|
+ sub_domain->genpd.power_off = stm32_pd_power_off;
|
||||||
|
+ sub_domain->genpd.power_on = stm32_pd_power_on;
|
||||||
|
+ sub_domain->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32(np_child, "reg", &sub_domain->id);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(sub_domain->dev, "no domain ID\n");
|
||||||
|
+ devm_kfree(dev, sub_domain);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = pm_genpd_init(&sub_domain->genpd, NULL, 0);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(sub_domain->dev, "failed to initialise PM domain %s: %d\n"
|
||||||
|
+ , np_child->name, ret);
|
||||||
|
+ devm_kfree(dev, sub_domain);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = of_genpd_add_provider_simple(np_child,
|
||||||
|
+ &sub_domain->genpd);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(sub_domain->dev, "failed to register PM domain %s: %d\n"
|
||||||
|
+ , np_child->name, ret);
|
||||||
|
+ stm32_pm_domain_remove(sub_domain);
|
||||||
|
+ devm_kfree(dev, sub_domain);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = pm_genpd_add_subdomain(&domain->genpd,
|
||||||
|
+ &sub_domain->genpd);
|
||||||
|
+
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(sub_domain->dev, "failed to add Sub PM domain %s: %d\n"
|
||||||
|
+ , np_child->name, ret);
|
||||||
|
+ stm32_pm_domain_remove(sub_domain);
|
||||||
|
+ devm_kfree(dev, sub_domain);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dev_info(sub_domain->dev, "subdomain %s registered\n",
|
||||||
|
+ np_child->name);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_pm_domain_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct device *dev = &pdev->dev;
|
||||||
|
+ struct device_node *np = dev->of_node, *child_np;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ for_each_child_of_node(np, child_np) {
|
||||||
|
+ struct stm32_pm_domain *domain;
|
||||||
|
+
|
||||||
|
+ domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL);
|
||||||
|
+ if (!domain)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ ret = stm32_pm_domain_add(domain, dev, child_np);
|
||||||
|
+ if (ret) {
|
||||||
|
+ devm_kfree(dev, domain);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ stm32_pm_subdomain_add(domain, dev, child_np);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dev_info(dev, "domains probed\n");
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct of_device_id stm32_pm_domain_matches[] = {
|
||||||
|
+ { .compatible = "st,stm32mp157c-pd", },
|
||||||
|
+ { },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct platform_driver stm32_pm_domains_driver = {
|
||||||
|
+ .probe = stm32_pm_domain_probe,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "stm32-pm-domain",
|
||||||
|
+ .of_match_table = stm32_pm_domain_matches,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init stm32_pm_domains_init(void)
|
||||||
|
+{
|
||||||
|
+ return platform_driver_register(&stm32_pm_domains_driver);
|
||||||
|
+}
|
||||||
|
+core_initcall(stm32_pm_domains_init);
|
||||||
|
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
|
||||||
|
index 671d078..448d441 100644
|
||||||
|
--- a/drivers/spi/Kconfig
|
||||||
|
+++ b/drivers/spi/Kconfig
|
||||||
|
@@ -613,6 +613,15 @@ config SPI_STM32
|
||||||
|
is not available, the driver automatically falls back to
|
||||||
|
PIO mode.
|
||||||
|
|
||||||
|
+config SPI_STM32_QSPI
|
||||||
|
+ tristate "STMicroelectronics STM32 QUAD SPI controller"
|
||||||
|
+ depends on ARCH_STM32 || COMPILE_TEST
|
||||||
|
+ depends on OF
|
||||||
|
+ help
|
||||||
|
+ This enables support for the Quad SPI controller in master mode.
|
||||||
|
+ This driver does not support generic SPI. The implementation only
|
||||||
|
+ supports spi-mem interface.
|
||||||
|
+
|
||||||
|
config SPI_ST_SSC4
|
||||||
|
tristate "STMicroelectronics SPI SSC-based driver"
|
||||||
|
depends on ARCH_STI || COMPILE_TEST
|
||||||
|
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
|
||||||
|
index a90d559..68a3c4e 100644
|
||||||
|
--- a/drivers/spi/Makefile
|
||||||
|
+++ b/drivers/spi/Makefile
|
||||||
|
@@ -90,6 +90,7 @@ obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
|
||||||
|
obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
|
||||||
|
obj-$(CONFIG_SPI_SPRD_ADI) += spi-sprd-adi.o
|
||||||
|
obj-$(CONFIG_SPI_STM32) += spi-stm32.o
|
||||||
|
+obj-$(CONFIG_SPI_STM32_QSPI) += spi-stm32-qspi.o
|
||||||
|
obj-$(CONFIG_SPI_ST_SSC4) += spi-st-ssc4.o
|
||||||
|
obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o
|
||||||
|
obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o
|
||||||
|
diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..3e8ca10
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/spi/spi-stm32-qspi.c
|
||||||
|
@@ -0,0 +1,541 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||||
|
+ * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
|
||||||
|
+ */
|
||||||
|
+#include <linux/bitfield.h>
|
||||||
|
+#include <linux/clk.h>
|
||||||
|
+#include <linux/errno.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/iopoll.h>
|
||||||
|
+#include <linux/interrupt.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/mutex.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/of_device.h>
|
||||||
|
+#include <linux/pinctrl/consumer.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/reset.h>
|
||||||
|
+#include <linux/sizes.h>
|
||||||
|
+#include <linux/spi/spi-mem.h>
|
||||||
|
+
|
||||||
|
+#define QSPI_CR 0x00
|
||||||
|
+#define CR_EN BIT(0)
|
||||||
|
+#define CR_ABORT BIT(1)
|
||||||
|
+#define CR_DMAEN BIT(2)
|
||||||
|
+#define CR_TCEN BIT(3)
|
||||||
|
+#define CR_SSHIFT BIT(4)
|
||||||
|
+#define CR_DFM BIT(6)
|
||||||
|
+#define CR_FSEL BIT(7)
|
||||||
|
+#define CR_FTHRES_MASK GENMASK(12, 8)
|
||||||
|
+#define CR_TEIE BIT(16)
|
||||||
|
+#define CR_TCIE BIT(17)
|
||||||
|
+#define CR_FTIE BIT(18)
|
||||||
|
+#define CR_SMIE BIT(19)
|
||||||
|
+#define CR_TOIE BIT(20)
|
||||||
|
+#define CR_PRESC_MASK GENMASK(31, 24)
|
||||||
|
+
|
||||||
|
+#define QSPI_DCR 0x04
|
||||||
|
+#define DCR_FSIZE_MASK GENMASK(20, 16)
|
||||||
|
+
|
||||||
|
+#define QSPI_SR 0x08
|
||||||
|
+#define SR_TEF BIT(0)
|
||||||
|
+#define SR_TCF BIT(1)
|
||||||
|
+#define SR_FTF BIT(2)
|
||||||
|
+#define SR_SMF BIT(3)
|
||||||
|
+#define SR_TOF BIT(4)
|
||||||
|
+#define SR_BUSY BIT(5)
|
||||||
|
+#define SR_FLEVEL_MASK GENMASK(13, 8)
|
||||||
|
+
|
||||||
|
+#define QSPI_FCR 0x0c
|
||||||
|
+#define FCR_CTEF BIT(0)
|
||||||
|
+#define FCR_CTCF BIT(1)
|
||||||
|
+
|
||||||
|
+#define QSPI_DLR 0x10
|
||||||
|
+
|
||||||
|
+#define QSPI_CCR 0x14
|
||||||
|
+#define CCR_INST_MASK GENMASK(7, 0)
|
||||||
|
+#define CCR_IMODE_MASK GENMASK(9, 8)
|
||||||
|
+#define CCR_ADMODE_MASK GENMASK(11, 10)
|
||||||
|
+#define CCR_ADSIZE_MASK GENMASK(13, 12)
|
||||||
|
+#define CCR_DCYC_MASK GENMASK(22, 18)
|
||||||
|
+#define CCR_DMODE_MASK GENMASK(25, 24)
|
||||||
|
+#define CCR_FMODE_MASK GENMASK(27, 26)
|
||||||
|
+#define CCR_FMODE_INDW (0U << 26)
|
||||||
|
+#define CCR_FMODE_INDR (1U << 26)
|
||||||
|
+#define CCR_FMODE_APM (2U << 26)
|
||||||
|
+#define CCR_FMODE_MM (3U << 26)
|
||||||
|
+#define CCR_BUSWIDTH_0 0x0
|
||||||
|
+#define CCR_BUSWIDTH_1 0x1
|
||||||
|
+#define CCR_BUSWIDTH_2 0x2
|
||||||
|
+#define CCR_BUSWIDTH_4 0x3
|
||||||
|
+
|
||||||
|
+#define QSPI_AR 0x18
|
||||||
|
+#define QSPI_ABR 0x1c
|
||||||
|
+#define QSPI_DR 0x20
|
||||||
|
+#define QSPI_PSMKR 0x24
|
||||||
|
+#define QSPI_PSMAR 0x28
|
||||||
|
+#define QSPI_PIR 0x2c
|
||||||
|
+#define QSPI_LPTR 0x30
|
||||||
|
+
|
||||||
|
+#define STM32_QSPI_MAX_MMAP_SZ SZ_256M
|
||||||
|
+#define STM32_QSPI_MAX_NORCHIP 2
|
||||||
|
+
|
||||||
|
+#define STM32_FIFO_TIMEOUT_US 30000
|
||||||
|
+#define STM32_BUSY_TIMEOUT_US 100000
|
||||||
|
+#define STM32_ABT_TIMEOUT_US 100000
|
||||||
|
+
|
||||||
|
+struct stm32_qspi_flash {
|
||||||
|
+ struct stm32_qspi *qspi;
|
||||||
|
+ u32 cs;
|
||||||
|
+ u32 presc;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct stm32_qspi {
|
||||||
|
+ struct device *dev;
|
||||||
|
+ void __iomem *io_base;
|
||||||
|
+ void __iomem *mm_base;
|
||||||
|
+ resource_size_t mm_size;
|
||||||
|
+ struct clk *clk;
|
||||||
|
+ u32 clk_rate;
|
||||||
|
+ struct stm32_qspi_flash flash[STM32_QSPI_MAX_NORCHIP];
|
||||||
|
+ struct completion data_completion;
|
||||||
|
+ u32 fmode;
|
||||||
|
+
|
||||||
|
+ u32 cr_reg;
|
||||||
|
+ u32 dcr_reg;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * to protect device configuration, could be different between
|
||||||
|
+ * 2 flash access (bk1, bk2)
|
||||||
|
+ */
|
||||||
|
+ struct mutex lock;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static irqreturn_t stm32_qspi_irq(int irq, void *dev_id)
|
||||||
|
+{
|
||||||
|
+ struct stm32_qspi *qspi = (struct stm32_qspi *)dev_id;
|
||||||
|
+ u32 cr, sr;
|
||||||
|
+
|
||||||
|
+ sr = readl_relaxed(qspi->io_base + QSPI_SR);
|
||||||
|
+
|
||||||
|
+ if (sr & (SR_TEF | SR_TCF)) {
|
||||||
|
+ /* disable irq */
|
||||||
|
+ cr = readl_relaxed(qspi->io_base + QSPI_CR);
|
||||||
|
+ cr &= ~CR_TCIE & ~CR_TEIE;
|
||||||
|
+ writel_relaxed(cr, qspi->io_base + QSPI_CR);
|
||||||
|
+ complete(&qspi->data_completion);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return IRQ_HANDLED;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32_qspi_read_fifo(u8 *val, void __iomem *addr)
|
||||||
|
+{
|
||||||
|
+ *val = readb_relaxed(addr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32_qspi_write_fifo(u8 *val, void __iomem *addr)
|
||||||
|
+{
|
||||||
|
+ writeb_relaxed(*val, addr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_tx_poll(struct stm32_qspi *qspi,
|
||||||
|
+ const struct spi_mem_op *op)
|
||||||
|
+{
|
||||||
|
+ void (*tx_fifo)(u8 *val, void __iomem *addr);
|
||||||
|
+ u32 len = op->data.nbytes, sr;
|
||||||
|
+ u8 *buf;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (op->data.dir == SPI_MEM_DATA_IN) {
|
||||||
|
+ tx_fifo = stm32_qspi_read_fifo;
|
||||||
|
+ buf = op->data.buf.in;
|
||||||
|
+
|
||||||
|
+ } else {
|
||||||
|
+ tx_fifo = stm32_qspi_write_fifo;
|
||||||
|
+ buf = (u8 *)op->data.buf.out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (len--) {
|
||||||
|
+ ret = readl_relaxed_poll_timeout_atomic(qspi->io_base + QSPI_SR,
|
||||||
|
+ sr, (sr & SR_FTF), 1,
|
||||||
|
+ STM32_FIFO_TIMEOUT_US);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(qspi->dev, "fifo timeout (len:%d stat:%#x)\n",
|
||||||
|
+ len, sr);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ tx_fifo(buf++, qspi->io_base + QSPI_DR);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_tx_mm(struct stm32_qspi *qspi,
|
||||||
|
+ const struct spi_mem_op *op)
|
||||||
|
+{
|
||||||
|
+ memcpy_fromio(op->data.buf.in, qspi->mm_base + op->addr.val,
|
||||||
|
+ op->data.nbytes);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_tx(struct stm32_qspi *qspi, const struct spi_mem_op *op)
|
||||||
|
+{
|
||||||
|
+ if (!op->data.nbytes)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ if (qspi->fmode == CCR_FMODE_MM)
|
||||||
|
+ return stm32_qspi_tx_mm(qspi, op);
|
||||||
|
+
|
||||||
|
+ return stm32_qspi_tx_poll(qspi, op);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_wait_nobusy(struct stm32_qspi *qspi)
|
||||||
|
+{
|
||||||
|
+ u32 sr;
|
||||||
|
+
|
||||||
|
+ return readl_relaxed_poll_timeout_atomic(qspi->io_base + QSPI_SR, sr,
|
||||||
|
+ !(sr & SR_BUSY), 1,
|
||||||
|
+ STM32_BUSY_TIMEOUT_US);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi,
|
||||||
|
+ const struct spi_mem_op *op)
|
||||||
|
+{
|
||||||
|
+ u32 cr, sr;
|
||||||
|
+ int err = 0;
|
||||||
|
+
|
||||||
|
+ if (!op->data.nbytes)
|
||||||
|
+ return stm32_qspi_wait_nobusy(qspi);
|
||||||
|
+
|
||||||
|
+ if (readl_relaxed(qspi->io_base + QSPI_SR) & SR_TCF)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ reinit_completion(&qspi->data_completion);
|
||||||
|
+ cr = readl_relaxed(qspi->io_base + QSPI_CR);
|
||||||
|
+ writel_relaxed(cr | CR_TCIE | CR_TEIE, qspi->io_base + QSPI_CR);
|
||||||
|
+
|
||||||
|
+ if (!wait_for_completion_interruptible_timeout(&qspi->data_completion,
|
||||||
|
+ msecs_to_jiffies(1000))) {
|
||||||
|
+ err = -ETIMEDOUT;
|
||||||
|
+ } else {
|
||||||
|
+ sr = readl_relaxed(qspi->io_base + QSPI_SR);
|
||||||
|
+ if (sr & SR_TEF)
|
||||||
|
+ err = -EIO;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ /* clear flags */
|
||||||
|
+ writel_relaxed(FCR_CTCF | FCR_CTEF, qspi->io_base + QSPI_FCR);
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_get_mode(struct stm32_qspi *qspi, u8 buswidth)
|
||||||
|
+{
|
||||||
|
+ if (buswidth == 4)
|
||||||
|
+ return CCR_BUSWIDTH_4;
|
||||||
|
+
|
||||||
|
+ return buswidth;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||||
|
+{
|
||||||
|
+ struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master);
|
||||||
|
+ struct stm32_qspi_flash *flash = &qspi->flash[mem->spi->chip_select];
|
||||||
|
+ u32 ccr, cr, addr_max;
|
||||||
|
+ int timeout, err = 0;
|
||||||
|
+
|
||||||
|
+ dev_dbg(qspi->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n",
|
||||||
|
+ op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
|
||||||
|
+ op->dummy.buswidth, op->data.buswidth,
|
||||||
|
+ op->addr.val, op->data.nbytes);
|
||||||
|
+
|
||||||
|
+ err = stm32_qspi_wait_nobusy(qspi);
|
||||||
|
+ if (err)
|
||||||
|
+ goto abort;
|
||||||
|
+
|
||||||
|
+ addr_max = op->addr.val + op->data.nbytes + 1;
|
||||||
|
+
|
||||||
|
+ if (op->data.dir == SPI_MEM_DATA_IN) {
|
||||||
|
+ if (addr_max < qspi->mm_size &&
|
||||||
|
+ op->addr.buswidth)
|
||||||
|
+ qspi->fmode = CCR_FMODE_MM;
|
||||||
|
+ else
|
||||||
|
+ qspi->fmode = CCR_FMODE_INDR;
|
||||||
|
+ } else {
|
||||||
|
+ qspi->fmode = CCR_FMODE_INDW;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ cr = readl_relaxed(qspi->io_base + QSPI_CR);
|
||||||
|
+ cr &= ~CR_PRESC_MASK & ~CR_FSEL;
|
||||||
|
+ cr |= FIELD_PREP(CR_PRESC_MASK, flash->presc);
|
||||||
|
+ cr |= FIELD_PREP(CR_FSEL, flash->cs);
|
||||||
|
+ writel_relaxed(cr, qspi->io_base + QSPI_CR);
|
||||||
|
+
|
||||||
|
+ if (op->data.nbytes)
|
||||||
|
+ writel_relaxed(op->data.nbytes - 1,
|
||||||
|
+ qspi->io_base + QSPI_DLR);
|
||||||
|
+ else
|
||||||
|
+ qspi->fmode = CCR_FMODE_INDW;
|
||||||
|
+
|
||||||
|
+ ccr = qspi->fmode;
|
||||||
|
+ ccr |= FIELD_PREP(CCR_INST_MASK, op->cmd.opcode);
|
||||||
|
+ ccr |= FIELD_PREP(CCR_IMODE_MASK,
|
||||||
|
+ stm32_qspi_get_mode(qspi, op->cmd.buswidth));
|
||||||
|
+
|
||||||
|
+ if (op->addr.nbytes) {
|
||||||
|
+ ccr |= FIELD_PREP(CCR_ADMODE_MASK,
|
||||||
|
+ stm32_qspi_get_mode(qspi, op->addr.buswidth));
|
||||||
|
+ ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (op->dummy.buswidth && op->dummy.nbytes)
|
||||||
|
+ ccr |= FIELD_PREP(CCR_DCYC_MASK,
|
||||||
|
+ op->dummy.nbytes * 8 / op->dummy.buswidth);
|
||||||
|
+
|
||||||
|
+ if (op->data.nbytes) {
|
||||||
|
+ ccr |= FIELD_PREP(CCR_DMODE_MASK,
|
||||||
|
+ stm32_qspi_get_mode(qspi, op->data.buswidth));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ writel_relaxed(ccr, qspi->io_base + QSPI_CCR);
|
||||||
|
+
|
||||||
|
+ if (op->addr.nbytes && qspi->fmode != CCR_FMODE_MM)
|
||||||
|
+ writel_relaxed(op->addr.val, qspi->io_base + QSPI_AR);
|
||||||
|
+
|
||||||
|
+ err = stm32_qspi_tx(qspi, op);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Abort in:
|
||||||
|
+ * -error case
|
||||||
|
+ * -read memory map: prefetching must be stopped if we read the last
|
||||||
|
+ * byte of device (device size - fifo size). like device size is not
|
||||||
|
+ * knows, the prefetching is always stop.
|
||||||
|
+ */
|
||||||
|
+ if (err || qspi->fmode == CCR_FMODE_MM)
|
||||||
|
+ goto abort;
|
||||||
|
+
|
||||||
|
+ /* wait end of tx in indirect mode */
|
||||||
|
+ err = stm32_qspi_wait_cmd(qspi, op);
|
||||||
|
+ if (err)
|
||||||
|
+ goto abort;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+abort:
|
||||||
|
+ cr = readl_relaxed(qspi->io_base + QSPI_CR) | CR_ABORT;
|
||||||
|
+ writel_relaxed(cr, qspi->io_base + QSPI_CR);
|
||||||
|
+
|
||||||
|
+ /* wait clear of abort bit by hw */
|
||||||
|
+ timeout = readl_relaxed_poll_timeout_atomic(qspi->io_base + QSPI_CR,
|
||||||
|
+ cr, !(cr & CR_ABORT), 1,
|
||||||
|
+ STM32_ABT_TIMEOUT_US);
|
||||||
|
+
|
||||||
|
+ writel_relaxed(FCR_CTCF, qspi->io_base + QSPI_FCR);
|
||||||
|
+
|
||||||
|
+ if (err || timeout)
|
||||||
|
+ dev_err(qspi->dev, "%s err:%d abort timeout:%d\n",
|
||||||
|
+ __func__, err, timeout);
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||||
|
+{
|
||||||
|
+ struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ mutex_lock(&qspi->lock);
|
||||||
|
+ ret = stm32_qspi_send(mem, op);
|
||||||
|
+ mutex_unlock(&qspi->lock);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_setup(struct spi_device *spi)
|
||||||
|
+{
|
||||||
|
+ struct spi_controller *ctrl = spi->master;
|
||||||
|
+ struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl);
|
||||||
|
+ struct stm32_qspi_flash *flash;
|
||||||
|
+ u32 presc;
|
||||||
|
+
|
||||||
|
+ if (ctrl->busy)
|
||||||
|
+ return -EBUSY;
|
||||||
|
+
|
||||||
|
+ if (!spi->max_speed_hz)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ presc = DIV_ROUND_UP(qspi->clk_rate, spi->max_speed_hz) - 1;
|
||||||
|
+
|
||||||
|
+ flash = &qspi->flash[spi->chip_select];
|
||||||
|
+ flash->qspi = qspi;
|
||||||
|
+ flash->cs = spi->chip_select;
|
||||||
|
+ flash->presc = presc;
|
||||||
|
+
|
||||||
|
+ mutex_lock(&qspi->lock);
|
||||||
|
+ qspi->cr_reg = FIELD_PREP(CR_FTHRES_MASK, 3) | CR_SSHIFT | CR_EN;
|
||||||
|
+ writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
|
||||||
|
+
|
||||||
|
+ /* set dcr fsize to max address */
|
||||||
|
+ qspi->dcr_reg = DCR_FSIZE_MASK;
|
||||||
|
+ writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
|
||||||
|
+ mutex_unlock(&qspi->lock);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * no special host constraint, so use default spi_mem_default_supports_op
|
||||||
|
+ * to check supported mode.
|
||||||
|
+ */
|
||||||
|
+static const struct spi_controller_mem_ops stm32_qspi_mem_ops = {
|
||||||
|
+ .exec_op = stm32_qspi_exec_op,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static void stm32_qspi_release(struct stm32_qspi *qspi)
|
||||||
|
+{
|
||||||
|
+ /* disable qspi */
|
||||||
|
+ writel_relaxed(0, qspi->io_base + QSPI_CR);
|
||||||
|
+ mutex_destroy(&qspi->lock);
|
||||||
|
+ clk_disable_unprepare(qspi->clk);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct device *dev = &pdev->dev;
|
||||||
|
+ struct spi_controller *ctrl;
|
||||||
|
+ struct reset_control *rstc;
|
||||||
|
+ struct stm32_qspi *qspi;
|
||||||
|
+ struct resource *res;
|
||||||
|
+ int ret, irq;
|
||||||
|
+
|
||||||
|
+ ctrl = spi_alloc_master(dev, sizeof(*qspi));
|
||||||
|
+ if (!ctrl)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ qspi = spi_controller_get_devdata(ctrl);
|
||||||
|
+
|
||||||
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi");
|
||||||
|
+ qspi->io_base = devm_ioremap_resource(dev, res);
|
||||||
|
+ if (IS_ERR(qspi->io_base))
|
||||||
|
+ return PTR_ERR(qspi->io_base);
|
||||||
|
+
|
||||||
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm");
|
||||||
|
+ qspi->mm_base = devm_ioremap_resource(dev, res);
|
||||||
|
+ if (IS_ERR(qspi->mm_base))
|
||||||
|
+ return PTR_ERR(qspi->mm_base);
|
||||||
|
+
|
||||||
|
+ qspi->mm_size = resource_size(res);
|
||||||
|
+ if (qspi->mm_size > STM32_QSPI_MAX_MMAP_SZ)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ irq = platform_get_irq(pdev, 0);
|
||||||
|
+ ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0,
|
||||||
|
+ dev_name(dev), qspi);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(dev, "failed to request irq\n");
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ init_completion(&qspi->data_completion);
|
||||||
|
+
|
||||||
|
+ qspi->clk = devm_clk_get(dev, NULL);
|
||||||
|
+ if (IS_ERR(qspi->clk))
|
||||||
|
+ return PTR_ERR(qspi->clk);
|
||||||
|
+
|
||||||
|
+ qspi->clk_rate = clk_get_rate(qspi->clk);
|
||||||
|
+ if (!qspi->clk_rate)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ ret = clk_prepare_enable(qspi->clk);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(dev, "can not enable the clock\n");
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rstc = devm_reset_control_get_exclusive(dev, NULL);
|
||||||
|
+ if (!IS_ERR(rstc)) {
|
||||||
|
+ reset_control_assert(rstc);
|
||||||
|
+ udelay(2);
|
||||||
|
+ reset_control_deassert(rstc);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ qspi->dev = dev;
|
||||||
|
+ platform_set_drvdata(pdev, qspi);
|
||||||
|
+ mutex_init(&qspi->lock);
|
||||||
|
+
|
||||||
|
+ ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD
|
||||||
|
+ | SPI_TX_DUAL | SPI_TX_QUAD;
|
||||||
|
+ ctrl->setup = stm32_qspi_setup;
|
||||||
|
+ ctrl->bus_num = -1;
|
||||||
|
+ ctrl->mem_ops = &stm32_qspi_mem_ops;
|
||||||
|
+ ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP;
|
||||||
|
+ ctrl->dev.of_node = dev->of_node;
|
||||||
|
+
|
||||||
|
+ ret = devm_spi_register_master(dev, ctrl);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto err_spi_register;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+err_spi_register:
|
||||||
|
+ stm32_qspi_release(qspi);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_qspi_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_qspi *qspi = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ stm32_qspi_release(qspi);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __maybe_unused stm32_qspi_suspend(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_qspi *qspi = dev_get_drvdata(dev);
|
||||||
|
+
|
||||||
|
+ clk_disable_unprepare(qspi->clk);
|
||||||
|
+ pinctrl_pm_select_sleep_state(dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __maybe_unused stm32_qspi_resume(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_qspi *qspi = dev_get_drvdata(dev);
|
||||||
|
+
|
||||||
|
+ pinctrl_pm_select_default_state(dev);
|
||||||
|
+ clk_prepare_enable(qspi->clk);
|
||||||
|
+
|
||||||
|
+ writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
|
||||||
|
+ writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+SIMPLE_DEV_PM_OPS(stm32_qspi_pm_ops, stm32_qspi_suspend, stm32_qspi_resume);
|
||||||
|
+
|
||||||
|
+static const struct of_device_id stm32_qspi_match[] = {
|
||||||
|
+ {.compatible = "st,stm32f469-qspi"},
|
||||||
|
+ {}
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, stm32_qspi_match);
|
||||||
|
+
|
||||||
|
+static struct platform_driver stm32_qspi_driver = {
|
||||||
|
+ .probe = stm32_qspi_probe,
|
||||||
|
+ .remove = stm32_qspi_remove,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "stm32-qspi",
|
||||||
|
+ .of_match_table = stm32_qspi_match,
|
||||||
|
+ .pm = &stm32_qspi_pm_ops,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+module_platform_driver(stm32_qspi_driver);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
|
||||||
|
+MODULE_DESCRIPTION("STMicroelectronics STM32 quad spi driver");
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,558 @@
|
||||||
|
From ae7d85a994c77d68e3e6a20a24160a5010ba42cc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Tue, 13 Nov 2018 12:32:03 +0100
|
||||||
|
Subject: [PATCH 17/52] ARM: stm32mp1-r0-rc1: DEFCONFIG
|
||||||
|
|
||||||
|
---
|
||||||
|
.../arm/configs/fragment-01-multiv7_cleanup.config | 69 +++
|
||||||
|
arch/arm/configs/fragment-02-multiv7_addons.config | 462 +++++++++++++++++++++
|
||||||
|
2 files changed, 531 insertions(+)
|
||||||
|
create mode 100644 arch/arm/configs/fragment-01-multiv7_cleanup.config
|
||||||
|
create mode 100644 arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
|
||||||
|
diff --git a/arch/arm/configs/fragment-01-multiv7_cleanup.config b/arch/arm/configs/fragment-01-multiv7_cleanup.config
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..22f6ffb
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/arch/arm/configs/fragment-01-multiv7_cleanup.config
|
||||||
|
@@ -0,0 +1,69 @@
|
||||||
|
+#
|
||||||
|
+# CPU Core family selection
|
||||||
|
+#
|
||||||
|
+# CONFIG_ARCH_VIRT is not set
|
||||||
|
+# CONFIG_ARCH_MVEBU is not set
|
||||||
|
+# CONFIG_ARCH_ALPINE is not set
|
||||||
|
+# CONFIG_ARCH_ARTPEC is not set
|
||||||
|
+# CONFIG_ARCH_AT91 is not set
|
||||||
|
+# CONFIG_ARCH_BCM is not set
|
||||||
|
+# CONFIG_ARCH_BERLIN is not set
|
||||||
|
+# CONFIG_ARCH_DIGICOLOR is not set
|
||||||
|
+# CONFIG_ARCH_HIGHBANK is not set
|
||||||
|
+# CONFIG_ARCH_HISI is not set
|
||||||
|
+# CONFIG_ARCH_KEYSTONE is not set
|
||||||
|
+# CONFIG_ARCH_MESON is not set
|
||||||
|
+# CONFIG_ARCH_MXC is not set
|
||||||
|
+# CONFIG_ARCH_MEDIATEK is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# TI OMAP/AM/DM/DRA Family
|
||||||
|
+#
|
||||||
|
+# CONFIG_ARCH_OMAP3 is not set
|
||||||
|
+# CONFIG_ARCH_OMAP4 is not set
|
||||||
|
+# CONFIG_SOC_OMAP5 is not set
|
||||||
|
+# CONFIG_SOC_AM33XX is not set
|
||||||
|
+# CONFIG_SOC_AM43XX is not set
|
||||||
|
+# CONFIG_SOC_DRA7XX is not set
|
||||||
|
+# CONFIG_ARCH_MMP is not set
|
||||||
|
+# CONFIG_ARCH_QCOM is not set
|
||||||
|
+# CONFIG_ARCH_REALVIEW is not set
|
||||||
|
+# CONFIG_ARCH_ROCKCHIP is not set
|
||||||
|
+# CONFIG_ARCH_SOCFPGA is not set
|
||||||
|
+# CONFIG_PLAT_SPEAR is not set
|
||||||
|
+# CONFIG_ARCH_STI is not set
|
||||||
|
+# CONFIG_ARCH_S5PV210 is not set
|
||||||
|
+# CONFIG_ARCH_EXYNOS is not set
|
||||||
|
+# CONFIG_ARCH_RENESAS is not set
|
||||||
|
+# CONFIG_ARCH_SUNXI is not set
|
||||||
|
+# CONFIG_ARCH_SIRF is not set
|
||||||
|
+# CONFIG_ARCH_TANGO is not set
|
||||||
|
+# CONFIG_ARCH_TEGRA is not set
|
||||||
|
+# CONFIG_ARCH_UNIPHIER is not set
|
||||||
|
+# CONFIG_ARCH_U8500 is not set
|
||||||
|
+# CONFIG_ARCH_VEXPRESS is not set
|
||||||
|
+# CONFIG_ARCH_WM8850 is not set
|
||||||
|
+# CONFIG_ARCH_ZX is not set
|
||||||
|
+# CONFIG_ARCH_ZYNQ is not set
|
||||||
|
+
|
||||||
|
+# CONFIG_CAN_RCAR is not set
|
||||||
|
+# CONFIG_GPIO_PCA953X is not set
|
||||||
|
+# CONFIG_GPIO_PCF857X is not set
|
||||||
|
+# CONFIG_STAGING is not set
|
||||||
|
+# CONFIG_CHROME_PLATFORMS is not set
|
||||||
|
+# CONFIG_SOC_BRCMSTB is not set
|
||||||
|
+# CONFIG_SUNXI_SRAM is not set
|
||||||
|
+# CONFIG_SOC_TI is not set
|
||||||
|
+# CONFIG_PM_DEVFREQ is not set
|
||||||
|
+# CONFIG_EXTCON is not set
|
||||||
|
+# CONFIG_MEMORY is not set
|
||||||
|
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
||||||
|
+# CONFIG_ENABLE_MUST_CHECK is not set
|
||||||
|
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
|
||||||
|
+# CONFIG_LOCKUP_DETECTOR is not set
|
||||||
|
+# CONFIG_DETECT_HUNG_TASK is not set
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..c91840c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
@@ -0,0 +1,462 @@
|
||||||
|
+#
|
||||||
|
+# General setup
|
||||||
|
+#
|
||||||
|
+CONFIG_POSIX_MQUEUE=y
|
||||||
|
+CONFIG_USELIB=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# RCU Subsystem
|
||||||
|
+#
|
||||||
|
+# allow user to access kernel config through /proc/config.gz
|
||||||
|
+CONFIG_IKCONFIG=y
|
||||||
|
+CONFIG_IKCONFIG_PROC=y
|
||||||
|
+CONFIG_LOG_BUF_SHIFT=16
|
||||||
|
+CONFIG_MEMCG=y
|
||||||
|
+CONFIG_NAMESPACES=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Kernel Performance Events And Counters
|
||||||
|
+#
|
||||||
|
+CONFIG_PROFILING=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# CPU Core family selection
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Processor Features
|
||||||
|
+#
|
||||||
|
+# CONFIG_CACHE_L2X0 is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Bus support
|
||||||
|
+#
|
||||||
|
+# CONFIG_PCI is not set
|
||||||
|
+# CONFIG_PCI_DOMAINS_GENERIC is not set
|
||||||
|
+# CONFIG_PCI_SYSCALL is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Kernel Features
|
||||||
|
+#
|
||||||
|
+CONFIG_MCPM=y
|
||||||
|
+CONFIG_NR_CPUS=4
|
||||||
|
+# CONFIG_PREEMPT_NONE is not set
|
||||||
|
+CONFIG_PREEMPT=y
|
||||||
|
+CONFIG_PREEMPT_COUNT=y
|
||||||
|
+CONFIG_AEABI=y
|
||||||
|
+CONFIG_HIGHMEM=y
|
||||||
|
+CONFIG_FORCE_MAX_ZONEORDER=12
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Boot options
|
||||||
|
+#
|
||||||
|
+# CONFIG_ATAGS is not set
|
||||||
|
+CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||||
|
+CONFIG_ZBOOT_ROM_BSS=0x0
|
||||||
|
+# CONFIG_KEXEC is not set
|
||||||
|
+# CONFIG_EFI is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# CPU Power Management
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# CPU Frequency scaling
|
||||||
|
+#
|
||||||
|
+# CONFIG_CPU_FREQ is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# CPU Idle
|
||||||
|
+#
|
||||||
|
+# CONFIG_CPU_IDLE is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Floating point emulation
|
||||||
|
+#
|
||||||
|
+CONFIG_VFP=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Networking options
|
||||||
|
+#
|
||||||
|
+CONFIG_DNS_RESOLVER=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# CAN Device Drivers
|
||||||
|
+#
|
||||||
|
+CONFIG_CAN_M_CAN=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# CAN SPI interfaces
|
||||||
|
+#
|
||||||
|
+# CONFIG_CAN_MCP251X is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# CAN USB interfaces
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Bluetooth device drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Device Drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Generic Driver Options
|
||||||
|
+#
|
||||||
|
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Default contiguous memory area size:
|
||||||
|
+#
|
||||||
|
+CONFIG_CMA_SIZE_MBYTES=128
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Disk-On-Chip Device Drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# LPDDR & LPDDR2 PCM memory drivers
|
||||||
|
+#
|
||||||
|
+CONFIG_OF_RESOLVE=y
|
||||||
|
+CONFIG_OF_OVERLAY=y
|
||||||
|
+CONFIG_OF_CONFIGFS=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Misc devices
|
||||||
|
+#
|
||||||
|
+CONFIG_SRAM=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# SCSI support type (disk, tape, CD-ROM)
|
||||||
|
+#
|
||||||
|
+CONFIG_CHR_DEV_SG=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# MII PHY device drivers
|
||||||
|
+#
|
||||||
|
+# CONFIG_REALTEK_PHY is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Input Device Drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Character devices
|
||||||
|
+#
|
||||||
|
+CONFIG_SERIAL_NONSTANDARD=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Serial drivers
|
||||||
|
+#
|
||||||
|
+# CONFIG_SERIAL_8250 is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Non-8250 serial port support
|
||||||
|
+#
|
||||||
|
+# CONFIG_SERIAL_BCM63XX is not set
|
||||||
|
+# CONFIG_SERIAL_XILINX_PS_UART is not set
|
||||||
|
+# CONFIG_SERIAL_FSL_LPUART is not set
|
||||||
|
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
|
||||||
|
+# CONFIG_SERIAL_ST_ASC is not set
|
||||||
|
+# CONFIG_VIRTIO_CONSOLE is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# I2C Hardware Bus support
|
||||||
|
+#
|
||||||
|
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
|
||||||
|
+# CONFIG_I2C_EMEV2 is not set
|
||||||
|
+# CONFIG_I2C_GPIO is not set
|
||||||
|
+# CONFIG_I2C_RK3X is not set
|
||||||
|
+# CONFIG_I2C_XILINX is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Other I2C/SMBus bus drivers
|
||||||
|
+#
|
||||||
|
+# CONFIG_I2C_SLAVE_EEPROM is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# SPI Master Controller Drivers
|
||||||
|
+#
|
||||||
|
+CONFIG_SPI_STM32_QSPI=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Pin controllers
|
||||||
|
+#
|
||||||
|
+CONFIG_PINCTRL_STMFX=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Memory mapped GPIO drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# USB GPIO expanders
|
||||||
|
+#
|
||||||
|
+# CONFIG_POWER_AVS is not set
|
||||||
|
+CONFIG_POWER_RESET=y
|
||||||
|
+CONFIG_POWER_RESET_SYSCON=y
|
||||||
|
+CONFIG_SYSCON_REBOOT_MODE=y
|
||||||
|
+# CONFIG_POWER_SUPPLY is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Native drivers
|
||||||
|
+#
|
||||||
|
+CONFIG_SENSORS_IIO_HWMON=y
|
||||||
|
+CONFIG_THERMAL=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STMicroelectronics thermal drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Watchdog Device Drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Sonics Silicon Backplane
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Multifunction device drivers
|
||||||
|
+#
|
||||||
|
+CONFIG_PROTECTION_CONSUMER=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STMicroelectronics STMPE Interface Drivers
|
||||||
|
+#
|
||||||
|
+# CONFIG_REGULATOR_WM8994 is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Multimedia core support
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# USB HDMI CEC adapters
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
|
||||||
|
+#
|
||||||
|
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Camera sensor devices
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Graphics support
|
||||||
|
+#
|
||||||
|
+# to solve issue on DK2 screen
|
||||||
|
+# CONFIG_DRM_FBDEV_EMULATION is not set
|
||||||
|
+# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Sub-drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Display Panels
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Display Interface Bridges
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Frame buffer hardware drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Console display driver support
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# HD-Audio
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# CODEC drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# USB Device Class drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# also be needed; see USB_STORAGE Help for more info
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# USB Imaging devices
|
||||||
|
+#
|
||||||
|
+# CONFIG_USB_MUSB_HDRC is not set
|
||||||
|
+# CONFIG_USB_DWC3 is not set
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# USB Physical Layer drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Platform Support
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Virtio drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Clock Source drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Rpmsg drivers
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# File systems
|
||||||
|
+#
|
||||||
|
+CONFIG_OVERLAY_FS=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Pseudo filesystems
|
||||||
|
+#
|
||||||
|
+CONFIG_TMPFS=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Kernel hacking
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# printk and dmesg options
|
||||||
|
+#
|
||||||
|
+CONFIG_DYNAMIC_DEBUG=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Compile-time checks and compiler options
|
||||||
|
+#
|
||||||
|
+CONFIG_DEBUG_INFO=y
|
||||||
|
+CONFIG_GDB_SCRIPTS=y
|
||||||
|
+CONFIG_DEBUG_SECTION_MISMATCH=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Debug Lockups and Hangs
|
||||||
|
+#
|
||||||
|
+# CONFIG_SCHED_DEBUG is not set
|
||||||
|
+CONFIG_DEBUG_PREEMPT=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Runtime Testing
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+# Security options
|
||||||
|
+#
|
||||||
|
+CONFIG_KEYS=y
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Library routines
|
||||||
|
+#
|
||||||
|
+CONFIG_CRC_ITU_T=m
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 PWR
|
||||||
|
+#
|
||||||
|
+CONFIG_MFD_STM32MP1_PWR=y
|
||||||
|
+CONFIG_REGULATOR_STM32_PWR=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STPMIC1
|
||||||
|
+#
|
||||||
|
+CONFIG_MFD_STPMIC1=y
|
||||||
|
+CONFIG_REGULATOR_STPMIC1=y
|
||||||
|
+CONFIG_STPMIC1_WATCHDOG=y
|
||||||
|
+CONFIG_INPUT_STPMIC1_ONKEY=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 TIMER
|
||||||
|
+#
|
||||||
|
+CONFIG_MFD_STM32_TIMERS=y
|
||||||
|
+CONFIG_IIO_STM32_TIMER_TRIGGER=y
|
||||||
|
+CONFIG_PWM_STM32=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 LPTIMER
|
||||||
|
+#
|
||||||
|
+CONFIG_MFD_STM32_LPTIMER=y
|
||||||
|
+CONFIG_PWM_STM32_LP=y
|
||||||
|
+CONFIG_IIO_STM32_LPTIMER_TRIGGER=y
|
||||||
|
+CONFIG_STM32_LPTIMER_CNT=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 DFSDM
|
||||||
|
+#
|
||||||
|
+CONFIG_SD_ADC_MODULATOR=y
|
||||||
|
+CONFIG_STM32_DFSDM_ADC=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# FMC2
|
||||||
|
+#
|
||||||
|
+CONFIG_MTD_NAND_STM32_FMC2=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 VREFBUF
|
||||||
|
+#
|
||||||
|
+CONFIG_REGULATOR_STM32_VREFBUF=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 BSEC NVMEM
|
||||||
|
+#
|
||||||
|
+CONFIG_NVMEM_STM32_ROMEM=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 IPCC
|
||||||
|
+#
|
||||||
|
+CONFIG_STM32_IPCC=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# RPMSG_TTY
|
||||||
|
+#
|
||||||
|
+CONFIG_RPMSG_VIRTIO=y
|
||||||
|
+CONFIG_RPMSG_TTY=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# RPMSG client sample
|
||||||
|
+#
|
||||||
|
+CONFIG_SAMPLES=y
|
||||||
|
+CONFIG_SAMPLE_RPMSG_CLIENT=m
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 RPROC
|
||||||
|
+#
|
||||||
|
+# CONFIG_MAILBOX is not set
|
||||||
|
+CONFIG_REMOTEPROC=y
|
||||||
|
+CONFIG_STM32_RPROC=y
|
||||||
|
+CONFIG_RPMSG_VIRTIO=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Cryptographic
|
||||||
|
+#
|
||||||
|
+CONFIG_CRYPTO_DEV_STM32_CRC=y
|
||||||
|
+CONFIG_CRYPTO_DEV_STM32_HASH=y
|
||||||
|
+CONFIG_CRYPTO_DEV_STM32_CRYP=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 ADC
|
||||||
|
+#
|
||||||
|
+CONFIG_STM32_ADC_CORE=y
|
||||||
|
+CONFIG_STM32_ADC=y
|
||||||
|
+CONFIG_STM32_ADC_TEMP=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 DAC
|
||||||
|
+#
|
||||||
|
+CONFIG_STM32_DAC=y
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,984 @@
|
||||||
|
From 8f36e7dd830ff5d93e240a62da54ea2afc580cca Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||||
|
Date: Mon, 26 Nov 2018 14:39:57 +0100
|
||||||
|
Subject: [PATCH 20/52] ARM-stm32mp1-r0-rc2-MEDIA
|
||||||
|
|
||||||
|
---
|
||||||
|
.../devicetree/bindings/media/video-interfaces.txt | 2 +
|
||||||
|
drivers/media/i2c/ov5640.c | 663 ++++++++++++---------
|
||||||
|
drivers/media/platform/stm32/stm32-dcmi.c | 41 +-
|
||||||
|
drivers/media/v4l2-core/v4l2-fwnode.c | 3 +
|
||||||
|
include/media/v4l2-fwnode.h | 2 +
|
||||||
|
5 files changed, 413 insertions(+), 298 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/media/video-interfaces.txt b/Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||||
|
index baf9d97..fa4c112 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||||
|
@@ -147,6 +147,8 @@ Optional endpoint properties
|
||||||
|
as 0 (normal). This property is valid for serial busses only.
|
||||||
|
- strobe: Whether the clock signal is used as clock (0) or strobe (1). Used
|
||||||
|
with CCP2, for instance.
|
||||||
|
+- pclk-max-frequency: maximum pixel clock frequency admissible by video
|
||||||
|
+ host interface.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
|
||||||
|
index 30b15e9..27b75e7 100644
|
||||||
|
--- a/drivers/media/i2c/ov5640.c
|
||||||
|
+++ b/drivers/media/i2c/ov5640.c
|
||||||
|
@@ -66,6 +66,7 @@
|
||||||
|
#define OV5640_REG_TIMING_VTS 0x380e
|
||||||
|
#define OV5640_REG_TIMING_TC_REG20 0x3820
|
||||||
|
#define OV5640_REG_TIMING_TC_REG21 0x3821
|
||||||
|
+#define OV5640_REG_DVP_PCLK_DIVIDER 0x3824
|
||||||
|
#define OV5640_REG_AEC_CTRL00 0x3a00
|
||||||
|
#define OV5640_REG_AEC_B50_STEP 0x3a08
|
||||||
|
#define OV5640_REG_AEC_B60_STEP 0x3a0a
|
||||||
|
@@ -261,8 +262,8 @@ static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
|
||||||
|
static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
|
||||||
|
{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
|
||||||
|
{0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
|
||||||
|
- {0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
|
||||||
|
- {0x3037, 0x13, 0, 0}, {0x3630, 0x36, 0, 0},
|
||||||
|
+ {0x3034, 0x18, 0, 0},
|
||||||
|
+ {0x3630, 0x36, 0, 0},
|
||||||
|
{0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
|
||||||
|
{0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
|
||||||
|
{0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
|
||||||
|
@@ -344,85 +345,8 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
|
||||||
|
{0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
|
||||||
|
- {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
- {0x3814, 0x31, 0, 0},
|
||||||
|
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||||
|
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||||
|
- {0x3810, 0x00, 0, 0},
|
||||||
|
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||||
|
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||||
|
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||||
|
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
|
||||||
|
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
|
||||||
|
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
- {0x3814, 0x31, 0, 0},
|
||||||
|
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||||
|
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||||
|
- {0x3810, 0x00, 0, 0},
|
||||||
|
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||||
|
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||||
|
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||||
|
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||||
|
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
|
||||||
|
- {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
- {0x3814, 0x31, 0, 0},
|
||||||
|
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||||
|
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||||
|
- {0x3810, 0x00, 0, 0},
|
||||||
|
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||||
|
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||||
|
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||||
|
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
|
||||||
|
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
|
||||||
|
- {0x3035, 0x12, 0, 0},
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
|
||||||
|
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
- {0x3814, 0x31, 0, 0},
|
||||||
|
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||||
|
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||||
|
- {0x3810, 0x00, 0, 0},
|
||||||
|
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||||
|
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||||
|
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||||
|
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||||
|
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
|
||||||
|
- {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
+static const struct reg_value ov5640_setting_VGA_640_480[] = {
|
||||||
|
+ {0x3c07, 0x08, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3814, 0x31, 0, 0},
|
||||||
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
@@ -436,12 +360,12 @@ static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
|
||||||
|
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
+ {0x4407, 0x04, 0, 0},
|
||||||
|
+ {0x5001, 0xa3, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
|
||||||
|
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
+static const struct reg_value ov5640_setting_XGA_1024_768[] = {
|
||||||
|
+ {0x3c07, 0x08, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3814, 0x31, 0, 0},
|
||||||
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
@@ -455,12 +379,11 @@ static const struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
|
||||||
|
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
|
||||||
|
- {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
+static const struct reg_value ov5640_setting_QVGA_320_240[] = {
|
||||||
|
+ {0x3c07, 0x08, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3814, 0x31, 0, 0},
|
||||||
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
@@ -474,12 +397,11 @@ static const struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
|
||||||
|
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
|
||||||
|
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
+static const struct reg_value ov5640_setting_QCIF_176_144[] = {
|
||||||
|
+ {0x3c07, 0x08, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3814, 0x31, 0, 0},
|
||||||
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
@@ -493,12 +415,11 @@ static const struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
|
||||||
|
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
|
||||||
|
- {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
+static const struct reg_value ov5640_setting_NTSC_720_480[] = {
|
||||||
|
+ {0x3c07, 0x08, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3814, 0x31, 0, 0},
|
||||||
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
@@ -512,31 +433,11 @@ static const struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
|
||||||
|
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
|
||||||
|
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
- {0x3814, 0x31, 0, 0},
|
||||||
|
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||||
|
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||||
|
- {0x3810, 0x00, 0, 0},
|
||||||
|
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
|
||||||
|
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||||
|
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||||
|
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||||
|
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
|
||||||
|
- {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
+static const struct reg_value ov5640_setting_PAL_720_576[] = {
|
||||||
|
+ {0x3c07, 0x08, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3814, 0x31, 0, 0},
|
||||||
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
@@ -550,52 +451,11 @@ static const struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
|
||||||
|
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
|
||||||
|
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
- {0x3814, 0x31, 0, 0},
|
||||||
|
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||||
|
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||||
|
- {0x3810, 0x00, 0, 0},
|
||||||
|
- {0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||||
|
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||||
|
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||||
|
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||||
|
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
|
||||||
|
- {0x3008, 0x42, 0, 0},
|
||||||
|
- {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
|
||||||
|
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
- {0x3814, 0x31, 0, 0},
|
||||||
|
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
- {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||||
|
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
|
||||||
|
- {0x3810, 0x00, 0, 0},
|
||||||
|
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
|
||||||
|
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||||
|
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
|
||||||
|
- {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
|
||||||
|
- {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
|
||||||
|
- {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
|
||||||
|
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
|
||||||
|
- {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, {0x4005, 0x1a, 0, 0},
|
||||||
|
- {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
|
||||||
|
- {0x3035, 0x41, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
|
||||||
|
+static const struct reg_value ov5640_setting_720P_1280_720[] = {
|
||||||
|
+ {0x3c07, 0x07, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3814, 0x31, 0, 0},
|
||||||
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
@@ -608,47 +468,13 @@ static const struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
|
||||||
|
{0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
|
||||||
|
{0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
|
||||||
|
{0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
|
||||||
|
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
|
||||||
|
- {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
|
||||||
|
- {0x3008, 0x42, 0, 0},
|
||||||
|
- {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
- {0x3814, 0x11, 0, 0},
|
||||||
|
- {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
- {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||||
|
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
|
||||||
|
- {0x3810, 0x00, 0, 0},
|
||||||
|
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
|
||||||
|
- {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
|
||||||
|
- {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||||
|
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||||
|
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
- {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x11, 0, 0},
|
||||||
|
- {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
|
||||||
|
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
- {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
|
||||||
|
- {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
|
||||||
|
- {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0},
|
||||||
|
- {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||||
|
- {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
|
||||||
|
- {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
|
||||||
|
- {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
|
||||||
|
- {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
|
||||||
|
- {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
|
||||||
|
- {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0},
|
||||||
|
- {0x3503, 0, 0, 0},
|
||||||
|
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
||||||
|
+static const struct reg_value ov5640_setting_1080P_1920_1080[] = {
|
||||||
|
{0x3008, 0x42, 0, 0},
|
||||||
|
- {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
+ {0x3c07, 0x08, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3814, 0x11, 0, 0},
|
||||||
|
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
@@ -662,9 +488,9 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
||||||
|
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
{0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x21, 0, 0},
|
||||||
|
- {0x3036, 0x54, 0, 1}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
|
||||||
|
+ {0x4407, 0x04, 0, 0},
|
||||||
|
+ {0x5001, 0x83, 0, 0},
|
||||||
|
+ {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
|
||||||
|
{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
|
||||||
|
@@ -674,12 +500,11 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
||||||
|
{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
|
||||||
|
{0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
|
||||||
|
{0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
|
||||||
|
- {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
|
||||||
|
{0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
|
||||||
|
- {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||||
|
+static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
|
||||||
|
+ {0x3c07, 0x08, 0, 0},
|
||||||
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||||
|
{0x3814, 0x11, 0, 0},
|
||||||
|
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||||
|
@@ -693,8 +518,8 @@ static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
|
||||||
|
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||||
|
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||||
|
{0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||||
|
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||||
|
- {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70},
|
||||||
|
+ {0x4407, 0x04, 0, 0},
|
||||||
|
+ {0x5001, 0x83, 0, 70},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* power-on sensor init reg table */
|
||||||
|
@@ -705,79 +530,43 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ov5640_mode_info
|
||||||
|
-ov5640_mode_data[OV5640_NUM_FRAMERATES][OV5640_NUM_MODES] = {
|
||||||
|
- {
|
||||||
|
- {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
|
||||||
|
- 176, 1896, 144, 984,
|
||||||
|
- ov5640_setting_15fps_QCIF_176_144,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
|
||||||
|
- {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
|
||||||
|
- 320, 1896, 240, 984,
|
||||||
|
- ov5640_setting_15fps_QVGA_320_240,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
|
||||||
|
- {OV5640_MODE_VGA_640_480, SUBSAMPLING,
|
||||||
|
- 640, 1896, 480, 1080,
|
||||||
|
- ov5640_setting_15fps_VGA_640_480,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
|
||||||
|
- {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
|
||||||
|
- 720, 1896, 480, 984,
|
||||||
|
- ov5640_setting_15fps_NTSC_720_480,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
|
||||||
|
- {OV5640_MODE_PAL_720_576, SUBSAMPLING,
|
||||||
|
- 720, 1896, 576, 984,
|
||||||
|
- ov5640_setting_15fps_PAL_720_576,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
|
||||||
|
- {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
|
||||||
|
- 1024, 1896, 768, 1080,
|
||||||
|
- ov5640_setting_15fps_XGA_1024_768,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
|
||||||
|
- {OV5640_MODE_720P_1280_720, SUBSAMPLING,
|
||||||
|
- 1280, 1892, 720, 740,
|
||||||
|
- ov5640_setting_15fps_720P_1280_720,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
|
||||||
|
- {OV5640_MODE_1080P_1920_1080, SCALING,
|
||||||
|
- 1920, 2500, 1080, 1120,
|
||||||
|
- ov5640_setting_15fps_1080P_1920_1080,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
|
||||||
|
- {OV5640_MODE_QSXGA_2592_1944, SCALING,
|
||||||
|
- 2592, 2844, 1944, 1968,
|
||||||
|
- ov5640_setting_15fps_QSXGA_2592_1944,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
|
||||||
|
- }, {
|
||||||
|
- {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
|
||||||
|
- 176, 1896, 144, 984,
|
||||||
|
- ov5640_setting_30fps_QCIF_176_144,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
|
||||||
|
- {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
|
||||||
|
- 320, 1896, 240, 984,
|
||||||
|
- ov5640_setting_30fps_QVGA_320_240,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
|
||||||
|
- {OV5640_MODE_VGA_640_480, SUBSAMPLING,
|
||||||
|
- 640, 1896, 480, 1080,
|
||||||
|
- ov5640_setting_30fps_VGA_640_480,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
|
||||||
|
- {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
|
||||||
|
- 720, 1896, 480, 984,
|
||||||
|
- ov5640_setting_30fps_NTSC_720_480,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
|
||||||
|
- {OV5640_MODE_PAL_720_576, SUBSAMPLING,
|
||||||
|
- 720, 1896, 576, 984,
|
||||||
|
- ov5640_setting_30fps_PAL_720_576,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
|
||||||
|
- {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
|
||||||
|
- 1024, 1896, 768, 1080,
|
||||||
|
- ov5640_setting_30fps_XGA_1024_768,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
|
||||||
|
- {OV5640_MODE_720P_1280_720, SUBSAMPLING,
|
||||||
|
- 1280, 1892, 720, 740,
|
||||||
|
- ov5640_setting_30fps_720P_1280_720,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
|
||||||
|
- {OV5640_MODE_1080P_1920_1080, SCALING,
|
||||||
|
- 1920, 2500, 1080, 1120,
|
||||||
|
- ov5640_setting_30fps_1080P_1920_1080,
|
||||||
|
- ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
|
||||||
|
- {OV5640_MODE_QSXGA_2592_1944, -1, 0, 0, 0, 0, NULL, 0},
|
||||||
|
- },
|
||||||
|
+ov5640_mode_data[OV5640_NUM_MODES] = {
|
||||||
|
+ {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
|
||||||
|
+ 176, 1896, 144, 984,
|
||||||
|
+ ov5640_setting_QCIF_176_144,
|
||||||
|
+ ARRAY_SIZE(ov5640_setting_QCIF_176_144)},
|
||||||
|
+ {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
|
||||||
|
+ 320, 1896, 240, 984,
|
||||||
|
+ ov5640_setting_QVGA_320_240,
|
||||||
|
+ ARRAY_SIZE(ov5640_setting_QVGA_320_240)},
|
||||||
|
+ {OV5640_MODE_VGA_640_480, SUBSAMPLING,
|
||||||
|
+ 640, 1896, 480, 1080,
|
||||||
|
+ ov5640_setting_VGA_640_480,
|
||||||
|
+ ARRAY_SIZE(ov5640_setting_VGA_640_480)},
|
||||||
|
+ {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
|
||||||
|
+ 720, 1896, 480, 984,
|
||||||
|
+ ov5640_setting_NTSC_720_480,
|
||||||
|
+ ARRAY_SIZE(ov5640_setting_NTSC_720_480)},
|
||||||
|
+ {OV5640_MODE_PAL_720_576, SUBSAMPLING,
|
||||||
|
+ 720, 1896, 576, 984,
|
||||||
|
+ ov5640_setting_PAL_720_576,
|
||||||
|
+ ARRAY_SIZE(ov5640_setting_PAL_720_576)},
|
||||||
|
+ {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
|
||||||
|
+ 1024, 1896, 768, 1080,
|
||||||
|
+ ov5640_setting_XGA_1024_768,
|
||||||
|
+ ARRAY_SIZE(ov5640_setting_XGA_1024_768)},
|
||||||
|
+ {OV5640_MODE_720P_1280_720, SUBSAMPLING,
|
||||||
|
+ 1280, 1892, 720, 740,
|
||||||
|
+ ov5640_setting_720P_1280_720,
|
||||||
|
+ ARRAY_SIZE(ov5640_setting_720P_1280_720)},
|
||||||
|
+ {OV5640_MODE_1080P_1920_1080, SCALING,
|
||||||
|
+ 1920, 2500, 1080, 1120,
|
||||||
|
+ ov5640_setting_1080P_1920_1080,
|
||||||
|
+ ARRAY_SIZE(ov5640_setting_1080P_1920_1080)},
|
||||||
|
+ {OV5640_MODE_QSXGA_2592_1944, SCALING,
|
||||||
|
+ 2592, 2844, 1944, 1968,
|
||||||
|
+ ov5640_setting_QSXGA_2592_1944,
|
||||||
|
+ ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944)},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ov5640_init_slave_id(struct ov5640_dev *sensor)
|
||||||
|
@@ -909,6 +698,272 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
|
||||||
|
return ov5640_write_reg(sensor, reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * After spending way too much time trying the various combinations, I
|
||||||
|
+ * believe the clock tree is as follows:
|
||||||
|
+ *
|
||||||
|
+ * +--------------+
|
||||||
|
+ * | Oscillator |
|
||||||
|
+ * +------+-------+
|
||||||
|
+ * |
|
||||||
|
+ * +------+-------+
|
||||||
|
+ * | System clock | - reg 0x3035, bits 4-7
|
||||||
|
+ * +------+-------+
|
||||||
|
+ * |
|
||||||
|
+ * +------+-------+ - reg 0x3036, for the multiplier
|
||||||
|
+ * | PLL | - reg 0x3037, bits 4 for the root divider
|
||||||
|
+ * +------+-------+ - reg 0x3037, bits 0-3 for the pre-divider
|
||||||
|
+ * |
|
||||||
|
+ * +------+-------+
|
||||||
|
+ * | SCLK | - reg 0x3108, bits 0-1 for the root divider
|
||||||
|
+ * +------+-------+
|
||||||
|
+ * |
|
||||||
|
+ * +------+-------+
|
||||||
|
+ * | PCLK | - reg 0x3108, bits 4-5 for the root divider
|
||||||
|
+ * +--------------+
|
||||||
|
+ *
|
||||||
|
+ * This is deviating from the datasheet at least for the register
|
||||||
|
+ * 0x3108, since it's said here that the PCLK would be clocked from
|
||||||
|
+ * the PLL. However, changing the SCLK divider value has a direct
|
||||||
|
+ * effect on the PCLK rate, which wouldn't be the case if both PCLK
|
||||||
|
+ * and SCLK were to be sourced from the PLL.
|
||||||
|
+ *
|
||||||
|
+ * These parameters also match perfectly the rate that is output by
|
||||||
|
+ * the sensor, so we shouldn't have too much factors missing (or they
|
||||||
|
+ * would be set to 1).
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * FIXME: This is supposed to be ranging from 1 to 16, but the value
|
||||||
|
+ * is always set to either 1 or 2 in the vendor kernels.
|
||||||
|
+ *
|
||||||
|
+ * Moreover issues are seen with SYSDIV set to 1:
|
||||||
|
+ * Strange behaviour is observed when requesting 75MHz pixel clock output
|
||||||
|
+ * for 1280x720 (1892x740) resolution, pixel clock is about 100MHz with
|
||||||
|
+ * blanking (register values: 0x3035=0x11 and 0x3036=0x13).
|
||||||
|
+ * When forcing system clock divider to 2, pixel clock is 75Mhz continuous
|
||||||
|
+ * as expected (register values: 0x3035=0x21 and 0x3036=0x26).
|
||||||
|
+ */
|
||||||
|
+#define OV5640_SYSDIV_MIN 2
|
||||||
|
+#define OV5640_SYSDIV_MAX 2
|
||||||
|
+
|
||||||
|
+static unsigned long ov5640_calc_sysclk(struct ov5640_dev *sensor,
|
||||||
|
+ unsigned long rate,
|
||||||
|
+ u8 *sysdiv)
|
||||||
|
+{
|
||||||
|
+ unsigned long best = ~0;
|
||||||
|
+ u8 best_sysdiv = 1;
|
||||||
|
+ u8 _sysdiv;
|
||||||
|
+
|
||||||
|
+ for (_sysdiv = OV5640_SYSDIV_MIN;
|
||||||
|
+ _sysdiv <= OV5640_SYSDIV_MAX;
|
||||||
|
+ _sysdiv++) {
|
||||||
|
+ unsigned long tmp;
|
||||||
|
+
|
||||||
|
+ tmp = sensor->xclk_freq / _sysdiv;
|
||||||
|
+ if (abs(rate - tmp) < abs(rate - best)) {
|
||||||
|
+ best = tmp;
|
||||||
|
+ best_sysdiv = _sysdiv;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (tmp == rate)
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ *sysdiv = best_sysdiv;
|
||||||
|
+ return best;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * FIXME: This is supposed to be ranging from 1 to 8, but the value is
|
||||||
|
+ * always set to 3 in the vendor kernels.
|
||||||
|
+ */
|
||||||
|
+#define OV5640_PLL_PREDIV_MIN 3
|
||||||
|
+#define OV5640_PLL_PREDIV_MAX 3
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * FIXME: This is supposed to be ranging from 1 to 2, but the value is
|
||||||
|
+ * always set to 1 in the vendor kernels.
|
||||||
|
+ */
|
||||||
|
+#define OV5640_PLL_ROOT_DIV_MIN 1
|
||||||
|
+#define OV5640_PLL_ROOT_DIV_MAX 1
|
||||||
|
+
|
||||||
|
+#define OV5640_PLL_MULT_MIN 4
|
||||||
|
+#define OV5640_PLL_MULT_MAX 252
|
||||||
|
+
|
||||||
|
+static unsigned long ov5640_calc_pll(struct ov5640_dev *sensor,
|
||||||
|
+ unsigned long rate,
|
||||||
|
+ u8 *sysdiv, u8 *prediv, u8 *rdiv, u8 *mult)
|
||||||
|
+{
|
||||||
|
+ unsigned long best = ~0;
|
||||||
|
+ u8 best_sysdiv = 1, best_prediv = 1, best_mult = 1, best_rdiv = 1;
|
||||||
|
+ u8 _prediv, _mult, _rdiv;
|
||||||
|
+
|
||||||
|
+ for (_prediv = OV5640_PLL_PREDIV_MIN;
|
||||||
|
+ _prediv <= OV5640_PLL_PREDIV_MAX;
|
||||||
|
+ _prediv++) {
|
||||||
|
+ for (_mult = OV5640_PLL_MULT_MIN;
|
||||||
|
+ _mult <= OV5640_PLL_MULT_MAX;
|
||||||
|
+ _mult++) {
|
||||||
|
+ for (_rdiv = OV5640_PLL_ROOT_DIV_MIN;
|
||||||
|
+ _rdiv <= OV5640_PLL_ROOT_DIV_MAX;
|
||||||
|
+ _rdiv++) {
|
||||||
|
+ unsigned long pll;
|
||||||
|
+ unsigned long sysclk;
|
||||||
|
+ u8 _sysdiv;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * The PLL multiplier cannot be odd if
|
||||||
|
+ * above 127.
|
||||||
|
+ */
|
||||||
|
+ if (_mult > 127 && !(_mult % 2))
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ sysclk = rate * _prediv * _rdiv / _mult;
|
||||||
|
+ sysclk = ov5640_calc_sysclk(sensor, sysclk,
|
||||||
|
+ &_sysdiv);
|
||||||
|
+
|
||||||
|
+ pll = sysclk / _rdiv / _prediv * _mult;
|
||||||
|
+ if (abs(rate - pll) < abs(rate - best)) {
|
||||||
|
+ best = pll;
|
||||||
|
+ best_sysdiv = _sysdiv;
|
||||||
|
+ best_prediv = _prediv;
|
||||||
|
+ best_mult = _mult;
|
||||||
|
+ best_rdiv = _rdiv;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (pll == rate)
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ *sysdiv = best_sysdiv;
|
||||||
|
+ *prediv = best_prediv;
|
||||||
|
+ *mult = best_mult;
|
||||||
|
+ *rdiv = best_rdiv;
|
||||||
|
+
|
||||||
|
+ return best;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * FIXME: This is supposed to be ranging from 1 to 8, but the value is
|
||||||
|
+ * always set to 1 in the vendor kernels.
|
||||||
|
+ */
|
||||||
|
+#define OV5640_PCLK_ROOT_DIV_MIN 1
|
||||||
|
+#define OV5640_PCLK_ROOT_DIV_MAX 1
|
||||||
|
+
|
||||||
|
+static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
|
||||||
|
+ unsigned long rate,
|
||||||
|
+ u8 *sysdiv, u8 *prediv, u8 *pll_rdiv,
|
||||||
|
+ u8 *mult, u8 *pclk_rdiv)
|
||||||
|
+{
|
||||||
|
+ unsigned long best = ~0;
|
||||||
|
+ u8 best_sysdiv = 1, best_prediv = 1, best_mult = 1, best_pll_rdiv = 1;
|
||||||
|
+ u8 best_pclk_rdiv = 1;
|
||||||
|
+ u8 _pclk_rdiv;
|
||||||
|
+
|
||||||
|
+ for (_pclk_rdiv = OV5640_PCLK_ROOT_DIV_MIN;
|
||||||
|
+ _pclk_rdiv <= OV5640_PCLK_ROOT_DIV_MAX;
|
||||||
|
+ _pclk_rdiv <<= 1) {
|
||||||
|
+ unsigned long pll, pclk;
|
||||||
|
+ u8 sysdiv, prediv, mult, pll_rdiv;
|
||||||
|
+
|
||||||
|
+ pll = rate * OV5640_SCLK_ROOT_DIVIDER_DEFAULT * _pclk_rdiv;
|
||||||
|
+ pll = ov5640_calc_pll(sensor, pll, &sysdiv, &prediv, &pll_rdiv,
|
||||||
|
+ &mult);
|
||||||
|
+
|
||||||
|
+ pclk = pll / OV5640_SCLK_ROOT_DIVIDER_DEFAULT / _pclk_rdiv;
|
||||||
|
+ if (abs(rate - pclk) < abs(rate - best)) {
|
||||||
|
+ best = pclk;
|
||||||
|
+ best_sysdiv = sysdiv;
|
||||||
|
+ best_prediv = prediv;
|
||||||
|
+ best_pll_rdiv = pll_rdiv;
|
||||||
|
+ best_pclk_rdiv = _pclk_rdiv;
|
||||||
|
+ best_mult = mult;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (pclk == rate)
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ *sysdiv = best_sysdiv;
|
||||||
|
+ *prediv = best_prediv;
|
||||||
|
+ *pll_rdiv = best_pll_rdiv;
|
||||||
|
+ *mult = best_mult;
|
||||||
|
+ *pclk_rdiv = best_pclk_rdiv;
|
||||||
|
+ return best;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor,
|
||||||
|
+ const struct ov5640_mode_info *mode,
|
||||||
|
+ unsigned long rate)
|
||||||
|
+{
|
||||||
|
+ u8 sysdiv, prediv, mult, pll_rdiv, pclk_rdiv;
|
||||||
|
+ int ret;
|
||||||
|
+ struct i2c_client *client = sensor->i2c_client;
|
||||||
|
+ u8 dvp_pclk_divider = mode->hact < 1024 ? 2 : 1;//FIXME
|
||||||
|
+ unsigned int pclk_freq, max_pclk_freq;
|
||||||
|
+
|
||||||
|
+ ret = ov5640_write_reg(sensor, OV5640_REG_DVP_PCLK_DIVIDER,
|
||||||
|
+ dvp_pclk_divider);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ pclk_freq = rate / dvp_pclk_divider;
|
||||||
|
+ max_pclk_freq = sensor->ep.bus.parallel.pclk_max_frequency;
|
||||||
|
+
|
||||||
|
+ /* clip rate according to optional maximum pixel clock limit */
|
||||||
|
+ if (max_pclk_freq && (pclk_freq > max_pclk_freq)) {
|
||||||
|
+ rate = max_pclk_freq * dvp_pclk_divider;
|
||||||
|
+ dev_dbg(&client->dev, "DVP pixel clock too high (%d > %d Hz), reducing rate...\n",
|
||||||
|
+ pclk_freq, max_pclk_freq);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ov5640_calc_pclk(sensor, rate, &sysdiv, &prediv, &pll_rdiv, &mult,
|
||||||
|
+ &pclk_rdiv);
|
||||||
|
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
|
||||||
|
+ 0xf0, sysdiv << 4);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL2,
|
||||||
|
+ 0xff, mult);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
|
||||||
|
+ 0xff, prediv | ((pll_rdiv - 1) << 4));
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER,
|
||||||
|
+ 0x30, ilog2(pclk_rdiv) << 4);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor, unsigned long rate)
|
||||||
|
+{
|
||||||
|
+ u8 sysdiv, prediv, mult, pll_rdiv, pclk_rdiv;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ov5640_calc_pclk(sensor, rate, &sysdiv, &prediv, &pll_rdiv, &mult,
|
||||||
|
+ &pclk_rdiv);
|
||||||
|
+ ret = ov5640_write_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
|
||||||
|
+ (sysdiv << 4) | pclk_rdiv);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL2,
|
||||||
|
+ 0xff, mult);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
|
||||||
|
+ 0xff, prediv | ((pll_rdiv - 1) << 4));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* download ov5640 settings to sensor through i2c */
|
||||||
|
static int ov5640_set_timings(struct ov5640_dev *sensor,
|
||||||
|
const struct ov5640_mode_info *mode)
|
||||||
|
@@ -1444,8 +1499,8 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
|
||||||
|
{
|
||||||
|
const struct ov5640_mode_info *mode;
|
||||||
|
|
||||||
|
- mode = v4l2_find_nearest_size(ov5640_mode_data[fr],
|
||||||
|
- ARRAY_SIZE(ov5640_mode_data[fr]),
|
||||||
|
+ mode = v4l2_find_nearest_size(ov5640_mode_data,
|
||||||
|
+ ARRAY_SIZE(ov5640_mode_data),
|
||||||
|
hact, vact,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
@@ -1637,8 +1692,12 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
|
||||||
|
enum ov5640_downsize_mode dn_mode, orig_dn_mode;
|
||||||
|
bool auto_gain = sensor->ctrls.auto_gain->val == 1;
|
||||||
|
bool auto_exp = sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
|
||||||
|
+ unsigned long rate;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ if (!orig_mode)
|
||||||
|
+ orig_mode = mode;
|
||||||
|
+
|
||||||
|
dn_mode = mode->dn_mode;
|
||||||
|
orig_dn_mode = orig_mode->dn_mode;
|
||||||
|
|
||||||
|
@@ -1655,6 +1714,24 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
|
||||||
|
goto restore_auto_gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * All the formats we support have 2 bytes per pixel, except for JPEG
|
||||||
|
+ * which is 1 byte per pixel, but JPEG requires the same rate
|
||||||
|
+ * than YUV (horizontal lines blanking).
|
||||||
|
+ */
|
||||||
|
+ rate = mode->vtot * mode->htot * 2;
|
||||||
|
+ rate *= ov5640_framerates[sensor->current_fr];
|
||||||
|
+
|
||||||
|
+ if (sensor->ep.bus_type == V4L2_MBUS_CSI2) {
|
||||||
|
+ rate = rate / sensor->ep.bus.mipi_csi2.num_data_lanes;
|
||||||
|
+ ret = ov5640_set_mipi_pclk(sensor, rate);
|
||||||
|
+ } else {
|
||||||
|
+ ret = ov5640_set_dvp_pclk(sensor, mode, rate);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
|
||||||
|
(dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
|
||||||
|
/*
|
||||||
|
@@ -2502,10 +2579,10 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
fse->min_width =
|
||||||
|
- ov5640_mode_data[0][fse->index].hact;
|
||||||
|
+ ov5640_mode_data[fse->index].hact;
|
||||||
|
fse->max_width = fse->min_width;
|
||||||
|
fse->min_height =
|
||||||
|
- ov5640_mode_data[0][fse->index].vact;
|
||||||
|
+ ov5640_mode_data[fse->index].vact;
|
||||||
|
fse->max_height = fse->min_height;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -2573,8 +2650,6 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
|
||||||
|
if (frame_rate < 0)
|
||||||
|
frame_rate = OV5640_15_FPS;
|
||||||
|
|
||||||
|
- sensor->current_fr = frame_rate;
|
||||||
|
- sensor->frame_interval = fi->interval;
|
||||||
|
mode = ov5640_find_mode(sensor, frame_rate, mode->hact,
|
||||||
|
mode->vact, true);
|
||||||
|
if (!mode) {
|
||||||
|
@@ -2582,7 +2657,10 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (mode != sensor->current_mode) {
|
||||||
|
+ if (mode != sensor->current_mode ||
|
||||||
|
+ (frame_rate != sensor->current_fr)) {
|
||||||
|
+ sensor->current_fr = frame_rate;
|
||||||
|
+ sensor->frame_interval = fi->interval;
|
||||||
|
sensor->current_mode = mode;
|
||||||
|
sensor->pending_mode_change = true;
|
||||||
|
}
|
||||||
|
@@ -2613,7 +2691,8 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
|
||||||
|
|
||||||
|
if (sensor->streaming == !enable) {
|
||||||
|
if (enable && sensor->pending_mode_change) {
|
||||||
|
- ret = ov5640_set_mode(sensor);
|
||||||
|
+ ret = ov5640_set_mode(sensor, sensor->last_mode);
|
||||||
|
+
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
@@ -2735,7 +2814,7 @@ static int ov5640_probe(struct i2c_client *client,
|
||||||
|
sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS];
|
||||||
|
sensor->current_fr = OV5640_30_FPS;
|
||||||
|
sensor->current_mode =
|
||||||
|
- &ov5640_mode_data[OV5640_30_FPS][OV5640_MODE_VGA_640_480];
|
||||||
|
+ &ov5640_mode_data[OV5640_MODE_VGA_640_480];
|
||||||
|
sensor->last_mode = sensor->current_mode;
|
||||||
|
|
||||||
|
sensor->ae_target = 52;
|
||||||
|
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
|
||||||
|
index 7215641..49849e6 100644
|
||||||
|
--- a/drivers/media/platform/stm32/stm32-dcmi.c
|
||||||
|
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
|
||||||
|
@@ -95,6 +95,9 @@ enum state {
|
||||||
|
#define MIN_HEIGHT 16U
|
||||||
|
#define MAX_HEIGHT 2592U
|
||||||
|
|
||||||
|
+/* DMA can sustain YUV 720p@15fps max */
|
||||||
|
+#define MAX_DMA_BANDWIDTH (1280 * 720 * 2 * 15)
|
||||||
|
+
|
||||||
|
#define TIMEOUT_MS 1000
|
||||||
|
|
||||||
|
struct dcmi_graph_entity {
|
||||||
|
@@ -570,9 +573,9 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pm_runtime_get_sync(dcmi->dev);
|
||||||
|
- if (ret) {
|
||||||
|
- dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync\n",
|
||||||
|
- __func__);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync (%d)\n",
|
||||||
|
+ __func__, ret);
|
||||||
|
goto err_release_buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -621,8 +624,31 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||||
|
dcmi_set_crop(dcmi);
|
||||||
|
|
||||||
|
/* Enable jpeg capture */
|
||||||
|
- if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG)
|
||||||
|
- reg_set(dcmi->regs, DCMI_CR, CR_CM);/* Snapshot mode */
|
||||||
|
+ if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG) {
|
||||||
|
+ unsigned int rate;
|
||||||
|
+ struct v4l2_streamparm p = {
|
||||||
|
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
|
||||||
|
+ };
|
||||||
|
+ struct v4l2_fract frame_interval = {1, 30};
|
||||||
|
+
|
||||||
|
+ ret = v4l2_g_parm_cap(dcmi->vdev, dcmi->entity.subdev, &p);
|
||||||
|
+ if (!ret)
|
||||||
|
+ frame_interval = p.parm.capture.timeperframe;
|
||||||
|
+
|
||||||
|
+ rate = dcmi->fmt.fmt.pix.sizeimage *
|
||||||
|
+ frame_interval.denominator / frame_interval.numerator;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If rate exceed DMA capabilities, switch to snapshot mode
|
||||||
|
+ * to ensure that current DMA transfer is elapsed before
|
||||||
|
+ * capturing a new JPEG.
|
||||||
|
+ */
|
||||||
|
+ if (rate > MAX_DMA_BANDWIDTH) {
|
||||||
|
+ reg_set(dcmi->regs, DCMI_CR, CR_CM);/* Snapshot mode */
|
||||||
|
+ dev_dbg(dcmi->dev, "Capture rate is too high for continuous mode (%d > %d bytes/s), switch to snapshot mode\n",
|
||||||
|
+ rate, MAX_DMA_BANDWIDTH);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Enable dcmi */
|
||||||
|
reg_set(dcmi->regs, DCMI_CR, CR_ENABLE);
|
||||||
|
@@ -659,7 +685,10 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable interruptions */
|
||||||
|
- reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
|
||||||
|
+ if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG)
|
||||||
|
+ reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
|
||||||
|
+ else
|
||||||
|
+ reg_set(dcmi->regs, DCMI_IER, IT_OVR | IT_ERR);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
|
||||||
|
index 169bdbb..505338e 100644
|
||||||
|
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
|
||||||
|
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
|
||||||
|
@@ -158,6 +158,9 @@ static void v4l2_fwnode_endpoint_parse_parallel_bus(
|
||||||
|
flags |= v ? V4L2_MBUS_DATA_ENABLE_HIGH :
|
||||||
|
V4L2_MBUS_DATA_ENABLE_LOW;
|
||||||
|
|
||||||
|
+ if (!fwnode_property_read_u32(fwnode, "pclk-max-frequency", &v))
|
||||||
|
+ bus->pclk_max_frequency = v;
|
||||||
|
+
|
||||||
|
bus->flags = flags;
|
||||||
|
|
||||||
|
}
|
||||||
|
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
|
||||||
|
index 9cccab6..946b48d 100644
|
||||||
|
--- a/include/media/v4l2-fwnode.h
|
||||||
|
+++ b/include/media/v4l2-fwnode.h
|
||||||
|
@@ -52,11 +52,13 @@ struct v4l2_fwnode_bus_mipi_csi2 {
|
||||||
|
* @flags: media bus (V4L2_MBUS_*) flags
|
||||||
|
* @bus_width: bus width in bits
|
||||||
|
* @data_shift: data shift in bits
|
||||||
|
+ * @max_pclk_frequency: maximum pixel clock in hertz
|
||||||
|
*/
|
||||||
|
struct v4l2_fwnode_bus_parallel {
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned char bus_width;
|
||||||
|
unsigned char data_shift;
|
||||||
|
+ unsigned int pclk_max_frequency;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,288 @@
|
||||||
|
From 85d48072cfb2e491d10a235c4ade2460e3bbc93a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||||
|
Date: Mon, 26 Nov 2018 14:40:42 +0100
|
||||||
|
Subject: [PATCH 21/52] ARM-stm32mp1-r0-rc2-PINCTRL
|
||||||
|
|
||||||
|
---
|
||||||
|
.../bindings/pinctrl/st,stm32-pinctrl.txt | 1 +
|
||||||
|
drivers/pinctrl/core.c | 15 +----
|
||||||
|
drivers/pinctrl/pinctrl-stmfx.c | 8 +++
|
||||||
|
drivers/pinctrl/stm32/pinctrl-stm32.c | 71 +++++++++++++++++++++-
|
||||||
|
include/linux/pinctrl/pinctrl.h | 2 +
|
||||||
|
5 files changed, 83 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
|
||||||
|
index 286c981..1a5d1e2 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
|
||||||
|
@@ -58,6 +58,7 @@ Optional properties:
|
||||||
|
used to select GPIOs as interrupts).
|
||||||
|
- st,package: Indicates the SOC package used.
|
||||||
|
More details in include/dt-bindings/pinctrl/stm32-pinfunc.h
|
||||||
|
+ - hwlocks: reference to a phandle of a hardware spinlock provider node.
|
||||||
|
|
||||||
|
Example 1:
|
||||||
|
#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
|
||||||
|
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
|
||||||
|
index a3dd777..0220d43 100644
|
||||||
|
--- a/drivers/pinctrl/core.c
|
||||||
|
+++ b/drivers/pinctrl/core.c
|
||||||
|
@@ -1992,7 +1992,7 @@ pinctrl_init_controller(struct pinctrl_desc *pctldesc, struct device *dev,
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
|
||||||
|
+int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
|
||||||
|
{
|
||||||
|
pctldev->p = create_pinctrl(pctldev->dev, pctldev);
|
||||||
|
if (PTR_ERR(pctldev->p) == -ENODEV) {
|
||||||
|
@@ -2030,21 +2030,10 @@ static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(pinctrl_claim_hogs);
|
||||||
|
|
||||||
|
int pinctrl_enable(struct pinctrl_dev *pctldev)
|
||||||
|
{
|
||||||
|
- int error;
|
||||||
|
-
|
||||||
|
- error = pinctrl_claim_hogs(pctldev);
|
||||||
|
- if (error) {
|
||||||
|
- dev_err(pctldev->dev, "could not claim hogs: %i\n",
|
||||||
|
- error);
|
||||||
|
- mutex_destroy(&pctldev->mutex);
|
||||||
|
- kfree(pctldev);
|
||||||
|
-
|
||||||
|
- return error;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
mutex_lock(&pinctrldev_list_mutex);
|
||||||
|
list_add_tail(&pctldev->node, &pinctrldev_list);
|
||||||
|
mutex_unlock(&pinctrldev_list_mutex);
|
||||||
|
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
|
||||||
|
index e253ed1..15d5757 100644
|
||||||
|
--- a/drivers/pinctrl/pinctrl-stmfx.c
|
||||||
|
+++ b/drivers/pinctrl/pinctrl-stmfx.c
|
||||||
|
@@ -663,6 +663,14 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev)
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Claim hogs after enabling gpio function, otherwise pin
|
||||||
|
+ * configuration will not apply
|
||||||
|
+ */
|
||||||
|
+ ret = pinctrl_claim_hogs(pctl->pctl_dev);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
pctl->irq_chip.name = dev_name(pctl->dev);
|
||||||
|
pctl->irq_chip.irq_mask = stmfx_pinctrl_irq_mask;
|
||||||
|
pctl->irq_chip.irq_unmask = stmfx_pinctrl_irq_unmask;
|
||||||
|
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||||
|
index e25917f..914bee4 100644
|
||||||
|
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||||
|
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||||
|
@@ -8,6 +8,7 @@
|
||||||
|
*/
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/gpio/driver.h>
|
||||||
|
+#include <linux/hwspinlock.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
#include <linux/mfd/syscon.h>
|
||||||
|
@@ -64,6 +65,8 @@
|
||||||
|
#define gpio_range_to_bank(chip) \
|
||||||
|
container_of(chip, struct stm32_gpio_bank, range)
|
||||||
|
|
||||||
|
+#define HWSPINLOCK_TIMEOUT 5 /* msec */
|
||||||
|
+
|
||||||
|
static const char * const stm32_gpio_functions[] = {
|
||||||
|
"gpio", "af0", "af1",
|
||||||
|
"af2", "af3", "af4",
|
||||||
|
@@ -111,6 +114,7 @@ struct stm32_pinctrl {
|
||||||
|
u32 npins;
|
||||||
|
u32 pkg;
|
||||||
|
u32 pin_base_shift;
|
||||||
|
+ struct hwspinlock *hwlock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int stm32_gpio_pin(int gpio)
|
||||||
|
@@ -598,14 +602,24 @@ static int stm32_pmx_get_func_groups(struct pinctrl_dev *pctldev,
|
||||||
|
static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||||
|
int pin, u32 mode, u32 alt)
|
||||||
|
{
|
||||||
|
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
u32 val;
|
||||||
|
int alt_shift = (pin % 8) * 4;
|
||||||
|
int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4;
|
||||||
|
unsigned long flags;
|
||||||
|
+ int err = 0;
|
||||||
|
|
||||||
|
clk_enable(bank->clk);
|
||||||
|
spin_lock_irqsave(&bank->lock, flags);
|
||||||
|
|
||||||
|
+ if (pctl->hwlock)
|
||||||
|
+ err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
+ goto unlock;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
val = readl_relaxed(bank->base + alt_offset);
|
||||||
|
val &= ~GENMASK(alt_shift + 3, alt_shift);
|
||||||
|
val |= (alt << alt_shift);
|
||||||
|
@@ -618,6 +632,10 @@ static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||||
|
|
||||||
|
stm32_gpio_backup_mode(bank, pin, mode, alt);
|
||||||
|
|
||||||
|
+ if (pctl->hwlock)
|
||||||
|
+ hwspin_unlock(pctl->hwlock);
|
||||||
|
+
|
||||||
|
+unlock:
|
||||||
|
spin_unlock_irqrestore(&bank->lock, flags);
|
||||||
|
clk_disable(bank->clk);
|
||||||
|
}
|
||||||
|
@@ -707,12 +725,22 @@ static const struct pinmux_ops stm32_pmx_ops = {
|
||||||
|
static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||||
|
unsigned offset, u32 drive)
|
||||||
|
{
|
||||||
|
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
unsigned long flags;
|
||||||
|
u32 val;
|
||||||
|
+ int err = 0;
|
||||||
|
|
||||||
|
clk_enable(bank->clk);
|
||||||
|
spin_lock_irqsave(&bank->lock, flags);
|
||||||
|
|
||||||
|
+ if (pctl->hwlock)
|
||||||
|
+ err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
+ goto unlock;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
val = readl_relaxed(bank->base + STM32_GPIO_TYPER);
|
||||||
|
val &= ~BIT(offset);
|
||||||
|
val |= drive << offset;
|
||||||
|
@@ -720,6 +748,10 @@ static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||||
|
|
||||||
|
stm32_gpio_backup_driving(bank, offset, drive);
|
||||||
|
|
||||||
|
+ if (pctl->hwlock)
|
||||||
|
+ hwspin_unlock(pctl->hwlock);
|
||||||
|
+
|
||||||
|
+unlock:
|
||||||
|
spin_unlock_irqrestore(&bank->lock, flags);
|
||||||
|
clk_disable(bank->clk);
|
||||||
|
}
|
||||||
|
@@ -745,12 +777,22 @@ static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank,
|
||||||
|
static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||||
|
unsigned offset, u32 speed)
|
||||||
|
{
|
||||||
|
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
unsigned long flags;
|
||||||
|
u32 val;
|
||||||
|
+ int err = 0;
|
||||||
|
|
||||||
|
clk_enable(bank->clk);
|
||||||
|
spin_lock_irqsave(&bank->lock, flags);
|
||||||
|
|
||||||
|
+ if (pctl->hwlock)
|
||||||
|
+ err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
+ goto unlock;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR);
|
||||||
|
val &= ~GENMASK(offset * 2 + 1, offset * 2);
|
||||||
|
val |= speed << (offset * 2);
|
||||||
|
@@ -758,6 +800,10 @@ static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||||
|
|
||||||
|
stm32_gpio_backup_speed(bank, offset, speed);
|
||||||
|
|
||||||
|
+ if (pctl->hwlock)
|
||||||
|
+ hwspin_unlock(pctl->hwlock);
|
||||||
|
+
|
||||||
|
+unlock:
|
||||||
|
spin_unlock_irqrestore(&bank->lock, flags);
|
||||||
|
clk_disable(bank->clk);
|
||||||
|
}
|
||||||
|
@@ -783,12 +829,22 @@ static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank,
|
||||||
|
static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||||
|
unsigned offset, u32 bias)
|
||||||
|
{
|
||||||
|
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
unsigned long flags;
|
||||||
|
u32 val;
|
||||||
|
+ int err = 0;
|
||||||
|
|
||||||
|
clk_enable(bank->clk);
|
||||||
|
spin_lock_irqsave(&bank->lock, flags);
|
||||||
|
|
||||||
|
+ if (pctl->hwlock)
|
||||||
|
+ err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
+ goto unlock;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
val = readl_relaxed(bank->base + STM32_GPIO_PUPDR);
|
||||||
|
val &= ~GENMASK(offset * 2 + 1, offset * 2);
|
||||||
|
val |= bias << (offset * 2);
|
||||||
|
@@ -796,6 +852,10 @@ static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||||
|
|
||||||
|
stm32_gpio_backup_bias(bank, offset, bias);
|
||||||
|
|
||||||
|
+ if (pctl->hwlock)
|
||||||
|
+ hwspin_unlock(pctl->hwlock);
|
||||||
|
+
|
||||||
|
+unlock:
|
||||||
|
spin_unlock_irqrestore(&bank->lock, flags);
|
||||||
|
clk_disable(bank->clk);
|
||||||
|
}
|
||||||
|
@@ -1206,7 +1266,7 @@ int stm32_pctl_probe(struct platform_device *pdev)
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct stm32_pinctrl *pctl;
|
||||||
|
struct pinctrl_pin_desc *pins;
|
||||||
|
- int i, ret, banks = 0;
|
||||||
|
+ int i, ret, hwlock_id, banks = 0;
|
||||||
|
|
||||||
|
if (!np)
|
||||||
|
return -EINVAL;
|
||||||
|
@@ -1226,6 +1286,15 @@ int stm32_pctl_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, pctl);
|
||||||
|
|
||||||
|
+ /* hwspinlock is optional */
|
||||||
|
+ hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
|
||||||
|
+ if (hwlock_id < 0) {
|
||||||
|
+ if (hwlock_id == -EPROBE_DEFER)
|
||||||
|
+ return hwlock_id;
|
||||||
|
+ } else {
|
||||||
|
+ pctl->hwlock = hwspin_lock_request_specific(hwlock_id);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
pctl->dev = dev;
|
||||||
|
pctl->match_data = match->data;
|
||||||
|
|
||||||
|
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
|
||||||
|
index 8f5dbb8..bbeaa29 100644
|
||||||
|
--- a/include/linux/pinctrl/pinctrl.h
|
||||||
|
+++ b/include/linux/pinctrl/pinctrl.h
|
||||||
|
@@ -148,6 +148,8 @@ extern int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
|
||||||
|
struct pinctrl_dev **pctldev);
|
||||||
|
extern int pinctrl_enable(struct pinctrl_dev *pctldev);
|
||||||
|
|
||||||
|
+extern int pinctrl_claim_hogs(struct pinctrl_dev *pctldev);
|
||||||
|
+
|
||||||
|
/* Please use pinctrl_register_and_init() and pinctrl_enable() instead */
|
||||||
|
extern struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||||
|
struct device *dev, void *driver_data);
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,781 @@
|
||||||
|
From aed35270f0be1c5c61a028d7c183e60269f3abe3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||||
|
Date: Mon, 26 Nov 2018 14:41:37 +0100
|
||||||
|
Subject: [PATCH 22/52] ARM-stm32mp1-r0-rc2-MFD-IRQ
|
||||||
|
|
||||||
|
---
|
||||||
|
.../interrupt-controller/st,stm32-exti.txt | 34 +++++-
|
||||||
|
.../devicetree/bindings/mfd/st,stpmic1.txt | 2 +-
|
||||||
|
Documentation/devicetree/bindings/mfd/syscon.txt | 1 +
|
||||||
|
drivers/irqchip/irq-stm32-exti.c | 133 ++++++++++++++++++---
|
||||||
|
drivers/mfd/stm32-pwr.c | 131 +++++++++-----------
|
||||||
|
drivers/mfd/stpmic1.c | 16 +--
|
||||||
|
drivers/mfd/syscon.c | 19 +++
|
||||||
|
drivers/mfd/wm8994-core.c | 15 +++
|
||||||
|
include/linux/mfd/stpmic1.h | 1 -
|
||||||
|
9 files changed, 247 insertions(+), 105 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
|
||||||
|
index 6a36bf6..abcf816 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
|
||||||
|
@@ -14,7 +14,23 @@ Required properties:
|
||||||
|
(only needed for exti controller with multiple exti under
|
||||||
|
same parent interrupt: st,stm32-exti and st,stm32h7-exti)
|
||||||
|
|
||||||
|
-Example:
|
||||||
|
+Optional properties:
|
||||||
|
+
|
||||||
|
+- hwlocks: reference to a phandle of a hardware spinlock provider node.
|
||||||
|
+
|
||||||
|
+Exti could have several parent interrupt controllers. In this case child nodes
|
||||||
|
+are used to describe those "extra" parent controllers. Properties to use are:
|
||||||
|
+
|
||||||
|
+- interrupt-controller: Indentifies the node as an interrupt controller
|
||||||
|
+- #interrupt-cells: Specifies the number of cells to encode an interrupt
|
||||||
|
+ specifier, shall be 2
|
||||||
|
+- interrupt-parent: Phandle to the interrupt parent node.
|
||||||
|
+- st,irq-number: Interrupt number mapped on the parent.
|
||||||
|
+
|
||||||
|
+See example 2.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+Example 1:
|
||||||
|
|
||||||
|
exti: interrupt-controller@40013c00 {
|
||||||
|
compatible = "st,stm32-exti";
|
||||||
|
@@ -23,3 +39,19 @@ exti: interrupt-controller@40013c00 {
|
||||||
|
reg = <0x40013C00 0x400>;
|
||||||
|
interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>;
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+Example 2:
|
||||||
|
+
|
||||||
|
+exti: interrupt-controller@5000d000 {
|
||||||
|
+ compatible = "st,stm32mp1-exti", "syscon";
|
||||||
|
+ interrupt-controller;
|
||||||
|
+ #interrupt-cells = <2>;
|
||||||
|
+ reg = <0x5000d000 0x400>;
|
||||||
|
+
|
||||||
|
+ exti_pwr: exti-pwr {
|
||||||
|
+ interrupt-controller;
|
||||||
|
+ #interrupt-cells = <2>;
|
||||||
|
+ interrupt-parent = <&pwr>;
|
||||||
|
+ st,irq-number = <6>;
|
||||||
|
+ };
|
||||||
|
+};
|
||||||
|
diff --git a/Documentation/devicetree/bindings/mfd/st,stpmic1.txt b/Documentation/devicetree/bindings/mfd/st,stpmic1.txt
|
||||||
|
index 54b64e2..0fab08a 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/mfd/st,stpmic1.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/mfd/st,stpmic1.txt
|
||||||
|
@@ -4,7 +4,6 @@ Required parent device properties:
|
||||||
|
- compatible: "st,stpmic1"
|
||||||
|
- reg: The I2C slave address for the STPMIC1 chip.
|
||||||
|
- interrupts: The interrupt lines the device is connected to.
|
||||||
|
- The second interrupt is used for wake-up.
|
||||||
|
- #interrupt-cells: Should be 2.
|
||||||
|
- interrupt-controller: Describes the STPMIC1 as an interrupt
|
||||||
|
controller (has its own domain). Interrupt number are the following:
|
||||||
|
@@ -81,6 +80,7 @@ Optional parent device properties:
|
||||||
|
-bit 5: SW_OUT discharge is enabled
|
||||||
|
-bit 6: VBUS_OTG detection is enabled
|
||||||
|
-bit 7: BOOST_OVP is disabled
|
||||||
|
+- wakeup-source: bool flag to indicate this device has wakeup capabilities
|
||||||
|
|
||||||
|
STPMIC1 consists in a varied group of sub-devices.
|
||||||
|
Each sub-device binding is be described in own documentation file.
|
||||||
|
diff --git a/Documentation/devicetree/bindings/mfd/syscon.txt b/Documentation/devicetree/bindings/mfd/syscon.txt
|
||||||
|
index 25d9e9c..a9aaa51 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/mfd/syscon.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/mfd/syscon.txt
|
||||||
|
@@ -17,6 +17,7 @@ Optional property:
|
||||||
|
- reg-io-width: the size (in bytes) of the IO accesses that should be
|
||||||
|
performed on the device.
|
||||||
|
- hwlocks: reference to a phandle of a hardware spinlock provider node.
|
||||||
|
+- clocks: phandle to the syscon clock
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
gpr: iomuxc-gpr@20e0000 {
|
||||||
|
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
index e185ed8..9cc15f1 100644
|
||||||
|
--- a/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
+++ b/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
@@ -6,6 +6,7 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
+#include <linux/hwspinlock.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
@@ -20,6 +21,8 @@
|
||||||
|
|
||||||
|
#define IRQS_PER_BANK 32
|
||||||
|
|
||||||
|
+#define HWSPINLOCK_TIMEOUT 5 /* msec */
|
||||||
|
+
|
||||||
|
struct stm32_exti_bank {
|
||||||
|
u32 imr_ofst;
|
||||||
|
u32 emr_ofst;
|
||||||
|
@@ -47,6 +50,7 @@ struct stm32_exti_drv_data {
|
||||||
|
struct stm32_exti_chip_data {
|
||||||
|
struct stm32_exti_host_data *host_data;
|
||||||
|
const struct stm32_exti_bank *reg_bank;
|
||||||
|
+ struct hwspinlock *hwlock;
|
||||||
|
struct raw_spinlock rlock;
|
||||||
|
u32 wake_active;
|
||||||
|
u32 mask_cache;
|
||||||
|
@@ -275,25 +279,34 @@ static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
|
||||||
|
struct stm32_exti_chip_data *chip_data = gc->private;
|
||||||
|
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
|
||||||
|
u32 rtsr, ftsr;
|
||||||
|
- int err;
|
||||||
|
+ int err = 0;
|
||||||
|
|
||||||
|
irq_gc_lock(gc);
|
||||||
|
|
||||||
|
+ if (chip_data->hwlock)
|
||||||
|
+ err = hwspin_lock_timeout(chip_data->hwlock,
|
||||||
|
+ HWSPINLOCK_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ if (err)
|
||||||
|
+ goto unlock;
|
||||||
|
+
|
||||||
|
rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
|
||||||
|
ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
|
||||||
|
|
||||||
|
err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
|
||||||
|
- if (err) {
|
||||||
|
- irq_gc_unlock(gc);
|
||||||
|
- return err;
|
||||||
|
- }
|
||||||
|
+ if (err)
|
||||||
|
+ goto unspinlock;
|
||||||
|
|
||||||
|
irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
|
||||||
|
irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
|
||||||
|
|
||||||
|
+unspinlock:
|
||||||
|
+ if (chip_data->hwlock)
|
||||||
|
+ hwspin_unlock(chip_data->hwlock);
|
||||||
|
+unlock:
|
||||||
|
irq_gc_unlock(gc);
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stm32_chip_suspend(struct stm32_exti_chip_data *chip_data,
|
||||||
|
@@ -457,22 +470,36 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type)
|
||||||
|
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
|
||||||
|
void __iomem *base = chip_data->host_data->base;
|
||||||
|
u32 rtsr, ftsr;
|
||||||
|
- int err;
|
||||||
|
+ int err = 0;
|
||||||
|
|
||||||
|
raw_spin_lock(&chip_data->rlock);
|
||||||
|
+
|
||||||
|
+ if (chip_data->hwlock)
|
||||||
|
+ err = hwspin_lock_timeout(chip_data->hwlock,
|
||||||
|
+ HWSPINLOCK_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ if (err)
|
||||||
|
+ goto unlock;
|
||||||
|
+
|
||||||
|
rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst);
|
||||||
|
ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst);
|
||||||
|
|
||||||
|
err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
|
||||||
|
- if (err) {
|
||||||
|
- raw_spin_unlock(&chip_data->rlock);
|
||||||
|
- return err;
|
||||||
|
- }
|
||||||
|
+ if (err)
|
||||||
|
+ goto unspinlock;
|
||||||
|
|
||||||
|
writel_relaxed(rtsr, base + stm32_bank->rtsr_ofst);
|
||||||
|
writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst);
|
||||||
|
+
|
||||||
|
+unspinlock:
|
||||||
|
+ if (chip_data->hwlock)
|
||||||
|
+ hwspin_unlock(chip_data->hwlock);
|
||||||
|
+unlock:
|
||||||
|
raw_spin_unlock(&chip_data->rlock);
|
||||||
|
|
||||||
|
+ if (d->parent_data->chip)
|
||||||
|
+ irq_chip_set_type_parent(d, type);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -490,6 +517,9 @@ static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on)
|
||||||
|
|
||||||
|
raw_spin_unlock(&chip_data->rlock);
|
||||||
|
|
||||||
|
+ if (d->parent_data->chip)
|
||||||
|
+ irq_chip_set_wake_parent(d, on);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -502,6 +532,12 @@ static int stm32_exti_h_set_affinity(struct irq_data *d,
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void stm32_exti_h_ack(struct irq_data *d)
|
||||||
|
+{
|
||||||
|
+ if (d->parent_data->chip)
|
||||||
|
+ irq_chip_ack_parent(d);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int stm32_exti_h_suspend(void)
|
||||||
|
{
|
||||||
|
@@ -547,6 +583,7 @@ static inline void stm32_exti_h_syscore_init(void) {}
|
||||||
|
static struct irq_chip stm32_exti_h_chip = {
|
||||||
|
.name = "stm32-exti-h",
|
||||||
|
.irq_eoi = stm32_exti_h_eoi,
|
||||||
|
+ .irq_ack = stm32_exti_h_ack,
|
||||||
|
.irq_mask = stm32_exti_h_mask,
|
||||||
|
.irq_unmask = stm32_exti_h_unmask,
|
||||||
|
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||||
|
@@ -574,15 +611,29 @@ static int stm32_exti_h_domain_alloc(struct irq_domain *dm,
|
||||||
|
irq_domain_set_hwirq_and_chip(dm, virq, hwirq,
|
||||||
|
&stm32_exti_h_chip, chip_data);
|
||||||
|
|
||||||
|
- p_irq = stm32_exti_to_irq(host_data->drv_data, hwirq);
|
||||||
|
- if (p_irq >= 0) {
|
||||||
|
+ /*
|
||||||
|
+ * EXTI 55 to 60 are mapped to PWR interrupt controller.
|
||||||
|
+ * The hwirq translation is done diferently than for GIC.
|
||||||
|
+ */
|
||||||
|
+ if (hwirq >= 55 && hwirq <= 60) {
|
||||||
|
p_fwspec.fwnode = dm->parent->fwnode;
|
||||||
|
- p_fwspec.param_count = 3;
|
||||||
|
- p_fwspec.param[0] = GIC_SPI;
|
||||||
|
- p_fwspec.param[1] = p_irq;
|
||||||
|
- p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
|
||||||
|
+ p_fwspec.param_count = 2;
|
||||||
|
+ p_fwspec.param[0] = hwirq - 55;
|
||||||
|
+ p_fwspec.param[1] = fwspec->param[1];
|
||||||
|
|
||||||
|
return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec);
|
||||||
|
+ } else {
|
||||||
|
+ p_irq = stm32_exti_to_irq(host_data->drv_data, hwirq);
|
||||||
|
+ if (p_irq >= 0) {
|
||||||
|
+ p_fwspec.fwnode = dm->parent->fwnode;
|
||||||
|
+ p_fwspec.param_count = 3;
|
||||||
|
+ p_fwspec.param[0] = GIC_SPI;
|
||||||
|
+ p_fwspec.param[1] = p_irq;
|
||||||
|
+ p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
|
||||||
|
+
|
||||||
|
+ return irq_domain_alloc_irqs_parent(dm, virq, 1,
|
||||||
|
+ &p_fwspec);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -665,6 +716,7 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
int nr_irqs, ret, i;
|
||||||
|
struct irq_chip_generic *gc;
|
||||||
|
struct irq_domain *domain;
|
||||||
|
+ struct hwspinlock *hwlock = NULL;
|
||||||
|
|
||||||
|
host_data = stm32_exti_host_init(drv_data, node);
|
||||||
|
if (!host_data)
|
||||||
|
@@ -687,12 +739,22 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
goto out_free_domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* hwspinlock is optional */
|
||||||
|
+ ret = of_hwspin_lock_get_id(node, 0);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ if (ret == -EPROBE_DEFER)
|
||||||
|
+ goto out_free_domain;
|
||||||
|
+ } else {
|
||||||
|
+ hwlock = hwspin_lock_request_specific(ret);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
for (i = 0; i < drv_data->bank_nr; i++) {
|
||||||
|
const struct stm32_exti_bank *stm32_bank;
|
||||||
|
struct stm32_exti_chip_data *chip_data;
|
||||||
|
|
||||||
|
stm32_bank = drv_data->exti_banks[i];
|
||||||
|
chip_data = stm32_exti_chip_init(host_data, i, node);
|
||||||
|
+ chip_data->hwlock = hwlock;
|
||||||
|
|
||||||
|
gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
|
||||||
|
|
||||||
|
@@ -760,11 +822,12 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
{
|
||||||
|
struct irq_domain *parent_domain, *domain;
|
||||||
|
struct stm32_exti_host_data *host_data;
|
||||||
|
+ struct device_node *child;
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
parent_domain = irq_find_host(parent);
|
||||||
|
if (!parent_domain) {
|
||||||
|
- pr_err("interrupt-parent not found\n");
|
||||||
|
+ pr_err("GIC interrupt-parent not found\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -786,6 +849,40 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
goto out_unmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ for_each_child_of_node(node, child) {
|
||||||
|
+ struct device_node *parent_node;
|
||||||
|
+ u32 nirqs;
|
||||||
|
+
|
||||||
|
+ parent_node = of_irq_find_parent(child);
|
||||||
|
+ parent_domain = irq_find_host(parent_node);
|
||||||
|
+
|
||||||
|
+ if (!parent_domain) {
|
||||||
|
+ pr_err("%s: child interrupt-parent not found\n",
|
||||||
|
+ child->name);
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto out_unmap;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32(child, "st,irq-number", &nirqs);
|
||||||
|
+ if (ret != 0 || nirqs == 0) {
|
||||||
|
+ pr_err("%s: Missing or bad irq-number property\n"
|
||||||
|
+ , __func__);
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto out_unmap;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ domain = irq_domain_add_hierarchy(parent_domain, 0, nirqs,
|
||||||
|
+ child,
|
||||||
|
+ &stm32_exti_h_domain_ops,
|
||||||
|
+ host_data);
|
||||||
|
+ if (!domain) {
|
||||||
|
+ pr_err("%s: Could not register exti domain.\n",
|
||||||
|
+ node->name);
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto out_unmap;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
stm32_exti_h_syscore_init();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
diff --git a/drivers/mfd/stm32-pwr.c b/drivers/mfd/stm32-pwr.c
|
||||||
|
index 377e2f5..206a933 100644
|
||||||
|
--- a/drivers/mfd/stm32-pwr.c
|
||||||
|
+++ b/drivers/mfd/stm32-pwr.c
|
||||||
|
@@ -5,7 +5,9 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/arm-smccc.h>
|
||||||
|
+#include <linux/irqchip.h>
|
||||||
|
#include <linux/irqchip/chained_irq.h>
|
||||||
|
+#include <linux/of_address.h>
|
||||||
|
#include <linux/of_irq.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <asm/exception.h>
|
||||||
|
@@ -45,7 +47,6 @@ enum wkup_pull_setting {
|
||||||
|
} \
|
||||||
|
|
||||||
|
struct stm32_pwr_data {
|
||||||
|
- struct device *dev; /* self device */
|
||||||
|
void __iomem *base; /* IO Memory base address */
|
||||||
|
struct irq_domain *domain; /* Domain for this controller */
|
||||||
|
int irq; /* Parent interrupt */
|
||||||
|
@@ -53,25 +54,19 @@ struct stm32_pwr_data {
|
||||||
|
|
||||||
|
static void stm32_pwr_irq_ack(struct irq_data *d)
|
||||||
|
{
|
||||||
|
- struct stm32_pwr_data *priv = d->domain->host_data;
|
||||||
|
-
|
||||||
|
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
|
||||||
|
+ pr_debug("irq:%lu\n", d->hwirq);
|
||||||
|
SMC(STM32_SVC_PWR, STM32_SET_BITS, WKUPCR, BIT(d->hwirq));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stm32_pwr_irq_mask(struct irq_data *d)
|
||||||
|
{
|
||||||
|
- struct stm32_pwr_data *priv = d->domain->host_data;
|
||||||
|
-
|
||||||
|
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
|
||||||
|
+ pr_debug("irq:%lu\n", d->hwirq);
|
||||||
|
SMC(STM32_SVC_PWR, STM32_CLEAR_BITS, MPUWKUPENR, BIT(d->hwirq));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stm32_pwr_irq_unmask(struct irq_data *d)
|
||||||
|
{
|
||||||
|
- struct stm32_pwr_data *priv = d->domain->host_data;
|
||||||
|
-
|
||||||
|
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
|
||||||
|
+ pr_debug("irq:%lu\n", d->hwirq);
|
||||||
|
SMC(STM32_SVC_PWR, STM32_SET_BITS, MPUWKUPENR, BIT(d->hwirq));
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -79,7 +74,7 @@ static int stm32_pwr_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||||
|
{
|
||||||
|
struct stm32_pwr_data *priv = d->domain->host_data;
|
||||||
|
|
||||||
|
- dev_dbg(priv->dev, "irq:%lu on:%d\n", d->hwirq, on);
|
||||||
|
+ pr_debug("irq:%lu on:%d\n", d->hwirq, on);
|
||||||
|
if (on)
|
||||||
|
enable_irq_wake(priv->irq);
|
||||||
|
else
|
||||||
|
@@ -95,7 +90,7 @@ static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||||
|
u32 wkupcr;
|
||||||
|
int en;
|
||||||
|
|
||||||
|
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
|
||||||
|
+ pr_debug("irq:%lu\n", d->hwirq);
|
||||||
|
|
||||||
|
en = readl_relaxed(priv->base + MPUWKUPENR) & BIT(pin_id);
|
||||||
|
/* reference manual request to disable the wakeup pin while
|
||||||
|
@@ -115,6 +110,7 @@ static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr);
|
||||||
|
|
||||||
|
if (en)
|
||||||
|
@@ -124,7 +120,7 @@ static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct irq_chip stm32_pwr_irq_chip = {
|
||||||
|
- .name = "stm32_pwr-irq",
|
||||||
|
+ .name = "stm32-pwr-irq",
|
||||||
|
.irq_ack = stm32_pwr_irq_ack,
|
||||||
|
.irq_mask = stm32_pwr_irq_mask,
|
||||||
|
.irq_unmask = stm32_pwr_irq_unmask,
|
||||||
|
@@ -132,29 +128,23 @@ static struct irq_chip stm32_pwr_irq_chip = {
|
||||||
|
.irq_set_wake = stm32_pwr_irq_set_wake,
|
||||||
|
};
|
||||||
|
|
||||||
|
-static int stm32_pwr_irq_map(struct irq_domain *h, unsigned int virq,
|
||||||
|
- irq_hw_number_t hw)
|
||||||
|
-{
|
||||||
|
- irq_set_chip_and_handler(virq, &stm32_pwr_irq_chip, handle_edge_irq);
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int stm32_pwr_irq_set_pull_config(struct irq_domain *d, int pin_id,
|
||||||
|
enum wkup_pull_setting config)
|
||||||
|
{
|
||||||
|
struct stm32_pwr_data *priv = d->host_data;
|
||||||
|
u32 wkupcr;
|
||||||
|
|
||||||
|
- dev_dbg(priv->dev, "irq:%d pull config:0x%x\n", pin_id, config);
|
||||||
|
+ pr_debug("irq:%d pull config:0x%x\n", pin_id, config);
|
||||||
|
|
||||||
|
if (config >= WKUP_PULL_RESERVED) {
|
||||||
|
- dev_err(priv->dev, "%s: bad irq pull config\n", __func__);
|
||||||
|
+ pr_err("%s: bad irq pull config\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wkupcr = readl_relaxed(priv->base + WKUPCR);
|
||||||
|
wkupcr &= ~((WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2));
|
||||||
|
wkupcr |= (config & WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2);
|
||||||
|
+
|
||||||
|
SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -164,10 +154,8 @@ static int stm32_pwr_xlate(struct irq_domain *d, struct device_node *ctrlr,
|
||||||
|
const u32 *intspec, unsigned int intsize,
|
||||||
|
irq_hw_number_t *out_hwirq, unsigned int *out_type)
|
||||||
|
{
|
||||||
|
- struct stm32_pwr_data *priv = d->host_data;
|
||||||
|
-
|
||||||
|
if (WARN_ON(intsize < 3)) {
|
||||||
|
- dev_err(priv->dev, "%s: bad irq config parameters\n", __func__);
|
||||||
|
+ pr_err("%s: bad irq config parameters\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -177,9 +165,23 @@ static int stm32_pwr_xlate(struct irq_domain *d, struct device_node *ctrlr,
|
||||||
|
return stm32_pwr_irq_set_pull_config(d, intspec[0], intspec[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int stm32_pwr_alloc(struct irq_domain *d, unsigned int virq,
|
||||||
|
+ unsigned int nr_irqs, void *data)
|
||||||
|
+{
|
||||||
|
+ struct irq_fwspec *fwspec = data;
|
||||||
|
+ irq_hw_number_t hwirq;
|
||||||
|
+
|
||||||
|
+ hwirq = fwspec->param[0];
|
||||||
|
+ irq_domain_set_info(d, virq, hwirq, &stm32_pwr_irq_chip, d->host_data,
|
||||||
|
+ handle_edge_irq, NULL, NULL);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const struct irq_domain_ops stm32_pwr_irq_domain_ops = {
|
||||||
|
- .map = stm32_pwr_irq_map,
|
||||||
|
+ .alloc = stm32_pwr_alloc,
|
||||||
|
.xlate = stm32_pwr_xlate,
|
||||||
|
+ .free = irq_domain_free_irqs_common,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -195,9 +197,10 @@ static void stm32_pwr_handle_irq(struct irq_desc *desc)
|
||||||
|
|
||||||
|
wkupfr = readl_relaxed(priv->base + WKUPFR);
|
||||||
|
wkupenr = readl_relaxed(priv->base + MPUWKUPENR);
|
||||||
|
+
|
||||||
|
for (i = 0; i < NB_WAKEUPPINS; i++) {
|
||||||
|
if ((wkupfr & BIT(i)) && (wkupenr & BIT(i))) {
|
||||||
|
- dev_dbg(priv->dev, "handle wkup irq:%d\n", i);
|
||||||
|
+ pr_debug("handle wkup irq:%d\n", i);
|
||||||
|
generic_handle_irq(irq_find_mapping(priv->domain, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -205,27 +208,21 @@ static void stm32_pwr_handle_irq(struct irq_desc *desc)
|
||||||
|
chained_irq_exit(chip, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int stm32_pwr_probe(struct platform_device *pdev)
|
||||||
|
+static int __init stm32_pwr_init(struct device_node *np,
|
||||||
|
+ struct device_node *parent)
|
||||||
|
{
|
||||||
|
- struct device *dev = &pdev->dev;
|
||||||
|
- struct device_node *np = pdev->dev.of_node;
|
||||||
|
struct stm32_pwr_data *priv;
|
||||||
|
-
|
||||||
|
- struct resource *res;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
- priv = devm_kzalloc(dev, sizeof(struct stm32_pwr_data), GFP_KERNEL);
|
||||||
|
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
- platform_set_drvdata(pdev, priv);
|
||||||
|
- priv->dev = dev;
|
||||||
|
-
|
||||||
|
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
- priv->base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
+ priv->base = of_iomap(np, 0);
|
||||||
|
if (IS_ERR(priv->base)) {
|
||||||
|
- dev_err(dev, "%s: Unable to map IO memory\n", __func__);
|
||||||
|
- return PTR_ERR(priv->base);
|
||||||
|
+ pr_err("%s: Unable to map IO memory\n", __func__);
|
||||||
|
+ ret = PTR_ERR(priv->base);
|
||||||
|
+ goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable all wake-up pins */
|
||||||
|
@@ -236,52 +233,38 @@ static int stm32_pwr_probe(struct platform_device *pdev)
|
||||||
|
priv->domain = irq_domain_add_linear(np, NB_WAKEUPPINS,
|
||||||
|
&stm32_pwr_irq_domain_ops, priv);
|
||||||
|
if (!priv->domain) {
|
||||||
|
- dev_err(dev, "%s: Unable to add irq domain!\n", __func__);
|
||||||
|
- goto out;
|
||||||
|
+ pr_err("%s: Unable to add irq domain!\n", __func__);
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto out_unmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = platform_get_irq(pdev, 0);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- dev_err(dev, "failed to get PWR IRQ\n");
|
||||||
|
- goto err;
|
||||||
|
+ priv->irq = irq_of_parse_and_map(np, 0);
|
||||||
|
+ if (priv->irq < 0) {
|
||||||
|
+ pr_err("failed to get PWR IRQ\n");
|
||||||
|
+ ret = priv->irq;
|
||||||
|
+ goto out_domain;
|
||||||
|
}
|
||||||
|
- priv->irq = ret;
|
||||||
|
|
||||||
|
irq_set_chained_handler_and_data(priv->irq,
|
||||||
|
stm32_pwr_handle_irq, priv);
|
||||||
|
|
||||||
|
-out:
|
||||||
|
+ of_node_clear_flag(np, OF_POPULATED);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
-err:
|
||||||
|
+
|
||||||
|
+out_domain:
|
||||||
|
irq_domain_remove(priv->domain);
|
||||||
|
+out_unmap:
|
||||||
|
+ iounmap(priv->base);
|
||||||
|
+out_free:
|
||||||
|
+ kfree(priv);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int stm32_pwr_remove(struct platform_device *pdev)
|
||||||
|
+static int __init stm32_pwr_of_init(struct device_node *np,
|
||||||
|
+ struct device_node *parent)
|
||||||
|
{
|
||||||
|
- struct stm32_pwr_data *priv = platform_get_drvdata(pdev);
|
||||||
|
-
|
||||||
|
- irq_domain_remove(priv->domain);
|
||||||
|
- return 0;
|
||||||
|
+ return stm32_pwr_init(np, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static const struct of_device_id stm32_pwr_match[] = {
|
||||||
|
- { .compatible = "st,stm32mp1-pwr" },
|
||||||
|
- {},
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static struct platform_driver stm32_pwr_driver = {
|
||||||
|
- .probe = stm32_pwr_probe,
|
||||||
|
- .remove = stm32_pwr_remove,
|
||||||
|
- .driver = {
|
||||||
|
- .name = "stm32-pwr",
|
||||||
|
- .owner = THIS_MODULE,
|
||||||
|
- .of_match_table = stm32_pwr_match,
|
||||||
|
- },
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static int __init stm32_pwr_init(void)
|
||||||
|
-{
|
||||||
|
- return platform_driver_register(&stm32_pwr_driver);
|
||||||
|
-}
|
||||||
|
-arch_initcall(stm32_pwr_init);
|
||||||
|
+IRQCHIP_DECLARE(stm32mp1_pwr_irq, "st,stm32mp1-pwr", stm32_pwr_of_init);
|
||||||
|
diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c
|
||||||
|
index 5bf6328..648315d 100644
|
||||||
|
--- a/drivers/mfd/stpmic1.c
|
||||||
|
+++ b/drivers/mfd/stpmic1.c
|
||||||
|
@@ -268,13 +268,8 @@ static int stpmic1_probe(struct i2c_client *i2c,
|
||||||
|
return ddata->irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ddata->irq_wake = of_irq_get(np, STPMIC1_WAKEUP_IRQ);
|
||||||
|
- if (ddata->irq_wake > 0) {
|
||||||
|
+ if (of_property_read_bool(np, "wakeup-source"))
|
||||||
|
device_init_wakeup(dev, true);
|
||||||
|
- ret = dev_pm_set_dedicated_wake_irq(dev, ddata->irq_wake);
|
||||||
|
- if (ret)
|
||||||
|
- dev_warn(dev, "failed to set up wakeup irq");
|
||||||
|
- }
|
||||||
|
|
||||||
|
if (!of_property_read_u32(np, "st,main-control-register", ®)) {
|
||||||
|
ret = regmap_update_bits(ddata->regmap,
|
||||||
|
@@ -371,8 +366,8 @@ static int stpmic1_suspend(struct device *dev)
|
||||||
|
struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
|
||||||
|
|
||||||
|
disable_irq(pmic_dev->irq);
|
||||||
|
- if ((pmic_dev->irq_wake > 0) && device_may_wakeup(dev))
|
||||||
|
- enable_irq_wake(pmic_dev->irq_wake);
|
||||||
|
+ if (device_may_wakeup(dev))
|
||||||
|
+ enable_irq_wake(pmic_dev->irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -387,9 +382,10 @@ static int stpmic1_resume(struct device *dev)
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
+ if (device_may_wakeup(dev))
|
||||||
|
+ disable_irq_wake(pmic_dev->irq);
|
||||||
|
+
|
||||||
|
enable_irq(pmic_dev->irq);
|
||||||
|
- if ((pmic_dev->irq_wake > 0) && device_may_wakeup(dev))
|
||||||
|
- disable_irq_wake(pmic_dev->irq_wake);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
|
||||||
|
index b6d05cd..a0ba4ff 100644
|
||||||
|
--- a/drivers/mfd/syscon.c
|
||||||
|
+++ b/drivers/mfd/syscon.c
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include <linux/clk.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/hwspinlock.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
@@ -45,6 +46,7 @@ static const struct regmap_config syscon_regmap_config = {
|
||||||
|
|
||||||
|
static struct syscon *of_syscon_register(struct device_node *np)
|
||||||
|
{
|
||||||
|
+ struct clk *clk;
|
||||||
|
struct syscon *syscon;
|
||||||
|
struct regmap *regmap;
|
||||||
|
void __iomem *base;
|
||||||
|
@@ -119,6 +121,18 @@ static struct syscon *of_syscon_register(struct device_node *np)
|
||||||
|
goto err_regmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ clk = of_clk_get(np, 0);
|
||||||
|
+ if (IS_ERR(clk)) {
|
||||||
|
+ ret = PTR_ERR(clk);
|
||||||
|
+ /* clock is optional */
|
||||||
|
+ if (ret != -ENOENT)
|
||||||
|
+ goto err_clk;
|
||||||
|
+ } else {
|
||||||
|
+ ret = regmap_mmio_attach_clk(regmap, clk);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto err_attach;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
syscon->regmap = regmap;
|
||||||
|
syscon->np = np;
|
||||||
|
|
||||||
|
@@ -128,6 +142,11 @@ static struct syscon *of_syscon_register(struct device_node *np)
|
||||||
|
|
||||||
|
return syscon;
|
||||||
|
|
||||||
|
+err_attach:
|
||||||
|
+ if (!IS_ERR(clk))
|
||||||
|
+ clk_put(clk);
|
||||||
|
+err_clk:
|
||||||
|
+ regmap_exit(regmap);
|
||||||
|
err_regmap:
|
||||||
|
iounmap(base);
|
||||||
|
err_map:
|
||||||
|
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
|
||||||
|
index 22bd652..755863a 100644
|
||||||
|
--- a/drivers/mfd/wm8994-core.c
|
||||||
|
+++ b/drivers/mfd/wm8994-core.c
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include <linux/clk.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
@@ -314,6 +315,20 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
|
||||||
|
if (pdata->ldo[1].enable < 0)
|
||||||
|
pdata->ldo[1].enable = 0;
|
||||||
|
|
||||||
|
+ pdata->mclk1 = devm_clk_get(wm8994->dev, "MCLK1");
|
||||||
|
+ if (IS_ERR(pdata->mclk1)) {
|
||||||
|
+ if (PTR_ERR(pdata->mclk1) != -ENOENT)
|
||||||
|
+ return PTR_ERR(pdata->mclk1);
|
||||||
|
+ pdata->mclk1 = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pdata->mclk2 = devm_clk_get(wm8994->dev, "MCLK2");
|
||||||
|
+ if (IS_ERR(pdata->mclk2)) {
|
||||||
|
+ if (PTR_ERR(pdata->mclk2) != -ENOENT)
|
||||||
|
+ return PTR_ERR(pdata->mclk2);
|
||||||
|
+ pdata->mclk2 = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
diff --git a/include/linux/mfd/stpmic1.h b/include/linux/mfd/stpmic1.h
|
||||||
|
index 4abe5f1..fa3f99f 100644
|
||||||
|
--- a/include/linux/mfd/stpmic1.h
|
||||||
|
+++ b/include/linux/mfd/stpmic1.h
|
||||||
|
@@ -206,7 +206,6 @@ struct stpmic1 {
|
||||||
|
struct device *dev;
|
||||||
|
struct regmap *regmap;
|
||||||
|
int irq;
|
||||||
|
- int irq_wake;
|
||||||
|
struct regmap_irq_chip_data *irq_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,914 @@
|
||||||
|
From 7a16fa25c3bd9a0c078b4d9d2ae445b975afaf69 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||||
|
Date: Mon, 26 Nov 2018 14:42:41 +0100
|
||||||
|
Subject: [PATCH 24/52] ARM-stm32mp1-r0-rc2-THERMAL
|
||||||
|
|
||||||
|
---
|
||||||
|
.../devicetree/bindings/thermal/stm32-thermal.txt | 61 ++
|
||||||
|
drivers/thermal/Kconfig | 2 +-
|
||||||
|
drivers/thermal/Makefile | 2 +-
|
||||||
|
drivers/thermal/st/Kconfig | 14 +
|
||||||
|
drivers/thermal/st/Makefile | 1 +
|
||||||
|
drivers/thermal/st/stm_thermal.c | 760 +++++++++++++++++++++
|
||||||
|
6 files changed, 838 insertions(+), 2 deletions(-)
|
||||||
|
create mode 100644 Documentation/devicetree/bindings/thermal/stm32-thermal.txt
|
||||||
|
create mode 100644 drivers/thermal/st/stm_thermal.c
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/thermal/stm32-thermal.txt b/Documentation/devicetree/bindings/thermal/stm32-thermal.txt
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..8c0d5a4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/devicetree/bindings/thermal/stm32-thermal.txt
|
||||||
|
@@ -0,0 +1,61 @@
|
||||||
|
+Binding for Thermal Sensor for STMicroelectronics STM32 series of SoCs.
|
||||||
|
+
|
||||||
|
+On STM32 SoCs, the Digital Temperature Sensor (DTS) is in charge of managing an
|
||||||
|
+analog block which delivers a frequency depending on the internal SoC's
|
||||||
|
+temperature. By using a reference frequency, DTS is able to provide a sample
|
||||||
|
+number which can be translated into a temperature by the user.
|
||||||
|
+
|
||||||
|
+DTS provides interrupt notification mechanism by threshold. This mechanism
|
||||||
|
+offers two temperature trip points: passive and critical. The first is intended
|
||||||
|
+for passive cooling notification while the second is used for over-temperature
|
||||||
|
+reset.
|
||||||
|
+
|
||||||
|
+Required parameters:
|
||||||
|
+-------------------
|
||||||
|
+
|
||||||
|
+compatible: Should be "st,stm32-thermal"
|
||||||
|
+reg: This should be the physical base address and length of the
|
||||||
|
+ sensor's registers.
|
||||||
|
+clocks: Phandle of the clock used by the thermal sensor.
|
||||||
|
+ See: Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
+clock-names: Should be "pclk" for register access clock and reference clock.
|
||||||
|
+ See: Documentation/devicetree/bindings/resource-names.txt
|
||||||
|
+#thermal-sensor-cells: Should be 0. See ./thermal.txt for a description.
|
||||||
|
+interrupts: Standard way to define interrupt number.
|
||||||
|
+
|
||||||
|
+Example:
|
||||||
|
+
|
||||||
|
+ thermal-zones {
|
||||||
|
+ cpu_thermal: cpu-thermal {
|
||||||
|
+ polling-delay-passive = <0>;
|
||||||
|
+ polling-delay = <0>;
|
||||||
|
+
|
||||||
|
+ thermal-sensors = <&thermal>;
|
||||||
|
+
|
||||||
|
+ trips {
|
||||||
|
+ cpu_alert1: cpu-alert1 {
|
||||||
|
+ temperature = <85000>;
|
||||||
|
+ hysteresis = <0>;
|
||||||
|
+ type = "passive";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ cpu-crit: cpu-crit {
|
||||||
|
+ temperature = <120000>;
|
||||||
|
+ hysteresis = <0>;
|
||||||
|
+ type = "critical";
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ cooling-maps {
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ thermal: thermal@50028000 {
|
||||||
|
+ compatible = "st,stm32-thermal";
|
||||||
|
+ reg = <0x50028000 0x100>;
|
||||||
|
+ clocks = <&rcc TMPSENS>;
|
||||||
|
+ clock-names = "pclk";
|
||||||
|
+ #thermal-sensor-cells = <0>;
|
||||||
|
+ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ };
|
||||||
|
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
|
||||||
|
index 0e69edc..5422523 100644
|
||||||
|
--- a/drivers/thermal/Kconfig
|
||||||
|
+++ b/drivers/thermal/Kconfig
|
||||||
|
@@ -432,7 +432,7 @@ source "drivers/thermal/samsung/Kconfig"
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
menu "STMicroelectronics thermal drivers"
|
||||||
|
-depends on ARCH_STI && OF
|
||||||
|
+depends on (ARCH_STI || ARCH_STM32) && OF
|
||||||
|
source "drivers/thermal/st/Kconfig"
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
|
||||||
|
index 610344e..82bb50d 100644
|
||||||
|
--- a/drivers/thermal/Makefile
|
||||||
|
+++ b/drivers/thermal/Makefile
|
||||||
|
@@ -53,7 +53,7 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
|
||||||
|
obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
|
||||||
|
obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
|
||||||
|
obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
|
||||||
|
-obj-$(CONFIG_ST_THERMAL) += st/
|
||||||
|
+obj-y += st/
|
||||||
|
obj-$(CONFIG_QCOM_TSENS) += qcom/
|
||||||
|
obj-y += tegra/
|
||||||
|
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
|
||||||
|
diff --git a/drivers/thermal/st/Kconfig b/drivers/thermal/st/Kconfig
|
||||||
|
index 490fdbe..b80f9a9 100644
|
||||||
|
--- a/drivers/thermal/st/Kconfig
|
||||||
|
+++ b/drivers/thermal/st/Kconfig
|
||||||
|
@@ -1,3 +1,7 @@
|
||||||
|
+#
|
||||||
|
+# STMicroelectronics thermal drivers configuration
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
config ST_THERMAL
|
||||||
|
tristate "Thermal sensors on STMicroelectronics STi series of SoCs"
|
||||||
|
help
|
||||||
|
@@ -10,3 +14,13 @@ config ST_THERMAL_SYSCFG
|
||||||
|
config ST_THERMAL_MEMMAP
|
||||||
|
select ST_THERMAL
|
||||||
|
tristate "STi series memory mapped access based thermal sensors"
|
||||||
|
+
|
||||||
|
+config STM32_THERMAL
|
||||||
|
+ tristate "Thermal framework support on STMicroelectronics STM32 series of SoCs"
|
||||||
|
+ depends on MACH_STM32MP157
|
||||||
|
+ default y
|
||||||
|
+ help
|
||||||
|
+ Support for thermal framework on STMicroelectronics STM32 series of
|
||||||
|
+ SoCs. This thermal driver allows to access to general thermal framework
|
||||||
|
+ functionalities and to acces to SoC sensor functionalities. This
|
||||||
|
+ configuration is fully dependent of MACH_STM32MP157.
|
||||||
|
diff --git a/drivers/thermal/st/Makefile b/drivers/thermal/st/Makefile
|
||||||
|
index b388789..b2b9e9b 100644
|
||||||
|
--- a/drivers/thermal/st/Makefile
|
||||||
|
+++ b/drivers/thermal/st/Makefile
|
||||||
|
@@ -1,3 +1,4 @@
|
||||||
|
obj-$(CONFIG_ST_THERMAL) := st_thermal.o
|
||||||
|
obj-$(CONFIG_ST_THERMAL_SYSCFG) += st_thermal_syscfg.o
|
||||||
|
obj-$(CONFIG_ST_THERMAL_MEMMAP) += st_thermal_memmap.o
|
||||||
|
+obj-$(CONFIG_STM32_THERMAL) := stm_thermal.o
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/drivers/thermal/st/stm_thermal.c b/drivers/thermal/st/stm_thermal.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..bbd73c5
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/thermal/st/stm_thermal.c
|
||||||
|
@@ -0,0 +1,760 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||||
|
+ * Author: David Hernandez Sanchez <david.hernandezsanchez@st.com> for
|
||||||
|
+ * STMicroelectronics.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/clk.h>
|
||||||
|
+#include <linux/clk-provider.h>
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
+#include <linux/err.h>
|
||||||
|
+#include <linux/interrupt.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/iopoll.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/of_address.h>
|
||||||
|
+#include <linux/of_device.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/thermal.h>
|
||||||
|
+
|
||||||
|
+#include "../thermal_core.h"
|
||||||
|
+#include "../thermal_hwmon.h"
|
||||||
|
+
|
||||||
|
+/* DTS register offsets */
|
||||||
|
+#define DTS_CFGR1_OFFSET 0x0
|
||||||
|
+#define DTS_T0VALR1_OFFSET 0x8
|
||||||
|
+#define DTS_RAMPVALR_OFFSET 0X10
|
||||||
|
+#define DTS_ITR1_OFFSET 0x14
|
||||||
|
+#define DTS_DR_OFFSET 0x1C
|
||||||
|
+#define DTS_SR_OFFSET 0x20
|
||||||
|
+#define DTS_ITENR_OFFSET 0x24
|
||||||
|
+#define DTS_CIFR_OFFSET 0x28
|
||||||
|
+
|
||||||
|
+/* DTS_CFGR1 register mask definitions */
|
||||||
|
+#define HSREF_CLK_DIV_MASK GENMASK(30, 24)
|
||||||
|
+#define TS1_SMP_TIME_MASK GENMASK(19, 16)
|
||||||
|
+#define TS1_INTRIG_SEL_MASK GENMASK(11, 8)
|
||||||
|
+
|
||||||
|
+/* DTS_T0VALR1 register mask definitions */
|
||||||
|
+#define TS1_T0_MASK GENMASK(17, 16)
|
||||||
|
+#define TS1_FMT0_MASK GENMASK(15, 0)
|
||||||
|
+
|
||||||
|
+/* DTS_RAMPVALR register mask definitions */
|
||||||
|
+#define TS1_RAMP_COEFF_MASK GENMASK(15, 0)
|
||||||
|
+
|
||||||
|
+/* DTS_ITR1 register mask definitions */
|
||||||
|
+#define TS1_HITTHD_MASK GENMASK(31, 16)
|
||||||
|
+#define TS1_LITTHD_MASK GENMASK(15, 0)
|
||||||
|
+
|
||||||
|
+/* DTS_DR register mask definitions */
|
||||||
|
+#define TS1_MFREQ_MASK GENMASK(15, 0)
|
||||||
|
+
|
||||||
|
+/* Less significant bit position definitions */
|
||||||
|
+#define TS1_T0_POS 16
|
||||||
|
+#define TS1_SMP_TIME_POS 16
|
||||||
|
+#define TS1_HITTHD_POS 16
|
||||||
|
+#define HSREF_CLK_DIV_POS 24
|
||||||
|
+
|
||||||
|
+/* DTS_CFGR1 bit definitions */
|
||||||
|
+#define TS1_EN BIT(0)
|
||||||
|
+#define TS1_START BIT(4)
|
||||||
|
+#define REFCLK_SEL BIT(20)
|
||||||
|
+#define REFCLK_LSE REFCLK_SEL
|
||||||
|
+#define Q_MEAS_OPT BIT(21)
|
||||||
|
+#define CALIBRATION_CONTROL Q_MEAS_OPT
|
||||||
|
+
|
||||||
|
+/* DTS_SR bit definitions */
|
||||||
|
+#define TS_RDY BIT(15)
|
||||||
|
+/* Bit definitions below are common for DTS_SR, DTS_ITENR and DTS_CIFR */
|
||||||
|
+#define HIGH_THRESHOLD BIT(2)
|
||||||
|
+#define LOW_THRESHOLD BIT(1)
|
||||||
|
+
|
||||||
|
+/* Constants */
|
||||||
|
+#define ADJUST 100
|
||||||
|
+#define ONE_MHZ 1000000
|
||||||
|
+#define POLL_TIMEOUT 5000
|
||||||
|
+#define STARTUP_TIME 40
|
||||||
|
+#define TS1_T0_VAL0 30
|
||||||
|
+#define TS1_T0_VAL1 130
|
||||||
|
+#define NO_HW_TRIG 0
|
||||||
|
+
|
||||||
|
+/* The Thermal Framework expects millidegrees */
|
||||||
|
+#define mcelsius(temp) ((temp) * 1000)
|
||||||
|
+
|
||||||
|
+/* The Sensor expects oC degrees */
|
||||||
|
+#define celsius(temp) ((temp) / 1000)
|
||||||
|
+
|
||||||
|
+struct stm_thermal_sensor {
|
||||||
|
+ struct device *dev;
|
||||||
|
+ struct thermal_zone_device *th_dev;
|
||||||
|
+ enum thermal_device_mode mode;
|
||||||
|
+ struct clk *clk;
|
||||||
|
+ int high_temp;
|
||||||
|
+ int low_temp;
|
||||||
|
+ int temp_critical;
|
||||||
|
+ int temp_passive;
|
||||||
|
+ unsigned int low_temp_enabled;
|
||||||
|
+ int num_trips;
|
||||||
|
+ int irq;
|
||||||
|
+ unsigned int irq_enabled;
|
||||||
|
+ void __iomem *base;
|
||||||
|
+ int t0, fmt0, ramp_coeff;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static irqreturn_t stm_thermal_alarm_irq(int irq, void *sdata)
|
||||||
|
+{
|
||||||
|
+ struct stm_thermal_sensor *sensor = sdata;
|
||||||
|
+
|
||||||
|
+ disable_irq_nosync(irq);
|
||||||
|
+ sensor->irq_enabled = false;
|
||||||
|
+
|
||||||
|
+ return IRQ_WAKE_THREAD;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static irqreturn_t stm_thermal_alarm_irq_thread(int irq, void *sdata)
|
||||||
|
+{
|
||||||
|
+ u32 value;
|
||||||
|
+ struct stm_thermal_sensor *sensor = sdata;
|
||||||
|
+
|
||||||
|
+ /* read IT reason in SR and clear flags */
|
||||||
|
+ value = readl_relaxed(sensor->base + DTS_SR_OFFSET);
|
||||||
|
+
|
||||||
|
+ if ((value & LOW_THRESHOLD) == LOW_THRESHOLD)
|
||||||
|
+ writel_relaxed(LOW_THRESHOLD, sensor->base + DTS_CIFR_OFFSET);
|
||||||
|
+
|
||||||
|
+ if ((value & HIGH_THRESHOLD) == HIGH_THRESHOLD)
|
||||||
|
+ writel_relaxed(HIGH_THRESHOLD, sensor->base + DTS_CIFR_OFFSET);
|
||||||
|
+
|
||||||
|
+ thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED);
|
||||||
|
+
|
||||||
|
+ return IRQ_HANDLED;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_sensor_power_on(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+ u32 value;
|
||||||
|
+
|
||||||
|
+ /* Enable sensor */
|
||||||
|
+ value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
|
||||||
|
+ value |= TS1_EN;
|
||||||
|
+ writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * The DTS block can be enabled by setting TSx_EN bit in
|
||||||
|
+ * DTS_CFGRx register. It requires a startup time of
|
||||||
|
+ * 40μs. Use 5 ms as arbitrary timeout.
|
||||||
|
+ */
|
||||||
|
+ ret = readl_poll_timeout(sensor->base + DTS_SR_OFFSET,
|
||||||
|
+ value, (value & TS_RDY),
|
||||||
|
+ STARTUP_TIME, POLL_TIMEOUT);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* Start continuous measuring */
|
||||||
|
+ value = readl_relaxed(sensor->base +
|
||||||
|
+ DTS_CFGR1_OFFSET);
|
||||||
|
+ value |= TS1_START;
|
||||||
|
+ writel_relaxed(value, sensor->base +
|
||||||
|
+ DTS_CFGR1_OFFSET);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_sensor_power_off(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ u32 value;
|
||||||
|
+
|
||||||
|
+ /* Stop measuring */
|
||||||
|
+ value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
|
||||||
|
+ value &= ~TS1_START;
|
||||||
|
+ writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
|
||||||
|
+
|
||||||
|
+ /* Ensure stop is taken into account */
|
||||||
|
+ usleep_range(STARTUP_TIME, POLL_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ /* Disable sensor */
|
||||||
|
+ value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
|
||||||
|
+ value &= ~TS1_EN;
|
||||||
|
+ writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
|
||||||
|
+
|
||||||
|
+ /* Ensure disable is taken into account */
|
||||||
|
+ return readl_poll_timeout(sensor->base + DTS_SR_OFFSET, value,
|
||||||
|
+ !(value & TS_RDY),
|
||||||
|
+ STARTUP_TIME, POLL_TIMEOUT);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_thermal_calibration(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ u32 value, clk_freq;
|
||||||
|
+ u32 prescaler;
|
||||||
|
+
|
||||||
|
+ /* Figure out prescaler value for PCLK during calibration */
|
||||||
|
+ clk_freq = clk_get_rate(sensor->clk);
|
||||||
|
+ if (!clk_freq)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ prescaler = 0;
|
||||||
|
+ clk_freq /= ONE_MHZ;
|
||||||
|
+ if (clk_freq) {
|
||||||
|
+ while (prescaler <= clk_freq)
|
||||||
|
+ prescaler++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
|
||||||
|
+
|
||||||
|
+ /* Clear prescaler */
|
||||||
|
+ value &= ~HSREF_CLK_DIV_MASK;
|
||||||
|
+
|
||||||
|
+ /* Set prescaler. pclk_freq/prescaler < 1MHz */
|
||||||
|
+ value |= (prescaler << HSREF_CLK_DIV_POS);
|
||||||
|
+
|
||||||
|
+ /* Select PCLK as reference clock */
|
||||||
|
+ value &= ~REFCLK_SEL;
|
||||||
|
+
|
||||||
|
+ /* Set maximal sampling time for better precision */
|
||||||
|
+ value |= TS1_SMP_TIME_MASK;
|
||||||
|
+
|
||||||
|
+ /* Measure with calibration */
|
||||||
|
+ value &= ~CALIBRATION_CONTROL;
|
||||||
|
+
|
||||||
|
+ /* select trigger */
|
||||||
|
+ value &= ~TS1_INTRIG_SEL_MASK;
|
||||||
|
+ value |= NO_HW_TRIG;
|
||||||
|
+
|
||||||
|
+ writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Fill in DTS structure with factory sensor values */
|
||||||
|
+static int stm_thermal_read_factory_settings(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ /* Retrieve engineering calibration temperature */
|
||||||
|
+ sensor->t0 = readl_relaxed(sensor->base + DTS_T0VALR1_OFFSET) &
|
||||||
|
+ TS1_T0_MASK;
|
||||||
|
+ if (!sensor->t0)
|
||||||
|
+ sensor->t0 = TS1_T0_VAL0;
|
||||||
|
+ else
|
||||||
|
+ sensor->t0 = TS1_T0_VAL1;
|
||||||
|
+
|
||||||
|
+ /* Retrieve fmt0 and put it on Hz */
|
||||||
|
+ sensor->fmt0 = ADJUST * (readl_relaxed(sensor->base +
|
||||||
|
+ DTS_T0VALR1_OFFSET) & TS1_FMT0_MASK);
|
||||||
|
+
|
||||||
|
+ /* Retrieve ramp coefficient */
|
||||||
|
+ sensor->ramp_coeff = readl_relaxed(sensor->base + DTS_RAMPVALR_OFFSET) &
|
||||||
|
+ TS1_RAMP_COEFF_MASK;
|
||||||
|
+
|
||||||
|
+ if (!sensor->fmt0 || !sensor->ramp_coeff) {
|
||||||
|
+ dev_err(sensor->dev, "%s: wrong setting\n", __func__);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dev_dbg(sensor->dev, "%s: T0 = %doC, FMT0 = %dHz, RAMP_COEFF = %dHz/oC",
|
||||||
|
+ __func__, sensor->t0, sensor->fmt0, sensor->ramp_coeff);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_thermal_calculate_threshold(struct stm_thermal_sensor *sensor,
|
||||||
|
+ int temp, u32 *th)
|
||||||
|
+{
|
||||||
|
+ int freqM;
|
||||||
|
+ u32 sampling_time;
|
||||||
|
+
|
||||||
|
+ /* Retrieve the number of periods to sample */
|
||||||
|
+ sampling_time = (readl_relaxed(sensor->base + DTS_CFGR1_OFFSET) &
|
||||||
|
+ TS1_SMP_TIME_MASK) >> TS1_SMP_TIME_POS;
|
||||||
|
+
|
||||||
|
+ /* Figure out the CLK_PTAT frequency for a given temperature */
|
||||||
|
+ freqM = ((temp - sensor->t0) * sensor->ramp_coeff)
|
||||||
|
+ + sensor->fmt0;
|
||||||
|
+
|
||||||
|
+ dev_dbg(sensor->dev, "%s: freqM for threshold = %d Hz",
|
||||||
|
+ __func__, freqM);
|
||||||
|
+
|
||||||
|
+ /* Figure out the threshold sample number */
|
||||||
|
+ *th = clk_get_rate(sensor->clk);
|
||||||
|
+ if (!*th)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ *th = *th / freqM;
|
||||||
|
+
|
||||||
|
+ *th *= sampling_time;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_thermal_set_threshold(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ u32 value, th;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ value = readl_relaxed(sensor->base + DTS_ITR1_OFFSET);
|
||||||
|
+
|
||||||
|
+ /* Erase threshold content */
|
||||||
|
+ value &= ~(TS1_LITTHD_MASK | TS1_HITTHD_MASK);
|
||||||
|
+
|
||||||
|
+ /* Retrieve the sample threshold number th for a given temperature */
|
||||||
|
+ ret = stm_thermal_calculate_threshold(sensor, sensor->high_temp, &th);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ value |= th & TS1_LITTHD_MASK;
|
||||||
|
+
|
||||||
|
+ if (sensor->low_temp_enabled) {
|
||||||
|
+ /* Retrieve the sample threshold */
|
||||||
|
+ ret = stm_thermal_calculate_threshold(sensor, sensor->low_temp,
|
||||||
|
+ &th);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ value |= (TS1_HITTHD_MASK & (th << TS1_HITTHD_POS));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Write value on the Low interrupt threshold */
|
||||||
|
+ writel_relaxed(value, sensor->base + DTS_ITR1_OFFSET);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Disable temperature interrupt */
|
||||||
|
+static int stm_disable_irq(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ u32 value;
|
||||||
|
+
|
||||||
|
+ /* Disable IT generation for low and high thresholds */
|
||||||
|
+ value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
|
||||||
|
+ writel_relaxed(value & ~(LOW_THRESHOLD | HIGH_THRESHOLD),
|
||||||
|
+ sensor->base + DTS_ITENR_OFFSET);
|
||||||
|
+
|
||||||
|
+ dev_dbg(sensor->dev, "%s: IT disabled on sensor side", __func__);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Enable temperature interrupt */
|
||||||
|
+static int stm_enable_irq(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ u32 value;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Code below enables High temperature threshold using a low threshold
|
||||||
|
+ * sampling value
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ /* Make sure LOW_THRESHOLD IT is clear before enabling */
|
||||||
|
+ writel_relaxed(LOW_THRESHOLD, sensor->base + DTS_CIFR_OFFSET);
|
||||||
|
+
|
||||||
|
+ /* Enable IT generation for low threshold */
|
||||||
|
+ value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
|
||||||
|
+ value |= LOW_THRESHOLD;
|
||||||
|
+
|
||||||
|
+ /* Enable the low temperature threshold if needed */
|
||||||
|
+ if (sensor->low_temp_enabled) {
|
||||||
|
+ /* Make sure HIGH_THRESHOLD IT is clear before enabling */
|
||||||
|
+ writel_relaxed(HIGH_THRESHOLD, sensor->base + DTS_CIFR_OFFSET);
|
||||||
|
+
|
||||||
|
+ /* Enable IT generation for high threshold */
|
||||||
|
+ value |= HIGH_THRESHOLD;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Enable thresholds */
|
||||||
|
+ writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET);
|
||||||
|
+
|
||||||
|
+ dev_dbg(sensor->dev, "%s: IT enabled on sensor side", __func__);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_thermal_update_threshold(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ sensor->mode = THERMAL_DEVICE_DISABLED;
|
||||||
|
+
|
||||||
|
+ ret = stm_sensor_power_off(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = stm_disable_irq(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = stm_thermal_set_threshold(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = stm_enable_irq(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = stm_sensor_power_on(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ sensor->mode = THERMAL_DEVICE_ENABLED;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Callback to get temperature from HW */
|
||||||
|
+static int stm_thermal_get_temp(void *data, int *temp)
|
||||||
|
+{
|
||||||
|
+ struct stm_thermal_sensor *sensor = data;
|
||||||
|
+ u32 sampling_time;
|
||||||
|
+ int freqM, ret;
|
||||||
|
+
|
||||||
|
+ if (sensor->mode != THERMAL_DEVICE_ENABLED)
|
||||||
|
+ return -EAGAIN;
|
||||||
|
+
|
||||||
|
+ /* Retrieve the number of samples */
|
||||||
|
+ ret = readl_poll_timeout(sensor->base + DTS_DR_OFFSET, freqM,
|
||||||
|
+ (freqM & TS1_MFREQ_MASK), STARTUP_TIME,
|
||||||
|
+ POLL_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ if (!freqM)
|
||||||
|
+ return -ENODATA;
|
||||||
|
+
|
||||||
|
+ /* Retrieve the number of periods sampled */
|
||||||
|
+ sampling_time = (readl_relaxed(sensor->base + DTS_CFGR1_OFFSET) &
|
||||||
|
+ TS1_SMP_TIME_MASK) >> TS1_SMP_TIME_POS;
|
||||||
|
+
|
||||||
|
+ /* Figure out the number of samples per period */
|
||||||
|
+ freqM /= sampling_time;
|
||||||
|
+
|
||||||
|
+ /* Figure out the CLK_PTAT frequency */
|
||||||
|
+ freqM = clk_get_rate(sensor->clk) / freqM;
|
||||||
|
+ if (!freqM)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ dev_dbg(sensor->dev, "%s: freqM=%d\n", __func__, freqM);
|
||||||
|
+
|
||||||
|
+ /* Figure out the temperature in mili celsius */
|
||||||
|
+ *temp = mcelsius(sensor->t0 + ((freqM - sensor->fmt0) /
|
||||||
|
+ sensor->ramp_coeff));
|
||||||
|
+
|
||||||
|
+ dev_dbg(sensor->dev, "%s: temperature = %d millicelsius",
|
||||||
|
+ __func__, *temp);
|
||||||
|
+
|
||||||
|
+ /* Update thresholds */
|
||||||
|
+ if (sensor->num_trips > 1) {
|
||||||
|
+ /* Update alarm threshold value to next higher trip point */
|
||||||
|
+ if (sensor->high_temp == sensor->temp_passive &&
|
||||||
|
+ celsius(*temp) >= sensor->temp_passive) {
|
||||||
|
+ sensor->high_temp = sensor->temp_critical;
|
||||||
|
+ sensor->low_temp = sensor->temp_passive;
|
||||||
|
+ sensor->low_temp_enabled = true;
|
||||||
|
+ ret = stm_thermal_update_threshold(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (sensor->high_temp == sensor->temp_critical &&
|
||||||
|
+ celsius(*temp) < sensor->temp_passive) {
|
||||||
|
+ sensor->high_temp = sensor->temp_passive;
|
||||||
|
+ sensor->low_temp_enabled = false;
|
||||||
|
+ ret = stm_thermal_update_threshold(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Re-enable alarm IRQ if temperature below critical
|
||||||
|
+ * temperature
|
||||||
|
+ */
|
||||||
|
+ if (!sensor->irq_enabled &&
|
||||||
|
+ (celsius(*temp) < sensor->temp_critical)) {
|
||||||
|
+ sensor->irq_enabled = true;
|
||||||
|
+ enable_irq(sensor->irq);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Registers DTS irq to be visible by GIC */
|
||||||
|
+static int stm_register_irq(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ struct device *dev = sensor->dev;
|
||||||
|
+ struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ sensor->irq = platform_get_irq(pdev, 0);
|
||||||
|
+ if (sensor->irq < 0) {
|
||||||
|
+ dev_err(dev, "%s: Unable to find IRQ\n", __func__);
|
||||||
|
+ return sensor->irq;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = devm_request_threaded_irq(dev, sensor->irq,
|
||||||
|
+ stm_thermal_alarm_irq,
|
||||||
|
+ stm_thermal_alarm_irq_thread,
|
||||||
|
+ IRQF_ONESHOT,
|
||||||
|
+ dev->driver->name, sensor);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(dev, "%s: Failed to register IRQ %d\n", __func__,
|
||||||
|
+ sensor->irq);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sensor->irq_enabled = true;
|
||||||
|
+
|
||||||
|
+ dev_dbg(dev, "%s: thermal IRQ registered", __func__);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_thermal_sensor_off(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = stm_sensor_power_off(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ clk_disable_unprepare(sensor->clk);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_thermal_prepare(struct stm_thermal_sensor *sensor)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+ struct device *dev = sensor->dev;
|
||||||
|
+
|
||||||
|
+ ret = clk_prepare_enable(sensor->clk);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = stm_thermal_read_factory_settings(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto thermal_unprepare;
|
||||||
|
+
|
||||||
|
+ ret = stm_thermal_calibration(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto thermal_unprepare;
|
||||||
|
+
|
||||||
|
+ /* Set threshold(s) for IRQ */
|
||||||
|
+ ret = stm_thermal_set_threshold(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto thermal_unprepare;
|
||||||
|
+
|
||||||
|
+ ret = stm_enable_irq(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto thermal_unprepare;
|
||||||
|
+
|
||||||
|
+ ret = stm_sensor_power_on(sensor);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(dev, "%s: failed to power on sensor\n", __func__);
|
||||||
|
+ goto irq_disable;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+irq_disable:
|
||||||
|
+ stm_disable_irq(sensor);
|
||||||
|
+
|
||||||
|
+thermal_unprepare:
|
||||||
|
+ clk_disable_unprepare(sensor->clk);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_PM_SLEEP
|
||||||
|
+static int stm_thermal_suspend(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+ struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
+ struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ ret = stm_thermal_sensor_off(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ sensor->mode = THERMAL_DEVICE_DISABLED;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_thermal_resume(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+ struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
+ struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ ret = stm_thermal_prepare(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ sensor->mode = THERMAL_DEVICE_ENABLED;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+#endif /* CONFIG_PM_SLEEP */
|
||||||
|
+
|
||||||
|
+SIMPLE_DEV_PM_OPS(stm_thermal_pm_ops, stm_thermal_suspend, stm_thermal_resume);
|
||||||
|
+
|
||||||
|
+static const struct thermal_zone_of_device_ops stm_tz_ops = {
|
||||||
|
+ .get_temp = stm_thermal_get_temp,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct of_device_id stm_thermal_of_match[] = {
|
||||||
|
+ { .compatible = "st,stm32-thermal"},
|
||||||
|
+ { /* sentinel */ }
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, stm_thermal_of_match);
|
||||||
|
+
|
||||||
|
+static int stm_thermal_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct stm_thermal_sensor *sensor;
|
||||||
|
+ struct resource *res;
|
||||||
|
+ const struct thermal_trip *trip;
|
||||||
|
+ void __iomem *base;
|
||||||
|
+ int ret, i;
|
||||||
|
+
|
||||||
|
+ if (!pdev->dev.of_node) {
|
||||||
|
+ dev_err(&pdev->dev, "%s: device tree node not found\n",
|
||||||
|
+ __func__);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
|
||||||
|
+ if (!sensor)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ platform_set_drvdata(pdev, sensor);
|
||||||
|
+
|
||||||
|
+ sensor->dev = &pdev->dev;
|
||||||
|
+
|
||||||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
+ base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
+ if (IS_ERR(base))
|
||||||
|
+ return PTR_ERR(base);
|
||||||
|
+
|
||||||
|
+ /* Populate sensor */
|
||||||
|
+ sensor->base = base;
|
||||||
|
+
|
||||||
|
+ sensor->clk = devm_clk_get(&pdev->dev, "pclk");
|
||||||
|
+ if (IS_ERR(sensor->clk)) {
|
||||||
|
+ dev_err(&pdev->dev, "%s: failed to fetch PCLK clock\n",
|
||||||
|
+ __func__);
|
||||||
|
+ return PTR_ERR(sensor->clk);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Register IRQ into GIC */
|
||||||
|
+ ret = stm_register_irq(sensor);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ sensor->th_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
|
||||||
|
+ sensor,
|
||||||
|
+ &stm_tz_ops);
|
||||||
|
+
|
||||||
|
+ if (IS_ERR(sensor->th_dev)) {
|
||||||
|
+ dev_err(&pdev->dev, "%s: thermal zone sensor registering KO\n",
|
||||||
|
+ __func__);
|
||||||
|
+ ret = PTR_ERR(sensor->th_dev);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!sensor->th_dev->ops->get_crit_temp) {
|
||||||
|
+ /* Critical point must be provided */
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto err_tz;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = sensor->th_dev->ops->get_crit_temp(sensor->th_dev,
|
||||||
|
+ &sensor->temp_critical);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(&pdev->dev,
|
||||||
|
+ "Not able to read critical_temp: %d\n", ret);
|
||||||
|
+ goto err_tz;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sensor->temp_critical = celsius(sensor->temp_critical);
|
||||||
|
+
|
||||||
|
+ /* Set thresholds for IRQ */
|
||||||
|
+ sensor->high_temp = sensor->temp_critical;
|
||||||
|
+
|
||||||
|
+ trip = of_thermal_get_trip_points(sensor->th_dev);
|
||||||
|
+ sensor->num_trips = of_thermal_get_ntrips(sensor->th_dev);
|
||||||
|
+
|
||||||
|
+ /* Find out passive temperature if it exists */
|
||||||
|
+ for (i = (sensor->num_trips - 1); i >= 0; i--) {
|
||||||
|
+ if (trip[i].type == THERMAL_TRIP_PASSIVE) {
|
||||||
|
+ sensor->temp_passive = celsius(trip[i].temperature);
|
||||||
|
+ /* Update high temperature threshold */
|
||||||
|
+ sensor->high_temp = sensor->temp_passive;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Ensure low_temp_enabled flag is disabled.
|
||||||
|
+ * By disabling low_temp_enabled, low threshold IT will not be
|
||||||
|
+ * configured neither enabled because it is not needed as high
|
||||||
|
+ * threshold is set on the lowest temperature trip point after
|
||||||
|
+ * probe.
|
||||||
|
+ */
|
||||||
|
+ sensor->low_temp_enabled = false;
|
||||||
|
+
|
||||||
|
+ /* Configure and enable HW sensor */
|
||||||
|
+ ret = stm_thermal_prepare(sensor);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(&pdev->dev,
|
||||||
|
+ "Not able to enable sensor: %d\n", ret);
|
||||||
|
+ goto err_tz;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Thermal_zone doesn't enable hwmon as default,
|
||||||
|
+ * enable it here
|
||||||
|
+ */
|
||||||
|
+ sensor->th_dev->tzp->no_hwmon = false;
|
||||||
|
+ ret = thermal_add_hwmon_sysfs(sensor->th_dev);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto err_tz;
|
||||||
|
+
|
||||||
|
+ sensor->mode = THERMAL_DEVICE_ENABLED;
|
||||||
|
+
|
||||||
|
+ dev_info(&pdev->dev, "%s: Driver initialized successfully\n",
|
||||||
|
+ __func__);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+err_tz:
|
||||||
|
+ thermal_zone_of_sensor_unregister(&pdev->dev, sensor->th_dev);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm_thermal_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ stm_thermal_sensor_off(sensor);
|
||||||
|
+ thermal_remove_hwmon_sysfs(sensor->th_dev);
|
||||||
|
+ thermal_zone_of_sensor_unregister(&pdev->dev, sensor->th_dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct platform_driver stm_thermal_driver = {
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "stm_thermal",
|
||||||
|
+ .pm = &stm_thermal_pm_ops,
|
||||||
|
+ .of_match_table = stm_thermal_of_match,
|
||||||
|
+ },
|
||||||
|
+ .probe = stm_thermal_probe,
|
||||||
|
+ .remove = stm_thermal_remove,
|
||||||
|
+};
|
||||||
|
+module_platform_driver(stm_thermal_driver);
|
||||||
|
+
|
||||||
|
+MODULE_DESCRIPTION("STMicroelectronics STM32 Thermal Sensor Driver");
|
||||||
|
+MODULE_AUTHOR("David Hernandez Sanchez <david.hernandezsanchez@st.com>");
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
+MODULE_ALIAS("platform:stm_thermal");
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,372 @@
|
||||||
|
From 222782ff647dfeb33bb442031792a893372fad82 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||||
|
Date: Mon, 26 Nov 2018 14:43:58 +0100
|
||||||
|
Subject: [PATCH 25/52] ARM-stm32mp1-r0-rc2-REMOTEPROC
|
||||||
|
|
||||||
|
---
|
||||||
|
.../devicetree/bindings/remoteproc/rproc-srm.txt | 14 ++-
|
||||||
|
.../devicetree/bindings/remoteproc/stm32-rproc.txt | 15 ++-
|
||||||
|
drivers/nvmem/stm32-romem.c | 44 +++++----
|
||||||
|
drivers/remoteproc/rproc_srm_core.h | 14 +--
|
||||||
|
drivers/remoteproc/rproc_srm_dev.c | 103 +--------------------
|
||||||
|
drivers/remoteproc/stm32_rproc.c | 2 +-
|
||||||
|
6 files changed, 42 insertions(+), 150 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt
|
||||||
|
index dce10c0..19a5255 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt
|
||||||
|
@@ -23,12 +23,16 @@ Optional properties:
|
||||||
|
- clocks: clocks required by the coprocessor
|
||||||
|
- clock-names: see clock-bindings.txt
|
||||||
|
- pinctrl-x: pins configurations required by the coprocessor
|
||||||
|
-- pinctrl-names: see pinctrl-bindings.txt.
|
||||||
|
- "rproc_default" is a special pin configuration which is applied except
|
||||||
|
- if the 'early-booted' property is set.
|
||||||
|
- In a general way, it is recommended to use names prefixed with "rproc_".
|
||||||
|
+ The SRM reserves the pins for the coprocessor, which prevents the local
|
||||||
|
+ processor to use them.
|
||||||
|
+- pinctrl-names: all names must be prefixed with "rproc_" (ex: "rproc_default").
|
||||||
|
+ This rule must be strictly followed in order to prevent the SRM to
|
||||||
|
+ (over)write a pin configuration which is done by the coprocessor.
|
||||||
|
- x-supply: power supplies required by the coprocessor
|
||||||
|
-- interrupts: see interrupts.txt
|
||||||
|
+- interrupts: external interrupts configurations required by the coprocessor.
|
||||||
|
+ This is optional since the configuration is done by the coprocessor.
|
||||||
|
+ When defined, the SRM (over)writes the configuration which allows the
|
||||||
|
+ interrupt controller to check for configuration conflicts.
|
||||||
|
- interrupt-parent: see interrupts.txt
|
||||||
|
- interrupt-names: see interrupts.txt
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt b/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt
|
||||||
|
index ee00f1c..7df6a26 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt
|
||||||
|
@@ -33,18 +33,15 @@ Optional properties:
|
||||||
|
- from local to remote = send message
|
||||||
|
- from remote to local = send message ack
|
||||||
|
- a channel (b) working the opposite direction of channel (a)
|
||||||
|
- - a channel (c) used for two different purposes:
|
||||||
|
- - used by the remote proc to signal when it has completed
|
||||||
|
- its critical initalisation.
|
||||||
|
- Mono-directional channel: from remote to local
|
||||||
|
- - used by the local proc to notify the remote proc that it
|
||||||
|
- is about to be shut down.
|
||||||
|
- Mono-directional channel: from local to remote, where ACK
|
||||||
|
- from the remote means that it is ready for shutdown
|
||||||
|
+ - a channel (c) used by the local proc to notify the remote proc
|
||||||
|
+ that it is about to be shut down.
|
||||||
|
+ Mono-directional channel:
|
||||||
|
+ - from local to remote, where ACK from the remote means
|
||||||
|
+ that it is ready for shutdown
|
||||||
|
- mbox-names: This property is required if the mboxes property is used.
|
||||||
|
- must be "vq0" for channel (a)
|
||||||
|
- must be "vq1" for channel (b)
|
||||||
|
- - must be "init_shdn" for channel (c)
|
||||||
|
+ - must be "shutdown" for channel (c)
|
||||||
|
- memory-region: phandle to the reserved memory node to be associated with the
|
||||||
|
remoteproc device.
|
||||||
|
- st,syscfg-pdds: Reference to the system configuration controlling the remote
|
||||||
|
diff --git a/drivers/nvmem/stm32-romem.c b/drivers/nvmem/stm32-romem.c
|
||||||
|
index 198872f..34b388c 100644
|
||||||
|
--- a/drivers/nvmem/stm32-romem.c
|
||||||
|
+++ b/drivers/nvmem/stm32-romem.c
|
||||||
|
@@ -19,6 +19,12 @@
|
||||||
|
#define STM32_SMC_WRITE_SHADOW 0x03
|
||||||
|
#define STM32_SMC_READ_OTP 0x04
|
||||||
|
|
||||||
|
+/* shadow registers offest */
|
||||||
|
+#define STM32MP15_BSEC_DATA0 0x200
|
||||||
|
+
|
||||||
|
+/* 32 (x 32-bits) lower shadow registers */
|
||||||
|
+#define STM32MP15_BSEC_NUM_LOWER 32
|
||||||
|
+
|
||||||
|
struct stm32_romem_cfg {
|
||||||
|
int size;
|
||||||
|
};
|
||||||
|
@@ -77,13 +83,21 @@ static int stm32_bsec_read(void *context, unsigned int offset, void *buf,
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = roffset; (i < roffset + rbytes); i += 4) {
|
||||||
|
- ret = stm32_bsec_smc(STM32_SMC_READ_OTP, i >> 2, 0, &val);
|
||||||
|
- if (ret) {
|
||||||
|
- dev_err(priv->dev, "Failed to read data%d (%d)\n",
|
||||||
|
- i >> 2, ret);
|
||||||
|
- return ret;
|
||||||
|
+ u32 otp = i >> 2;
|
||||||
|
+
|
||||||
|
+ if (otp < STM32MP15_BSEC_NUM_LOWER) {
|
||||||
|
+ /* read lower data from shadow registers */
|
||||||
|
+ val = readl_relaxed(
|
||||||
|
+ priv->base + STM32MP15_BSEC_DATA0 + i);
|
||||||
|
+ } else {
|
||||||
|
+ ret = stm32_bsec_smc(STM32_SMC_READ_SHADOW, otp, 0,
|
||||||
|
+ &val);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(priv->dev, "Can't read data%d (%d)\n",
|
||||||
|
+ otp, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
-
|
||||||
|
/* skip first bytes in case of unaligned read */
|
||||||
|
if (skip_bytes)
|
||||||
|
size = min(bytes, (size_t)(4 - skip_bytes));
|
||||||
|
@@ -127,7 +141,6 @@ static int stm32_romem_probe(struct platform_device *pdev)
|
||||||
|
const struct stm32_romem_cfg *cfg;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct stm32_romem_priv *priv;
|
||||||
|
- struct nvmem_device *nvmem;
|
||||||
|
struct resource *res;
|
||||||
|
|
||||||
|
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
@@ -154,26 +167,12 @@ static int stm32_romem_probe(struct platform_device *pdev)
|
||||||
|
priv->cfg.size = resource_size(res);
|
||||||
|
priv->cfg.reg_read = stm32_romem_read;
|
||||||
|
} else {
|
||||||
|
- priv->cfg.read_only = false;
|
||||||
|
priv->cfg.size = cfg->size;
|
||||||
|
priv->cfg.reg_read = stm32_bsec_read;
|
||||||
|
priv->cfg.reg_write = stm32_bsec_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
- nvmem = nvmem_register(&priv->cfg);
|
||||||
|
- if (IS_ERR(nvmem))
|
||||||
|
- return PTR_ERR(nvmem);
|
||||||
|
-
|
||||||
|
- platform_set_drvdata(pdev, nvmem);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int stm32_romem_remove(struct platform_device *pdev)
|
||||||
|
-{
|
||||||
|
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
|
||||||
|
-
|
||||||
|
- return nvmem_unregister(nvmem);
|
||||||
|
+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct stm32_romem_cfg stm32mp15_bsec_cfg = {
|
||||||
|
@@ -191,7 +190,6 @@ MODULE_DEVICE_TABLE(of, stm32_romem_of_match);
|
||||||
|
|
||||||
|
static struct platform_driver stm32_romem_driver = {
|
||||||
|
.probe = stm32_romem_probe,
|
||||||
|
- .remove = stm32_romem_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "stm32-romem",
|
||||||
|
.of_match_table = of_match_ptr(stm32_romem_of_match),
|
||||||
|
diff --git a/drivers/remoteproc/rproc_srm_core.h b/drivers/remoteproc/rproc_srm_core.h
|
||||||
|
index 7915f35..7dffdb38 100644
|
||||||
|
--- a/drivers/remoteproc/rproc_srm_core.h
|
||||||
|
+++ b/drivers/remoteproc/rproc_srm_core.h
|
||||||
|
@@ -20,12 +20,10 @@
|
||||||
|
/**
|
||||||
|
* Resource type used in resource manager rpmsg:
|
||||||
|
* RPROC_SRM_RSC_CLOCK: clock resource
|
||||||
|
- * RPROC_SRM_RSC_PIN: pin resource
|
||||||
|
* RPROC_SRM_RSC_REGU: regulator resource
|
||||||
|
*/
|
||||||
|
#define RPROC_SRM_RSC_CLOCK 0x00
|
||||||
|
-#define RPROC_SRM_RSC_PIN 0x01
|
||||||
|
-#define RPROC_SRM_RSC_REGU 0x02
|
||||||
|
+#define RPROC_SRM_RSC_REGU 0x01
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct clock_cfg - clock configuration used in resource manager rpmsg
|
||||||
|
@@ -63,14 +61,6 @@ struct regu_cfg {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
- * struct pin_cfg - pin configuration used in resource manager rpmsg
|
||||||
|
- * @name: current pin configuration name (meaningful in GetConfig message)
|
||||||
|
- */
|
||||||
|
-struct pin_cfg {
|
||||||
|
- u8 name[16];
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-/**
|
||||||
|
* struct rpmsg_srm_msg - message structure used between processors to
|
||||||
|
* dynamically update resources configuration
|
||||||
|
* @message_type: type of the message: see RPROC_SRM_MSG*
|
||||||
|
@@ -81,7 +71,6 @@ struct pin_cfg {
|
||||||
|
* see RPROC_SRM_RSC*
|
||||||
|
* @clock_cfg: clock config - relevant if &rsc_type is RPROC_SRM_RSC_CLOCK
|
||||||
|
* @regu_cfg: regulator config - relevant if &rsc_type is RPROC_SRM_RSC_REGU
|
||||||
|
- * @pin_cfg: pin config - relevant if &rsc_type is RPROC_SRM_RSC_PIN
|
||||||
|
*/
|
||||||
|
struct rpmsg_srm_msg {
|
||||||
|
u32 message_type;
|
||||||
|
@@ -90,7 +79,6 @@ struct rpmsg_srm_msg {
|
||||||
|
union {
|
||||||
|
struct clock_cfg clock_cfg;
|
||||||
|
struct regu_cfg regu_cfg;
|
||||||
|
- struct pin_cfg pin_cfg;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/drivers/remoteproc/rproc_srm_dev.c b/drivers/remoteproc/rproc_srm_dev.c
|
||||||
|
index b026f961..7dc99c5 100644
|
||||||
|
--- a/drivers/remoteproc/rproc_srm_dev.c
|
||||||
|
+++ b/drivers/remoteproc/rproc_srm_dev.c
|
||||||
|
@@ -31,7 +31,6 @@ struct rproc_srm_pin_info {
|
||||||
|
struct list_head list;
|
||||||
|
unsigned int index;
|
||||||
|
char *name;
|
||||||
|
- bool selected;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rproc_srm_regu_info {
|
||||||
|
@@ -544,83 +543,6 @@ static int rproc_srm_dev_regus_get(struct rproc_srm_dev *rproc_srm_dev)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pins */
|
||||||
|
-static int rproc_srm_dev_pin_set_cfg(struct rproc_srm_dev *rproc_srm_dev,
|
||||||
|
- struct pin_cfg *cfg)
|
||||||
|
-{
|
||||||
|
- struct rproc_srm_pin_info *pi, *p = NULL;
|
||||||
|
- struct device *dev = rproc_srm_dev->dev;
|
||||||
|
- struct pinctrl_state *state;
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
- list_for_each_entry(pi, &rproc_srm_dev->pin_list_head, list) {
|
||||||
|
- if (!strcmp(pi->name, cfg->name)) {
|
||||||
|
- p = pi;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (!p) {
|
||||||
|
- dev_err(dev, "unknown pin config (%s)\n", cfg->name);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- state = pinctrl_lookup_state(rproc_srm_dev->pctrl, cfg->name);
|
||||||
|
- if (IS_ERR(state)) {
|
||||||
|
- dev_err(dev, "cannot get pin config (%s)\n", cfg->name);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- ret = pinctrl_select_state(rproc_srm_dev->pctrl, state);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- dev_err(dev, "cannot set pin config (%s)\n", cfg->name);
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- list_for_each_entry(pi, &rproc_srm_dev->pin_list_head, list) {
|
||||||
|
- pi->selected = (pi == p);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- dev_dbg(dev, "pin config (%s) selected\n", p->name);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int rproc_srm_dev_pin_get_cfg(struct rproc_srm_dev *rproc_srm_dev,
|
||||||
|
- struct pin_cfg *cfg)
|
||||||
|
-{
|
||||||
|
- struct rproc_srm_pin_info *p;
|
||||||
|
-
|
||||||
|
- list_for_each_entry(p, &rproc_srm_dev->pin_list_head, list) {
|
||||||
|
- if (p->selected) {
|
||||||
|
- strlcpy(cfg->name, p->name, sizeof(cfg->name));
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- dev_warn(rproc_srm_dev->dev, "cannot find selected pin state\n");
|
||||||
|
- strcpy(cfg->name, "");
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int rproc_srm_dev_pins_setup(struct rproc_srm_dev *rproc_srm_dev)
|
||||||
|
-{
|
||||||
|
- struct rproc_srm_pin_info *p;
|
||||||
|
- struct pin_cfg cfg = { .name = "rproc_default" };
|
||||||
|
-
|
||||||
|
- if (rproc_srm_dev->early_boot)
|
||||||
|
- /* in early_boot mode do not update pin config */
|
||||||
|
- return 0;
|
||||||
|
-
|
||||||
|
- /* set the "rproc_default" pin config if defined */
|
||||||
|
- list_for_each_entry(p, &rproc_srm_dev->pin_list_head, list) {
|
||||||
|
- if (!strcmp(p->name, cfg.name))
|
||||||
|
- return rproc_srm_dev_pin_set_cfg(rproc_srm_dev, &cfg);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void rproc_srm_dev_pins_put(struct rproc_srm_dev *rproc_srm_dev)
|
||||||
|
{
|
||||||
|
struct device *dev = rproc_srm_dev->dev;
|
||||||
|
@@ -677,11 +599,9 @@ static int rproc_srm_dev_pins_get(struct rproc_srm_dev *rproc_srm_dev)
|
||||||
|
}
|
||||||
|
p->name = devm_kstrdup(dev, name, GFP_KERNEL);
|
||||||
|
|
||||||
|
- if (!strcmp(p->name, PINCTRL_STATE_DEFAULT)) {
|
||||||
|
- if (rproc_srm_dev->early_boot)
|
||||||
|
- dev_warn(dev, "pin config potentially overwritten!\n");
|
||||||
|
- p->selected = true;
|
||||||
|
- }
|
||||||
|
+ /* pinctrl-names shall not be "default" (but "rproc_default") */
|
||||||
|
+ if (!strcmp(p->name, PINCTRL_STATE_DEFAULT))
|
||||||
|
+ dev_warn(dev, "pin config potentially overwritten!\n");
|
||||||
|
|
||||||
|
p->index = i;
|
||||||
|
|
||||||
|
@@ -726,13 +646,6 @@ static int rproc_srm_dev_notify_cb(struct notifier_block *nb, unsigned long evt,
|
||||||
|
ret = rproc_srm_dev_clock_get_cfg(rproc_srm_dev,
|
||||||
|
&o.clock_cfg);
|
||||||
|
break;
|
||||||
|
- case RPROC_SRM_RSC_PIN:
|
||||||
|
- ret = rproc_srm_dev_pin_set_cfg(rproc_srm_dev,
|
||||||
|
- &i->pin_cfg);
|
||||||
|
- if (!ret)
|
||||||
|
- ret = rproc_srm_dev_pin_get_cfg(rproc_srm_dev,
|
||||||
|
- &o.pin_cfg);
|
||||||
|
- break;
|
||||||
|
case RPROC_SRM_RSC_REGU:
|
||||||
|
ret = rproc_srm_dev_regu_set_cfg(rproc_srm_dev,
|
||||||
|
&i->regu_cfg);
|
||||||
|
@@ -752,10 +665,6 @@ static int rproc_srm_dev_notify_cb(struct notifier_block *nb, unsigned long evt,
|
||||||
|
ret = rproc_srm_dev_clock_get_cfg(rproc_srm_dev,
|
||||||
|
&o.clock_cfg);
|
||||||
|
break;
|
||||||
|
- case RPROC_SRM_RSC_PIN:
|
||||||
|
- ret = rproc_srm_dev_pin_get_cfg(rproc_srm_dev,
|
||||||
|
- &o.pin_cfg);
|
||||||
|
- break;
|
||||||
|
case RPROC_SRM_RSC_REGU:
|
||||||
|
ret = rproc_srm_dev_regu_get_cfg(rproc_srm_dev,
|
||||||
|
&o.regu_cfg);
|
||||||
|
@@ -810,11 +719,7 @@ rproc_srm_dev_bind(struct device *dev, struct device *master, void *data)
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
- ret = rproc_srm_dev_pins_setup(rproc_srm_dev);
|
||||||
|
- if (ret)
|
||||||
|
- return ret;
|
||||||
|
-
|
||||||
|
- /* For IRQs: nothing to setup */
|
||||||
|
+ /* For pins and IRQs: nothing to setup */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
|
||||||
|
index 998de67..548afdd 100644
|
||||||
|
--- a/drivers/remoteproc/stm32_rproc.c
|
||||||
|
+++ b/drivers/remoteproc/stm32_rproc.c
|
||||||
|
@@ -29,7 +29,7 @@
|
||||||
|
|
||||||
|
#define STM32_MBX_VQ0 "vq0"
|
||||||
|
#define STM32_MBX_VQ1 "vq1"
|
||||||
|
-#define STM32_MBX_SHUTDOWN "init_shdn"
|
||||||
|
+#define STM32_MBX_SHUTDOWN "shutdown"
|
||||||
|
|
||||||
|
struct stm32_syscon {
|
||||||
|
struct regmap *map;
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,273 @@
|
||||||
|
From f03da721a19075ead436b2edbe4c4080feb8dac8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||||
|
Date: Mon, 26 Nov 2018 14:44:24 +0100
|
||||||
|
Subject: [PATCH 26/52] ARM-stm32mp1-r0-rc2-NET
|
||||||
|
|
||||||
|
---
|
||||||
|
.../devicetree/bindings/net/stm32-dwmac.txt | 6 +-
|
||||||
|
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 102 +++++++++++++++++----
|
||||||
|
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +
|
||||||
|
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 6 ++
|
||||||
|
4 files changed, 94 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.txt b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||||
|
index 1341012..f42dc68 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||||
|
@@ -24,9 +24,9 @@ Required properties:
|
||||||
|
encompases the glue register, and the offset of the control register.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
-- clock-names: For MPU family "mac-clk-ck" for PHY without quartz
|
||||||
|
-- st,int-phyclk (boolean) : valid only where PHY do not have quartz and need to be clock
|
||||||
|
- by RCC
|
||||||
|
+- clock-names: For MPU family "eth-ck" for PHY without quartz
|
||||||
|
+- st,eth_clk_sel (boolean) : set this property in RGMII PHY when you do not want use 125Mhz
|
||||||
|
+- st,eth_ref_clk_sel (boolean) : set this property in RMII mode when you have PHY without crystal 50MHz
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||||
|
index d1cf145..545b168 100644
|
||||||
|
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||||
|
@@ -25,9 +25,24 @@
|
||||||
|
|
||||||
|
#define SYSCFG_MCU_ETH_MASK BIT(23)
|
||||||
|
#define SYSCFG_MP1_ETH_MASK GENMASK(23, 16)
|
||||||
|
+#define SYSCFG_PMCCLRR_OFFSET 0x40
|
||||||
|
|
||||||
|
#define SYSCFG_PMCR_ETH_CLK_SEL BIT(16)
|
||||||
|
#define SYSCFG_PMCR_ETH_REF_CLK_SEL BIT(17)
|
||||||
|
+
|
||||||
|
+/* Ethernet PHY interface selection in register SYSCFG Configuration
|
||||||
|
+ *------------------------------------------
|
||||||
|
+ * src |BIT(23)| BIT(22)| BIT(21)|BIT(20)|
|
||||||
|
+ *------------------------------------------
|
||||||
|
+ * MII | 0 | 0 | 0 | 1 |
|
||||||
|
+ *------------------------------------------
|
||||||
|
+ * GMII | 0 | 0 | 0 | 0 |
|
||||||
|
+ *------------------------------------------
|
||||||
|
+ * RGMII | 0 | 0 | 1 | n/a |
|
||||||
|
+ *------------------------------------------
|
||||||
|
+ * RMII | 1 | 0 | 0 | n/a |
|
||||||
|
+ *------------------------------------------
|
||||||
|
+ */
|
||||||
|
#define SYSCFG_PMCR_ETH_SEL_MII BIT(20)
|
||||||
|
#define SYSCFG_PMCR_ETH_SEL_RGMII BIT(21)
|
||||||
|
#define SYSCFG_PMCR_ETH_SEL_RMII BIT(23)
|
||||||
|
@@ -35,15 +50,54 @@
|
||||||
|
#define SYSCFG_MCU_ETH_SEL_MII 0
|
||||||
|
#define SYSCFG_MCU_ETH_SEL_RMII 1
|
||||||
|
|
||||||
|
+/* STM32MP1 register definitions
|
||||||
|
+ *
|
||||||
|
+ * Below table summarizes the clock requirement and clock sources for
|
||||||
|
+ * supported phy interface modes.
|
||||||
|
+ * __________________________________________________________________________
|
||||||
|
+ *|PHY_MODE | Normal | PHY wo crystal| PHY wo crystal |No 125Mhz from PHY|
|
||||||
|
+ *| | | 25MHz | 50MHz | |
|
||||||
|
+ * ---------------------------------------------------------------------------
|
||||||
|
+ *| MII | - | eth-ck | n/a | n/a |
|
||||||
|
+ *| | | | | |
|
||||||
|
+ * ---------------------------------------------------------------------------
|
||||||
|
+ *| GMII | - | eth-ck | n/a | n/a |
|
||||||
|
+ *| | | | | |
|
||||||
|
+ * ---------------------------------------------------------------------------
|
||||||
|
+ *| RGMII | - | eth-ck | n/a | eth-ck (no pin) |
|
||||||
|
+ *| | | | | st,eth_clk_sel |
|
||||||
|
+ * ---------------------------------------------------------------------------
|
||||||
|
+ *| RMII | - | eth-ck | eth-ck | n/a |
|
||||||
|
+ *| | | | st,eth_ref_clk_sel | |
|
||||||
|
+ * ---------------------------------------------------------------------------
|
||||||
|
+ *
|
||||||
|
+ * BIT(17) : set this bit in RMII mode when you have PHY without crystal 50MHz
|
||||||
|
+ * BIT(16) : set this bit in GMII/RGMII PHY when you do not want use 125Mhz
|
||||||
|
+ * from PHY
|
||||||
|
+ *-----------------------------------------------------
|
||||||
|
+ * src | BIT(17) | BIT(16) |
|
||||||
|
+ *-----------------------------------------------------
|
||||||
|
+ * MII | n/a | n/a |
|
||||||
|
+ *-----------------------------------------------------
|
||||||
|
+ * GMII | n/a | st,eth_clk_sel |
|
||||||
|
+ *-----------------------------------------------------
|
||||||
|
+ * RGMII | n/a | st,eth_clk_sel |
|
||||||
|
+ *-----------------------------------------------------
|
||||||
|
+ * RMII | st,eth_ref_clk_sel | n/a |
|
||||||
|
+ *-----------------------------------------------------
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
struct stm32_dwmac {
|
||||||
|
struct clk *clk_tx;
|
||||||
|
struct clk *clk_rx;
|
||||||
|
struct clk *clk_eth_ck;
|
||||||
|
struct clk *clk_ethstp;
|
||||||
|
struct clk *syscfg_clk;
|
||||||
|
- bool int_phyclk; /* Clock from RCC to drive PHY */
|
||||||
|
+ int eth_clk_sel_reg;
|
||||||
|
+ int eth_ref_clk_sel_reg;
|
||||||
|
int irq_pwr_wakeup;
|
||||||
|
- u32 mode_reg; /* MAC glue-logic mode register */
|
||||||
|
+ u32 mode_reg; /* MAC glue-logic mode register */
|
||||||
|
struct regmap *regmap;
|
||||||
|
u32 speed;
|
||||||
|
const struct stm32_ops *ops;
|
||||||
|
@@ -103,7 +157,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
- if (dwmac->int_phyclk) {
|
||||||
|
+ if (dwmac->clk_eth_ck) {
|
||||||
|
ret = clk_prepare_enable(dwmac->clk_eth_ck);
|
||||||
|
if (ret) {
|
||||||
|
clk_disable_unprepare(dwmac->syscfg_clk);
|
||||||
|
@@ -112,7 +166,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clk_disable_unprepare(dwmac->syscfg_clk);
|
||||||
|
- if (dwmac->int_phyclk)
|
||||||
|
+ if (dwmac->clk_eth_ck)
|
||||||
|
clk_disable_unprepare(dwmac->clk_eth_ck);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
@@ -122,7 +176,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||||
|
{
|
||||||
|
struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
|
||||||
|
u32 reg = dwmac->mode_reg;
|
||||||
|
- int val;
|
||||||
|
+ int val, ret;
|
||||||
|
|
||||||
|
switch (plat_dat->interface) {
|
||||||
|
case PHY_INTERFACE_MODE_MII:
|
||||||
|
@@ -131,19 +185,19 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||||
|
break;
|
||||||
|
case PHY_INTERFACE_MODE_GMII:
|
||||||
|
val = SYSCFG_PMCR_ETH_SEL_GMII;
|
||||||
|
- if (dwmac->int_phyclk)
|
||||||
|
+ if (dwmac->eth_clk_sel_reg)
|
||||||
|
val |= SYSCFG_PMCR_ETH_CLK_SEL;
|
||||||
|
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n");
|
||||||
|
break;
|
||||||
|
case PHY_INTERFACE_MODE_RMII:
|
||||||
|
val = SYSCFG_PMCR_ETH_SEL_RMII;
|
||||||
|
- if (dwmac->int_phyclk)
|
||||||
|
+ if (dwmac->eth_ref_clk_sel_reg)
|
||||||
|
val |= SYSCFG_PMCR_ETH_REF_CLK_SEL;
|
||||||
|
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n");
|
||||||
|
break;
|
||||||
|
case PHY_INTERFACE_MODE_RGMII:
|
||||||
|
val = SYSCFG_PMCR_ETH_SEL_RGMII;
|
||||||
|
- if (dwmac->int_phyclk)
|
||||||
|
+ if (dwmac->eth_clk_sel_reg)
|
||||||
|
val |= SYSCFG_PMCR_ETH_CLK_SEL;
|
||||||
|
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n");
|
||||||
|
break;
|
||||||
|
@@ -154,6 +208,11 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Need to update PMCCLRR (clear register) */
|
||||||
|
+ ret = regmap_update_bits(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
|
||||||
|
+ dwmac->ops->syscfg_eth_mask, ~val);
|
||||||
|
+
|
||||||
|
+ /* Update PMCSETR (set register) */
|
||||||
|
return regmap_update_bits(dwmac->regmap, reg,
|
||||||
|
dwmac->ops->syscfg_eth_mask, val);
|
||||||
|
}
|
||||||
|
@@ -237,22 +296,25 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||||
|
struct device_node *np = dev->of_node;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
- dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk");
|
||||||
|
+ /* Gigabit Ethernet 125MHz clock selection. */
|
||||||
|
+ dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth_clk_sel");
|
||||||
|
|
||||||
|
- /* Check if internal clk from RCC selected */
|
||||||
|
- if (dwmac->int_phyclk) {
|
||||||
|
- /* Get ETH_CLK clocks */
|
||||||
|
- dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
|
||||||
|
- if (IS_ERR(dwmac->clk_eth_ck)) {
|
||||||
|
- dev_err(dev, "No ETH CK clock provided...\n");
|
||||||
|
- return PTR_ERR(dwmac->clk_eth_ck);
|
||||||
|
- }
|
||||||
|
+ /* Ethernet 50Mhz RMII clock selection */
|
||||||
|
+ dwmac->eth_ref_clk_sel_reg =
|
||||||
|
+ of_property_read_bool(np, "st,eth_ref_clk_sel");
|
||||||
|
+
|
||||||
|
+ /* Get ETH_CLK clocks */
|
||||||
|
+ dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
|
||||||
|
+ if (IS_ERR(dwmac->clk_eth_ck)) {
|
||||||
|
+ dev_warn(dev, "No phy clock provided...\n");
|
||||||
|
+ dwmac->clk_eth_ck = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clock used for low power mode */
|
||||||
|
dwmac->clk_ethstp = devm_clk_get(dev, "ethstp");
|
||||||
|
if (IS_ERR(dwmac->clk_ethstp)) {
|
||||||
|
- dev_err(dev, "No ETH peripheral clock provided for CStop mode ...\n");
|
||||||
|
+ dev_err(dev,
|
||||||
|
+ "No ETH peripheral clock provided for CStop mode ...\n");
|
||||||
|
return PTR_ERR(dwmac->clk_ethstp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -268,7 +330,7 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||||
|
*/
|
||||||
|
dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev,
|
||||||
|
"stm32_pwr_wakeup");
|
||||||
|
- if (!dwmac->int_phyclk && dwmac->irq_pwr_wakeup >= 0) {
|
||||||
|
+ if ((!dwmac->clk_eth_ck) && dwmac->irq_pwr_wakeup >= 0) {
|
||||||
|
err = device_init_wakeup(&pdev->dev, true);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&pdev->dev, "Failed to init wake up irq\n");
|
||||||
|
@@ -370,7 +432,7 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
|
||||||
|
|
||||||
|
clk_disable_unprepare(dwmac->clk_tx);
|
||||||
|
clk_disable_unprepare(dwmac->syscfg_clk);
|
||||||
|
- if (dwmac->int_phyclk)
|
||||||
|
+ if (dwmac->clk_eth_ck)
|
||||||
|
clk_disable_unprepare(dwmac->clk_eth_ck);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||||||
|
index 2b800ce..3031f2b 100644
|
||||||
|
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||||||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||||||
|
@@ -408,6 +408,9 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
|
||||||
|
/* Default to phy auto-detection */
|
||||||
|
plat->phy_addr = -1;
|
||||||
|
|
||||||
|
+ /* Get clk_csr from device tree */
|
||||||
|
+ of_property_read_u32(np, "clk_csr", &plat->clk_csr);
|
||||||
|
+
|
||||||
|
/* "snps,phy-addr" is not a standard property. Mark it as deprecated
|
||||||
|
* and warn of its use. Remove this when phy node support is added.
|
||||||
|
*/
|
||||||
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||||
|
index d2f788d..c7b41ce 100644
|
||||||
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||||
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||||
|
@@ -1129,7 +1129,10 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
|
||||||
|
enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
|
||||||
|
else
|
||||||
|
sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
|
||||||
|
+ } else {
|
||||||
|
+ brcmf_sdiod_intr_unregister(sdiodev);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
|
||||||
|
brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
|
||||||
|
return 0;
|
||||||
|
@@ -1145,6 +1148,9 @@ static int brcmf_ops_sdio_resume(struct device *dev)
|
||||||
|
if (func->num != 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
+ if (!sdiodev->wowl_enabled)
|
||||||
|
+ brcmf_sdiod_intr_register(sdiodev);
|
||||||
|
+
|
||||||
|
brcmf_sdiod_freezer_off(sdiodev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,241 @@
|
||||||
|
From bf3772b12539b3595e60b8b334051160269f9071 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||||
|
Date: Mon, 26 Nov 2018 14:45:33 +0100
|
||||||
|
Subject: [PATCH 28/52] ARM-stm32mp1-r0-rc2-MMC
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/mmc/host/mmci.c | 36 +++++++++++++++++++++++++-----------
|
||||||
|
drivers/mmc/host/mmci.h | 13 +++++++++++--
|
||||||
|
2 files changed, 36 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
|
||||||
|
index db50d1e..02b631f 100644
|
||||||
|
--- a/drivers/mmc/host/mmci.c
|
||||||
|
+++ b/drivers/mmc/host/mmci.c
|
||||||
|
@@ -135,7 +135,6 @@ static struct variant_data variant_u300 = {
|
||||||
|
.datactrl_blocksz = 11,
|
||||||
|
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||||
|
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||||
|
- .st_sdio = true,
|
||||||
|
.pwrreg_powerup = MCI_PWR_ON,
|
||||||
|
.f_max = 100000000,
|
||||||
|
.signal_direction = true,
|
||||||
|
@@ -146,6 +145,7 @@ static struct variant_data variant_u300 = {
|
||||||
|
.start_err = MCI_STARTBITERR,
|
||||||
|
.opendrain = MCI_OD,
|
||||||
|
.init = mmci_variant_init,
|
||||||
|
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct variant_data variant_nomadik = {
|
||||||
|
@@ -161,7 +161,6 @@ static struct variant_data variant_nomadik = {
|
||||||
|
.datactrl_blocksz = 11,
|
||||||
|
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||||
|
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||||
|
- .st_sdio = true,
|
||||||
|
.st_clkdiv = true,
|
||||||
|
.pwrreg_powerup = MCI_PWR_ON,
|
||||||
|
.f_max = 100000000,
|
||||||
|
@@ -173,6 +172,7 @@ static struct variant_data variant_nomadik = {
|
||||||
|
.start_err = MCI_STARTBITERR,
|
||||||
|
.opendrain = MCI_OD,
|
||||||
|
.init = mmci_variant_init,
|
||||||
|
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct variant_data variant_ux500 = {
|
||||||
|
@@ -190,7 +190,6 @@ static struct variant_data variant_ux500 = {
|
||||||
|
.datactrl_blocksz = 11,
|
||||||
|
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||||
|
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||||
|
- .st_sdio = true,
|
||||||
|
.st_clkdiv = true,
|
||||||
|
.pwrreg_powerup = MCI_PWR_ON,
|
||||||
|
.f_max = 100000000,
|
||||||
|
@@ -206,6 +205,7 @@ static struct variant_data variant_ux500 = {
|
||||||
|
.start_err = MCI_STARTBITERR,
|
||||||
|
.opendrain = MCI_OD,
|
||||||
|
.init = mmci_variant_init,
|
||||||
|
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct variant_data variant_ux500v2 = {
|
||||||
|
@@ -224,7 +224,6 @@ static struct variant_data variant_ux500v2 = {
|
||||||
|
.datactrl_blocksz = 11,
|
||||||
|
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||||
|
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||||
|
- .st_sdio = true,
|
||||||
|
.st_clkdiv = true,
|
||||||
|
.blksz_datactrl16 = true,
|
||||||
|
.pwrreg_powerup = MCI_PWR_ON,
|
||||||
|
@@ -241,6 +240,7 @@ static struct variant_data variant_ux500v2 = {
|
||||||
|
.start_err = MCI_STARTBITERR,
|
||||||
|
.opendrain = MCI_OD,
|
||||||
|
.init = mmci_variant_init,
|
||||||
|
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct variant_data variant_stm32 = {
|
||||||
|
@@ -259,13 +259,13 @@ static struct variant_data variant_stm32 = {
|
||||||
|
.datactrl_blocksz = 11,
|
||||||
|
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||||
|
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||||
|
- .st_sdio = true,
|
||||||
|
.st_clkdiv = true,
|
||||||
|
.pwrreg_powerup = MCI_PWR_ON,
|
||||||
|
.f_max = 48000000,
|
||||||
|
.pwrreg_clkgate = true,
|
||||||
|
.pwrreg_nopower = true,
|
||||||
|
.init = mmci_variant_init,
|
||||||
|
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct variant_data variant_stm32_sdmmc = {
|
||||||
|
@@ -284,12 +284,14 @@ static struct variant_data variant_stm32_sdmmc = {
|
||||||
|
.datacnt_useless = true,
|
||||||
|
.datalength_bits = 25,
|
||||||
|
.datactrl_blocksz = 14,
|
||||||
|
+ .datactrl_mask_sdio = MCI_DPSM_STM32_SDIOEN,
|
||||||
|
.stm32_idmabsize_mask = GENMASK(12, 5),
|
||||||
|
.busy_detect = true,
|
||||||
|
.busy_timeout = true,
|
||||||
|
.busy_detect_flag = MCI_STM32_BUSYD0,
|
||||||
|
.busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
|
||||||
|
.init = sdmmc_variant_init,
|
||||||
|
+ .quirks = MMCI_QUIRK_STM32_DTMODE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct variant_data variant_stm32_sdmmcv2 = {
|
||||||
|
@@ -308,6 +310,7 @@ static struct variant_data variant_stm32_sdmmcv2 = {
|
||||||
|
.datacnt_useless = true,
|
||||||
|
.datalength_bits = 25,
|
||||||
|
.datactrl_blocksz = 14,
|
||||||
|
+ .datactrl_mask_sdio = MCI_DPSM_STM32_SDIOEN,
|
||||||
|
.stm32_idmabsize_mask = GENMASK(16, 5),
|
||||||
|
.dma_lli = true,
|
||||||
|
.busy_detect = true,
|
||||||
|
@@ -315,6 +318,7 @@ static struct variant_data variant_stm32_sdmmcv2 = {
|
||||||
|
.busy_detect_flag = MCI_STM32_BUSYD0,
|
||||||
|
.busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
|
||||||
|
.init = sdmmc_variant_init,
|
||||||
|
+ .quirks = MMCI_QUIRK_STM32_DTMODE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct variant_data variant_qcom = {
|
||||||
|
@@ -505,7 +509,8 @@ static int mmci_validate_data(struct mmci_host *host,
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- if (!is_power_of_2(data->blksz)) {
|
||||||
|
+ if ((host->mmc->card && !mmc_card_sdio(host->mmc->card)) &&
|
||||||
|
+ !is_power_of_2(data->blksz)) {
|
||||||
|
dev_err(mmc_dev(host->mmc),
|
||||||
|
"unsupported block size (%d bytes)\n", data->blksz);
|
||||||
|
return -EINVAL;
|
||||||
|
@@ -1068,7 +1073,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
|
||||||
|
writel(host->size, base + MMCIDATALENGTH);
|
||||||
|
|
||||||
|
blksz_bits = ffs(data->blksz) - 1;
|
||||||
|
- BUG_ON(1 << blksz_bits != data->blksz);
|
||||||
|
|
||||||
|
if (variant->blksz_datactrl16)
|
||||||
|
datactrl = variant->datactrl_dpsm_enable | (data->blksz << 16);
|
||||||
|
@@ -1077,6 +1081,16 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
|
||||||
|
else
|
||||||
|
datactrl = variant->datactrl_dpsm_enable | blksz_bits << 4;
|
||||||
|
|
||||||
|
+ if (variant->quirks & MMCI_QUIRK_STM32_DTMODE) {
|
||||||
|
+ if (host->mmc->card && mmc_card_sdio(host->mmc->card) &&
|
||||||
|
+ data->blocks == 1)
|
||||||
|
+ datactrl |= MCI_DPSM_STM32_MODE_SDIO;
|
||||||
|
+ else if (data->stop && !host->mrq->sbc)
|
||||||
|
+ datactrl |= MCI_DPSM_STM32_MODE_BLOCK_STOP;
|
||||||
|
+ else
|
||||||
|
+ datactrl |= MCI_DPSM_STM32_MODE_BLOCK;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (data->flags & MMC_DATA_READ)
|
||||||
|
datactrl |= MCI_DPSM_DIRECTION;
|
||||||
|
|
||||||
|
@@ -1091,7 +1105,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
|
||||||
|
* otherwise the transfer will not start. The threshold
|
||||||
|
* depends on the rate of MCLK.
|
||||||
|
*/
|
||||||
|
- if (variant->st_sdio && data->flags & MMC_DATA_WRITE &&
|
||||||
|
+ if (variant->quirks & MMCI_QUIRK_ST_SDIO &&
|
||||||
|
+ data->flags & MMC_DATA_WRITE &&
|
||||||
|
(host->size < 8 ||
|
||||||
|
(host->size <= 8 && host->mclk > 50000000)))
|
||||||
|
clk = host->clk_reg & ~variant->clkreg_enable;
|
||||||
|
@@ -1257,11 +1272,10 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
|
||||||
|
/* The error clause is handled above, success! */
|
||||||
|
data->bytes_xfered = data->blksz * data->blocks;
|
||||||
|
|
||||||
|
- if (!data->stop || host->mrq->sbc) {
|
||||||
|
+ if (!data->stop || (host->mrq->sbc && !data->error))
|
||||||
|
mmci_request_end(host, data->mrq);
|
||||||
|
- } else {
|
||||||
|
+ else
|
||||||
|
mmci_start_command(host, data->stop, 0);
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
|
||||||
|
index 36a744a..55867fc 100644
|
||||||
|
--- a/drivers/mmc/host/mmci.h
|
||||||
|
+++ b/drivers/mmc/host/mmci.h
|
||||||
|
@@ -131,6 +131,12 @@
|
||||||
|
/* Control register extensions in the Qualcomm versions */
|
||||||
|
#define MCI_DPSM_QCOM_DATA_PEND BIT(17)
|
||||||
|
#define MCI_DPSM_QCOM_RX_DATA_PEND BIT(20)
|
||||||
|
+/* Control register extensions in STM32 versions */
|
||||||
|
+#define MCI_DPSM_STM32_MODE_BLOCK (0 << 2)
|
||||||
|
+#define MCI_DPSM_STM32_MODE_SDIO (1 << 2)
|
||||||
|
+#define MCI_DPSM_STM32_MODE_STREAM (2 << 2)
|
||||||
|
+#define MCI_DPSM_STM32_MODE_BLOCK_STOP (3 << 2)
|
||||||
|
+#define MCI_DPSM_STM32_SDIOEN BIT(11)
|
||||||
|
|
||||||
|
#define MMCIDATACNT 0x030
|
||||||
|
#define MMCISTATUS 0x034
|
||||||
|
@@ -273,7 +279,6 @@ struct mmci_host;
|
||||||
|
* @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
|
||||||
|
* is asserted (likewise for RX)
|
||||||
|
* @data_cmd_enable: enable value for data commands.
|
||||||
|
- * @st_sdio: enable ST specific SDIO logic
|
||||||
|
* @st_clkdiv: true if using a ST-specific clock divider algorithm
|
||||||
|
* @stm32_clkdiv: true if using a STM32-specific clock divider algorithm
|
||||||
|
* @datactrl_mask_ddrmode: ddr mode mask in datactrl register.
|
||||||
|
@@ -309,6 +314,7 @@ struct mmci_host;
|
||||||
|
* @opendrain: bitmask identifying the OPENDRAIN bit inside MMCIPOWER register
|
||||||
|
* @dma_lli: true if variant has dma link list feature.
|
||||||
|
* @stm32_idmabsize_mask: stm32 sdmmc idma buffer size.
|
||||||
|
+ * @quirks: A bitmap of hardware quirks that require some special action.
|
||||||
|
*/
|
||||||
|
struct variant_data {
|
||||||
|
unsigned int clkreg;
|
||||||
|
@@ -330,7 +336,6 @@ struct variant_data {
|
||||||
|
unsigned int datactrl_dpsm_enable;
|
||||||
|
u8 datactrl_first:1;
|
||||||
|
u8 datacnt_useless:1;
|
||||||
|
- u8 st_sdio:1;
|
||||||
|
u8 st_clkdiv:1;
|
||||||
|
u8 stm32_clkdiv:1;
|
||||||
|
u8 blksz_datactrl16:1;
|
||||||
|
@@ -355,9 +360,13 @@ struct variant_data {
|
||||||
|
u32 opendrain;
|
||||||
|
u8 dma_lli:1;
|
||||||
|
u32 stm32_idmabsize_mask;
|
||||||
|
+ u32 quirks;
|
||||||
|
void (*init)(struct mmci_host *host);
|
||||||
|
};
|
||||||
|
|
||||||
|
+#define MMCI_QUIRK_STM32_DTMODE BIT(0)
|
||||||
|
+#define MMCI_QUIRK_ST_SDIO BIT(2) /* enable ST specific SDIO logic */
|
||||||
|
+
|
||||||
|
/* mmci variant callbacks */
|
||||||
|
struct mmci_host_ops {
|
||||||
|
int (*validate_data)(struct mmci_host *host, struct mmc_data *data);
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,771 @@
|
||||||
|
From 72179a889501ef339df094abe108846b19e7a06c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||||
|
Date: Mon, 26 Nov 2018 14:46:26 +0100
|
||||||
|
Subject: [PATCH 29/52] ARM-stm32mp1-r0-rc2-HWSPINLOCK-IIO-I2C
|
||||||
|
|
||||||
|
---
|
||||||
|
.../devicetree/bindings/iio/adc/st,stm32-adc.txt | 34 +++
|
||||||
|
arch/arm/Kconfig.debug | 27 ++
|
||||||
|
drivers/hwspinlock/Kconfig | 9 +
|
||||||
|
drivers/hwspinlock/Makefile | 1 +
|
||||||
|
drivers/hwspinlock/stm32_hwspinlock.c | 157 +++++++++++
|
||||||
|
drivers/i2c/busses/i2c-stm32f7.c | 6 +-
|
||||||
|
drivers/iio/adc/stm32-adc-core.c | 296 ++++++++++++++++++++-
|
||||||
|
drivers/iio/adc/stm32-adc.c | 4 +-
|
||||||
|
8 files changed, 529 insertions(+), 5 deletions(-)
|
||||||
|
create mode 100644 drivers/hwspinlock/stm32_hwspinlock.c
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
|
||||||
|
index c46598c..a6aa796 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
|
||||||
|
@@ -49,6 +49,40 @@ Optional properties:
|
||||||
|
- st,max-clk-rate-hz: Allow to specify desired max clock rate used by analog
|
||||||
|
circuitry.
|
||||||
|
|
||||||
|
+- vdda-supply: Phandle to the vdda input voltage. It can be used to supply ADC
|
||||||
|
+ analog inputs switches on stm32mp1 and stm32h7.
|
||||||
|
+
|
||||||
|
+- vdd-supply: Phandle to the vdd input voltage. It can be used to supply ADC
|
||||||
|
+ analog inputs switches on stm32mp1.
|
||||||
|
+
|
||||||
|
+- st,syscfg-vbooster: Voltage booster control for analog switches supply.
|
||||||
|
+ This is available on stm32mp1 and stm32h7 (requires vdda-supply property).
|
||||||
|
+ It must be composed of 3 cells:
|
||||||
|
+ 1st cell: phandle to syscfg
|
||||||
|
+ 2nd cell: register offset within SYSCFG
|
||||||
|
+ 3rd cell: bitmask for BOOSTE on stm32h7, EN_BOOSTER set bit on stm32mp1
|
||||||
|
+
|
||||||
|
+- st,syscfg-vbooster-clr: Voltage booster clear for analog switches supply.
|
||||||
|
+ This is available on stm32mp1 (requires st,syscfg-vbooster and vdda-supply).
|
||||||
|
+ 1st cell: phandle to syscfg
|
||||||
|
+ 2nd cell: clear register offset within SYSCFG
|
||||||
|
+ 3rd cell: bitmask for EN_BOOSTER clear bit on stm32mp1
|
||||||
|
+
|
||||||
|
+- st,syscfg-anaswvdd: VDDA / VDD selection for analog switches supply.
|
||||||
|
+ This is available on stm32mp1 (requires vdda-supply and vdd-supply).
|
||||||
|
+ It must be composed of 3 cells:
|
||||||
|
+ 1st cell: phandle to syscfg
|
||||||
|
+ 2nd cell: register offset within SYSCFG
|
||||||
|
+ 3rd cell: bitmask for ANASWVDD set bit
|
||||||
|
+
|
||||||
|
+- st,syscfg-anaswvdd-clr: VDDA / VDD selection clear for analog switches supply.
|
||||||
|
+ This is available on stm32mp1 (requires st,syscfg-anaswvdd, vdda-supply and
|
||||||
|
+ vdd-supply).
|
||||||
|
+ It must be composed of 3 cells:
|
||||||
|
+ 1st cell: phandle to syscfg
|
||||||
|
+ 2nd cell: clear register offset within SYSCFG
|
||||||
|
+ 3rd cell: bitmask for ANASWVDD clear bit
|
||||||
|
+
|
||||||
|
Contents of a stm32 adc child node:
|
||||||
|
-----------------------------------
|
||||||
|
An ADC block node should contain at least one subnode, representing an
|
||||||
|
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
|
||||||
|
index f6fcb8a..d5ec6c3 100644
|
||||||
|
--- a/arch/arm/Kconfig.debug
|
||||||
|
+++ b/arch/arm/Kconfig.debug
|
||||||
|
@@ -1184,6 +1184,28 @@ choice
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
|
+ config STM32F4_DEBUG_UART
|
||||||
|
+ bool "Use STM32F4 UART for low-level debug"
|
||||||
|
+ depends on ARCH_STM32
|
||||||
|
+ select DEBUG_STM32_UART
|
||||||
|
+ help
|
||||||
|
+ Say Y here if you want kernel low-level debugging support
|
||||||
|
+ on STM32F4 based platforms, which default UART is wired on
|
||||||
|
+ USART1.
|
||||||
|
+
|
||||||
|
+ If unsure, say N.
|
||||||
|
+
|
||||||
|
+ config STM32F7_DEBUG_UART
|
||||||
|
+ bool "Use STM32F7 UART for low-level debug"
|
||||||
|
+ depends on ARCH_STM32
|
||||||
|
+ select DEBUG_STM32_UART
|
||||||
|
+ help
|
||||||
|
+ Say Y here if you want kernel low-level debugging support
|
||||||
|
+ on STM32F7 based platforms, which default UART is wired on
|
||||||
|
+ USART1.
|
||||||
|
+
|
||||||
|
+ If unsure, say N.
|
||||||
|
+
|
||||||
|
config TEGRA_DEBUG_UART_AUTO_ODMDATA
|
||||||
|
bool "Kernel low-level debugging messages via Tegra UART via ODMDATA"
|
||||||
|
depends on ARCH_TEGRA
|
||||||
|
@@ -1468,6 +1490,10 @@ config DEBUG_STI_UART
|
||||||
|
bool
|
||||||
|
depends on ARCH_STI
|
||||||
|
|
||||||
|
+config DEBUG_STM32_UART
|
||||||
|
+ bool
|
||||||
|
+ depends on ARCH_STM32
|
||||||
|
+
|
||||||
|
config DEBUG_SIRFSOC_UART
|
||||||
|
bool
|
||||||
|
depends on ARCH_SIRF
|
||||||
|
@@ -1517,6 +1543,7 @@ config DEBUG_LL_INCLUDE
|
||||||
|
default "debug/s5pv210.S" if DEBUG_S5PV210_UART
|
||||||
|
default "debug/sirf.S" if DEBUG_SIRFSOC_UART
|
||||||
|
default "debug/sti.S" if DEBUG_STI_UART
|
||||||
|
+ default "debug/stm32.S" if DEBUG_STM32_UART
|
||||||
|
default "debug/tegra.S" if DEBUG_TEGRA_UART
|
||||||
|
default "debug/ux500.S" if DEBUG_UX500_UART
|
||||||
|
default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
|
||||||
|
diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
|
||||||
|
index e895d29..7869c67 100644
|
||||||
|
--- a/drivers/hwspinlock/Kconfig
|
||||||
|
+++ b/drivers/hwspinlock/Kconfig
|
||||||
|
@@ -49,6 +49,15 @@ config HWSPINLOCK_SPRD
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
|
+config HWSPINLOCK_STM32
|
||||||
|
+ tristate "STM32 Hardware Spinlock device"
|
||||||
|
+ depends on MACH_STM32MP157
|
||||||
|
+ depends on HWSPINLOCK
|
||||||
|
+ help
|
||||||
|
+ Say y here to support the STM32 Hardware Spinlock device.
|
||||||
|
+
|
||||||
|
+ If unsure, say N.
|
||||||
|
+
|
||||||
|
config HSEM_U8500
|
||||||
|
tristate "STE Hardware Semaphore functionality"
|
||||||
|
depends on HWSPINLOCK
|
||||||
|
diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile
|
||||||
|
index b87c01a..ed053e3 100644
|
||||||
|
--- a/drivers/hwspinlock/Makefile
|
||||||
|
+++ b/drivers/hwspinlock/Makefile
|
||||||
|
@@ -8,4 +8,5 @@ obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o
|
||||||
|
obj-$(CONFIG_HWSPINLOCK_QCOM) += qcom_hwspinlock.o
|
||||||
|
obj-$(CONFIG_HWSPINLOCK_SIRF) += sirf_hwspinlock.o
|
||||||
|
obj-$(CONFIG_HWSPINLOCK_SPRD) += sprd_hwspinlock.o
|
||||||
|
+obj-$(CONFIG_HWSPINLOCK_STM32) += stm32_hwspinlock.o
|
||||||
|
obj-$(CONFIG_HSEM_U8500) += u8500_hsem.o
|
||||||
|
diff --git a/drivers/hwspinlock/stm32_hwspinlock.c b/drivers/hwspinlock/stm32_hwspinlock.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..3242b72
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/hwspinlock/stm32_hwspinlock.c
|
||||||
|
@@ -0,0 +1,157 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) STMicroelectronics SA 2018
|
||||||
|
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/clk.h>
|
||||||
|
+#include <linux/hwspinlock.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/pm_runtime.h>
|
||||||
|
+
|
||||||
|
+#include "hwspinlock_internal.h"
|
||||||
|
+
|
||||||
|
+#define STM32_MUTEX_COREID BIT(8)
|
||||||
|
+#define STM32_MUTEX_LOCK_BIT BIT(31)
|
||||||
|
+#define STM32_MUTEX_NUM_LOCKS 32
|
||||||
|
+
|
||||||
|
+struct stm32_hwspinlock {
|
||||||
|
+ struct clk *clk;
|
||||||
|
+ struct hwspinlock_device bank;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int stm32_hwspinlock_trylock(struct hwspinlock *lock)
|
||||||
|
+{
|
||||||
|
+ void __iomem *lock_addr = lock->priv;
|
||||||
|
+ u32 status;
|
||||||
|
+
|
||||||
|
+ writel(STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID, lock_addr);
|
||||||
|
+ status = readl(lock_addr);
|
||||||
|
+
|
||||||
|
+ return status == (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32_hwspinlock_unlock(struct hwspinlock *lock)
|
||||||
|
+{
|
||||||
|
+ void __iomem *lock_addr = lock->priv;
|
||||||
|
+
|
||||||
|
+ writel(STM32_MUTEX_COREID, lock_addr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct hwspinlock_ops stm32_hwspinlock_ops = {
|
||||||
|
+ .trylock = stm32_hwspinlock_trylock,
|
||||||
|
+ .unlock = stm32_hwspinlock_unlock,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int stm32_hwspinlock_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_hwspinlock *hw;
|
||||||
|
+ void __iomem *io_base;
|
||||||
|
+ struct resource *res;
|
||||||
|
+ size_t array_size;
|
||||||
|
+ int i, ret;
|
||||||
|
+
|
||||||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
+ io_base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
+ if (!io_base)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ array_size = STM32_MUTEX_NUM_LOCKS * sizeof(struct hwspinlock);
|
||||||
|
+ hw = devm_kzalloc(&pdev->dev, sizeof(*hw) + array_size, GFP_KERNEL);
|
||||||
|
+ if (!hw)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ hw->clk = devm_clk_get(&pdev->dev, "hsem");
|
||||||
|
+ if (IS_ERR(hw->clk))
|
||||||
|
+ return PTR_ERR(hw->clk);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < STM32_MUTEX_NUM_LOCKS; i++)
|
||||||
|
+ hw->bank.lock[i].priv = io_base + i * sizeof(u32);
|
||||||
|
+
|
||||||
|
+ platform_set_drvdata(pdev, hw);
|
||||||
|
+ pm_runtime_enable(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ ret = hwspin_lock_register(&hw->bank, &pdev->dev, &stm32_hwspinlock_ops,
|
||||||
|
+ 0, STM32_MUTEX_NUM_LOCKS);
|
||||||
|
+
|
||||||
|
+ if (ret)
|
||||||
|
+ pm_runtime_disable(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_hwspinlock_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_hwspinlock *hw = platform_get_drvdata(pdev);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = hwspin_lock_unregister(&hw->bank);
|
||||||
|
+ if (ret)
|
||||||
|
+ dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
|
||||||
|
+
|
||||||
|
+ pm_runtime_disable(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __maybe_unused stm32_hwspinlock_runtime_suspend(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_hwspinlock *hw = dev_get_drvdata(dev);
|
||||||
|
+
|
||||||
|
+ clk_disable_unprepare(hw->clk);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __maybe_unused stm32_hwspinlock_runtime_resume(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_hwspinlock *hw = dev_get_drvdata(dev);
|
||||||
|
+
|
||||||
|
+ clk_prepare_enable(hw->clk);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct dev_pm_ops stm32_hwspinlock_pm_ops = {
|
||||||
|
+ SET_RUNTIME_PM_OPS(stm32_hwspinlock_runtime_suspend,
|
||||||
|
+ stm32_hwspinlock_runtime_resume,
|
||||||
|
+ NULL)
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct of_device_id stm32_hwpinlock_ids[] = {
|
||||||
|
+ { .compatible = "st,stm32-hwspinlock", },
|
||||||
|
+ {},
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, stm32_hwpinlock_ids);
|
||||||
|
+
|
||||||
|
+static struct platform_driver stm32_hwspinlock_driver = {
|
||||||
|
+ .probe = stm32_hwspinlock_probe,
|
||||||
|
+ .remove = stm32_hwspinlock_remove,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "stm32_hwspinlock",
|
||||||
|
+ .of_match_table = stm32_hwpinlock_ids,
|
||||||
|
+ .pm = &stm32_hwspinlock_pm_ops,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init stm32_hwspinlock_init(void)
|
||||||
|
+{
|
||||||
|
+ return platform_driver_register(&stm32_hwspinlock_driver);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* board init code might need to reserve hwspinlocks for predefined purposes */
|
||||||
|
+postcore_initcall(stm32_hwspinlock_init);
|
||||||
|
+
|
||||||
|
+static void __exit stm32_hwspinlock_exit(void)
|
||||||
|
+{
|
||||||
|
+ platform_driver_unregister(&stm32_hwspinlock_driver);
|
||||||
|
+}
|
||||||
|
+module_exit(stm32_hwspinlock_exit);
|
||||||
|
+
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
+MODULE_DESCRIPTION("Hardware spinlock driver for STM32 SoCs");
|
||||||
|
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
|
||||||
|
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
|
||||||
|
index c1cbf93..ac30aea 100644
|
||||||
|
--- a/drivers/i2c/busses/i2c-stm32f7.c
|
||||||
|
+++ b/drivers/i2c/busses/i2c-stm32f7.c
|
||||||
|
@@ -457,7 +457,7 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
|
||||||
|
STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0);
|
||||||
|
dnf_delay = setup->dnf * i2cclk;
|
||||||
|
|
||||||
|
- sdadel_min = setup->fall_time - i2c_specs[setup->speed].hddat_min -
|
||||||
|
+ sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time -
|
||||||
|
af_delay_min - (setup->dnf + 3) * i2cclk;
|
||||||
|
|
||||||
|
sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time -
|
||||||
|
@@ -501,8 +501,12 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
|
||||||
|
|
||||||
|
list_add_tail(&v->node,
|
||||||
|
&solutions);
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (p_prev == p)
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
|
||||||
|
index a32e826..6234456 100644
|
||||||
|
--- a/drivers/iio/adc/stm32-adc-core.c
|
||||||
|
+++ b/drivers/iio/adc/stm32-adc-core.c
|
||||||
|
@@ -16,10 +16,12 @@
|
||||||
|
#include <linux/irqchip/chained_irq.h>
|
||||||
|
#include <linux/irqdesc.h>
|
||||||
|
#include <linux/irqdomain.h>
|
||||||
|
+#include <linux/mfd/syscon.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/of_irq.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
+#include <linux/regmap.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
@@ -88,6 +90,8 @@
|
||||||
|
#define STM32H7_CKMODE_SHIFT 16
|
||||||
|
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
|
||||||
|
|
||||||
|
+#define STM32_ADC_CORE_SLEEP_DELAY_MS 2000
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* stm32_adc_common_regs - stm32 common registers, compatible dependent data
|
||||||
|
* @csr: common status register offset
|
||||||
|
@@ -117,16 +121,30 @@ struct stm32_adc_priv;
|
||||||
|
* @regs: common registers for all instances
|
||||||
|
* @clk_sel: clock selection routine
|
||||||
|
* @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
|
||||||
|
+ * @has_syscfg_clr: analog switch control use set and clear registers
|
||||||
|
* @exti_trigs EXTI triggers info
|
||||||
|
*/
|
||||||
|
struct stm32_adc_priv_cfg {
|
||||||
|
const struct stm32_adc_common_regs *regs;
|
||||||
|
int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
|
||||||
|
u32 max_clk_rate_hz;
|
||||||
|
+ int has_syscfg_clr;
|
||||||
|
struct stm32_adc_trig_info *exti_trigs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * stm32_adc_syscfg - stm32 ADC SYSCFG data
|
||||||
|
+ * @regmap: reference to syscon
|
||||||
|
+ * @reg: register offset within SYSCFG
|
||||||
|
+ * @mask: bitmask within SYSCFG register
|
||||||
|
+ */
|
||||||
|
+struct stm32_adc_syscfg {
|
||||||
|
+ struct regmap *regmap;
|
||||||
|
+ u32 reg;
|
||||||
|
+ u32 mask;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* struct stm32_adc_priv - stm32 ADC core private data
|
||||||
|
* @irq: irq(s) for ADC block
|
||||||
|
* @domain: irq domain reference
|
||||||
|
@@ -137,6 +155,10 @@ struct stm32_adc_priv_cfg {
|
||||||
|
* @cfg: compatible configuration data
|
||||||
|
* @common: common data for all ADC instances
|
||||||
|
* @ccr_bak: backup'ed CCR in low power mode
|
||||||
|
+ * @vbooster: BOOSTE syscfg / EN_BOOSTER syscfg set
|
||||||
|
+ * @vbooster_clr: EN_BOOSTER syscfg clear
|
||||||
|
+ * @anaswvdd: ANASWVDD syscfg set
|
||||||
|
+ * @anaswvdd_clr: ANASWVDD syscfg clear
|
||||||
|
*/
|
||||||
|
struct stm32_adc_priv {
|
||||||
|
int irq[STM32_ADC_MAX_ADCS];
|
||||||
|
@@ -144,10 +166,16 @@ struct stm32_adc_priv {
|
||||||
|
struct clk *aclk;
|
||||||
|
struct clk *bclk;
|
||||||
|
u32 max_clk_rate;
|
||||||
|
+ struct regulator *vdd;
|
||||||
|
+ struct regulator *vdda;
|
||||||
|
struct regulator *vref;
|
||||||
|
const struct stm32_adc_priv_cfg *cfg;
|
||||||
|
struct stm32_adc_common common;
|
||||||
|
u32 ccr_bak;
|
||||||
|
+ struct stm32_adc_syscfg vbooster;
|
||||||
|
+ struct stm32_adc_syscfg vbooster_clr;
|
||||||
|
+ struct stm32_adc_syscfg anaswvdd;
|
||||||
|
+ struct stm32_adc_syscfg anaswvdd_clr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)
|
||||||
|
@@ -567,16 +595,187 @@ static int stm32_adc_triggers_probe(struct platform_device *pdev,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int stm32_adc_switches_supply_en(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_adc_common *common = dev_get_drvdata(dev);
|
||||||
|
+ struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
|
||||||
|
+ int ret, vdda, vdd = 0;
|
||||||
|
+ u32 anaswvdd, en_booster;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * On STM32H7 and STM32MP1, the ADC inputs are multiplexed with analog
|
||||||
|
+ * switches (e.g. PCSEL) which have reduced performances when their
|
||||||
|
+ * supply is below 2.7V (vdda by default):
|
||||||
|
+ * - Voltage booster can be used, to get full ADC performances
|
||||||
|
+ * (increases power consumption).
|
||||||
|
+ * - Vdd can be used if above 2.7V (STM32MP1 only).
|
||||||
|
+ *
|
||||||
|
+ * Make all this optional, since this is a trade-off between analog
|
||||||
|
+ * performance and power consumption.
|
||||||
|
+ */
|
||||||
|
+ if (IS_ERR(priv->vdda) || IS_ERR(priv->vbooster.regmap)) {
|
||||||
|
+ dev_dbg(dev, "%s: nothing to do\n", __func__);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = regulator_enable(priv->vdda);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(dev, "vdda enable failed %d\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = regulator_get_voltage(priv->vdda);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(dev, "vdda get voltage failed %d\n", ret);
|
||||||
|
+ goto vdda_dis;
|
||||||
|
+ }
|
||||||
|
+ vdda = ret;
|
||||||
|
+
|
||||||
|
+ if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap)) {
|
||||||
|
+ ret = regulator_enable(priv->vdd);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(dev, "vdd enable failed %d\n", ret);
|
||||||
|
+ goto vdda_dis;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = regulator_get_voltage(priv->vdd);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(dev, "vdd get voltage failed %d\n", ret);
|
||||||
|
+ goto vdd_dis;
|
||||||
|
+ }
|
||||||
|
+ vdd = ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Recommended settings for ANASWVDD and EN_BOOSTER:
|
||||||
|
+ * - vdda > 2.7V: ANASWVDD = 0, EN_BOOSTER = 0
|
||||||
|
+ * - vdda < 2.7V and vdd < 2.7V: ANASWVDD = 0, EN_BOOSTER = 1
|
||||||
|
+ * - vdda < 2.7V but vdd > 2.7V: ANASWVDD = 1, EN_BOOSTER = 0 (stm32mp1)
|
||||||
|
+ */
|
||||||
|
+ if (vdda > 2700000) {
|
||||||
|
+ /* analog switches supplied by vdda (default) */
|
||||||
|
+ anaswvdd = 0;
|
||||||
|
+ en_booster = 0;
|
||||||
|
+ } else {
|
||||||
|
+ if (vdd < 2700000) {
|
||||||
|
+ /* Voltage booster enabled */
|
||||||
|
+ anaswvdd = 0;
|
||||||
|
+ en_booster = priv->vbooster.mask;
|
||||||
|
+ } else {
|
||||||
|
+ /* analog switches supplied by vdd */
|
||||||
|
+ anaswvdd = priv->anaswvdd.mask;
|
||||||
|
+ en_booster = 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dev_dbg(dev, "vdda=%d, vdd=%d, setting: en_booster=%x, anaswvdd=%x\n",
|
||||||
|
+ vdda, vdd, en_booster, anaswvdd);
|
||||||
|
+
|
||||||
|
+ /* direct write en_booster value (or use clear register) */
|
||||||
|
+ if (en_booster || IS_ERR(priv->vbooster_clr.regmap))
|
||||||
|
+ ret = regmap_update_bits(priv->vbooster.regmap,
|
||||||
|
+ priv->vbooster.reg,
|
||||||
|
+ priv->vbooster.mask, en_booster);
|
||||||
|
+ else
|
||||||
|
+ ret = regmap_update_bits(priv->vbooster_clr.regmap,
|
||||||
|
+ priv->vbooster_clr.reg,
|
||||||
|
+ priv->vbooster_clr.mask,
|
||||||
|
+ priv->vbooster_clr.mask);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(dev, "can't access voltage booster, %d\n", ret);
|
||||||
|
+ goto vdd_dis;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Booster voltage can take up to 50 μs to stabilize */
|
||||||
|
+ if (en_booster)
|
||||||
|
+ usleep_range(50, 100);
|
||||||
|
+
|
||||||
|
+ if (!IS_ERR(priv->anaswvdd.regmap)) {
|
||||||
|
+ /* direct write anaswvdd value (or use clear register) */
|
||||||
|
+ if (anaswvdd || IS_ERR(priv->anaswvdd_clr.regmap))
|
||||||
|
+ ret = regmap_update_bits(priv->anaswvdd.regmap,
|
||||||
|
+ priv->anaswvdd.reg,
|
||||||
|
+ priv->anaswvdd.mask, anaswvdd);
|
||||||
|
+ else
|
||||||
|
+ ret = regmap_update_bits(priv->anaswvdd_clr.regmap,
|
||||||
|
+ priv->anaswvdd_clr.reg,
|
||||||
|
+ priv->anaswvdd_clr.mask,
|
||||||
|
+ priv->anaswvdd_clr.mask);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(dev, "can't access anaswvdd, %d\n", ret);
|
||||||
|
+ goto booster_dis;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+booster_dis:
|
||||||
|
+ if (IS_ERR(priv->vbooster_clr.regmap))
|
||||||
|
+ regmap_update_bits(priv->vbooster.regmap, priv->vbooster.reg,
|
||||||
|
+ priv->vbooster.mask, 0);
|
||||||
|
+ else
|
||||||
|
+ regmap_update_bits(priv->vbooster_clr.regmap,
|
||||||
|
+ priv->vbooster_clr.reg,
|
||||||
|
+ priv->vbooster_clr.mask,
|
||||||
|
+ priv->vbooster_clr.mask);
|
||||||
|
+vdd_dis:
|
||||||
|
+ if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap))
|
||||||
|
+ regulator_disable(priv->vdd);
|
||||||
|
+vdda_dis:
|
||||||
|
+ regulator_disable(priv->vdda);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32_adc_switches_supply_dis(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_adc_common *common = dev_get_drvdata(dev);
|
||||||
|
+ struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
|
||||||
|
+
|
||||||
|
+ if (IS_ERR(priv->vdda) || IS_ERR(priv->vbooster.regmap))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (!IS_ERR(priv->anaswvdd.regmap)) {
|
||||||
|
+ if (IS_ERR(priv->anaswvdd_clr.regmap))
|
||||||
|
+ regmap_update_bits(priv->anaswvdd.regmap,
|
||||||
|
+ priv->anaswvdd.reg,
|
||||||
|
+ priv->anaswvdd.mask, 0);
|
||||||
|
+ else
|
||||||
|
+ regmap_update_bits(priv->anaswvdd_clr.regmap,
|
||||||
|
+ priv->anaswvdd_clr.reg,
|
||||||
|
+ priv->anaswvdd_clr.mask,
|
||||||
|
+ priv->anaswvdd_clr.mask);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (IS_ERR(priv->vbooster_clr.regmap))
|
||||||
|
+ regmap_update_bits(priv->vbooster.regmap, priv->vbooster.reg,
|
||||||
|
+ priv->vbooster.mask, 0);
|
||||||
|
+ else
|
||||||
|
+ regmap_update_bits(priv->vbooster_clr.regmap,
|
||||||
|
+ priv->vbooster_clr.reg,
|
||||||
|
+ priv->vbooster_clr.mask,
|
||||||
|
+ priv->vbooster_clr.mask);
|
||||||
|
+
|
||||||
|
+ if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap))
|
||||||
|
+ regulator_disable(priv->vdd);
|
||||||
|
+
|
||||||
|
+ regulator_disable(priv->vdda);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int stm32_adc_core_hw_start(struct device *dev)
|
||||||
|
{
|
||||||
|
struct stm32_adc_common *common = dev_get_drvdata(dev);
|
||||||
|
struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ ret = stm32_adc_switches_supply_en(dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
ret = regulator_enable(priv->vref);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "vref enable failed\n");
|
||||||
|
- return ret;
|
||||||
|
+ goto err_switches_disable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->bclk) {
|
||||||
|
@@ -604,6 +803,8 @@ static int stm32_adc_core_hw_start(struct device *dev)
|
||||||
|
clk_disable_unprepare(priv->bclk);
|
||||||
|
err_regulator_disable:
|
||||||
|
regulator_disable(priv->vref);
|
||||||
|
+err_switches_disable:
|
||||||
|
+ stm32_adc_switches_supply_dis(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -620,6 +821,68 @@ static void stm32_adc_core_hw_stop(struct device *dev)
|
||||||
|
if (priv->bclk)
|
||||||
|
clk_disable_unprepare(priv->bclk);
|
||||||
|
regulator_disable(priv->vref);
|
||||||
|
+ stm32_adc_switches_supply_dis(dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_adc_get_syscfg_cell(struct device_node *np,
|
||||||
|
+ struct stm32_adc_syscfg *syscfg,
|
||||||
|
+ const char * prop)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ syscfg->regmap = syscon_regmap_lookup_by_phandle(np, prop);
|
||||||
|
+ if (IS_ERR(syscfg->regmap)) {
|
||||||
|
+ pr_debug("FGA: %s %ld\n", prop, PTR_ERR(syscfg->regmap));
|
||||||
|
+ /* Optional */
|
||||||
|
+ if (PTR_ERR(syscfg->regmap) == -ENODEV)
|
||||||
|
+ return 0;
|
||||||
|
+ else
|
||||||
|
+ return PTR_ERR(syscfg->regmap);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32_index(np, prop, 1, &syscfg->reg);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return of_property_read_u32_index(np, prop, 2, &syscfg->mask);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_adc_syscfg_probe(struct platform_device *pdev,
|
||||||
|
+ struct stm32_adc_priv *priv)
|
||||||
|
+{
|
||||||
|
+ struct device_node *np = pdev->dev.of_node;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ /* Start to lookup BOOSTE/EN_BOOSTER first, for stm32h7/stm32mp1 */
|
||||||
|
+ ret = stm32_adc_get_syscfg_cell(np, &priv->vbooster,
|
||||||
|
+ "st,syscfg-vbooster");
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* Continue with stm32mp1 EN_BOOSTER/ANASWVDD set and clear bits*/
|
||||||
|
+ ret = stm32_adc_get_syscfg_cell(np, &priv->vbooster_clr,
|
||||||
|
+ "st,syscfg-vbooster-clr");
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = stm32_adc_get_syscfg_cell(np, &priv->anaswvdd,
|
||||||
|
+ "st,syscfg-anaswvdd");
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = stm32_adc_get_syscfg_cell(np, &priv->anaswvdd_clr,
|
||||||
|
+ "st,syscfg-anaswvdd-clr");
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* Sanity, check syscfg set/clear pairs are filled in */
|
||||||
|
+ if (priv->cfg->has_syscfg_clr && ((!IS_ERR(priv->vbooster.regmap) &&
|
||||||
|
+ IS_ERR(priv->vbooster_clr.regmap)) ||
|
||||||
|
+ (!IS_ERR(priv->anaswvdd.regmap) &&
|
||||||
|
+ IS_ERR(priv->anaswvdd_clr.regmap))))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32_adc_probe(struct platform_device *pdev)
|
||||||
|
@@ -657,6 +920,24 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ priv->vdda = devm_regulator_get_optional(&pdev->dev, "vdda");
|
||||||
|
+ if (IS_ERR(priv->vdda)) {
|
||||||
|
+ ret = PTR_ERR(priv->vdda);
|
||||||
|
+ if (ret != -ENODEV) {
|
||||||
|
+ dev_err(&pdev->dev, "vdda get failed, %d\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ priv->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
|
||||||
|
+ if (IS_ERR(priv->vdd)) {
|
||||||
|
+ ret = PTR_ERR(priv->vdd);
|
||||||
|
+ if (ret != -ENODEV) {
|
||||||
|
+ dev_err(&pdev->dev, "vdd get failed, %d\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
priv->aclk = devm_clk_get(&pdev->dev, "adc");
|
||||||
|
if (IS_ERR(priv->aclk)) {
|
||||||
|
ret = PTR_ERR(priv->aclk);
|
||||||
|
@@ -677,8 +958,17 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||||
|
priv->bclk = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ret = stm32_adc_syscfg_probe(pdev, priv);
|
||||||
|
+ if (ret) {
|
||||||
|
+ if (ret != -EPROBE_DEFER)
|
||||||
|
+ dev_err(&pdev->dev, "Can't probe syscfg: %d\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
pm_runtime_get_noresume(dev);
|
||||||
|
pm_runtime_set_active(dev);
|
||||||
|
+ pm_runtime_set_autosuspend_delay(dev, STM32_ADC_CORE_SLEEP_DELAY_MS);
|
||||||
|
+ pm_runtime_use_autosuspend(dev);
|
||||||
|
pm_runtime_enable(dev);
|
||||||
|
|
||||||
|
ret = stm32_adc_core_hw_start(dev);
|
||||||
|
@@ -718,7 +1008,8 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||||
|
goto err_irq_remove;
|
||||||
|
}
|
||||||
|
|
||||||
|
- pm_runtime_put(dev);
|
||||||
|
+ pm_runtime_mark_last_busy(dev);
|
||||||
|
+ pm_runtime_put_autosuspend(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
@@ -789,6 +1080,7 @@ static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
|
||||||
|
static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
|
||||||
|
.regs = &stm32h7_adc_common_regs,
|
||||||
|
.clk_sel = stm32h7_adc_clk_sel,
|
||||||
|
+ .has_syscfg_clr = true,
|
||||||
|
.max_clk_rate_hz = 40000000,
|
||||||
|
.exti_trigs = stm32h7_adc_exti_trigs,
|
||||||
|
};
|
||||||
|
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
|
||||||
|
index 980355e..13d2e3c 100644
|
||||||
|
--- a/drivers/iio/adc/stm32-adc.c
|
||||||
|
+++ b/drivers/iio/adc/stm32-adc.c
|
||||||
|
@@ -201,7 +201,7 @@ enum stm32h7_adc_dmngt {
|
||||||
|
#define STM32_ADC_MAX_SMP 7 /* SMPx range is [0..7] */
|
||||||
|
#define STM32_ADC_TIMEOUT_US 100000
|
||||||
|
#define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
|
||||||
|
-#define STM32_ADC_AUTO_SUSPEND_DELAY_MS 2000
|
||||||
|
+#define STM32_ADC_HW_STOP_DELAY_MS 100
|
||||||
|
|
||||||
|
#define STM32_DMA_BUFFER_SIZE PAGE_SIZE
|
||||||
|
|
||||||
|
@@ -2783,7 +2783,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||||
|
/* Get stm32-adc-core PM online */
|
||||||
|
pm_runtime_get_noresume(dev);
|
||||||
|
pm_runtime_set_active(dev);
|
||||||
|
- pm_runtime_set_autosuspend_delay(dev, STM32_ADC_AUTO_SUSPEND_DELAY_MS);
|
||||||
|
+ pm_runtime_set_autosuspend_delay(dev, STM32_ADC_HW_STOP_DELAY_MS);
|
||||||
|
pm_runtime_use_autosuspend(dev);
|
||||||
|
pm_runtime_enable(dev);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,130 @@
|
||||||
|
From 73813749b7f0f33a59eb8f321f7d0f9d88dbfbb3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||||
|
Date: Mon, 26 Nov 2018 14:46:52 +0100
|
||||||
|
Subject: [PATCH 31/52] ARM-stm32mp1-r0-rc2-DEFCONFIG
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/configs/fragment-02-multiv7_addons.config | 42 +++++++++++++++++++++-
|
||||||
|
1 file changed, 41 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
index c91840c..4470d85 100644
|
||||||
|
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
@@ -3,6 +3,7 @@
|
||||||
|
#
|
||||||
|
CONFIG_POSIX_MQUEUE=y
|
||||||
|
CONFIG_USELIB=y
|
||||||
|
+CONFIG_FUTEX=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# RCU Subsystem
|
||||||
|
@@ -153,6 +154,12 @@ CONFIG_SERIAL_NONSTANDARD=y
|
||||||
|
# CONFIG_SERIAL_8250 is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
+# Touchscreen drivers
|
||||||
|
+#
|
||||||
|
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
|
||||||
|
+CONFIG_TOUCHSCREEN_GOODIX=m
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
# Non-8250 serial port support
|
||||||
|
#
|
||||||
|
# CONFIG_SERIAL_BCM63XX is not set
|
||||||
|
@@ -179,6 +186,7 @@ CONFIG_SERIAL_NONSTANDARD=y
|
||||||
|
#
|
||||||
|
# SPI Master Controller Drivers
|
||||||
|
#
|
||||||
|
+CONFIG_SPI_STM32=y
|
||||||
|
CONFIG_SPI_STM32_QSPI=y
|
||||||
|
|
||||||
|
#
|
||||||
|
@@ -237,6 +245,7 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||||
|
#
|
||||||
|
# USB HDMI CEC adapters
|
||||||
|
#
|
||||||
|
+CONFIG_VIDEO_STM32_HDMI_CEC=m
|
||||||
|
|
||||||
|
#
|
||||||
|
# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
|
||||||
|
@@ -246,6 +255,7 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||||
|
#
|
||||||
|
# Camera sensor devices
|
||||||
|
#
|
||||||
|
+CONFIG_VIDEO_OV5640=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Graphics support
|
||||||
|
@@ -261,10 +271,14 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||||
|
#
|
||||||
|
# Display Panels
|
||||||
|
#
|
||||||
|
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
|
||||||
|
+CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
|
||||||
|
|
||||||
|
#
|
||||||
|
# Display Interface Bridges
|
||||||
|
#
|
||||||
|
+CONFIG_VIDEO_ADV7511=m
|
||||||
|
+CONFIG_DRM_SII902X=m
|
||||||
|
|
||||||
|
#
|
||||||
|
# Frame buffer hardware drivers
|
||||||
|
@@ -273,15 +287,34 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||||
|
#
|
||||||
|
# Console display driver support
|
||||||
|
#
|
||||||
|
+CONFIG_DRM_STM=m
|
||||||
|
+CONFIG_DRM_STM_DSI=m
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Backlight support
|
||||||
|
+#
|
||||||
|
+CONFIG_BACKLIGHT_GPIO=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# HD-Audio
|
||||||
|
#
|
||||||
|
+CONFIG_SOUND=y
|
||||||
|
+CONFIG_SND=y
|
||||||
|
+CONFIG_SND_SOC=y
|
||||||
|
+CONFIG_SND_SOC_STM32_SAI=y
|
||||||
|
+CONFIG_SND_SOC_STM32_I2S=y
|
||||||
|
+CONFIG_SND_SOC_STM32_SPDIFRX=y
|
||||||
|
+CONFIG_SND_SOC_STM32_DFSDM=y
|
||||||
|
+CONFIG_SND_AUDIO_GRAPH_CARD=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# CODEC drivers
|
||||||
|
#
|
||||||
|
-
|
||||||
|
+CONFIG_MFD_WM8994=y
|
||||||
|
+CONFIG_SND_SOC_WM8994=y
|
||||||
|
+CONFIG_SND_SOC_DMIC=y
|
||||||
|
+CONFIG_SND_SOC_CS42L42=y
|
||||||
|
+CONFIG_SND_SOC_CS42L51_I2C=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# USB Device Class drivers
|
||||||
|
@@ -300,6 +333,7 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||||
|
#
|
||||||
|
# Gadget/Dual-role mode requires USB Gadget support to be enabled
|
||||||
|
#
|
||||||
|
+CONFIG_USB_CONFIGFS=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# USB Physical Layer drivers
|
||||||
|
@@ -460,3 +494,9 @@ CONFIG_STM32_ADC_TEMP=y
|
||||||
|
# STM32 DAC
|
||||||
|
#
|
||||||
|
CONFIG_STM32_DAC=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# STM32 HSEM
|
||||||
|
+#
|
||||||
|
+CONFIG_HWSPINLOCK=y
|
||||||
|
+CONFIG_HWSPINLOCK_STM32=y
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
From 1028166948f7116f4dcddc74094125db0a7595c8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:34:56 +0100
|
||||||
|
Subject: [PATCH 32/52] ARM: stm32mp1-r0-rc3: DMA
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/dma/stm32-dma.c | 11 +++++++----
|
||||||
|
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
|
||||||
|
index 4830f8e..1f9d606 100644
|
||||||
|
--- a/drivers/dma/stm32-dma.c
|
||||||
|
+++ b/drivers/dma/stm32-dma.c
|
||||||
|
@@ -212,6 +212,7 @@ struct stm32_dma_desc {
|
||||||
|
u32 num_sgs;
|
||||||
|
dma_addr_t dma_buf;
|
||||||
|
void *dma_buf_cpu;
|
||||||
|
+ u32 dma_buf_size;
|
||||||
|
struct stm32_dma_sg_req sg_req[];
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1224,6 +1225,7 @@ static int stm32_dma_mdma_prep_slave_sg(struct stm32_dma_chan *chan,
|
||||||
|
&desc->dma_buf);
|
||||||
|
if (!desc->dma_buf_cpu)
|
||||||
|
return -ENOMEM;
|
||||||
|
+ desc->dma_buf_size = chan->sram_size;
|
||||||
|
|
||||||
|
sram_period = chan->sram_size / 2;
|
||||||
|
|
||||||
|
@@ -1316,7 +1318,7 @@ static int stm32_dma_mdma_prep_slave_sg(struct stm32_dma_chan *chan,
|
||||||
|
}
|
||||||
|
free_alloc:
|
||||||
|
gen_pool_free(dmadev->sram_pool, (unsigned long)desc->dma_buf_cpu,
|
||||||
|
- chan->sram_size);
|
||||||
|
+ desc->dma_buf_size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1437,7 +1439,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
|
||||||
|
|
||||||
|
gen_pool_free(dmadev->sram_pool,
|
||||||
|
(unsigned long)desc->dma_buf_cpu,
|
||||||
|
- chan->sram_size);
|
||||||
|
+ desc->dma_buf_size);
|
||||||
|
}
|
||||||
|
kfree(desc);
|
||||||
|
|
||||||
|
@@ -1462,6 +1464,7 @@ static int stm32_dma_mdma_prep_dma_cyclic(struct stm32_dma_chan *chan,
|
||||||
|
&desc->dma_buf);
|
||||||
|
if (!desc->dma_buf_cpu)
|
||||||
|
return -ENOMEM;
|
||||||
|
+ desc->dma_buf_size = 2 * chan->sram_size;
|
||||||
|
|
||||||
|
memset(&config, 0, sizeof(config));
|
||||||
|
mem = buf_addr;
|
||||||
|
@@ -1511,7 +1514,7 @@ static int stm32_dma_mdma_prep_dma_cyclic(struct stm32_dma_chan *chan,
|
||||||
|
err:
|
||||||
|
gen_pool_free(dmadev->sram_pool,
|
||||||
|
(unsigned long)desc->dma_buf_cpu,
|
||||||
|
- chan->sram_size);
|
||||||
|
+ desc->dma_buf_size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1813,7 +1816,7 @@ static void stm32_dma_desc_free(struct virt_dma_desc *vdesc)
|
||||||
|
|
||||||
|
gen_pool_free(dmadev->sram_pool,
|
||||||
|
(unsigned long)desc->dma_buf_cpu,
|
||||||
|
- chan->sram_size);
|
||||||
|
+ desc->dma_buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(desc);
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
From dc9ea19f397651b7671ec4268a12d3f49e2bbda0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:48:07 +0100
|
||||||
|
Subject: [PATCH 33/52] ARM: stm32mp1-r0-rc3: DISPLAY
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/bridge/sii902x.c | 31 +++++++++++++++++++++++++++----
|
||||||
|
drivers/gpu/drm/drm_gem.c | 6 ------
|
||||||
|
2 files changed, 27 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
|
||||||
|
index 512eb03..170657a 100644
|
||||||
|
--- a/drivers/gpu/drm/bridge/sii902x.c
|
||||||
|
+++ b/drivers/gpu/drm/bridge/sii902x.c
|
||||||
|
@@ -397,7 +397,6 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge)
|
||||||
|
regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
|
||||||
|
SII902X_SYS_CTRL_PWR_DWN,
|
||||||
|
SII902X_SYS_CTRL_PWR_DWN);
|
||||||
|
- pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sii902x_bridge_enable(struct drm_bridge *bridge)
|
||||||
|
@@ -405,7 +404,6 @@ static void sii902x_bridge_enable(struct drm_bridge *bridge)
|
||||||
|
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||||
|
bool hdmi_mode;
|
||||||
|
|
||||||
|
- pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||||
|
regmap_update_bits(sii902x->regmap, SII902X_PWR_STATE_CTRL,
|
||||||
|
SII902X_AVI_POWER_STATE_MSK,
|
||||||
|
SII902X_AVI_POWER_STATE_D(0));
|
||||||
|
@@ -430,8 +428,17 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
||||||
|
struct regmap *regmap = sii902x->regmap;
|
||||||
|
u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
|
||||||
|
struct hdmi_avi_infoframe frame;
|
||||||
|
+ unsigned int status = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ DRM_DEBUG_DRIVER("\n");
|
||||||
|
+
|
||||||
|
+ regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||||
|
+
|
||||||
|
+ /* due to old tv, need to restore pinctrl as soon as possible */
|
||||||
|
+ if (status & SII902X_PLUGGED_STATUS)
|
||||||
|
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||||
|
+
|
||||||
|
buf[0] = adj->clock;
|
||||||
|
buf[1] = adj->clock >> 8;
|
||||||
|
buf[2] = adj->vrefresh;
|
||||||
|
@@ -819,6 +826,11 @@ static irqreturn_t sii902x_interrupt(int irq, void *data)
|
||||||
|
regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||||
|
regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
|
||||||
|
|
||||||
|
+ if (status & SII902X_PLUGGED_STATUS)
|
||||||
|
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||||
|
+ else
|
||||||
|
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||||
|
+
|
||||||
|
if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev)
|
||||||
|
drm_helper_hpd_irq_event(sii902x->bridge.dev);
|
||||||
|
|
||||||
|
@@ -1045,14 +1057,15 @@ static int sii902x_probe(struct i2c_client *client,
|
||||||
|
sii902x_i2c_bypass_deselect);
|
||||||
|
if (!sii902x->i2cmux) {
|
||||||
|
dev_err(dev, "failed to allocate I2C mux\n");
|
||||||
|
- return -ENOMEM;
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto err_disable_regulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
sii902x->i2cmux->priv = sii902x;
|
||||||
|
ret = i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Couldn't add i2c mux adapter\n");
|
||||||
|
- return ret;
|
||||||
|
+ goto err_disable_regulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
sii902x_register_audio_driver(dev, sii902x);
|
||||||
|
@@ -1060,6 +1073,7 @@ static int sii902x_probe(struct i2c_client *client,
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_disable_regulator:
|
||||||
|
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||||
|
regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
|
||||||
|
sii902x->supplies);
|
||||||
|
|
||||||
|
@@ -1095,6 +1109,8 @@ static int sii902x_pm_suspend(struct device *dev)
|
||||||
|
regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
|
||||||
|
sii902x->supplies);
|
||||||
|
|
||||||
|
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1109,10 +1125,17 @@ static int sii902x_pm_resume(struct device *dev)
|
||||||
|
.len = 2,
|
||||||
|
.buf = data,
|
||||||
|
};
|
||||||
|
+ unsigned int status = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
DRM_DEBUG_DRIVER("\n");
|
||||||
|
|
||||||
|
+ regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||||
|
+
|
||||||
|
+ /* due to old tv, need to restore pinctrl as soon as possible */
|
||||||
|
+ if (status & SII902X_PLUGGED_STATUS)
|
||||||
|
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||||
|
+
|
||||||
|
ret = regulator_bulk_enable(ARRAY_SIZE(sii902x->supplies),
|
||||||
|
sii902x->supplies);
|
||||||
|
if (ret) {
|
||||||
|
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
|
||||||
|
index bf90625..c7217b1 100644
|
||||||
|
--- a/drivers/gpu/drm/drm_gem.c
|
||||||
|
+++ b/drivers/gpu/drm/drm_gem.c
|
||||||
|
@@ -326,12 +326,6 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
|
||||||
|
if (!obj)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
- /* Don't allow imported objects to be mapped */
|
||||||
|
- if (obj->import_attach) {
|
||||||
|
- ret = -EINVAL;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
ret = drm_gem_create_mmap_offset(obj);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
From f7da805ac84601d1dbbaf51e8f080844e1e5ae4e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:40:00 +0100
|
||||||
|
Subject: [PATCH 34/52] ARM: stm32mp1-r0-rc3: ETH
|
||||||
|
|
||||||
|
---
|
||||||
|
.../devicetree/bindings/net/stm32-dwmac.txt | 4 +--
|
||||||
|
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 36 ++++++++++++++--------
|
||||||
|
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 20 ++++++------
|
||||||
|
3 files changed, 36 insertions(+), 24 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.txt b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||||
|
index f42dc68..5f6a6ba 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||||
|
@@ -14,8 +14,7 @@ Required properties:
|
||||||
|
- clock-names: Should be "stmmaceth" for the host clock.
|
||||||
|
Should be "mac-clk-tx" for the MAC TX clock.
|
||||||
|
Should be "mac-clk-rx" for the MAC RX clock.
|
||||||
|
- For MPU family need to add also "ethstp" for power mode clock and,
|
||||||
|
- "syscfg-clk" for SYSCFG clock.
|
||||||
|
+ For MPU family need to add also "ethstp" for power mode clock.
|
||||||
|
- interrupt-names: Should contain a list of interrupt names corresponding to
|
||||||
|
the interrupts in the interrupts property, if available.
|
||||||
|
Should be "macirq" for the main MAC IRQ
|
||||||
|
@@ -25,6 +24,7 @@ Required properties:
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- clock-names: For MPU family "eth-ck" for PHY without quartz
|
||||||
|
+ "syscfg-clk" for SYSCFG clock.
|
||||||
|
- st,eth_clk_sel (boolean) : set this property in RGMII PHY when you do not want use 125Mhz
|
||||||
|
- st,eth_ref_clk_sel (boolean) : set this property in RMII mode when you have PHY without crystal 50MHz
|
||||||
|
|
||||||
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||||
|
index 545b168..8b4ca12 100644
|
||||||
|
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||||
|
@@ -153,23 +153,32 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (prepare) {
|
||||||
|
- ret = clk_prepare_enable(dwmac->syscfg_clk);
|
||||||
|
- if (ret)
|
||||||
|
- return ret;
|
||||||
|
-
|
||||||
|
+ if (dwmac->syscfg_clk) {
|
||||||
|
+ ret = clk_prepare_enable(dwmac->syscfg_clk);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
if (dwmac->clk_eth_ck) {
|
||||||
|
ret = clk_prepare_enable(dwmac->clk_eth_ck);
|
||||||
|
if (ret) {
|
||||||
|
- clk_disable_unprepare(dwmac->syscfg_clk);
|
||||||
|
+ if (dwmac->syscfg_clk)
|
||||||
|
+ goto unprepare_syscfg;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
- clk_disable_unprepare(dwmac->syscfg_clk);
|
||||||
|
+ if (dwmac->syscfg_clk)
|
||||||
|
+ clk_disable_unprepare(dwmac->syscfg_clk);
|
||||||
|
+
|
||||||
|
if (dwmac->clk_eth_ck)
|
||||||
|
clk_disable_unprepare(dwmac->clk_eth_ck);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
+
|
||||||
|
+unprepare_syscfg:
|
||||||
|
+ clk_disable_unprepare(dwmac->syscfg_clk);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||||
|
@@ -209,8 +218,8 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Need to update PMCCLRR (clear register) */
|
||||||
|
- ret = regmap_update_bits(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
|
||||||
|
- dwmac->ops->syscfg_eth_mask, ~val);
|
||||||
|
+ ret = regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
|
||||||
|
+ dwmac->ops->syscfg_eth_mask);
|
||||||
|
|
||||||
|
/* Update PMCSETR (set register) */
|
||||||
|
return regmap_update_bits(dwmac->regmap, reg,
|
||||||
|
@@ -318,11 +327,13 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||||
|
return PTR_ERR(dwmac->clk_ethstp);
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Clock for sysconfig */
|
||||||
|
+ /* Optional Clock for sysconfig */
|
||||||
|
dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk");
|
||||||
|
if (IS_ERR(dwmac->syscfg_clk)) {
|
||||||
|
- dev_err(dev, "No syscfg clock provided...\n");
|
||||||
|
- return PTR_ERR(dwmac->syscfg_clk);
|
||||||
|
+ err = PTR_ERR(dwmac->syscfg_clk);
|
||||||
|
+ if (err != -ENOENT)
|
||||||
|
+ return err;
|
||||||
|
+ dwmac->syscfg_clk = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get IRQ information early to have an ability to ask for deferred
|
||||||
|
@@ -431,7 +442,8 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
clk_disable_unprepare(dwmac->clk_tx);
|
||||||
|
- clk_disable_unprepare(dwmac->syscfg_clk);
|
||||||
|
+ if (dwmac->syscfg_clk)
|
||||||
|
+ clk_disable_unprepare(dwmac->syscfg_clk);
|
||||||
|
if (dwmac->clk_eth_ck)
|
||||||
|
clk_disable_unprepare(dwmac->clk_eth_ck);
|
||||||
|
|
||||||
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||||||
|
index 75896d6..281d9c7 100644
|
||||||
|
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||||||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||||||
|
@@ -2547,12 +2547,6 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
|
||||||
|
netdev_warn(priv->dev, "PTP init failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
-#ifdef CONFIG_DEBUG_FS
|
||||||
|
- ret = stmmac_init_fs(dev);
|
||||||
|
- if (ret < 0)
|
||||||
|
- netdev_warn(priv->dev, "%s: failed debugFS registration\n",
|
||||||
|
- __func__);
|
||||||
|
-#endif
|
||||||
|
priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
|
||||||
|
|
||||||
|
if (priv->use_riwt) {
|
||||||
|
@@ -2753,10 +2747,6 @@ static int stmmac_release(struct net_device *dev)
|
||||||
|
|
||||||
|
netif_carrier_off(dev);
|
||||||
|
|
||||||
|
-#ifdef CONFIG_DEBUG_FS
|
||||||
|
- stmmac_exit_fs(dev);
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
stmmac_release_ptp(priv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -4394,6 +4384,13 @@ int stmmac_dvr_probe(struct device *device,
|
||||||
|
goto error_netdev_register;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef CONFIG_DEBUG_FS
|
||||||
|
+ ret = stmmac_init_fs(ndev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ netdev_warn(priv->dev, "%s: failed debugFS registration\n",
|
||||||
|
+ __func__);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
error_netdev_register:
|
||||||
|
@@ -4429,6 +4426,9 @@ int stmmac_dvr_remove(struct device *dev)
|
||||||
|
|
||||||
|
netdev_info(priv->dev, "%s: removing driver", __func__);
|
||||||
|
|
||||||
|
+#ifdef CONFIG_DEBUG_FS
|
||||||
|
+ stmmac_exit_fs(ndev);
|
||||||
|
+#endif
|
||||||
|
stmmac_stop_all_dma(priv);
|
||||||
|
|
||||||
|
stmmac_mac_set(priv, priv->ioaddr, false);
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,479 @@
|
||||||
|
From 461aa8f3143d009efd0365889bddf247cfeafdce Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:35:33 +0100
|
||||||
|
Subject: [PATCH 35/52] ARM: stm32mp1-r0-rc3: IIO
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/iio/adc/stm32-adc-core.c | 35 +++++-----
|
||||||
|
drivers/iio/dac/stm32-dac-core.c | 142 ++++++++++++++++++++++++++++++---------
|
||||||
|
drivers/iio/dac/stm32-dac.c | 96 +++++++++++++++++++++++++-
|
||||||
|
3 files changed, 220 insertions(+), 53 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
|
||||||
|
index 6234456..ed64bb0 100644
|
||||||
|
--- a/drivers/iio/adc/stm32-adc-core.c
|
||||||
|
+++ b/drivers/iio/adc/stm32-adc-core.c
|
||||||
|
@@ -677,10 +677,9 @@ static int stm32_adc_switches_supply_en(struct device *dev)
|
||||||
|
priv->vbooster.reg,
|
||||||
|
priv->vbooster.mask, en_booster);
|
||||||
|
else
|
||||||
|
- ret = regmap_update_bits(priv->vbooster_clr.regmap,
|
||||||
|
- priv->vbooster_clr.reg,
|
||||||
|
- priv->vbooster_clr.mask,
|
||||||
|
- priv->vbooster_clr.mask);
|
||||||
|
+ ret = regmap_write(priv->vbooster_clr.regmap,
|
||||||
|
+ priv->vbooster_clr.reg,
|
||||||
|
+ priv->vbooster_clr.mask);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "can't access voltage booster, %d\n", ret);
|
||||||
|
goto vdd_dis;
|
||||||
|
@@ -697,10 +696,9 @@ static int stm32_adc_switches_supply_en(struct device *dev)
|
||||||
|
priv->anaswvdd.reg,
|
||||||
|
priv->anaswvdd.mask, anaswvdd);
|
||||||
|
else
|
||||||
|
- ret = regmap_update_bits(priv->anaswvdd_clr.regmap,
|
||||||
|
- priv->anaswvdd_clr.reg,
|
||||||
|
- priv->anaswvdd_clr.mask,
|
||||||
|
- priv->anaswvdd_clr.mask);
|
||||||
|
+ ret = regmap_write(priv->anaswvdd_clr.regmap,
|
||||||
|
+ priv->anaswvdd_clr.reg,
|
||||||
|
+ priv->anaswvdd_clr.mask);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "can't access anaswvdd, %d\n", ret);
|
||||||
|
goto booster_dis;
|
||||||
|
@@ -714,10 +712,9 @@ static int stm32_adc_switches_supply_en(struct device *dev)
|
||||||
|
regmap_update_bits(priv->vbooster.regmap, priv->vbooster.reg,
|
||||||
|
priv->vbooster.mask, 0);
|
||||||
|
else
|
||||||
|
- regmap_update_bits(priv->vbooster_clr.regmap,
|
||||||
|
- priv->vbooster_clr.reg,
|
||||||
|
- priv->vbooster_clr.mask,
|
||||||
|
- priv->vbooster_clr.mask);
|
||||||
|
+ regmap_write(priv->vbooster_clr.regmap,
|
||||||
|
+ priv->vbooster_clr.reg,
|
||||||
|
+ priv->vbooster_clr.mask);
|
||||||
|
vdd_dis:
|
||||||
|
if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap))
|
||||||
|
regulator_disable(priv->vdd);
|
||||||
|
@@ -741,20 +738,18 @@ static void stm32_adc_switches_supply_dis(struct device *dev)
|
||||||
|
priv->anaswvdd.reg,
|
||||||
|
priv->anaswvdd.mask, 0);
|
||||||
|
else
|
||||||
|
- regmap_update_bits(priv->anaswvdd_clr.regmap,
|
||||||
|
- priv->anaswvdd_clr.reg,
|
||||||
|
- priv->anaswvdd_clr.mask,
|
||||||
|
- priv->anaswvdd_clr.mask);
|
||||||
|
+ regmap_write(priv->anaswvdd_clr.regmap,
|
||||||
|
+ priv->anaswvdd_clr.reg,
|
||||||
|
+ priv->anaswvdd_clr.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ERR(priv->vbooster_clr.regmap))
|
||||||
|
regmap_update_bits(priv->vbooster.regmap, priv->vbooster.reg,
|
||||||
|
priv->vbooster.mask, 0);
|
||||||
|
else
|
||||||
|
- regmap_update_bits(priv->vbooster_clr.regmap,
|
||||||
|
- priv->vbooster_clr.reg,
|
||||||
|
- priv->vbooster_clr.mask,
|
||||||
|
- priv->vbooster_clr.mask);
|
||||||
|
+ regmap_write(priv->vbooster_clr.regmap,
|
||||||
|
+ priv->vbooster_clr.reg,
|
||||||
|
+ priv->vbooster_clr.mask);
|
||||||
|
|
||||||
|
if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap))
|
||||||
|
regulator_disable(priv->vdd);
|
||||||
|
diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c
|
||||||
|
index d0fb312..280322b 100644
|
||||||
|
--- a/drivers/iio/dac/stm32-dac-core.c
|
||||||
|
+++ b/drivers/iio/dac/stm32-dac-core.c
|
||||||
|
@@ -11,6 +11,7 @@
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
+#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
|
||||||
|
@@ -50,6 +51,41 @@ static const struct regmap_config stm32_dac_regmap_cfg = {
|
||||||
|
.max_register = 0x3fc,
|
||||||
|
};
|
||||||
|
|
||||||
|
+static int stm32_dac_core_hw_start(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_dac_common *common = dev_get_drvdata(dev);
|
||||||
|
+ struct stm32_dac_priv *priv = to_stm32_dac_priv(common);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = regulator_enable(priv->vref);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(dev, "vref enable failed: %d\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = clk_prepare_enable(priv->pclk);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(dev, "pclk enable failed: %d\n", ret);
|
||||||
|
+ goto err_regulator_disable;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+err_regulator_disable:
|
||||||
|
+ regulator_disable(priv->vref);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32_dac_core_hw_stop(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_dac_common *common = dev_get_drvdata(dev);
|
||||||
|
+ struct stm32_dac_priv *priv = to_stm32_dac_priv(common);
|
||||||
|
+
|
||||||
|
+ clk_disable_unprepare(priv->pclk);
|
||||||
|
+ regulator_disable(priv->vref);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int stm32_dac_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
@@ -66,6 +102,8 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||||
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
+ platform_set_drvdata(pdev, &priv->common);
|
||||||
|
+
|
||||||
|
cfg = (const struct stm32_dac_cfg *)
|
||||||
|
of_match_device(dev->driver->of_match_table, dev)->data;
|
||||||
|
|
||||||
|
@@ -74,11 +112,19 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||||
|
if (IS_ERR(mmio))
|
||||||
|
return PTR_ERR(mmio);
|
||||||
|
|
||||||
|
- regmap = devm_regmap_init_mmio(dev, mmio, &stm32_dac_regmap_cfg);
|
||||||
|
+ regmap = devm_regmap_init_mmio_clk(dev, "pclk", mmio,
|
||||||
|
+ &stm32_dac_regmap_cfg);
|
||||||
|
if (IS_ERR(regmap))
|
||||||
|
return PTR_ERR(regmap);
|
||||||
|
priv->common.regmap = regmap;
|
||||||
|
|
||||||
|
+ priv->pclk = devm_clk_get(dev, "pclk");
|
||||||
|
+ if (IS_ERR(priv->pclk)) {
|
||||||
|
+ ret = PTR_ERR(priv->pclk);
|
||||||
|
+ dev_err(dev, "pclk get failed\n");
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
priv->vref = devm_regulator_get(dev, "vref");
|
||||||
|
if (IS_ERR(priv->vref)) {
|
||||||
|
ret = PTR_ERR(priv->vref);
|
||||||
|
@@ -86,33 +132,22 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = regulator_enable(priv->vref);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- dev_err(dev, "vref enable failed\n");
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
+ pm_runtime_get_noresume(dev);
|
||||||
|
+ pm_runtime_set_active(dev);
|
||||||
|
+ pm_runtime_enable(dev);
|
||||||
|
+
|
||||||
|
+ ret = stm32_dac_core_hw_start(dev);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto err_pm_stop;
|
||||||
|
|
||||||
|
ret = regulator_get_voltage(priv->vref);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "vref get voltage failed, %d\n", ret);
|
||||||
|
- goto err_vref;
|
||||||
|
+ goto err_hw_stop;
|
||||||
|
}
|
||||||
|
priv->common.vref_mv = ret / 1000;
|
||||||
|
dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv);
|
||||||
|
|
||||||
|
- priv->pclk = devm_clk_get(dev, "pclk");
|
||||||
|
- if (IS_ERR(priv->pclk)) {
|
||||||
|
- ret = PTR_ERR(priv->pclk);
|
||||||
|
- dev_err(dev, "pclk get failed\n");
|
||||||
|
- goto err_vref;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- ret = clk_prepare_enable(priv->pclk);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- dev_err(dev, "pclk enable failed\n");
|
||||||
|
- goto err_vref;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
priv->rst = devm_reset_control_get_exclusive(dev, NULL);
|
||||||
|
if (!IS_ERR(priv->rst)) {
|
||||||
|
reset_control_assert(priv->rst);
|
||||||
|
@@ -128,39 +163,83 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||||
|
priv->common.hfsel ?
|
||||||
|
STM32H7_DAC_CR_HFSEL : 0);
|
||||||
|
if (ret)
|
||||||
|
- goto err_pclk;
|
||||||
|
+ goto err_hw_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
- platform_set_drvdata(pdev, &priv->common);
|
||||||
|
|
||||||
|
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "failed to populate DT children\n");
|
||||||
|
- goto err_pclk;
|
||||||
|
+ goto err_hw_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ pm_runtime_put(dev);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
-err_pclk:
|
||||||
|
- clk_disable_unprepare(priv->pclk);
|
||||||
|
-err_vref:
|
||||||
|
- regulator_disable(priv->vref);
|
||||||
|
+err_hw_stop:
|
||||||
|
+ stm32_dac_core_hw_stop(dev);
|
||||||
|
+err_pm_stop:
|
||||||
|
+ pm_runtime_disable(dev);
|
||||||
|
+ pm_runtime_set_suspended(dev);
|
||||||
|
+ pm_runtime_put_noidle(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32_dac_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
- struct stm32_dac_common *common = platform_get_drvdata(pdev);
|
||||||
|
+ pm_runtime_get_sync(&pdev->dev);
|
||||||
|
+ of_platform_depopulate(&pdev->dev);
|
||||||
|
+ stm32_dac_core_hw_stop(&pdev->dev);
|
||||||
|
+ pm_runtime_disable(&pdev->dev);
|
||||||
|
+ pm_runtime_set_suspended(&pdev->dev);
|
||||||
|
+ pm_runtime_put_noidle(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#if defined(CONFIG_PM_SLEEP)
|
||||||
|
+static int stm32_dac_core_resume(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct stm32_dac_common *common = dev_get_drvdata(dev);
|
||||||
|
struct stm32_dac_priv *priv = to_stm32_dac_priv(common);
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
- of_platform_depopulate(&pdev->dev);
|
||||||
|
- clk_disable_unprepare(priv->pclk);
|
||||||
|
- regulator_disable(priv->vref);
|
||||||
|
+ /* Unconditionally restore hfsel (maybe lost under low power state) */
|
||||||
|
+ if (priv->common.hfsel) {
|
||||||
|
+ ret = regmap_update_bits(priv->common.regmap, STM32_DAC_CR,
|
||||||
|
+ STM32H7_DAC_CR_HFSEL,
|
||||||
|
+ STM32H7_DAC_CR_HFSEL);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return pm_runtime_force_resume(dev);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if defined(CONFIG_PM)
|
||||||
|
+static int stm32_dac_core_runtime_suspend(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ stm32_dac_core_hw_stop(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int stm32_dac_core_runtime_resume(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ return stm32_dac_core_hw_start(dev);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+static const struct dev_pm_ops stm32_dac_core_pm_ops = {
|
||||||
|
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, stm32_dac_core_resume)
|
||||||
|
+ SET_RUNTIME_PM_OPS(stm32_dac_core_runtime_suspend,
|
||||||
|
+ stm32_dac_core_runtime_resume,
|
||||||
|
+ NULL)
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static const struct stm32_dac_cfg stm32h7_dac_cfg = {
|
||||||
|
.has_hfsel = true,
|
||||||
|
};
|
||||||
|
@@ -182,6 +261,7 @@ static struct platform_driver stm32_dac_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "stm32-dac-core",
|
||||||
|
.of_match_table = stm32_dac_of_match,
|
||||||
|
+ .pm = &stm32_dac_core_pm_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
module_platform_driver(stm32_dac_driver);
|
||||||
|
diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c
|
||||||
|
index cce26a3..0a8abc5 100644
|
||||||
|
--- a/drivers/iio/dac/stm32-dac.c
|
||||||
|
+++ b/drivers/iio/dac/stm32-dac.c
|
||||||
|
@@ -13,6 +13,7 @@
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
+#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
|
#include "stm32-dac-core.h"
|
||||||
|
|
||||||
|
@@ -20,6 +21,8 @@
|
||||||
|
#define STM32_DAC_CHANNEL_2 2
|
||||||
|
#define STM32_DAC_IS_CHAN_1(ch) ((ch) & STM32_DAC_CHANNEL_1)
|
||||||
|
|
||||||
|
+#define STM32_DAC_AUTO_SUSPEND_DELAY_MS 2000
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* struct stm32_dac - private data of DAC driver
|
||||||
|
* @common: reference to DAC common data
|
||||||
|
@@ -49,15 +52,34 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch,
|
||||||
|
bool enable)
|
||||||
|
{
|
||||||
|
struct stm32_dac *dac = iio_priv(indio_dev);
|
||||||
|
+ struct device *dev = indio_dev->dev.parent;
|
||||||
|
u32 msk = STM32_DAC_IS_CHAN_1(ch) ? STM32_DAC_CR_EN1 : STM32_DAC_CR_EN2;
|
||||||
|
u32 en = enable ? msk : 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ /* already enabled / disabled ? */
|
||||||
|
+ mutex_lock(&indio_dev->mlock);
|
||||||
|
+ ret = stm32_dac_is_enabled(indio_dev, ch);
|
||||||
|
+ if (ret < 0 || enable == !!ret) {
|
||||||
|
+ mutex_unlock(&indio_dev->mlock);
|
||||||
|
+ return ret < 0 ? ret : 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (enable) {
|
||||||
|
+ ret = pm_runtime_get_sync(dev);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ pm_runtime_put_noidle(dev);
|
||||||
|
+ mutex_unlock(&indio_dev->mlock);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = regmap_update_bits(dac->common->regmap, STM32_DAC_CR, msk, en);
|
||||||
|
+ mutex_unlock(&indio_dev->mlock);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&indio_dev->dev, "%s failed\n", en ?
|
||||||
|
"Enable" : "Disable");
|
||||||
|
- return ret;
|
||||||
|
+ goto err_put_pm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -68,7 +90,20 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch,
|
||||||
|
if (en && dac->common->hfsel)
|
||||||
|
udelay(1);
|
||||||
|
|
||||||
|
+ if (!enable) {
|
||||||
|
+ pm_runtime_mark_last_busy(dev);
|
||||||
|
+ pm_runtime_put_autosuspend(dev);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
+
|
||||||
|
+err_put_pm:
|
||||||
|
+ if (enable) {
|
||||||
|
+ pm_runtime_mark_last_busy(dev);
|
||||||
|
+ pm_runtime_put_autosuspend(dev);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32_dac_get_value(struct stm32_dac *dac, int channel, int *val)
|
||||||
|
@@ -272,6 +307,7 @@ static int stm32_dac_chan_of_init(struct iio_dev *indio_dev)
|
||||||
|
static int stm32_dac_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device_node *np = pdev->dev.of_node;
|
||||||
|
+ struct device *dev = &pdev->dev;
|
||||||
|
struct iio_dev *indio_dev;
|
||||||
|
struct stm32_dac *dac;
|
||||||
|
int ret;
|
||||||
|
@@ -296,9 +332,63 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
- return devm_iio_device_register(&pdev->dev, indio_dev);
|
||||||
|
+ /* Get stm32-dac-core PM online */
|
||||||
|
+ pm_runtime_get_noresume(dev);
|
||||||
|
+ pm_runtime_set_active(dev);
|
||||||
|
+ pm_runtime_set_autosuspend_delay(dev, STM32_DAC_AUTO_SUSPEND_DELAY_MS);
|
||||||
|
+ pm_runtime_use_autosuspend(dev);
|
||||||
|
+ pm_runtime_enable(dev);
|
||||||
|
+
|
||||||
|
+ ret = iio_device_register(indio_dev);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto err_pm_put;
|
||||||
|
+
|
||||||
|
+ pm_runtime_mark_last_busy(dev);
|
||||||
|
+ pm_runtime_put_autosuspend(dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+err_pm_put:
|
||||||
|
+ pm_runtime_disable(dev);
|
||||||
|
+ pm_runtime_set_suspended(dev);
|
||||||
|
+ pm_runtime_put_noidle(dev);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int stm32_dac_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ pm_runtime_get_sync(&pdev->dev);
|
||||||
|
+ iio_device_unregister(indio_dev);
|
||||||
|
+ pm_runtime_disable(&pdev->dev);
|
||||||
|
+ pm_runtime_set_suspended(&pdev->dev);
|
||||||
|
+ pm_runtime_put_noidle(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#if defined(CONFIG_PM_SLEEP)
|
||||||
|
+static int stm32_dac_suspend(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||||
|
+ int channel = indio_dev->channels[0].channel;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ /* Ensure DAC is disabled before suspend */
|
||||||
|
+ ret = stm32_dac_is_enabled(indio_dev, channel);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret < 0 ? ret : -EBUSY;
|
||||||
|
+
|
||||||
|
+ return pm_runtime_force_suspend(dev);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+static const struct dev_pm_ops stm32_dac_pm_ops = {
|
||||||
|
+ SET_SYSTEM_SLEEP_PM_OPS(stm32_dac_suspend, pm_runtime_force_resume)
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static const struct of_device_id stm32_dac_of_match[] = {
|
||||||
|
{ .compatible = "st,stm32-dac", },
|
||||||
|
{},
|
||||||
|
@@ -307,9 +397,11 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
|
||||||
|
|
||||||
|
static struct platform_driver stm32_dac_driver = {
|
||||||
|
.probe = stm32_dac_probe,
|
||||||
|
+ .remove = stm32_dac_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "stm32-dac",
|
||||||
|
.of_match_table = stm32_dac_of_match,
|
||||||
|
+ .pm = &stm32_dac_pm_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
module_platform_driver(stm32_dac_driver);
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
From adfe9751275d51343a5b7f26ea93246ae617d986 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:37:06 +0100
|
||||||
|
Subject: [PATCH 36/52] ARM: stm32mp1-r0-rc3: INPUT TTY
|
||||||
|
|
||||||
|
---
|
||||||
|
.../devicetree/bindings/serial/st,stm32-usart.txt | 1 +
|
||||||
|
drivers/input/touchscreen/edt-ft5x06.c | 8 +++++++-
|
||||||
|
drivers/input/touchscreen/goodix.c | 9 +++++++++
|
||||||
|
drivers/tty/serial/stm32-usart.c | 18 ++++++++++++++++--
|
||||||
|
4 files changed, 33 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
|
||||||
|
index 90ba52f..08b4990 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
|
||||||
|
@@ -14,6 +14,7 @@ Required properties:
|
||||||
|
- clocks: The input clock of the USART instance
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
+- resets: Must contain the phandle to the reset controller.
|
||||||
|
- pinctrl-names: Set to "default". An additional "sleep" state can be defined
|
||||||
|
to set pins in sleep state when in low power. In case the device is used as
|
||||||
|
a wakeup source, "idle" state is defined in order to keep RX pin active.
|
||||||
|
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
|
||||||
|
index 1e18ca0..c1c6f2a 100644
|
||||||
|
--- a/drivers/input/touchscreen/edt-ft5x06.c
|
||||||
|
+++ b/drivers/input/touchscreen/edt-ft5x06.c
|
||||||
|
@@ -1033,7 +1033,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
|
||||||
|
|
||||||
|
error = edt_ft5x06_ts_identify(client, tsdata, fw_version);
|
||||||
|
if (error) {
|
||||||
|
- dev_err(&client->dev, "touchscreen probe failed\n");
|
||||||
|
+ dev_dbg(&client->dev, "touchscreen probe failed\n");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1152,11 +1152,16 @@ static const struct edt_i2c_chip_data edt_ft6236_data = {
|
||||||
|
.max_support_points = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
+static const struct edt_i2c_chip_data edt_ft6336_data = {
|
||||||
|
+ .max_support_points = 2,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static const struct i2c_device_id edt_ft5x06_ts_id[] = {
|
||||||
|
{ .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
|
||||||
|
{ .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data },
|
||||||
|
/* Note no edt- prefix for compatibility with the ft6236.c driver */
|
||||||
|
{ .name = "ft6236", .driver_data = (long)&edt_ft6236_data },
|
||||||
|
+ { .name = "ft6336", .driver_data = (long)&edt_ft6336_data },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
|
||||||
|
@@ -1169,6 +1174,7 @@ static const struct of_device_id edt_ft5x06_of_match[] = {
|
||||||
|
{ .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data },
|
||||||
|
/* Note focaltech vendor prefix for compatibility with ft6236.c */
|
||||||
|
{ .compatible = "focaltech,ft6236", .data = &edt_ft6236_data },
|
||||||
|
+ { .compatible = "focaltech,ft6336", .data = &edt_ft6336_data },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
|
||||||
|
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
|
||||||
|
index f2d9c2c..9ce8db4 100644
|
||||||
|
--- a/drivers/input/touchscreen/goodix.c
|
||||||
|
+++ b/drivers/input/touchscreen/goodix.c
|
||||||
|
@@ -27,6 +27,7 @@
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
+#include <linux/gpio.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
@@ -357,6 +358,13 @@ static void goodix_free_irq(struct goodix_ts_data *ts)
|
||||||
|
|
||||||
|
static int goodix_request_irq(struct goodix_ts_data *ts)
|
||||||
|
{
|
||||||
|
+ int gpio;
|
||||||
|
+
|
||||||
|
+ gpio = desc_to_gpio(ts->gpiod_int);
|
||||||
|
+
|
||||||
|
+ if (gpio_is_valid(gpio))
|
||||||
|
+ ts->client->irq = gpio_to_irq(gpio);
|
||||||
|
+
|
||||||
|
return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
|
||||||
|
NULL, goodix_ts_irq_handler,
|
||||||
|
ts->irq_flags, ts->client->name, ts);
|
||||||
|
@@ -949,6 +957,7 @@ static const struct of_device_id goodix_of_match[] = {
|
||||||
|
{ .compatible = "goodix,gt9271" },
|
||||||
|
{ .compatible = "goodix,gt928" },
|
||||||
|
{ .compatible = "goodix,gt967" },
|
||||||
|
+ { .compatible = "goodix,gt9147",},
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, goodix_of_match);
|
||||||
|
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
|
||||||
|
index 5c6c3c0..d606eb5 100644
|
||||||
|
--- a/drivers/tty/serial/stm32-usart.c
|
||||||
|
+++ b/drivers/tty/serial/stm32-usart.c
|
||||||
|
@@ -938,6 +938,7 @@ static int stm32_init_port(struct stm32_port *stm32port,
|
||||||
|
{
|
||||||
|
struct uart_port *port = &stm32port->port;
|
||||||
|
struct resource *res;
|
||||||
|
+ struct pinctrl *uart_pinctrl;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
port->iotype = UPIO_MEM;
|
||||||
|
@@ -952,8 +953,21 @@ static int stm32_init_port(struct stm32_port *stm32port,
|
||||||
|
|
||||||
|
stm32port->wakeirq = platform_get_irq_byname(pdev, "wakeup");
|
||||||
|
stm32port->fifoen = stm32port->info->cfg.has_fifo;
|
||||||
|
- stm32port->console_pins = pinctrl_lookup_state(pdev->dev.pins->p,
|
||||||
|
- "no_console_suspend");
|
||||||
|
+
|
||||||
|
+ uart_pinctrl = devm_pinctrl_get(&pdev->dev);
|
||||||
|
+ if (IS_ERR(uart_pinctrl)) {
|
||||||
|
+ ret = PTR_ERR(uart_pinctrl);
|
||||||
|
+ if (ret != -ENODEV) {
|
||||||
|
+ dev_err(&pdev->dev,"Can't get pinctrl, error %d\n",
|
||||||
|
+ ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ stm32port->console_pins = ERR_PTR(-ENODEV);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ stm32port->console_pins = pinctrl_lookup_state
|
||||||
|
+ (uart_pinctrl,"no_console_suspend");
|
||||||
|
+
|
||||||
|
if (IS_ERR(stm32port->console_pins)
|
||||||
|
&& PTR_ERR(stm32port->console_pins) != -ENODEV)
|
||||||
|
return PTR_ERR(stm32port->console_pins);
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,277 @@
|
||||||
|
From 4cc987cced2179b54ebc0a977ff3ef4210acb38c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:36:09 +0100
|
||||||
|
Subject: [PATCH 37/52] ARM: stm32mp1-r0-rc3: IRQ Mailbox
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/irqchip/irq-stm32-exti.c | 122 ++++++++++++++++++++++++++-------------
|
||||||
|
1 file changed, 83 insertions(+), 39 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
index 9cc15f1..223ee2e 100644
|
||||||
|
--- a/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
+++ b/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
@@ -6,6 +6,7 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
#include <linux/hwspinlock.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
@@ -21,7 +22,8 @@
|
||||||
|
|
||||||
|
#define IRQS_PER_BANK 32
|
||||||
|
|
||||||
|
-#define HWSPINLOCK_TIMEOUT 5 /* msec */
|
||||||
|
+#define HWSPNLCK_TIMEOUT 1000 /* usec */
|
||||||
|
+#define HWSPNLCK_RETRY_DELAY 100 /* usec */
|
||||||
|
|
||||||
|
struct stm32_exti_bank {
|
||||||
|
u32 imr_ofst;
|
||||||
|
@@ -35,6 +37,12 @@ struct stm32_exti_bank {
|
||||||
|
|
||||||
|
#define UNDEF_REG ~0
|
||||||
|
|
||||||
|
+enum stm32_exti_hwspinlock {
|
||||||
|
+ HWSPINLOCK_UNKNOWN,
|
||||||
|
+ HWSPINLOCK_NONE,
|
||||||
|
+ HWSPINLOCK_READY,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
struct stm32_desc_irq {
|
||||||
|
u32 exti;
|
||||||
|
u32 irq_parent;
|
||||||
|
@@ -50,7 +58,6 @@ struct stm32_exti_drv_data {
|
||||||
|
struct stm32_exti_chip_data {
|
||||||
|
struct stm32_exti_host_data *host_data;
|
||||||
|
const struct stm32_exti_bank *reg_bank;
|
||||||
|
- struct hwspinlock *hwlock;
|
||||||
|
struct raw_spinlock rlock;
|
||||||
|
u32 wake_active;
|
||||||
|
u32 mask_cache;
|
||||||
|
@@ -62,6 +69,9 @@ struct stm32_exti_host_data {
|
||||||
|
void __iomem *base;
|
||||||
|
struct stm32_exti_chip_data *chips_data;
|
||||||
|
const struct stm32_exti_drv_data *drv_data;
|
||||||
|
+ struct device_node *node;
|
||||||
|
+ enum stm32_exti_hwspinlock hwlock_state;
|
||||||
|
+ struct hwspinlock *hwlock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct stm32_exti_host_data *stm32_host_data;
|
||||||
|
@@ -273,20 +283,75 @@ static int stm32_exti_set_type(struct irq_data *d,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data)
|
||||||
|
+{
|
||||||
|
+ struct stm32_exti_host_data *host_data = chip_data->host_data;
|
||||||
|
+ struct hwspinlock *hwlock;
|
||||||
|
+ int id, ret = 0, timeout = 0;
|
||||||
|
+
|
||||||
|
+ /* first time, check for hwspinlock availability */
|
||||||
|
+ if (unlikely(host_data->hwlock_state == HWSPINLOCK_UNKNOWN)) {
|
||||||
|
+ id = of_hwspin_lock_get_id(host_data->node, 0);
|
||||||
|
+ if (id >= 0) {
|
||||||
|
+ hwlock = hwspin_lock_request_specific(id);
|
||||||
|
+ if (hwlock) {
|
||||||
|
+ /* found valid hwspinlock */
|
||||||
|
+ host_data->hwlock_state = HWSPINLOCK_READY;
|
||||||
|
+ host_data->hwlock = hwlock;
|
||||||
|
+ pr_debug("%s hwspinlock = %d\n", __func__, id);
|
||||||
|
+ } else {
|
||||||
|
+ host_data->hwlock_state = HWSPINLOCK_NONE;
|
||||||
|
+ }
|
||||||
|
+ } else if (id != -EPROBE_DEFER) {
|
||||||
|
+ host_data->hwlock_state = HWSPINLOCK_NONE;
|
||||||
|
+ } else {
|
||||||
|
+ /* hwspinlock driver shall be ready at that stage */
|
||||||
|
+ ret = -EPROBE_DEFER;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (likely(host_data->hwlock_state == HWSPINLOCK_READY)) {
|
||||||
|
+ /*
|
||||||
|
+ * Use the x_raw API since we are under spin_lock protection.
|
||||||
|
+ * Do not use the x_timeout API because we are under irq_disable
|
||||||
|
+ * mode (see __setup_irq())
|
||||||
|
+ */
|
||||||
|
+ do {
|
||||||
|
+ ret = hwspin_trylock_raw(host_data->hwlock);
|
||||||
|
+ if (!ret)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ udelay(HWSPNLCK_RETRY_DELAY);
|
||||||
|
+ timeout += HWSPNLCK_RETRY_DELAY;
|
||||||
|
+ } while (timeout < HWSPNLCK_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ if (ret == -EBUSY)
|
||||||
|
+ ret = -ETIMEDOUT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ret)
|
||||||
|
+ pr_err("%s can't get hwspinlock (%d)\n", __func__, ret);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data)
|
||||||
|
+{
|
||||||
|
+ if (likely(chip_data->host_data->hwlock_state == HWSPINLOCK_READY))
|
||||||
|
+ hwspin_unlock_raw(chip_data->host_data->hwlock);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
|
||||||
|
{
|
||||||
|
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||||
|
struct stm32_exti_chip_data *chip_data = gc->private;
|
||||||
|
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
|
||||||
|
u32 rtsr, ftsr;
|
||||||
|
- int err = 0;
|
||||||
|
+ int err;
|
||||||
|
|
||||||
|
irq_gc_lock(gc);
|
||||||
|
|
||||||
|
- if (chip_data->hwlock)
|
||||||
|
- err = hwspin_lock_timeout(chip_data->hwlock,
|
||||||
|
- HWSPINLOCK_TIMEOUT);
|
||||||
|
-
|
||||||
|
+ err = stm32_exti_hwspin_lock(chip_data);
|
||||||
|
if (err)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
@@ -301,8 +366,7 @@ static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
|
||||||
|
irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
|
||||||
|
|
||||||
|
unspinlock:
|
||||||
|
- if (chip_data->hwlock)
|
||||||
|
- hwspin_unlock(chip_data->hwlock);
|
||||||
|
+ stm32_exti_hwspin_unlock(chip_data);
|
||||||
|
unlock:
|
||||||
|
irq_gc_unlock(gc);
|
||||||
|
|
||||||
|
@@ -470,14 +534,11 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type)
|
||||||
|
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
|
||||||
|
void __iomem *base = chip_data->host_data->base;
|
||||||
|
u32 rtsr, ftsr;
|
||||||
|
- int err = 0;
|
||||||
|
+ int err;
|
||||||
|
|
||||||
|
raw_spin_lock(&chip_data->rlock);
|
||||||
|
|
||||||
|
- if (chip_data->hwlock)
|
||||||
|
- err = hwspin_lock_timeout(chip_data->hwlock,
|
||||||
|
- HWSPINLOCK_TIMEOUT);
|
||||||
|
-
|
||||||
|
+ err = stm32_exti_hwspin_lock(chip_data);
|
||||||
|
if (err)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
@@ -492,15 +553,14 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type)
|
||||||
|
writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst);
|
||||||
|
|
||||||
|
unspinlock:
|
||||||
|
- if (chip_data->hwlock)
|
||||||
|
- hwspin_unlock(chip_data->hwlock);
|
||||||
|
+ stm32_exti_hwspin_unlock(chip_data);
|
||||||
|
unlock:
|
||||||
|
raw_spin_unlock(&chip_data->rlock);
|
||||||
|
|
||||||
|
if (d->parent_data->chip)
|
||||||
|
irq_chip_set_type_parent(d, type);
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on)
|
||||||
|
@@ -650,6 +710,8 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
host_data->drv_data = dd;
|
||||||
|
+ host_data->node = node;
|
||||||
|
+ host_data->hwlock_state = HWSPINLOCK_UNKNOWN;
|
||||||
|
host_data->chips_data = kcalloc(dd->bank_nr,
|
||||||
|
sizeof(struct stm32_exti_chip_data),
|
||||||
|
GFP_KERNEL);
|
||||||
|
@@ -676,13 +738,11 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
|
||||||
|
|
||||||
|
static struct
|
||||||
|
stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||||
|
- u32 bank_idx,
|
||||||
|
- struct device_node *node)
|
||||||
|
+ u32 bank_idx)
|
||||||
|
{
|
||||||
|
const struct stm32_exti_bank *stm32_bank;
|
||||||
|
struct stm32_exti_chip_data *chip_data;
|
||||||
|
void __iomem *base = h_data->base;
|
||||||
|
- u32 irqs_mask;
|
||||||
|
|
||||||
|
stm32_bank = h_data->drv_data->exti_banks[bank_idx];
|
||||||
|
chip_data = &h_data->chips_data[bank_idx];
|
||||||
|
@@ -691,10 +751,6 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||||
|
|
||||||
|
raw_spin_lock_init(&chip_data->rlock);
|
||||||
|
|
||||||
|
- /* Determine number of irqs supported */
|
||||||
|
- writel_relaxed(~0UL, base + stm32_bank->rtsr_ofst);
|
||||||
|
- irqs_mask = readl_relaxed(base + stm32_bank->rtsr_ofst);
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* This IP has no reset, so after hot reboot we should
|
||||||
|
* clear registers to avoid residue
|
||||||
|
@@ -702,8 +758,7 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||||
|
writel_relaxed(0, base + stm32_bank->imr_ofst);
|
||||||
|
writel_relaxed(0, base + stm32_bank->emr_ofst);
|
||||||
|
|
||||||
|
- pr_info("%s: bank%d, External IRQs available:%#x\n",
|
||||||
|
- node->full_name, bank_idx, irqs_mask);
|
||||||
|
+ pr_info("%pOF: bank%d\n", h_data->node, bank_idx);
|
||||||
|
|
||||||
|
return chip_data;
|
||||||
|
}
|
||||||
|
@@ -716,7 +771,6 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
int nr_irqs, ret, i;
|
||||||
|
struct irq_chip_generic *gc;
|
||||||
|
struct irq_domain *domain;
|
||||||
|
- struct hwspinlock *hwlock = NULL;
|
||||||
|
|
||||||
|
host_data = stm32_exti_host_init(drv_data, node);
|
||||||
|
if (!host_data)
|
||||||
|
@@ -739,22 +793,12 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
goto out_free_domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* hwspinlock is optional */
|
||||||
|
- ret = of_hwspin_lock_get_id(node, 0);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- if (ret == -EPROBE_DEFER)
|
||||||
|
- goto out_free_domain;
|
||||||
|
- } else {
|
||||||
|
- hwlock = hwspin_lock_request_specific(ret);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
for (i = 0; i < drv_data->bank_nr; i++) {
|
||||||
|
const struct stm32_exti_bank *stm32_bank;
|
||||||
|
struct stm32_exti_chip_data *chip_data;
|
||||||
|
|
||||||
|
stm32_bank = drv_data->exti_banks[i];
|
||||||
|
- chip_data = stm32_exti_chip_init(host_data, i, node);
|
||||||
|
- chip_data->hwlock = hwlock;
|
||||||
|
+ chip_data = stm32_exti_chip_init(host_data, i);
|
||||||
|
|
||||||
|
gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
|
||||||
|
|
||||||
|
@@ -836,7 +880,7 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = 0; i < drv_data->bank_nr; i++)
|
||||||
|
- stm32_exti_chip_init(host_data, i, node);
|
||||||
|
+ stm32_exti_chip_init(host_data, i);
|
||||||
|
|
||||||
|
domain = irq_domain_add_hierarchy(parent_domain, 0,
|
||||||
|
drv_data->bank_nr * IRQS_PER_BANK,
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
From 6c1f5d14ed9c421276ad7beac5475e1114520369 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:48:55 +0100
|
||||||
|
Subject: [PATCH 38/52] ARM: stm32mp1-r0-rc3: MEDIA
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/media/i2c/ov5640.c | 3 +--
|
||||||
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
|
||||||
|
index 27b75e7..22ddfca4 100644
|
||||||
|
--- a/drivers/media/i2c/ov5640.c
|
||||||
|
+++ b/drivers/media/i2c/ov5640.c
|
||||||
|
@@ -2691,8 +2691,7 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
|
||||||
|
|
||||||
|
if (sensor->streaming == !enable) {
|
||||||
|
if (enable && sensor->pending_mode_change) {
|
||||||
|
- ret = ov5640_set_mode(sensor, sensor->last_mode);
|
||||||
|
-
|
||||||
|
+ ret = ov5640_set_mode(sensor);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,478 @@
|
||||||
|
From 0affc90bd300ecd2c60aee7fd97251a8d2aad01f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:38:59 +0100
|
||||||
|
Subject: [PATCH 39/52] ARM: stm32mp1-r0-rc3: MMC MTD
|
||||||
|
|
||||||
|
---
|
||||||
|
Documentation/devicetree/bindings/mmc/mmci.txt | 2 +
|
||||||
|
drivers/mmc/host/mmci.c | 61 +++++++++-
|
||||||
|
drivers/mmc/host/mmci.h | 8 +-
|
||||||
|
drivers/mmc/host/mmci_stm32_sdmmc.c | 162 ++++++++++++++++++++++++-
|
||||||
|
4 files changed, 219 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/mmc/mmci.txt b/Documentation/devicetree/bindings/mmc/mmci.txt
|
||||||
|
index 6d3c626..da6d59e 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/mmc/mmci.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/mmc/mmci.txt
|
||||||
|
@@ -15,6 +15,8 @@ Required properties:
|
||||||
|
Optional properties:
|
||||||
|
- arm,primecell-periphid : contains the PrimeCell Peripheral ID, it overrides
|
||||||
|
the ID provided by the HW
|
||||||
|
+- reg : sdmmc variant could have a second base register for
|
||||||
|
+ delay block.
|
||||||
|
- resets : phandle to internal reset line.
|
||||||
|
Should be defined for sdmmc variant.
|
||||||
|
- vqmmc-supply : phandle to the regulator device tree node, mentioned
|
||||||
|
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
|
||||||
|
index 02b631f..6c2b1a0 100644
|
||||||
|
--- a/drivers/mmc/host/mmci.c
|
||||||
|
+++ b/drivers/mmc/host/mmci.c
|
||||||
|
@@ -14,6 +14,7 @@
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
+#include <linux/iopoll.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
@@ -25,6 +26,7 @@
|
||||||
|
#include <linux/mmc/pm.h>
|
||||||
|
#include <linux/mmc/host.h>
|
||||||
|
#include <linux/mmc/card.h>
|
||||||
|
+#include <linux/mmc/sd.h>
|
||||||
|
#include <linux/mmc/slot-gpio.h>
|
||||||
|
#include <linux/amba/bus.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
@@ -291,7 +293,8 @@ static struct variant_data variant_stm32_sdmmc = {
|
||||||
|
.busy_detect_flag = MCI_STM32_BUSYD0,
|
||||||
|
.busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
|
||||||
|
.init = sdmmc_variant_init,
|
||||||
|
- .quirks = MMCI_QUIRK_STM32_DTMODE,
|
||||||
|
+ .quirks = MMCI_QUIRK_STM32_DTMODE |
|
||||||
|
+ MMCI_QUIRK_STM32_VSWITCH,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct variant_data variant_stm32_sdmmcv2 = {
|
||||||
|
@@ -318,7 +321,8 @@ static struct variant_data variant_stm32_sdmmcv2 = {
|
||||||
|
.busy_detect_flag = MCI_STM32_BUSYD0,
|
||||||
|
.busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
|
||||||
|
.init = sdmmc_variant_init,
|
||||||
|
- .quirks = MMCI_QUIRK_STM32_DTMODE,
|
||||||
|
+ .quirks = MMCI_QUIRK_STM32_DTMODE |
|
||||||
|
+ MMCI_QUIRK_STM32_VSWITCH,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct variant_data variant_qcom = {
|
||||||
|
@@ -1191,6 +1195,10 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
|
||||||
|
writel_relaxed(clks, host->base + MMCIDATATIMER);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (host->variant->quirks & MMCI_QUIRK_STM32_VSWITCH &&
|
||||||
|
+ cmd->opcode == SD_SWITCH_VOLTAGE)
|
||||||
|
+ mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCHEN);
|
||||||
|
+
|
||||||
|
if (/*interrupt*/0)
|
||||||
|
c |= MCI_CPSM_INTERRUPT;
|
||||||
|
|
||||||
|
@@ -1284,13 +1292,13 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
|
||||||
|
unsigned int status)
|
||||||
|
{
|
||||||
|
void __iomem *base = host->base;
|
||||||
|
- bool busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
|
||||||
|
- bool sbc;
|
||||||
|
+ bool busy_resp, sbc;
|
||||||
|
u32 err_msk;
|
||||||
|
|
||||||
|
if (!cmd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
+ busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
|
||||||
|
sbc = (cmd == host->mrq->sbc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1575,11 +1583,14 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
|
||||||
|
static irqreturn_t mmci_irq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct mmci_host *host = dev_id;
|
||||||
|
+ bool busy_resp;
|
||||||
|
u32 status;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
spin_lock(&host->lock);
|
||||||
|
|
||||||
|
+ busy_resp = host->cmd ? !!(host->cmd->flags & MMC_RSP_BUSY) : false;
|
||||||
|
+
|
||||||
|
do {
|
||||||
|
status = readl(host->base + MMCISTATUS);
|
||||||
|
|
||||||
|
@@ -1619,9 +1630,12 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Don't poll for busy completion in irq context.
|
||||||
|
+ * Don't poll for:
|
||||||
|
+ * -busy completion in irq context.
|
||||||
|
+ * -cmd without busy response check like cmd11
|
||||||
|
*/
|
||||||
|
- if (host->variant->busy_detect && host->busy_status)
|
||||||
|
+ if (host->variant->busy_detect &&
|
||||||
|
+ (!busy_resp || host->busy_status))
|
||||||
|
status &= ~host->variant->busy_detect_flag;
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
@@ -1796,6 +1810,8 @@ static int mmci_get_cd(struct mmc_host *mmc)
|
||||||
|
|
||||||
|
static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||||
|
{
|
||||||
|
+ struct mmci_host *host = mmc_priv(mmc);
|
||||||
|
+ unsigned long flags;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!IS_ERR(mmc->supply.vqmmc)) {
|
||||||
|
@@ -1808,6 +1824,28 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||||
|
case MMC_SIGNAL_VOLTAGE_180:
|
||||||
|
ret = regulator_set_voltage(mmc->supply.vqmmc,
|
||||||
|
1700000, 1950000);
|
||||||
|
+
|
||||||
|
+ if (ret)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ if (host->variant->quirks & MMCI_QUIRK_STM32_VSWITCH) {
|
||||||
|
+ u32 status;
|
||||||
|
+
|
||||||
|
+ spin_lock_irqsave(&host->lock, flags);
|
||||||
|
+
|
||||||
|
+ mmci_write_pwrreg(host, host->pwr_reg |
|
||||||
|
+ MCI_STM32_VSWITCH);
|
||||||
|
+
|
||||||
|
+ spin_unlock_irqrestore(&host->lock, flags);
|
||||||
|
+
|
||||||
|
+ /* wait voltage switch completion while 10ms */
|
||||||
|
+ ret = readl_relaxed_poll_timeout(
|
||||||
|
+ host->base + MMCISTATUS,
|
||||||
|
+ status,
|
||||||
|
+ (status & MCI_STM32_VSWEND),
|
||||||
|
+ 10, 10000);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
break;
|
||||||
|
case MMC_SIGNAL_VOLTAGE_120:
|
||||||
|
ret = regulator_set_voltage(mmc->supply.vqmmc,
|
||||||
|
@@ -1822,6 +1860,16 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int mmci_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||||
|
+{
|
||||||
|
+ struct mmci_host *host = mmc_priv(mmc);
|
||||||
|
+
|
||||||
|
+ if (host->ops && host->ops->execute_tuning)
|
||||||
|
+ return host->ops->execute_tuning(mmc, opcode);
|
||||||
|
+
|
||||||
|
+ return -EINVAL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static struct mmc_host_ops mmci_ops = {
|
||||||
|
.request = mmci_request,
|
||||||
|
.pre_req = mmci_pre_request,
|
||||||
|
@@ -1830,6 +1878,7 @@ static struct mmc_host_ops mmci_ops = {
|
||||||
|
.get_ro = mmc_gpio_get_ro,
|
||||||
|
.get_cd = mmci_get_cd,
|
||||||
|
.start_signal_voltage_switch = mmci_sig_volt_switch,
|
||||||
|
+ .execute_tuning = mmci_execute_tuning,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc)
|
||||||
|
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
|
||||||
|
index 55867fc..e10093e 100644
|
||||||
|
--- a/drivers/mmc/host/mmci.h
|
||||||
|
+++ b/drivers/mmc/host/mmci.h
|
||||||
|
@@ -170,6 +170,7 @@
|
||||||
|
#define MCI_STM32_DPSMACTIVE BIT(12)
|
||||||
|
#define MCI_STM32_BUSYD0 BIT(20)
|
||||||
|
#define MCI_STM32_BUSYD0END BIT(21)
|
||||||
|
+#define MCI_STM32_VSWEND BIT(25)
|
||||||
|
|
||||||
|
#define MMCICLEAR 0x038
|
||||||
|
#define MCI_CMDCRCFAILCLR (1 << 0)
|
||||||
|
@@ -364,8 +365,9 @@ struct variant_data {
|
||||||
|
void (*init)(struct mmci_host *host);
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define MMCI_QUIRK_STM32_DTMODE BIT(0)
|
||||||
|
-#define MMCI_QUIRK_ST_SDIO BIT(2) /* enable ST specific SDIO logic */
|
||||||
|
+#define MMCI_QUIRK_STM32_DTMODE BIT(0)
|
||||||
|
+#define MMCI_QUIRK_ST_SDIO BIT(2) /* enable ST specific SDIO logic */
|
||||||
|
+#define MMCI_QUIRK_STM32_VSWITCH BIT(3)
|
||||||
|
|
||||||
|
/* mmci variant callbacks */
|
||||||
|
struct mmci_host_ops {
|
||||||
|
@@ -382,6 +384,7 @@ struct mmci_host_ops {
|
||||||
|
void (*dma_error)(struct mmci_host *host);
|
||||||
|
void (*set_clkreg)(struct mmci_host *host, unsigned int desired);
|
||||||
|
void (*set_pwrreg)(struct mmci_host *host, unsigned int pwr);
|
||||||
|
+ int (*execute_tuning)(struct mmc_host *mmc, u32 opcode);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mmci_host {
|
||||||
|
@@ -414,6 +417,7 @@ struct mmci_host {
|
||||||
|
struct mmci_platform_data *plat;
|
||||||
|
struct mmci_host_ops *ops;
|
||||||
|
struct variant_data *variant;
|
||||||
|
+ void *variant_priv;
|
||||||
|
struct pinctrl *pinctrl;
|
||||||
|
struct pinctrl_state *pins_default;
|
||||||
|
struct pinctrl_state *pins_opendrain;
|
||||||
|
diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c
|
||||||
|
index cfbfc6f..e5ccc68 100644
|
||||||
|
--- a/drivers/mmc/host/mmci_stm32_sdmmc.c
|
||||||
|
+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c
|
||||||
|
@@ -3,14 +3,31 @@
|
||||||
|
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||||
|
* Author: Ludovic.barre@st.com for STMicroelectronics.
|
||||||
|
*/
|
||||||
|
+#include <linux/bitfield.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
+#include <linux/iopoll.h>
|
||||||
|
#include <linux/mmc/host.h>
|
||||||
|
#include <linux/mmc/card.h>
|
||||||
|
+#include <linux/of_address.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
#include <linux/scatterlist.h>
|
||||||
|
#include "mmci.h"
|
||||||
|
|
||||||
|
+#define DLYB_CR 0x0
|
||||||
|
+#define DLYB_CR_DEN BIT(0)
|
||||||
|
+#define DLYB_CR_SEN BIT(1)
|
||||||
|
+
|
||||||
|
+#define DLYB_CFGR 0x4
|
||||||
|
+#define DLYB_CFGR_SEL_MASK GENMASK(3, 0)
|
||||||
|
+#define DLYB_CFGR_UNIT_MASK GENMASK(14, 8)
|
||||||
|
+#define DLYB_CFGR_LNG_MASK GENMASK(27, 16)
|
||||||
|
+#define DLYB_CFGR_LNGF BIT(31)
|
||||||
|
+
|
||||||
|
+#define DLYB_NB_DELAY 11
|
||||||
|
+#define DLYB_CFGR_SEL_MAX (DLYB_NB_DELAY + 1)
|
||||||
|
+#define DLYB_CFGR_UNIT_MAX 127
|
||||||
|
+
|
||||||
|
#define SDMMC_LLI_BUF_LEN PAGE_SIZE
|
||||||
|
#define SDMMC_IDMA_BURST BIT(MMCI_STM32_IDMABNDT_SHIFT)
|
||||||
|
|
||||||
|
@@ -20,11 +37,17 @@ struct sdmmc_lli_desc {
|
||||||
|
u32 idmasize;
|
||||||
|
};
|
||||||
|
|
||||||
|
-struct sdmmc_priv {
|
||||||
|
+struct sdmmc_idma {
|
||||||
|
dma_addr_t sg_dma;
|
||||||
|
void *sg_cpu;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct sdmmc_dlyb {
|
||||||
|
+ void __iomem *base;
|
||||||
|
+ u32 unit;
|
||||||
|
+ u32 max;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
int sdmmc_idma_validate_data(struct mmci_host *host,
|
||||||
|
struct mmc_data *data)
|
||||||
|
{
|
||||||
|
@@ -36,8 +59,8 @@ int sdmmc_idma_validate_data(struct mmci_host *host,
|
||||||
|
* excepted the last element which has no constraint on idmasize
|
||||||
|
*/
|
||||||
|
for_each_sg(data->sg, sg, data->sg_len - 1, i) {
|
||||||
|
- if (!IS_ALIGNED(sg_dma_address(data->sg), sizeof(u32)) ||
|
||||||
|
- !IS_ALIGNED(sg_dma_len(data->sg), SDMMC_IDMA_BURST)) {
|
||||||
|
+ if (!IS_ALIGNED(data->sg->offset, sizeof(u32)) ||
|
||||||
|
+ !IS_ALIGNED(data->sg->length, SDMMC_IDMA_BURST)) {
|
||||||
|
dev_err(mmc_dev(host->mmc),
|
||||||
|
"unaligned scatterlist: ofst:%x length:%d\n",
|
||||||
|
data->sg->offset, data->sg->length);
|
||||||
|
@@ -45,7 +68,7 @@ int sdmmc_idma_validate_data(struct mmci_host *host,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!IS_ALIGNED(sg_dma_address(data->sg), sizeof(u32))) {
|
||||||
|
+ if (!IS_ALIGNED(data->sg->offset, sizeof(u32))) {
|
||||||
|
dev_err(mmc_dev(host->mmc),
|
||||||
|
"unaligned last scatterlist: ofst:%x length:%d\n",
|
||||||
|
data->sg->offset, data->sg->length);
|
||||||
|
@@ -92,7 +115,7 @@ static void sdmmc_idma_unprep_data(struct mmci_host *host,
|
||||||
|
|
||||||
|
static int sdmmc_idma_setup(struct mmci_host *host)
|
||||||
|
{
|
||||||
|
- struct sdmmc_priv *idma;
|
||||||
|
+ struct sdmmc_idma *idma;
|
||||||
|
|
||||||
|
idma = devm_kzalloc(mmc_dev(host->mmc), sizeof(*idma), GFP_KERNEL);
|
||||||
|
if (!idma)
|
||||||
|
@@ -123,7 +146,7 @@ static int sdmmc_idma_setup(struct mmci_host *host)
|
||||||
|
static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl)
|
||||||
|
|
||||||
|
{
|
||||||
|
- struct sdmmc_priv *idma = host->dma_priv;
|
||||||
|
+ struct sdmmc_idma *idma = host->dma_priv;
|
||||||
|
struct sdmmc_lli_desc *desc = (struct sdmmc_lli_desc *)idma->sg_cpu;
|
||||||
|
struct mmc_data *data = host->data;
|
||||||
|
struct scatterlist *sg;
|
||||||
|
@@ -226,12 +249,24 @@ static void mmci_sdmmc_set_clkreg(struct mmci_host *host, unsigned int desired)
|
||||||
|
mmci_write_clkreg(host, clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void sdmmc_dlyb_input_ck(struct sdmmc_dlyb *dlyb)
|
||||||
|
+{
|
||||||
|
+ if (!dlyb || !dlyb->base)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ /* Output clock = Input clock */
|
||||||
|
+ writel_relaxed(0, dlyb->base + DLYB_CR);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void mmci_sdmmc_set_pwrreg(struct mmci_host *host, unsigned int pwr)
|
||||||
|
{
|
||||||
|
struct mmc_ios ios = host->mmc->ios;
|
||||||
|
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
|
||||||
|
|
||||||
|
pwr = host->pwr_reg_add;
|
||||||
|
|
||||||
|
+ sdmmc_dlyb_input_ck(dlyb);
|
||||||
|
+
|
||||||
|
if (ios.power_mode == MMC_POWER_OFF) {
|
||||||
|
/* Only a reset could power-off sdmmc */
|
||||||
|
reset_control_assert(host->rst);
|
||||||
|
@@ -265,6 +300,105 @@ static void mmci_sdmmc_set_pwrreg(struct mmci_host *host, unsigned int pwr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void sdmmc_dlyb_set_cfgr(struct sdmmc_dlyb *dlyb,
|
||||||
|
+ int unit, int phase, bool sampler)
|
||||||
|
+{
|
||||||
|
+ u32 cr, cfgr;
|
||||||
|
+
|
||||||
|
+ writel_relaxed(DLYB_CR_SEN, dlyb->base + DLYB_CR);
|
||||||
|
+
|
||||||
|
+ cfgr = FIELD_PREP(DLYB_CFGR_UNIT_MASK, unit) |
|
||||||
|
+ FIELD_PREP(DLYB_CFGR_SEL_MASK, phase);
|
||||||
|
+ writel_relaxed(cfgr, dlyb->base + DLYB_CFGR);
|
||||||
|
+
|
||||||
|
+ cr = DLYB_CR_DEN;
|
||||||
|
+ if (sampler)
|
||||||
|
+ cr |= DLYB_CR_SEN;
|
||||||
|
+
|
||||||
|
+ writel_relaxed(cr, dlyb->base + DLYB_CR);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int sdmmc_dlyb_lng_tuning(struct mmci_host *host)
|
||||||
|
+{
|
||||||
|
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
|
||||||
|
+ u32 cfgr;
|
||||||
|
+ int i, lng, ret;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i <= DLYB_CFGR_UNIT_MAX; i++) {
|
||||||
|
+ sdmmc_dlyb_set_cfgr(dlyb, i, DLYB_CFGR_SEL_MAX, true);
|
||||||
|
+
|
||||||
|
+ ret = readl_relaxed_poll_timeout(dlyb->base + DLYB_CFGR, cfgr,
|
||||||
|
+ (cfgr & DLYB_CFGR_LNGF),
|
||||||
|
+ 1, 1000);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_warn(mmc_dev(host->mmc),
|
||||||
|
+ "delay line cfg timeout unit:%d cfgr:%d\n",
|
||||||
|
+ i, cfgr);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ lng = FIELD_GET(DLYB_CFGR_LNG_MASK, cfgr);
|
||||||
|
+ if (lng < BIT(DLYB_NB_DELAY) && lng > 0)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (i > DLYB_CFGR_UNIT_MAX)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ dlyb->unit = i;
|
||||||
|
+ dlyb->max = __fls(lng);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode)
|
||||||
|
+{
|
||||||
|
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
|
||||||
|
+ int cur_len = 0, max_len = 0, end_of_len = 0;
|
||||||
|
+ int phase;
|
||||||
|
+
|
||||||
|
+ for (phase = 0; phase <= dlyb->max; phase++) {
|
||||||
|
+ sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false);
|
||||||
|
+
|
||||||
|
+ if (mmc_send_tuning(host->mmc, opcode, NULL)) {
|
||||||
|
+ cur_len = 0;
|
||||||
|
+ } else {
|
||||||
|
+ cur_len++;
|
||||||
|
+ if (cur_len > max_len) {
|
||||||
|
+ max_len = cur_len;
|
||||||
|
+ end_of_len = phase;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!max_len) {
|
||||||
|
+ dev_err(mmc_dev(host->mmc), "no tuning point found\n");
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ phase = end_of_len - max_len / 2;
|
||||||
|
+ sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false);
|
||||||
|
+
|
||||||
|
+ dev_dbg(mmc_dev(host->mmc), "unit:%d max_dly:%d phase:%d\n",
|
||||||
|
+ dlyb->unit, dlyb->max, phase);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||||
|
+{
|
||||||
|
+ struct mmci_host *host = mmc_priv(mmc);
|
||||||
|
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
|
||||||
|
+
|
||||||
|
+ if (!dlyb || !dlyb->base)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ if (sdmmc_dlyb_lng_tuning(host))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ return sdmmc_dlyb_phase_tuning(host, opcode);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static struct mmci_host_ops sdmmc_variant_ops = {
|
||||||
|
.validate_data = sdmmc_idma_validate_data,
|
||||||
|
.prep_data = sdmmc_idma_prep_data,
|
||||||
|
@@ -274,9 +408,25 @@ static struct mmci_host_ops sdmmc_variant_ops = {
|
||||||
|
.dma_finalize = sdmmc_idma_finalize,
|
||||||
|
.set_clkreg = mmci_sdmmc_set_clkreg,
|
||||||
|
.set_pwrreg = mmci_sdmmc_set_pwrreg,
|
||||||
|
+ .execute_tuning = sdmmc_execute_tuning,
|
||||||
|
};
|
||||||
|
|
||||||
|
void sdmmc_variant_init(struct mmci_host *host)
|
||||||
|
{
|
||||||
|
+ struct device_node *np = host->mmc->parent->of_node;
|
||||||
|
+ void __iomem *base_dlyb;
|
||||||
|
+ struct sdmmc_dlyb *dlyb;
|
||||||
|
+
|
||||||
|
host->ops = &sdmmc_variant_ops;
|
||||||
|
+
|
||||||
|
+ base_dlyb = devm_of_iomap(mmc_dev(host->mmc), np, 1, NULL);
|
||||||
|
+ if (IS_ERR(base_dlyb))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ dlyb = devm_kzalloc(mmc_dev(host->mmc), sizeof(*dlyb), GFP_KERNEL);
|
||||||
|
+ if (!dlyb)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ dlyb->base = base_dlyb;
|
||||||
|
+ host->variant_priv = dlyb;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,604 @@
|
||||||
|
From d00006c83840de8fa5a6049ce31117d4e9c76184 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:40:47 +0100
|
||||||
|
Subject: [PATCH 40/52] ARM: stm32mp1-r0-rc3: PINCTRL PWM RESET RTC
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/pinctrl/stm32/pinctrl-stm32.c | 219 +++++++++++++++++++++++-----------
|
||||||
|
drivers/regulator/stpmic1_regulator.c | 17 +--
|
||||||
|
2 files changed, 152 insertions(+), 84 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||||
|
index 914bee4..7a27431 100644
|
||||||
|
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||||
|
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||||
|
@@ -7,6 +7,7 @@
|
||||||
|
* Heavily based on Mediatek's pinctrl driver
|
||||||
|
*/
|
||||||
|
#include <linux/clk.h>
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
#include <linux/gpio/driver.h>
|
||||||
|
#include <linux/hwspinlock.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
@@ -65,7 +66,8 @@
|
||||||
|
#define gpio_range_to_bank(chip) \
|
||||||
|
container_of(chip, struct stm32_gpio_bank, range)
|
||||||
|
|
||||||
|
-#define HWSPINLOCK_TIMEOUT 5 /* msec */
|
||||||
|
+#define HWSPNLCK_TIMEOUT 1000 /* usec */
|
||||||
|
+#define HWSPNLCK_RETRY_DELAY 100 /* usec */
|
||||||
|
|
||||||
|
static const char * const stm32_gpio_functions[] = {
|
||||||
|
"gpio", "af0", "af1",
|
||||||
|
@@ -110,6 +112,8 @@ struct stm32_pinctrl {
|
||||||
|
struct irq_domain *domain;
|
||||||
|
struct regmap *regmap;
|
||||||
|
struct regmap_field *irqmux[STM32_GPIO_PINS_PER_BANK];
|
||||||
|
+ u16 irqmux_map;
|
||||||
|
+ spinlock_t irqmux_lock; /* interrupt mux lock */
|
||||||
|
struct stm32_desc_pin *pins;
|
||||||
|
u32 npins;
|
||||||
|
u32 pkg;
|
||||||
|
@@ -150,6 +154,26 @@ static inline u32 stm32_gpio_get_alt(u32 function)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int stm32_pctrl_hwspin_lock_timeout(struct hwspinlock *hwlock)
|
||||||
|
+{
|
||||||
|
+ int ret, timeout = 0;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Use the x_raw API since we are under spin_lock protection and do not
|
||||||
|
+ * use the x_timeout API because we are under irq_disable mode
|
||||||
|
+ */
|
||||||
|
+ do {
|
||||||
|
+ ret = hwspin_trylock_raw(hwlock);
|
||||||
|
+ if (!ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ udelay(HWSPNLCK_RETRY_DELAY);
|
||||||
|
+ timeout += HWSPNLCK_RETRY_DELAY;
|
||||||
|
+ } while (timeout < HWSPNLCK_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ return ret == -EBUSY ? -ETIMEDOUT : ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* GPIO functions */
|
||||||
|
|
||||||
|
static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank,
|
||||||
|
@@ -326,9 +350,40 @@ static int stm32_gpio_domain_activate(struct irq_domain *d,
|
||||||
|
{
|
||||||
|
struct stm32_gpio_bank *bank = d->host_data;
|
||||||
|
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
+ unsigned long flags;
|
||||||
|
+ int ret = 0;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * gpio irq mux is shared between several banks, a lock has to be done
|
||||||
|
+ * to avoid overriding.
|
||||||
|
+ */
|
||||||
|
+ spin_lock_irqsave(&pctl->irqmux_lock, flags);
|
||||||
|
+
|
||||||
|
+ if (pctl->irqmux_map & BIT(irq_data->hwirq)) {
|
||||||
|
+ dev_err(pctl->dev, "irq line %ld already requested.\n",
|
||||||
|
+ irq_data->hwirq);
|
||||||
|
+ ret = -EBUSY;
|
||||||
|
+ goto unlock;
|
||||||
|
+ } else {
|
||||||
|
+ pctl->irqmux_map |= BIT(irq_data->hwirq);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
regmap_field_write(pctl->irqmux[irq_data->hwirq], bank->bank_ioport_nr);
|
||||||
|
- return 0;
|
||||||
|
+unlock:
|
||||||
|
+ spin_unlock_irqrestore(&pctl->irqmux_lock, flags);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void stm32_gpio_domain_deactivate(struct irq_domain *d,
|
||||||
|
+ struct irq_data *irq_data)
|
||||||
|
+{
|
||||||
|
+ struct stm32_gpio_bank *bank = d->host_data;
|
||||||
|
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
+ unsigned long flags;
|
||||||
|
+
|
||||||
|
+ spin_lock_irqsave(&pctl->irqmux_lock, flags);
|
||||||
|
+ pctl->irqmux_map &= ~BIT(irq_data->hwirq);
|
||||||
|
+ spin_unlock_irqrestore(&pctl->irqmux_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32_gpio_domain_alloc(struct irq_domain *d,
|
||||||
|
@@ -357,6 +412,7 @@ static const struct irq_domain_ops stm32_gpio_domain_ops = {
|
||||||
|
.alloc = stm32_gpio_domain_alloc,
|
||||||
|
.free = irq_domain_free_irqs_common,
|
||||||
|
.activate = stm32_gpio_domain_activate,
|
||||||
|
+ .deactivate = stm32_gpio_domain_deactivate,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Pinctrl functions */
|
||||||
|
@@ -436,7 +492,7 @@ static int stm32_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||||
|
unsigned int num_configs;
|
||||||
|
bool has_config = 0;
|
||||||
|
unsigned reserve = 0;
|
||||||
|
- int num_pins, num_funcs, maps_per_pin, i, err;
|
||||||
|
+ int num_pins, num_funcs, maps_per_pin, i, err = 0;
|
||||||
|
|
||||||
|
pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
|
|
||||||
|
@@ -463,41 +519,45 @@ static int stm32_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||||
|
if (has_config && num_pins >= 1)
|
||||||
|
maps_per_pin++;
|
||||||
|
|
||||||
|
- if (!num_pins || !maps_per_pin)
|
||||||
|
- return -EINVAL;
|
||||||
|
+ if (!num_pins || !maps_per_pin) {
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ goto exit;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
reserve = num_pins * maps_per_pin;
|
||||||
|
|
||||||
|
err = pinctrl_utils_reserve_map(pctldev, map,
|
||||||
|
reserved_maps, num_maps, reserve);
|
||||||
|
if (err)
|
||||||
|
- return err;
|
||||||
|
+ goto exit;
|
||||||
|
|
||||||
|
for (i = 0; i < num_pins; i++) {
|
||||||
|
err = of_property_read_u32_index(node, "pinmux",
|
||||||
|
i, &pinfunc);
|
||||||
|
if (err)
|
||||||
|
- return err;
|
||||||
|
+ goto exit;
|
||||||
|
|
||||||
|
pin = STM32_GET_PIN_NO(pinfunc);
|
||||||
|
func = STM32_GET_PIN_FUNC(pinfunc);
|
||||||
|
|
||||||
|
if (!stm32_pctrl_is_function_valid(pctl, pin, func)) {
|
||||||
|
dev_err(pctl->dev, "invalid function.\n");
|
||||||
|
- return -EINVAL;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
grp = stm32_pctrl_find_group_by_pin(pctl, pin);
|
||||||
|
if (!grp) {
|
||||||
|
dev_err(pctl->dev, "unable to match pin %d to group\n",
|
||||||
|
pin);
|
||||||
|
- return -EINVAL;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = stm32_pctrl_dt_node_to_map_func(pctl, pin, func, grp, map,
|
||||||
|
reserved_maps, num_maps);
|
||||||
|
if (err)
|
||||||
|
- return err;
|
||||||
|
+ goto exit;
|
||||||
|
|
||||||
|
if (has_config) {
|
||||||
|
err = pinctrl_utils_add_map_configs(pctldev, map,
|
||||||
|
@@ -505,11 +565,13 @@ static int stm32_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||||
|
configs, num_configs,
|
||||||
|
PIN_MAP_TYPE_CONFIGS_GROUP);
|
||||||
|
if (err)
|
||||||
|
- return err;
|
||||||
|
+ goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+exit:
|
||||||
|
+ kfree(configs);
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||||
|
@@ -599,8 +661,8 @@ static int stm32_pmx_get_func_groups(struct pinctrl_dev *pctldev,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||||
|
- int pin, u32 mode, u32 alt)
|
||||||
|
+static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||||
|
+ int pin, u32 mode, u32 alt)
|
||||||
|
{
|
||||||
|
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
u32 val;
|
||||||
|
@@ -612,12 +674,12 @@ static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||||
|
clk_enable(bank->clk);
|
||||||
|
spin_lock_irqsave(&bank->lock, flags);
|
||||||
|
|
||||||
|
- if (pctl->hwlock)
|
||||||
|
- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||||
|
-
|
||||||
|
- if (err) {
|
||||||
|
- dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
- goto unlock;
|
||||||
|
+ if (pctl->hwlock) {
|
||||||
|
+ err = stm32_pctrl_hwspin_lock_timeout(pctl->hwlock);
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
+ goto unlock;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
val = readl_relaxed(bank->base + alt_offset);
|
||||||
|
@@ -633,11 +695,12 @@ static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||||
|
stm32_gpio_backup_mode(bank, pin, mode, alt);
|
||||||
|
|
||||||
|
if (pctl->hwlock)
|
||||||
|
- hwspin_unlock(pctl->hwlock);
|
||||||
|
+ hwspin_unlock_raw(pctl->hwlock);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
spin_unlock_irqrestore(&bank->lock, flags);
|
||||||
|
clk_disable(bank->clk);
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode,
|
||||||
|
@@ -694,9 +757,7 @@ static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||||
|
mode = stm32_gpio_get_mode(function);
|
||||||
|
alt = stm32_gpio_get_alt(function);
|
||||||
|
|
||||||
|
- stm32_pmx_set_mode(bank, pin, mode, alt);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
+ return stm32_pmx_set_mode(bank, pin, mode, alt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||||
|
@@ -706,9 +767,7 @@ static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||||
|
struct stm32_gpio_bank *bank = gpiochip_get_data(range->gc);
|
||||||
|
int pin = stm32_gpio_pin(gpio);
|
||||||
|
|
||||||
|
- stm32_pmx_set_mode(bank, pin, !input, 0);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
+ return stm32_pmx_set_mode(bank, pin, !input, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pinmux_ops stm32_pmx_ops = {
|
||||||
|
@@ -722,8 +781,8 @@ static const struct pinmux_ops stm32_pmx_ops = {
|
||||||
|
|
||||||
|
/* Pinconf functions */
|
||||||
|
|
||||||
|
-static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||||
|
- unsigned offset, u32 drive)
|
||||||
|
+static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||||
|
+ unsigned offset, u32 drive)
|
||||||
|
{
|
||||||
|
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
unsigned long flags;
|
||||||
|
@@ -733,12 +792,12 @@ static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||||
|
clk_enable(bank->clk);
|
||||||
|
spin_lock_irqsave(&bank->lock, flags);
|
||||||
|
|
||||||
|
- if (pctl->hwlock)
|
||||||
|
- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||||
|
-
|
||||||
|
- if (err) {
|
||||||
|
- dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
- goto unlock;
|
||||||
|
+ if (pctl->hwlock) {
|
||||||
|
+ err = stm32_pctrl_hwspin_lock_timeout(pctl->hwlock);
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
+ goto unlock;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
val = readl_relaxed(bank->base + STM32_GPIO_TYPER);
|
||||||
|
@@ -749,11 +808,12 @@ static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||||
|
stm32_gpio_backup_driving(bank, offset, drive);
|
||||||
|
|
||||||
|
if (pctl->hwlock)
|
||||||
|
- hwspin_unlock(pctl->hwlock);
|
||||||
|
+ hwspin_unlock_raw(pctl->hwlock);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
spin_unlock_irqrestore(&bank->lock, flags);
|
||||||
|
clk_disable(bank->clk);
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank,
|
||||||
|
@@ -774,8 +834,8 @@ static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank,
|
||||||
|
return (val >> offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||||
|
- unsigned offset, u32 speed)
|
||||||
|
+static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||||
|
+ unsigned offset, u32 speed)
|
||||||
|
{
|
||||||
|
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
unsigned long flags;
|
||||||
|
@@ -785,12 +845,12 @@ static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||||
|
clk_enable(bank->clk);
|
||||||
|
spin_lock_irqsave(&bank->lock, flags);
|
||||||
|
|
||||||
|
- if (pctl->hwlock)
|
||||||
|
- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||||
|
-
|
||||||
|
- if (err) {
|
||||||
|
- dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
- goto unlock;
|
||||||
|
+ if (pctl->hwlock) {
|
||||||
|
+ err = stm32_pctrl_hwspin_lock_timeout(pctl->hwlock);
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
+ goto unlock;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR);
|
||||||
|
@@ -801,11 +861,12 @@ static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||||
|
stm32_gpio_backup_speed(bank, offset, speed);
|
||||||
|
|
||||||
|
if (pctl->hwlock)
|
||||||
|
- hwspin_unlock(pctl->hwlock);
|
||||||
|
+ hwspin_unlock_raw(pctl->hwlock);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
spin_unlock_irqrestore(&bank->lock, flags);
|
||||||
|
clk_disable(bank->clk);
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank,
|
||||||
|
@@ -826,8 +887,8 @@ static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank,
|
||||||
|
return (val >> (offset * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||||
|
- unsigned offset, u32 bias)
|
||||||
|
+static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||||
|
+ unsigned offset, u32 bias)
|
||||||
|
{
|
||||||
|
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||||
|
unsigned long flags;
|
||||||
|
@@ -837,12 +898,12 @@ static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||||
|
clk_enable(bank->clk);
|
||||||
|
spin_lock_irqsave(&bank->lock, flags);
|
||||||
|
|
||||||
|
- if (pctl->hwlock)
|
||||||
|
- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||||
|
-
|
||||||
|
- if (err) {
|
||||||
|
- dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
- goto unlock;
|
||||||
|
+ if (pctl->hwlock) {
|
||||||
|
+ err = stm32_pctrl_hwspin_lock_timeout(pctl->hwlock);
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||||
|
+ goto unlock;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
val = readl_relaxed(bank->base + STM32_GPIO_PUPDR);
|
||||||
|
@@ -853,11 +914,12 @@ static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||||
|
stm32_gpio_backup_bias(bank, offset, bias);
|
||||||
|
|
||||||
|
if (pctl->hwlock)
|
||||||
|
- hwspin_unlock(pctl->hwlock);
|
||||||
|
+ hwspin_unlock_raw(pctl->hwlock);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
spin_unlock_irqrestore(&bank->lock, flags);
|
||||||
|
clk_disable(bank->clk);
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank,
|
||||||
|
@@ -920,22 +982,22 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
|
||||||
|
|
||||||
|
switch (param) {
|
||||||
|
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||||
|
- stm32_pconf_set_driving(bank, offset, 0);
|
||||||
|
+ ret = stm32_pconf_set_driving(bank, offset, 0);
|
||||||
|
break;
|
||||||
|
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||||
|
- stm32_pconf_set_driving(bank, offset, 1);
|
||||||
|
+ ret = stm32_pconf_set_driving(bank, offset, 1);
|
||||||
|
break;
|
||||||
|
case PIN_CONFIG_SLEW_RATE:
|
||||||
|
- stm32_pconf_set_speed(bank, offset, arg);
|
||||||
|
+ ret = stm32_pconf_set_speed(bank, offset, arg);
|
||||||
|
break;
|
||||||
|
case PIN_CONFIG_BIAS_DISABLE:
|
||||||
|
- stm32_pconf_set_bias(bank, offset, 0);
|
||||||
|
+ ret = stm32_pconf_set_bias(bank, offset, 0);
|
||||||
|
break;
|
||||||
|
case PIN_CONFIG_BIAS_PULL_UP:
|
||||||
|
- stm32_pconf_set_bias(bank, offset, 1);
|
||||||
|
+ ret = stm32_pconf_set_bias(bank, offset, 1);
|
||||||
|
break;
|
||||||
|
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||||
|
- stm32_pconf_set_bias(bank, offset, 2);
|
||||||
|
+ ret = stm32_pconf_set_bias(bank, offset, 2);
|
||||||
|
break;
|
||||||
|
case PIN_CONFIG_OUTPUT:
|
||||||
|
__stm32_gpio_set(bank, offset, arg);
|
||||||
|
@@ -1295,6 +1357,8 @@ int stm32_pctl_probe(struct platform_device *pdev)
|
||||||
|
pctl->hwlock = hwspin_lock_request_specific(hwlock_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ spin_lock_init(&pctl->irqmux_lock);
|
||||||
|
+
|
||||||
|
pctl->dev = dev;
|
||||||
|
pctl->match_data = match->data;
|
||||||
|
|
||||||
|
@@ -1414,22 +1478,23 @@ void stm32_gpio_backup_bias(struct stm32_gpio_bank *bank,
|
||||||
|
bank->pin_backup[offset] |= bias << STM32_GPIO_BKP_PUPD_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void stm32_pinctrl_restore_gpio_regs(struct stm32_pinctrl *pctl, u32 pin)
|
||||||
|
+int stm32_pinctrl_restore_gpio_regs(struct stm32_pinctrl *pctl, u32 pin)
|
||||||
|
{
|
||||||
|
const struct pin_desc *desc = pin_desc_get(pctl->pctl_dev, pin);
|
||||||
|
struct pinctrl_gpio_range *range;
|
||||||
|
struct stm32_gpio_bank *bank;
|
||||||
|
u32 val, alt, mode, offset = stm32_gpio_pin(pin);
|
||||||
|
bool pin_is_irq;
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
range = pinctrl_find_gpio_range_from_pin(pctl->pctl_dev, pin);
|
||||||
|
if (!range)
|
||||||
|
- return;
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
pin_is_irq = gpiochip_line_is_irq(range->gc, offset);
|
||||||
|
|
||||||
|
if (!desc || (!pin_is_irq && !desc->gpio_owner))
|
||||||
|
- return;
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
bank = gpiochip_get_data(range->gc);
|
||||||
|
|
||||||
|
@@ -1438,7 +1503,10 @@ void stm32_pinctrl_restore_gpio_regs(struct stm32_pinctrl *pctl, u32 pin)
|
||||||
|
mode = bank->pin_backup[offset] & STM32_GPIO_BKP_MODE_MASK;
|
||||||
|
mode >>= STM32_GPIO_BKP_MODE_SHIFT;
|
||||||
|
|
||||||
|
- stm32_pmx_set_mode(bank, offset, mode, alt);
|
||||||
|
+ ret = stm32_pmx_set_mode(bank, offset, mode, alt);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
if (mode == 1) {
|
||||||
|
val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_VAL);
|
||||||
|
val = val >> STM32_GPIO_BKP_VAL;
|
||||||
|
@@ -1447,28 +1515,39 @@ void stm32_pinctrl_restore_gpio_regs(struct stm32_pinctrl *pctl, u32 pin)
|
||||||
|
|
||||||
|
val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_TYPE);
|
||||||
|
val >>= STM32_GPIO_BKP_TYPE;
|
||||||
|
- stm32_pconf_set_driving(bank, offset, val);
|
||||||
|
+ ret = stm32_pconf_set_driving(bank, offset, val);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
|
||||||
|
val = bank->pin_backup[offset] & STM32_GPIO_BKP_SPEED_MASK;
|
||||||
|
val >>= STM32_GPIO_BKP_SPEED_SHIFT;
|
||||||
|
- stm32_pconf_set_speed(bank, offset, val);
|
||||||
|
+ ret = stm32_pconf_set_speed(bank, offset, val);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
|
||||||
|
val = bank->pin_backup[offset] & STM32_GPIO_BKP_PUPD_MASK;
|
||||||
|
val >>= STM32_GPIO_BKP_PUPD_SHIFT;
|
||||||
|
- stm32_pconf_set_bias(bank, offset, val);
|
||||||
|
+ ret = stm32_pconf_set_bias(bank, offset, val);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
|
||||||
|
if (pin_is_irq)
|
||||||
|
regmap_field_write(pctl->irqmux[offset], bank->bank_ioport_nr);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stm32_pinctrl_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct stm32_pinctrl *pctl = dev_get_drvdata(dev);
|
||||||
|
struct stm32_pinctrl_group *g = pctl->groups;
|
||||||
|
- int i;
|
||||||
|
+ int i, ret;
|
||||||
|
|
||||||
|
- for (i = g->pin; i < g->pin + pctl->ngroups; i++)
|
||||||
|
- stm32_pinctrl_restore_gpio_regs(pctl, i);
|
||||||
|
+ for (i = g->pin; i < g->pin + pctl->ngroups; i++) {
|
||||||
|
+ ret = stm32_pinctrl_restore_gpio_regs(pctl, i);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c
|
||||||
|
index 96f1808..31c960c 100644
|
||||||
|
--- a/drivers/regulator/stpmic1_regulator.c
|
||||||
|
+++ b/drivers/regulator/stpmic1_regulator.c
|
||||||
|
@@ -76,8 +76,9 @@ enum {
|
||||||
|
#define STPMIC1_BUCK_MODE_LP BUCK_HPLP_ENABLE_MASK
|
||||||
|
|
||||||
|
struct regulator_linear_range buck1_ranges[] = {
|
||||||
|
- REGULATOR_LINEAR_RANGE(600000, 0, 30, 25000),
|
||||||
|
- REGULATOR_LINEAR_RANGE(1350000, 31, 63, 0),
|
||||||
|
+ REGULATOR_LINEAR_RANGE(725000, 0, 4, 0),
|
||||||
|
+ REGULATOR_LINEAR_RANGE(725000, 5, 36, 25000),
|
||||||
|
+ REGULATOR_LINEAR_RANGE(1500000, 37, 63, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct regulator_linear_range buck2_ranges[] = {
|
||||||
|
@@ -157,7 +158,6 @@ static struct regulator_ops stpmic1_ldo_ops = {
|
||||||
|
.disable = regulator_disable_regmap,
|
||||||
|
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||||
|
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||||
|
- .set_pull_down = regulator_set_pull_down_regmap,
|
||||||
|
.set_over_current_protection = stpmic1_set_icc,
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -169,7 +169,6 @@ static struct regulator_ops stpmic1_ldo3_ops = {
|
||||||
|
.disable = regulator_disable_regmap,
|
||||||
|
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||||
|
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||||
|
- .set_pull_down = regulator_set_pull_down_regmap,
|
||||||
|
.get_bypass = regulator_get_bypass_regmap,
|
||||||
|
.set_bypass = regulator_set_bypass_regmap,
|
||||||
|
.set_over_current_protection = stpmic1_set_icc,
|
||||||
|
@@ -179,7 +178,6 @@ static struct regulator_ops stpmic1_ldo4_fixed_regul_ops = {
|
||||||
|
.is_enabled = regulator_is_enabled_regmap,
|
||||||
|
.enable = regulator_enable_regmap,
|
||||||
|
.disable = regulator_disable_regmap,
|
||||||
|
- .set_pull_down = regulator_set_pull_down_regmap,
|
||||||
|
.set_over_current_protection = stpmic1_set_icc,
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -201,7 +199,6 @@ static struct regulator_ops stpmic1_vref_ddr_ops = {
|
||||||
|
.is_enabled = regulator_is_enabled_regmap,
|
||||||
|
.enable = regulator_enable_regmap,
|
||||||
|
.disable = regulator_disable_regmap,
|
||||||
|
- .set_pull_down = regulator_set_pull_down_regmap,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||||
|
@@ -227,8 +224,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||||
|
.enable_val = 1, \
|
||||||
|
.disable_val = 0, \
|
||||||
|
.enable_time = PMIC_ENABLE_TIME_US, \
|
||||||
|
- .pull_down_reg = ids##_PULL_DOWN_REG, \
|
||||||
|
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
|
||||||
|
.supply_name = #base, \
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -252,8 +247,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||||
|
.bypass_mask = LDO_BYPASS_MASK, \
|
||||||
|
.bypass_val_on = LDO_BYPASS_MASK, \
|
||||||
|
.bypass_val_off = 0, \
|
||||||
|
- .pull_down_reg = ids##_PULL_DOWN_REG, \
|
||||||
|
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
|
||||||
|
.supply_name = #base, \
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -271,8 +264,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||||
|
.enable_val = 1, \
|
||||||
|
.disable_val = 0, \
|
||||||
|
.enable_time = PMIC_ENABLE_TIME_US, \
|
||||||
|
- .pull_down_reg = ids##_PULL_DOWN_REG, \
|
||||||
|
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
|
||||||
|
.supply_name = #base, \
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -312,8 +303,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||||
|
.enable_val = 1, \
|
||||||
|
.disable_val = 0, \
|
||||||
|
.enable_time = PMIC_ENABLE_TIME_US, \
|
||||||
|
- .pull_down_reg = ids##_PULL_DOWN_REG, \
|
||||||
|
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
|
||||||
|
.supply_name = #base, \
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,112 @@
|
||||||
|
From 6c92e60d3e402e1fcbd1bfa11185c995ce41d190 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:47:43 +0100
|
||||||
|
Subject: [PATCH 42/52] ARM: stm32mp1-r0-rc3: SOUND
|
||||||
|
|
||||||
|
---
|
||||||
|
sound/soc/stm/stm32_sai_sub.c | 58 ++++++++++++++++++++++++++++++-------------
|
||||||
|
1 file changed, 41 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
|
||||||
|
index 1f23ca4..3f0540a 100644
|
||||||
|
--- a/sound/soc/stm/stm32_sai_sub.c
|
||||||
|
+++ b/sound/soc/stm/stm32_sai_sub.c
|
||||||
|
@@ -313,6 +313,23 @@ static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai,
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int stm32_sai_set_parent_clock(struct stm32_sai_sub_data *sai,
|
||||||
|
+ unsigned int rate)
|
||||||
|
+{
|
||||||
|
+ struct platform_device *pdev = sai->pdev;
|
||||||
|
+ struct clk *parent_clk = sai->pdata->clk_x8k;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (!(rate % 11025))
|
||||||
|
+ parent_clk = sai->pdata->clk_x11k;
|
||||||
|
+
|
||||||
|
+ ret = clk_set_parent(sai->sai_ck, parent_clk);
|
||||||
|
+ if (ret)
|
||||||
|
+ dev_err(&pdev->dev, "Set parent clock returned: %d\n", ret);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *prate)
|
||||||
|
{
|
||||||
|
@@ -492,25 +509,26 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai,
|
||||||
|
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
- if (dir == SND_SOC_CLOCK_OUT) {
|
||||||
|
+ if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) {
|
||||||
|
ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
|
||||||
|
SAI_XCR1_NODIV,
|
||||||
|
(unsigned int)~SAI_XCR1_NODIV);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
- dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
|
||||||
|
- sai->mclk_rate = freq;
|
||||||
|
+ /* If master clock is used, set parent clock now */
|
||||||
|
+ ret = stm32_sai_set_parent_clock(sai, freq);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
|
||||||
|
- if (sai->sai_mclk) {
|
||||||
|
- ret = clk_set_rate_exclusive(sai->sai_mclk,
|
||||||
|
- sai->mclk_rate);
|
||||||
|
- if (ret) {
|
||||||
|
- dev_err(cpu_dai->dev,
|
||||||
|
- "Could not set mclk rate\n");
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
+ ret = clk_set_rate_exclusive(sai->sai_mclk, freq);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(cpu_dai->dev, "Could not set mclk rate\n");
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
|
||||||
|
+ sai->mclk_rate = freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -906,11 +924,13 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
|
||||||
|
int cr1, mask, div = 0;
|
||||||
|
int sai_clk_rate, mclk_ratio, den;
|
||||||
|
unsigned int rate = params_rate(params);
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
- if (!(rate % 11025))
|
||||||
|
- clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k);
|
||||||
|
- else
|
||||||
|
- clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k);
|
||||||
|
+ if (!sai->sai_mclk) {
|
||||||
|
+ ret = stm32_sai_set_parent_clock(sai, rate);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
sai_clk_rate = clk_get_rate(sai->sai_ck);
|
||||||
|
|
||||||
|
if (STM_SAI_IS_F4(sai->pdata)) {
|
||||||
|
@@ -1064,9 +1084,13 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
|
||||||
|
regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV,
|
||||||
|
SAI_XCR1_NODIV);
|
||||||
|
|
||||||
|
- clk_disable_unprepare(sai->sai_ck);
|
||||||
|
+ /* Release mclk rate only if rate was actually set */
|
||||||
|
+ if (sai->mclk_rate) {
|
||||||
|
+ clk_rate_exclusive_put(sai->sai_mclk);
|
||||||
|
+ sai->mclk_rate = 0;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- clk_rate_exclusive_put(sai->sai_mclk);
|
||||||
|
+ clk_disable_unprepare(sai->sai_ck);
|
||||||
|
|
||||||
|
sai->substream = NULL;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,101 @@
|
||||||
|
From c38f0f42372e03b8b284804190fdf53ce02722db Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Mon, 10 Dec 2018 15:53:55 +0100
|
||||||
|
Subject: [PATCH 45/52] ARM: stm32mp1-r0-rc3: DEFCONFIG
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/configs/fragment-02-multiv7_addons.config | 39 +++++++++++++++++-----
|
||||||
|
1 file changed, 31 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
index 4470d85..6ae0453 100644
|
||||||
|
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
@@ -98,7 +98,10 @@ CONFIG_CAN_M_CAN=y
|
||||||
|
#
|
||||||
|
# Bluetooth device drivers
|
||||||
|
#
|
||||||
|
-
|
||||||
|
+CONFIG_BT_RTL=m
|
||||||
|
+CONFIG_BT_HCIBTUSB=m
|
||||||
|
+CONFIG_BT_HCIBTUSB=m
|
||||||
|
+CONFIG_BT_HCIBTUSB_RTL=y
|
||||||
|
#
|
||||||
|
# Device Drivers
|
||||||
|
#
|
||||||
|
@@ -138,7 +141,12 @@ CONFIG_CHR_DEV_SG=y
|
||||||
|
# MII PHY device drivers
|
||||||
|
#
|
||||||
|
# CONFIG_REALTEK_PHY is not set
|
||||||
|
-
|
||||||
|
+CONFIG_RTL_CARDS=m
|
||||||
|
+CONFIG_RTL8192CU=m
|
||||||
|
+CONFIG_RTLWIFI=m
|
||||||
|
+CONFIG_RTLWIFI_USB=m
|
||||||
|
+CONFIG_RTLWIFI_DEBUG=y
|
||||||
|
+CONFIG_RTL8192C_COMMON=m
|
||||||
|
#
|
||||||
|
# Input Device Drivers
|
||||||
|
#
|
||||||
|
@@ -271,14 +279,14 @@ CONFIG_VIDEO_OV5640=y
|
||||||
|
#
|
||||||
|
# Display Panels
|
||||||
|
#
|
||||||
|
-CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
|
||||||
|
-CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
|
||||||
|
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A=y
|
||||||
|
+CONFIG_DRM_PANEL_RAYDIUM_RM68200=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Display Interface Bridges
|
||||||
|
#
|
||||||
|
-CONFIG_VIDEO_ADV7511=m
|
||||||
|
-CONFIG_DRM_SII902X=m
|
||||||
|
+CONFIG_VIDEO_ADV7511=y
|
||||||
|
+CONFIG_DRM_SII902X=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Frame buffer hardware drivers
|
||||||
|
@@ -287,8 +295,8 @@ CONFIG_DRM_SII902X=m
|
||||||
|
#
|
||||||
|
# Console display driver support
|
||||||
|
#
|
||||||
|
-CONFIG_DRM_STM=m
|
||||||
|
-CONFIG_DRM_STM_DSI=m
|
||||||
|
+CONFIG_DRM_STM=y
|
||||||
|
+CONFIG_DRM_STM_DSI=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Backlight support
|
||||||
|
@@ -359,6 +367,8 @@ CONFIG_USB_CONFIGFS=y
|
||||||
|
# File systems
|
||||||
|
#
|
||||||
|
CONFIG_OVERLAY_FS=y
|
||||||
|
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||||
|
+CONFIG_JFFS2_FS=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Pseudo filesystems
|
||||||
|
@@ -452,6 +462,19 @@ CONFIG_REGULATOR_STM32_VREFBUF=y
|
||||||
|
CONFIG_NVMEM_STM32_ROMEM=y
|
||||||
|
|
||||||
|
#
|
||||||
|
+# STM32 CORESIGHT
|
||||||
|
+#
|
||||||
|
+CONFIG_STM_SOURCE_CONSOLE=y
|
||||||
|
+CONFIG_STM_SOURCE_FTRACE=y
|
||||||
|
+CONFIG_FUNCTION_TRACER=y
|
||||||
|
+CONFIG_CORESIGHT=y
|
||||||
|
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
|
||||||
|
+CONFIG_CORESIGHT_SINK_TPIU=y
|
||||||
|
+CONFIG_CORESIGHT_SINK_ETBV10=y
|
||||||
|
+CONFIG_CORESIGHT_SOURCE_ETM3X=y
|
||||||
|
+CONFIG_CORESIGHT_STM=y
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
# STM32 IPCC
|
||||||
|
#
|
||||||
|
CONFIG_STM32_IPCC=y
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
From 1c6166a178939316cfdd437f8c999616ddf9a7bd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Fri, 21 Dec 2018 16:57:57 +0100
|
||||||
|
Subject: [PATCH 46/52] ARM: stm32mp1-r0-rc4: MMC MTD
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/mmc/host/mmci.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
|
||||||
|
index 6c2b1a0..0b7b607 100644
|
||||||
|
--- a/drivers/mmc/host/mmci.c
|
||||||
|
+++ b/drivers/mmc/host/mmci.c
|
||||||
|
@@ -2072,6 +2072,8 @@ static int mmci_probe(struct amba_device *dev,
|
||||||
|
else if (plat->ocr_mask)
|
||||||
|
dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
|
||||||
|
|
||||||
|
+ host->pwr_reg = readl_relaxed(host->base + MMCIPOWER);
|
||||||
|
+
|
||||||
|
/* We support these capabilities. */
|
||||||
|
mmc->caps |= MMC_CAP_CMD23;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
From 41d9204c142d8245f898ca877b4e4044d5db2426 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Fri, 21 Dec 2018 16:58:12 +0100
|
||||||
|
Subject: [PATCH 47/52] ARM: stm32mp1-r0-rc4: PINCTRL PWM RESET RTC
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/pinctrl/pinctrl-stmfx.c | 10 ++++++----
|
||||||
|
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
|
||||||
|
index 15d5757..b68fece 100644
|
||||||
|
--- a/drivers/pinctrl/pinctrl-stmfx.c
|
||||||
|
+++ b/drivers/pinctrl/pinctrl-stmfx.c
|
||||||
|
@@ -542,6 +542,7 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
|
||||||
|
struct stmfx_pinctrl *pctl = (struct stmfx_pinctrl *)dev_id;
|
||||||
|
struct gpio_chip *gc = &pctl->gpio_chip;
|
||||||
|
u8 pending[NR_GPIO_REGS];
|
||||||
|
+ u8 src[NR_GPIO_REGS] = {0, 0, 0};
|
||||||
|
unsigned long n, status;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
@@ -550,10 +551,8 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
|
||||||
|
if (ret)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
- ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_ACK,
|
||||||
|
- pending, NR_GPIO_REGS);
|
||||||
|
- if (ret)
|
||||||
|
- return IRQ_NONE;
|
||||||
|
+ regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
|
||||||
|
+ src, NR_GPIO_REGS);
|
||||||
|
|
||||||
|
status = *(unsigned long *)pending;
|
||||||
|
for_each_set_bit(n, &status, gc->ngpio) {
|
||||||
|
@@ -561,6 +560,9 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
|
||||||
|
stmfx_pinctrl_irq_toggle_trigger(pctl, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
|
||||||
|
+ pctl->irq_gpi_src, NR_GPIO_REGS);
|
||||||
|
+
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
From 457cfdb049a39670f15df8cae1d78a2479962ef9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Fri, 21 Dec 2018 16:57:38 +0100
|
||||||
|
Subject: [PATCH 48/52] ARM: stm32mp1-r0-rc4: REMOTEPROC RPMSG
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/remoteproc/rproc_srm_core.c | 2 +-
|
||||||
|
drivers/remoteproc/stm32_rproc.c | 40 +++++++++++++++++++++++++++----------
|
||||||
|
2 files changed, 30 insertions(+), 12 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/remoteproc/rproc_srm_core.c b/drivers/remoteproc/rproc_srm_core.c
|
||||||
|
index 66be92e..fc61e8b 100644
|
||||||
|
--- a/drivers/remoteproc/rproc_srm_core.c
|
||||||
|
+++ b/drivers/remoteproc/rproc_srm_core.c
|
||||||
|
@@ -189,7 +189,7 @@ static int rproc_srm_core_prepare(struct rproc_subdev *subdev)
|
||||||
|
/* Wait for every child to be bound */
|
||||||
|
if (!wait_for_completion_timeout(&rproc_srm_core->all_bound,
|
||||||
|
msecs_to_jiffies(BIND_TIMEOUT))) {
|
||||||
|
- dev_err(dev, "bind timeout\n");
|
||||||
|
+ dev_err(dev, "failed to bind one or more system resource device(s)\n");
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
goto master;
|
||||||
|
}
|
||||||
|
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
|
||||||
|
index 9a7e034..70b7e55c 100644
|
||||||
|
--- a/drivers/remoteproc/stm32_rproc.c
|
||||||
|
+++ b/drivers/remoteproc/stm32_rproc.c
|
||||||
|
@@ -196,22 +196,12 @@ static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name)
|
||||||
|
static int stm32_rproc_elf_load_rsc_table(struct rproc *rproc,
|
||||||
|
const struct firmware *fw)
|
||||||
|
{
|
||||||
|
- int status, i;
|
||||||
|
+ int status;
|
||||||
|
struct resource_table *table = NULL;
|
||||||
|
struct stm32_rproc *ddata = rproc->priv;
|
||||||
|
size_t tablesz = 0;
|
||||||
|
- const struct elf32_hdr *ehdr;
|
||||||
|
- const struct elf32_phdr *phdr;
|
||||||
|
|
||||||
|
if (!rproc->early_boot) {
|
||||||
|
- /* set coredump segments */
|
||||||
|
- ehdr = (const struct elf32_hdr *)fw->data;
|
||||||
|
- phdr = (const struct elf32_phdr *)(fw->data + ehdr->e_phoff);
|
||||||
|
- for (i = 0; i < ehdr->e_phnum; i++, phdr++)
|
||||||
|
- rproc_coredump_add_segment(rproc, phdr->p_paddr,
|
||||||
|
- phdr->p_memsz);
|
||||||
|
-
|
||||||
|
- /* load resource table */
|
||||||
|
status = rproc_elf_load_rsc_table(rproc, fw);
|
||||||
|
if (status)
|
||||||
|
goto no_rsc_table;
|
||||||
|
@@ -276,6 +266,10 @@ static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
|
||||||
|
stm32_rproc_mem_alloc,
|
||||||
|
stm32_rproc_mem_release,
|
||||||
|
it.node->name);
|
||||||
|
+
|
||||||
|
+ if (mem)
|
||||||
|
+ rproc_coredump_add_segment(rproc, da,
|
||||||
|
+ rmem->size);
|
||||||
|
} else {
|
||||||
|
/* Register reserved memory for vdev buffer alloc */
|
||||||
|
mem = rproc_of_resm_mem_entry_init(dev, index,
|
||||||
|
@@ -436,10 +430,34 @@ static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void stm32_rproc_add_coredump_trace(struct rproc *rproc)
|
||||||
|
+{
|
||||||
|
+ struct rproc_debug_trace *trace;
|
||||||
|
+ struct rproc_dump_segment *segment;
|
||||||
|
+ bool already_added;
|
||||||
|
+
|
||||||
|
+ list_for_each_entry(trace, &rproc->traces, node) {
|
||||||
|
+ already_added = false;
|
||||||
|
+
|
||||||
|
+ list_for_each_entry(segment, &rproc->dump_segments, node) {
|
||||||
|
+ if (segment->da == trace->trace_mem.da) {
|
||||||
|
+ already_added = true;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!already_added)
|
||||||
|
+ rproc_coredump_add_segment(rproc, trace->trace_mem.da,
|
||||||
|
+ trace->trace_mem.len);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int stm32_rproc_start(struct rproc *rproc)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
+ stm32_rproc_add_coredump_trace(rproc);
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* If M4 previously started by bootloader, just guarantee holdboot
|
||||||
|
* is set to catch any crash.
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
From 06f5ef8ca4c11074b595a4318dba9766092886d5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Fri, 21 Dec 2018 16:58:47 +0100
|
||||||
|
Subject: [PATCH 49/52] ARM: stm32mp1-r0-rc4: SOUND
|
||||||
|
|
||||||
|
---
|
||||||
|
sound/soc/codecs/wm8994.c | 3 +--
|
||||||
|
sound/soc/stm/stm32_sai_sub.c | 21 ++++++++++++++++++++-
|
||||||
|
2 files changed, 21 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
|
||||||
|
index eb222da..c83ae39 100644
|
||||||
|
--- a/sound/soc/codecs/wm8994.c
|
||||||
|
+++ b/sound/soc/codecs/wm8994.c
|
||||||
|
@@ -868,7 +868,7 @@ static int mclk_event(struct snd_soc_dapm_widget *w,
|
||||||
|
break;
|
||||||
|
case SND_SOC_DAPM_POST_PMD:
|
||||||
|
dev_dbg(comp->dev, "Disable master clock %s\n",
|
||||||
|
- mclk_id ? "MCLK1" : "MCLK2");
|
||||||
|
+ mclk_id ? "MCLK2" : "MCLK1");
|
||||||
|
clk_disable_unprepare(mclk);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -1193,7 +1193,6 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w,
|
||||||
|
else
|
||||||
|
adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA;
|
||||||
|
|
||||||
|
-
|
||||||
|
val = snd_soc_component_read32(component, WM8994_AIF2_CONTROL_2);
|
||||||
|
if ((val & WM8994_AIF2DACL_SRC) &&
|
||||||
|
(val & WM8994_AIF2DACR_SRC))
|
||||||
|
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
|
||||||
|
index 3f0540a..a9b37f9 100644
|
||||||
|
--- a/sound/soc/stm/stm32_sai_sub.c
|
||||||
|
+++ b/sound/soc/stm/stm32_sai_sub.c
|
||||||
|
@@ -102,6 +102,7 @@
|
||||||
|
* @spdif_frm_cnt: S/PDIF playback frame counter
|
||||||
|
* @snd_aes_iec958: iec958 data
|
||||||
|
* @ctrl_lock: control lock
|
||||||
|
+ * @spinlock_t: prevent race condition with IRQ
|
||||||
|
*/
|
||||||
|
struct stm32_sai_sub_data {
|
||||||
|
struct platform_device *pdev;
|
||||||
|
@@ -133,6 +134,7 @@ struct stm32_sai_sub_data {
|
||||||
|
unsigned int spdif_frm_cnt;
|
||||||
|
struct snd_aes_iec958 iec958;
|
||||||
|
struct mutex ctrl_lock; /* protect resources accessed by controls */
|
||||||
|
+ spinlock_t irq_lock; /* used to prevent race condition with IRQ */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum stm32_sai_fifo_th {
|
||||||
|
@@ -497,8 +499,10 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
|
||||||
|
status = SNDRV_PCM_STATE_XRUN;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (status != SNDRV_PCM_STATE_RUNNING)
|
||||||
|
+ spin_lock(&sai->irq_lock);
|
||||||
|
+ if (status != SNDRV_PCM_STATE_RUNNING && sai->substream)
|
||||||
|
snd_pcm_stop_xrun(sai->substream);
|
||||||
|
+ spin_unlock(&sai->irq_lock);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
@@ -703,8 +707,19 @@ static int stm32_sai_startup(struct snd_pcm_substream *substream,
|
||||||
|
{
|
||||||
|
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
||||||
|
int imr, cr2, ret;
|
||||||
|
+ unsigned long flags;
|
||||||
|
|
||||||
|
+ spin_lock_irqsave(&sai->irq_lock, flags);
|
||||||
|
sai->substream = substream;
|
||||||
|
+ spin_unlock_irqrestore(&sai->irq_lock, flags);
|
||||||
|
+
|
||||||
|
+ if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
|
||||||
|
+ snd_pcm_hw_constraint_mask64(substream->runtime,
|
||||||
|
+ SNDRV_PCM_HW_PARAM_FORMAT,
|
||||||
|
+ SNDRV_PCM_FMTBIT_S32_LE);
|
||||||
|
+ snd_pcm_hw_constraint_single(substream->runtime,
|
||||||
|
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(sai->sai_ck);
|
||||||
|
if (ret < 0) {
|
||||||
|
@@ -1078,6 +1093,7 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_soc_dai *cpu_dai)
|
||||||
|
{
|
||||||
|
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
||||||
|
+ unsigned long flags;
|
||||||
|
|
||||||
|
regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0);
|
||||||
|
|
||||||
|
@@ -1092,7 +1108,9 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
|
clk_disable_unprepare(sai->sai_ck);
|
||||||
|
|
||||||
|
+ spin_lock_irqsave(&sai->irq_lock, flags);
|
||||||
|
sai->substream = NULL;
|
||||||
|
+ spin_unlock_irqrestore(&sai->irq_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32_sai_pcm_new(struct snd_soc_pcm_runtime *rtd,
|
||||||
|
@@ -1459,6 +1477,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
|
sai->pdev = pdev;
|
||||||
|
mutex_init(&sai->ctrl_lock);
|
||||||
|
+ spin_lock_init(&sai->irq_lock);
|
||||||
|
platform_set_drvdata(pdev, sai);
|
||||||
|
|
||||||
|
sai->pdata = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,266 @@
|
||||||
|
From fc74bada7f6940619f8930556b7c61fe618f2a64 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Fri, 21 Dec 2018 16:56:27 +0100
|
||||||
|
Subject: [PATCH 50/52] ARM: stm32mp1-r0-rc4: USB
|
||||||
|
|
||||||
|
---
|
||||||
|
Documentation/devicetree/bindings/usb/dwc2.txt | 2 +
|
||||||
|
drivers/usb/dwc2/core.h | 11 ++++
|
||||||
|
drivers/usb/dwc2/core_intr.c | 4 +-
|
||||||
|
drivers/usb/dwc2/hw.h | 2 +
|
||||||
|
drivers/usb/dwc2/params.c | 7 ++-
|
||||||
|
drivers/usb/dwc2/platform.c | 74 +++++++++++++++++++++++---
|
||||||
|
6 files changed, 90 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt
|
||||||
|
index 32b245c..03c62de 100644
|
||||||
|
--- a/Documentation/devicetree/bindings/usb/dwc2.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/usb/dwc2.txt
|
||||||
|
@@ -43,6 +43,8 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties
|
||||||
|
doesn't drive it.
|
||||||
|
- usb33d-supply: external VBUS and ID sensing comparators supply, in order to
|
||||||
|
perform OTG operation, used on STM32MP1 SoCs.
|
||||||
|
+- force-b-session-valid: force B-peripheral session instead of relying on
|
||||||
|
+ VBUS sensing (only valid when dr_mode = "peripheral").
|
||||||
|
|
||||||
|
Deprecated properties:
|
||||||
|
- g-use-dma: gadget DMA mode is automatically detected
|
||||||
|
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
|
||||||
|
index 4c689d1..4c1736f 100644
|
||||||
|
--- a/drivers/usb/dwc2/core.h
|
||||||
|
+++ b/drivers/usb/dwc2/core.h
|
||||||
|
@@ -415,6 +415,12 @@ enum dwc2_ep0_state {
|
||||||
|
* in DWORDS with possible values from from
|
||||||
|
* 16-32768 (default: 256, 256, 256, 256, 768,
|
||||||
|
* 768, 768, 768, 0, 0, 0, 0, 0, 0, 0).
|
||||||
|
+ * @force_b_session_valid: force B-peripheral session instead of relying on
|
||||||
|
+ * VBUS sensing (only valid when dr_mode = "peripheral").
|
||||||
|
+ * @suspend_ignore_power_down: prevent the controller to enter low power mode
|
||||||
|
+ * upon suspend interrupt. This may help in device mode,
|
||||||
|
+ * when suspend (3ms idle bus) gets detected before
|
||||||
|
+ * device session end (VBUS discharge > 3ms).
|
||||||
|
* @change_speed_quirk: Change speed configuration to DWC2_SPEED_PARAM_FULL
|
||||||
|
* while full&low speed device connect. And change speed
|
||||||
|
* back to DWC2_SPEED_PARAM_HIGH while device is gone.
|
||||||
|
@@ -492,6 +498,8 @@ struct dwc2_core_params {
|
||||||
|
u32 g_rx_fifo_size;
|
||||||
|
u32 g_np_tx_fifo_size;
|
||||||
|
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
|
||||||
|
+ bool force_b_session_valid;
|
||||||
|
+ bool suspend_ignore_power_down;
|
||||||
|
|
||||||
|
bool change_speed_quirk;
|
||||||
|
};
|
||||||
|
@@ -849,6 +857,8 @@ struct dwc2_hregs_backup {
|
||||||
|
* removed once all SoCs support usb transceiver.
|
||||||
|
* @supplies: Definition of USB power supplies
|
||||||
|
* @vbus_supply: Regulator supplying vbus.
|
||||||
|
+ * @usb33d: Optional 3.3v regulator used on some stm32 devices to
|
||||||
|
+ * supply ID and VBUS detection hardware.
|
||||||
|
* @phyif: PHY interface width
|
||||||
|
* @lock: Spinlock that protects all the driver data structures
|
||||||
|
* @priv: Stores a pointer to the struct usb_hcd
|
||||||
|
@@ -1032,6 +1042,7 @@ struct dwc2_hsotg {
|
||||||
|
struct dwc2_hsotg_plat *plat;
|
||||||
|
struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES];
|
||||||
|
struct regulator *vbus_supply;
|
||||||
|
+ struct regulator *usb33d;
|
||||||
|
u32 phyif;
|
||||||
|
|
||||||
|
spinlock_t lock;
|
||||||
|
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
|
||||||
|
index 19ae259..7b4162c 100644
|
||||||
|
--- a/drivers/usb/dwc2/core_intr.c
|
||||||
|
+++ b/drivers/usb/dwc2/core_intr.c
|
||||||
|
@@ -492,7 +492,9 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
|
||||||
|
hsotg->hw_params.hibernation);
|
||||||
|
|
||||||
|
/* Ignore suspend request before enumeration */
|
||||||
|
- if (!dwc2_is_device_connected(hsotg)) {
|
||||||
|
+ if (!dwc2_is_device_connected(hsotg) ||
|
||||||
|
+ hsotg->params.force_b_session_valid ||
|
||||||
|
+ hsotg->params.suspend_ignore_power_down) {
|
||||||
|
dev_dbg(hsotg->dev,
|
||||||
|
"ignore suspend request before enumeration\n");
|
||||||
|
return;
|
||||||
|
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
|
||||||
|
index afde335..31f8c60 100644
|
||||||
|
--- a/drivers/usb/dwc2/hw.h
|
||||||
|
+++ b/drivers/usb/dwc2/hw.h
|
||||||
|
@@ -54,6 +54,8 @@
|
||||||
|
#define GOTGCTL_HSTSETHNPEN BIT(10)
|
||||||
|
#define GOTGCTL_HNPREQ BIT(9)
|
||||||
|
#define GOTGCTL_HSTNEGSCS BIT(8)
|
||||||
|
+#define GOTGCTL_BVALOVAL BIT(7)
|
||||||
|
+#define GOTGCTL_BVALOEN BIT(6)
|
||||||
|
#define GOTGCTL_SESREQ BIT(1)
|
||||||
|
#define GOTGCTL_SESREQSCS BIT(0)
|
||||||
|
|
||||||
|
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
|
||||||
|
index 63ccfc9..7fef905 100644
|
||||||
|
--- a/drivers/usb/dwc2/params.c
|
||||||
|
+++ b/drivers/usb/dwc2/params.c
|
||||||
|
@@ -167,7 +167,7 @@ static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_hsotg *hsotg)
|
||||||
|
p->host_rx_fifo_size = 440;
|
||||||
|
p->host_nperio_tx_fifo_size = 256;
|
||||||
|
p->host_perio_tx_fifo_size = 256;
|
||||||
|
- p->power_down = false;
|
||||||
|
+ p->suspend_ignore_power_down = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct of_device_id dwc2_of_match_table[] = {
|
||||||
|
@@ -404,6 +404,11 @@ static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg)
|
||||||
|
|
||||||
|
if (of_find_property(hsotg->dev->of_node, "disable-over-current", NULL))
|
||||||
|
p->oc_disable = true;
|
||||||
|
+
|
||||||
|
+ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
|
||||||
|
+ p->force_b_session_valid =
|
||||||
|
+ of_property_read_bool(hsotg->dev->of_node,
|
||||||
|
+ "force-b-session-valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwc2_check_param_otg_cap(struct dwc2_hsotg *hsotg)
|
||||||
|
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
|
||||||
|
index 2061254..b2e5ddc 100644
|
||||||
|
--- a/drivers/usb/dwc2/platform.c
|
||||||
|
+++ b/drivers/usb/dwc2/platform.c
|
||||||
|
@@ -324,6 +324,10 @@ static int dwc2_driver_remove(struct platform_device *dev)
|
||||||
|
if (hsotg->gadget_enabled)
|
||||||
|
dwc2_hsotg_remove(hsotg);
|
||||||
|
|
||||||
|
+ if (hsotg->params.activate_stm_id_vb_detection &&
|
||||||
|
+ !hsotg->params.force_b_session_valid)
|
||||||
|
+ regulator_disable(hsotg->usb33d);
|
||||||
|
+
|
||||||
|
if (hsotg->ll_hw_enabled)
|
||||||
|
dwc2_lowlevel_hw_disable(hsotg);
|
||||||
|
|
||||||
|
@@ -474,18 +478,18 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||||
|
if (retval)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
- if (hsotg->params.activate_stm_id_vb_detection) {
|
||||||
|
- struct regulator *usb33d;
|
||||||
|
+ if (hsotg->params.activate_stm_id_vb_detection &&
|
||||||
|
+ !hsotg->params.force_b_session_valid) {
|
||||||
|
u32 ggpio;
|
||||||
|
|
||||||
|
- usb33d = devm_regulator_get(hsotg->dev, "usb33d");
|
||||||
|
- if (IS_ERR(usb33d)) {
|
||||||
|
- retval = PTR_ERR(usb33d);
|
||||||
|
+ hsotg->usb33d = devm_regulator_get(hsotg->dev, "usb33d");
|
||||||
|
+ if (IS_ERR(hsotg->usb33d)) {
|
||||||
|
+ retval = PTR_ERR(hsotg->usb33d);
|
||||||
|
dev_err(hsotg->dev,
|
||||||
|
"can't get voltage level detector supply\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
- retval = regulator_enable(usb33d);
|
||||||
|
+ retval = regulator_enable(hsotg->usb33d);
|
||||||
|
if (retval) {
|
||||||
|
dev_err(hsotg->dev,
|
||||||
|
"can't enable voltage level detector supply\n");
|
||||||
|
@@ -498,6 +502,15 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||||
|
dwc2_writel(hsotg, ggpio, GGPIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (hsotg->params.force_b_session_valid) {
|
||||||
|
+ u32 gotgctl;
|
||||||
|
+
|
||||||
|
+ gotgctl = dwc2_readl(hsotg, GOTGCTL);
|
||||||
|
+ gotgctl |= GOTGCTL_BVALOVAL; /* B-peripheral session value */
|
||||||
|
+ gotgctl |= GOTGCTL_BVALOEN; /* B-peripheral override enable */
|
||||||
|
+ dwc2_writel(hsotg, gotgctl, GOTGCTL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (hsotg->params.activate_stm_fs_transceiver) {
|
||||||
|
u32 ggpio;
|
||||||
|
|
||||||
|
@@ -516,7 +529,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||||
|
if (hsotg->dr_mode != USB_DR_MODE_HOST) {
|
||||||
|
retval = dwc2_gadget_init(hsotg);
|
||||||
|
if (retval)
|
||||||
|
- goto error;
|
||||||
|
+ goto error_init;
|
||||||
|
hsotg->gadget_enabled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -525,7 +538,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||||
|
if (retval) {
|
||||||
|
if (hsotg->gadget_enabled)
|
||||||
|
dwc2_hsotg_remove(hsotg);
|
||||||
|
- goto error;
|
||||||
|
+ goto error_init;
|
||||||
|
}
|
||||||
|
hsotg->hcd_enabled = 1;
|
||||||
|
}
|
||||||
|
@@ -541,6 +554,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
+error_init:
|
||||||
|
+ if (hsotg->params.activate_stm_id_vb_detection &&
|
||||||
|
+ !hsotg->params.force_b_session_valid)
|
||||||
|
+ regulator_disable(hsotg->usb33d);
|
||||||
|
error:
|
||||||
|
dwc2_lowlevel_hw_disable(hsotg);
|
||||||
|
return retval;
|
||||||
|
@@ -554,6 +571,18 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||||
|
if (dwc2_is_device_mode(dwc2))
|
||||||
|
dwc2_hsotg_suspend(dwc2);
|
||||||
|
|
||||||
|
+ if (dwc2->params.activate_stm_id_vb_detection &&
|
||||||
|
+ !dwc2->params.force_b_session_valid) {
|
||||||
|
+ u32 ggpio;
|
||||||
|
+
|
||||||
|
+ ggpio = dwc2_readl(dwc2, GGPIO);
|
||||||
|
+ ggpio &= ~GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||||
|
+ ggpio &= ~GGPIO_STM32_OTG_GCCFG_VBDEN;
|
||||||
|
+ dwc2_writel(dwc2, ggpio, GGPIO);
|
||||||
|
+
|
||||||
|
+ regulator_disable(dwc2->usb33d);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (dwc2->ll_hw_enabled)
|
||||||
|
ret = __dwc2_lowlevel_hw_disable(dwc2);
|
||||||
|
|
||||||
|
@@ -571,6 +600,35 @@ static int __maybe_unused dwc2_resume(struct device *dev)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Need to restore FORCEDEVMODE/FORCEHOSTMODE */
|
||||||
|
+ dwc2_force_dr_mode(dwc2);
|
||||||
|
+
|
||||||
|
+ if (dwc2->params.activate_stm_id_vb_detection &&
|
||||||
|
+ !dwc2->params.force_b_session_valid) {
|
||||||
|
+ u32 ggpio;
|
||||||
|
+
|
||||||
|
+ ret = regulator_enable(dwc2->usb33d);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ggpio = dwc2_readl(dwc2, GGPIO);
|
||||||
|
+ ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||||
|
+ ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN;
|
||||||
|
+ dwc2_writel(dwc2, ggpio, GGPIO);
|
||||||
|
+
|
||||||
|
+ /* ID/VBUS detection startup time */
|
||||||
|
+ usleep_range(5000, 7000);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (dwc2->params.force_b_session_valid) {
|
||||||
|
+ u32 gotgctl;
|
||||||
|
+
|
||||||
|
+ gotgctl = dwc2_readl(dwc2, GOTGCTL);
|
||||||
|
+ gotgctl |= GOTGCTL_BVALOVAL; /* B-peripheral session value */
|
||||||
|
+ gotgctl |= GOTGCTL_BVALOEN; /* B-peripheral override enable */
|
||||||
|
+ dwc2_writel(dwc2, gotgctl, GOTGCTL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (dwc2_is_device_mode(dwc2))
|
||||||
|
ret = dwc2_hsotg_resume(dwc2);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,607 @@
|
||||||
|
From a3f6ac74fe67cfacb73bda2ba631d1e5e2680988 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Fri, 21 Dec 2018 16:56:44 +0100
|
||||||
|
Subject: [PATCH 51/52] ARM: stm32mp1-r0-rc4: DEVICETREE
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/stm32mp157a-dk1.dts | 14 ++--
|
||||||
|
arch/arm/boot/dts/stm32mp157c-ed1.dts | 9 ---
|
||||||
|
arch/arm/boot/dts/stm32mp157c-ev1.dts | 2 -
|
||||||
|
arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi | 122 +++++++++++++++---------------
|
||||||
|
arch/arm/boot/dts/stm32mp157c.dtsi | 2 +-
|
||||||
|
5 files changed, 67 insertions(+), 82 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
index 0a6cf35..7e911f3 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
@@ -77,11 +77,6 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
- iio-hwmon {
|
||||||
|
- compatible = "iio-hwmon";
|
||||||
|
- io-channels = <&adc_temp>;
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
sram: sram@10050000 {
|
||||||
|
compatible = "mmio-sram";
|
||||||
|
reg = <0x10050000 0x10000>;
|
||||||
|
@@ -174,6 +169,10 @@
|
||||||
|
sram = <&dma_pool>;
|
||||||
|
};
|
||||||
|
|
||||||
|
+&dts {
|
||||||
|
+ status = "okay";
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
ðernet0 {
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-0 = <ðernet0_rgmii_pins_a>;
|
||||||
|
@@ -198,10 +197,6 @@
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
-&hsem {
|
||||||
|
- status = "okay";
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
&i2c1 {
|
||||||
|
pinctrl-names = "default", "sleep";
|
||||||
|
pinctrl-0 = <&i2c1_pins_a>;
|
||||||
|
@@ -679,6 +674,7 @@
|
||||||
|
|
||||||
|
&usbotg_hs {
|
||||||
|
dr_mode = "peripheral";
|
||||||
|
+ force-b-session-valid;
|
||||||
|
phys = <&usbphyc_port1 0>;
|
||||||
|
phy-names = "usb2-phy";
|
||||||
|
status = "okay";
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||||
|
index 798580e..cf2750e 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||||
|
@@ -74,11 +74,6 @@
|
||||||
|
serial0 = &uart4;
|
||||||
|
};
|
||||||
|
|
||||||
|
- iio-hwmon {
|
||||||
|
- compatible = "iio-hwmon";
|
||||||
|
- io-channels = <&adc_temp>;
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
sram: sram@10050000 {
|
||||||
|
compatible = "mmio-sram";
|
||||||
|
reg = <0x10050000 0x10000>;
|
||||||
|
@@ -173,10 +168,6 @@
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
-&hsem {
|
||||||
|
- status = "okay";
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
&i2c4 {
|
||||||
|
pinctrl-names = "default", "sleep";
|
||||||
|
pinctrl-0 = <&i2c4_pins_a>;
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts
|
||||||
|
index 49a62aa..18742e8 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c-ev1.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts
|
||||||
|
@@ -177,7 +177,6 @@
|
||||||
|
pinctrl-names = "default", "sleep";
|
||||||
|
pinctrl-0 = <&cec_pins_a>;
|
||||||
|
pinctrl-1 = <&cec_pins_sleep_a>;
|
||||||
|
- status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&dcmi {
|
||||||
|
@@ -530,7 +529,6 @@
|
||||||
|
pinctrl-1 = <&i2c5_pins_sleep_a>;
|
||||||
|
i2c-scl-rising-time-ns = <185>;
|
||||||
|
i2c-scl-falling-time-ns = <20>;
|
||||||
|
- status = "okay";
|
||||||
|
/delete-property/dmas;
|
||||||
|
/delete-property/dma-names;
|
||||||
|
};
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi b/arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi
|
||||||
|
index a1d132d0..5ebe24b 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi
|
||||||
|
@@ -5,106 +5,106 @@
|
||||||
|
|
||||||
|
m4_timers2: timer@40000000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40000000 0x400>;
|
||||||
|
+ reg = <0x40000000>;
|
||||||
|
clocks = <&rcc TIM2_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers3: timer@40001000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40001000 0x400>;
|
||||||
|
+ reg = <0x40001000>;
|
||||||
|
clocks = <&rcc TIM3_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers4: timer@40002000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40002000 0x400>;
|
||||||
|
+ reg = <0x40002000>;
|
||||||
|
clocks = <&rcc TIM4_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers5: timer@40003000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40003000 0x400>;
|
||||||
|
+ reg = <0x40003000>;
|
||||||
|
clocks = <&rcc TIM5_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers6: timer@40004000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40004000 0x400>;
|
||||||
|
+ reg = <0x40004000>;
|
||||||
|
clocks = <&rcc TIM6_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers7: timer@40005000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40005000 0x400>;
|
||||||
|
+ reg = <0x40005000>;
|
||||||
|
clocks = <&rcc TIM7_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers12: timer@40006000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40006000 0x400>;
|
||||||
|
+ reg = <0x40006000>;
|
||||||
|
clocks = <&rcc TIM12_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers13: timer@40007000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40007000 0x400>;
|
||||||
|
+ reg = <0x40007000>;
|
||||||
|
clocks = <&rcc TIM13_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers14: timer@40008000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40008000 0x400>;
|
||||||
|
+ reg = <0x40008000>;
|
||||||
|
clocks = <&rcc TIM14_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_lptimer1: timer@40009000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40009000 0x400>;
|
||||||
|
+ reg = <0x40009000>;
|
||||||
|
clocks = <&rcc LPTIM1_K>;
|
||||||
|
clock-names = "mux";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_spi2: spi@4000b000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4000b000 0x400>;
|
||||||
|
+ reg = <0x4000b000>;
|
||||||
|
clocks = <&rcc SPI2_K>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_i2s2: audio-controller@4000b000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4000b000 0x400>;
|
||||||
|
+ reg = <0x4000b000>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_spi3: spi@4000c000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4000c000 0x400>;
|
||||||
|
+ reg = <0x4000c000>;
|
||||||
|
clocks = <&rcc SPI3_K>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_i2s3: audio-controller@4000c000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4000c000 0x400>;
|
||||||
|
+ reg = <0x4000c000>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_spdifrx: audio-controller@4000d000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4000d000 0x400>;
|
||||||
|
+ reg = <0x4000d000>;
|
||||||
|
clocks = <&rcc SPDIF_K>;
|
||||||
|
clock-names = "kclk";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_usart2: serial@4000e000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4000e000 0x400>;
|
||||||
|
+ reg = <0x4000e000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <27 1>;
|
||||||
|
clocks = <&rcc USART2_K>;
|
||||||
|
@@ -112,7 +112,7 @@
|
||||||
|
};
|
||||||
|
m4_usart3: serial@4000f000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4000f000 0x400>;
|
||||||
|
+ reg = <0x4000f000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <28 1>;
|
||||||
|
clocks = <&rcc USART3_K>;
|
||||||
|
@@ -120,7 +120,7 @@
|
||||||
|
};
|
||||||
|
m4_uart4: serial@40010000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40010000 0x400>;
|
||||||
|
+ reg = <0x40010000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <30 1>;
|
||||||
|
clocks = <&rcc UART4_K>;
|
||||||
|
@@ -128,7 +128,7 @@
|
||||||
|
};
|
||||||
|
m4_uart5: serial@40011000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40011000 0x400>;
|
||||||
|
+ reg = <0x40011000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <31 1>;
|
||||||
|
clocks = <&rcc UART5_K>;
|
||||||
|
@@ -136,7 +136,7 @@
|
||||||
|
};
|
||||||
|
m4_i2c1: i2c@40012000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40012000 0x400>;
|
||||||
|
+ reg = <0x40012000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <21 1>;
|
||||||
|
clocks = <&rcc I2C1_K>;
|
||||||
|
@@ -144,7 +144,7 @@
|
||||||
|
};
|
||||||
|
m4_i2c2: i2c@40013000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40013000 0x400>;
|
||||||
|
+ reg = <0x40013000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <22 1>;
|
||||||
|
clocks = <&rcc I2C2_K>;
|
||||||
|
@@ -152,7 +152,7 @@
|
||||||
|
};
|
||||||
|
m4_i2c3: i2c@40014000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40014000 0x400>;
|
||||||
|
+ reg = <0x40014000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <23 1>;
|
||||||
|
clocks = <&rcc I2C3_K>;
|
||||||
|
@@ -160,7 +160,7 @@
|
||||||
|
};
|
||||||
|
m4_i2c5: i2c@40015000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40015000 0x400>;
|
||||||
|
+ reg = <0x40015000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <25 1>;
|
||||||
|
clocks = <&rcc I2C5_K>;
|
||||||
|
@@ -168,7 +168,7 @@
|
||||||
|
};
|
||||||
|
m4_cec: cec@40016000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40016000 0x400>;
|
||||||
|
+ reg = <0x40016000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <69 1>;
|
||||||
|
clocks = <&rcc CEC_K>, <&rcc CK_LSE>;
|
||||||
|
@@ -177,14 +177,14 @@
|
||||||
|
};
|
||||||
|
m4_dac: dac@40017000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40017000 0x400>;
|
||||||
|
+ reg = <0x40017000>;
|
||||||
|
clocks = <&rcc DAC12>;
|
||||||
|
clock-names = "pclk";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_uart7: serial@40018000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40018000 0x400>;
|
||||||
|
+ reg = <0x40018000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <32 1>;
|
||||||
|
clocks = <&rcc UART7_K>;
|
||||||
|
@@ -192,7 +192,7 @@
|
||||||
|
};
|
||||||
|
m4_uart8: serial@40019000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x40019000 0x400>;
|
||||||
|
+ reg = <0x40019000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <33 1>;
|
||||||
|
clocks = <&rcc UART8_K>;
|
||||||
|
@@ -200,21 +200,21 @@
|
||||||
|
};
|
||||||
|
m4_timers1: timer@44000000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44000000 0x400>;
|
||||||
|
+ reg = <0x44000000>;
|
||||||
|
clocks = <&rcc TIM1_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers8: timer@44001000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44001000 0x400>;
|
||||||
|
+ reg = <0x44001000>;
|
||||||
|
clocks = <&rcc TIM8_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_usart6: serial@44003000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44003000 0x400>;
|
||||||
|
+ reg = <0x44003000>;
|
||||||
|
interrupt-parent = <&exti>;
|
||||||
|
interrupts = <29 1>;
|
||||||
|
clocks = <&rcc USART6_K>;
|
||||||
|
@@ -222,203 +222,203 @@
|
||||||
|
};
|
||||||
|
m4_spi1: spi@44004000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44004000 0x400>;
|
||||||
|
+ reg = <0x44004000>;
|
||||||
|
clocks = <&rcc SPI1_K>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_i2s1: audio-controller@44004000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44004000 0x400>;
|
||||||
|
+ reg = <0x44004000>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_spi4: spi@44005000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44005000 0x400>;
|
||||||
|
+ reg = <0x44005000>;
|
||||||
|
clocks = <&rcc SPI4_K>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers15: timer@44006000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44006000 0x400>;
|
||||||
|
+ reg = <0x44006000>;
|
||||||
|
clocks = <&rcc TIM15_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers16: timer@44007000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44007000 0x400>;
|
||||||
|
+ reg = <0x44007000>;
|
||||||
|
clocks = <&rcc TIM16_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_timers17: timer@44008000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44008000 0x400>;
|
||||||
|
+ reg = <0x44008000>;
|
||||||
|
clocks = <&rcc TIM17_K>;
|
||||||
|
clock-names = "int";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_spi5: spi@44009000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x44009000 0x400>;
|
||||||
|
+ reg = <0x44009000>;
|
||||||
|
clocks = <&rcc SPI5_K>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_sai1: sai@4400a000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4400a000 0x4>;
|
||||||
|
+ reg = <0x4400a000>;
|
||||||
|
clocks = <&rcc SAI1_K>;
|
||||||
|
clock-names = "sai_ck";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_sai2: sai@4400b000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4400b000 0x4>;
|
||||||
|
+ reg = <0x4400b000>;
|
||||||
|
clocks = <&rcc SAI2_K>;
|
||||||
|
clock-names = "sai_ck";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_sai3: sai@4400c000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4400c000 0x4>;
|
||||||
|
+ reg = <0x4400c000>;
|
||||||
|
clocks = <&rcc SAI3_K>;
|
||||||
|
clock-names = "sai_ck";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_dfsdm: dfsdm@4400d000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4400d000 0x800>;
|
||||||
|
+ reg = <0x4400d000>;
|
||||||
|
clocks = <&rcc DFSDM_K>;
|
||||||
|
clock-names = "dfsdm";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_m_can1: can@4400e000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4400e000 0x400>, <0x44011000 0x2800>;
|
||||||
|
+ reg = <0x4400e000>, <0x44011000>;
|
||||||
|
clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
|
||||||
|
clock-names = "hclk", "cclk";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_m_can2: can@4400f000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4400f000 0x400>, <0x44011000 0x2800>;
|
||||||
|
+ reg = <0x4400f000>, <0x44011000>;
|
||||||
|
clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
|
||||||
|
clock-names = "hclk", "cclk";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_dma1: dma@48000000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x48000000 0x400>;
|
||||||
|
+ reg = <0x48000000>;
|
||||||
|
clocks = <&rcc DMA1>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_dma2: dma@48001000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x48001000 0x400>;
|
||||||
|
+ reg = <0x48001000>;
|
||||||
|
clocks = <&rcc DMA2>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_dmamux1: dma-router@48002000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x48002000 0x1c>;
|
||||||
|
+ reg = <0x48002000>;
|
||||||
|
clocks = <&rcc DMAMUX>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_adc: adc@48003000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x48003000 0x400>;
|
||||||
|
+ reg = <0x48003000>;
|
||||||
|
clocks = <&rcc ADC12>, <&rcc ADC12_K>;
|
||||||
|
clock-names = "bus", "adc";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_sdmmc3: sdmmc@48004000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x48004000 0x400>, <0x48005000 0x400>;
|
||||||
|
+ reg = <0x48004000>, <0x48005000>;
|
||||||
|
clocks = <&rcc SDMMC3_K>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_usbotg_hs: usb-otg@49000000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x49000000 0x10000>;
|
||||||
|
+ reg = <0x49000000>;
|
||||||
|
clocks = <&rcc USBO_K>;
|
||||||
|
clock-names = "otg";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_hash2: hash@4c002000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4c002000 0x400>;
|
||||||
|
+ reg = <0x4c002000>;
|
||||||
|
clocks = <&rcc HASH2>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_rng2: rng@4c003000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4c003000 0x400>;
|
||||||
|
+ reg = <0x4c003000>;
|
||||||
|
clocks = <&rcc RNG2_K>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_crc2: crc@4c004000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4c004000 0x400>;
|
||||||
|
+ reg = <0x4c004000>;
|
||||||
|
clocks = <&rcc CRC2>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_cryp2: cryp@4c005000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4c005000 0x400>;
|
||||||
|
+ reg = <0x4c005000>;
|
||||||
|
clocks = <&rcc CRYP2>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_dcmi: dcmi@4c006000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x4c006000 0x400>;
|
||||||
|
+ reg = <0x4c006000>;
|
||||||
|
clocks = <&rcc DCMI>;
|
||||||
|
clock-names = "mclk";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_lptimer2: timer@50021000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x50021000 0x400>;
|
||||||
|
+ reg = <0x50021000>;
|
||||||
|
clocks = <&rcc LPTIM2_K>;
|
||||||
|
clock-names = "mux";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_lptimer3: timer@50022000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x50022000 0x400>;
|
||||||
|
+ reg = <0x50022000>;
|
||||||
|
clocks = <&rcc LPTIM3_K>;
|
||||||
|
clock-names = "mux";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_lptimer4: timer@50023000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x50023000 0x400>;
|
||||||
|
+ reg = <0x50023000>;
|
||||||
|
clocks = <&rcc LPTIM4_K>;
|
||||||
|
clock-names = "mux";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_lptimer5: timer@50024000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x50024000 0x400>;
|
||||||
|
+ reg = <0x50024000>;
|
||||||
|
clocks = <&rcc LPTIM5_K>;
|
||||||
|
clock-names = "mux";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_sai4: sai@50027000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x50027000 0x4>;
|
||||||
|
+ reg = <0x50027000>;
|
||||||
|
clocks = <&rcc SAI4_K>;
|
||||||
|
clock-names = "sai_ck";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_qspi: qspi@58003000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
|
||||||
|
+ reg = <0x58003000>, <0x70000000>;
|
||||||
|
clocks = <&rcc QSPI_K>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
m4_ethernet0: ethernet@5800a000 {
|
||||||
|
compatible = "rproc-srm-dev";
|
||||||
|
- reg = <0x5800a000 0x2000>;
|
||||||
|
+ reg = <0x5800a000>;
|
||||||
|
clock-names = "stmmaceth",
|
||||||
|
"mac-clk-tx",
|
||||||
|
"mac-clk-rx",
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
index 7a7ef47..4de499e 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
@@ -1231,7 +1231,7 @@
|
||||||
|
reg = <0x4c000000 0x400>;
|
||||||
|
clocks = <&rcc HSEM>;
|
||||||
|
clock-names = "hsem";
|
||||||
|
- status = "disabled";
|
||||||
|
+ status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
ipcc: mailbox@4c001000 {
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
From 619ff8e35045cb1cb0f235bd24236ff36453186a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||||
|
Date: Fri, 21 Dec 2018 16:57:19 +0100
|
||||||
|
Subject: [PATCH 52/52] ARM: stm32mp1-r0-rc4: DEFCONFIG
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/configs/fragment-02-multiv7_addons.config | 13 -------------
|
||||||
|
1 file changed, 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
index 6ae0453..38c5562 100644
|
||||||
|
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
@@ -462,19 +462,6 @@ CONFIG_REGULATOR_STM32_VREFBUF=y
|
||||||
|
CONFIG_NVMEM_STM32_ROMEM=y
|
||||||
|
|
||||||
|
#
|
||||||
|
-# STM32 CORESIGHT
|
||||||
|
-#
|
||||||
|
-CONFIG_STM_SOURCE_CONSOLE=y
|
||||||
|
-CONFIG_STM_SOURCE_FTRACE=y
|
||||||
|
-CONFIG_FUNCTION_TRACER=y
|
||||||
|
-CONFIG_CORESIGHT=y
|
||||||
|
-CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
|
||||||
|
-CONFIG_CORESIGHT_SINK_TPIU=y
|
||||||
|
-CONFIG_CORESIGHT_SINK_ETBV10=y
|
||||||
|
-CONFIG_CORESIGHT_SOURCE_ETM3X=y
|
||||||
|
-CONFIG_CORESIGHT_STM=y
|
||||||
|
-
|
||||||
|
-#
|
||||||
|
# STM32 IPCC
|
||||||
|
#
|
||||||
|
CONFIG_STM32_IPCC=y
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,117 @@
|
||||||
|
From 5648392b05ff7bb1f513ad9e9eb27b5420ce745d Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Mon, 14 Jan 2019 17:19:51 +0100
|
||||||
|
Subject: [PATCH 54/55] ARM stm32mp1 r0 rc4 hotfix-w903.1 DEVICETREE
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/stm32mp157a-dk1.dts | 13 +++++++++++++
|
||||||
|
arch/arm/boot/dts/stm32mp157c-dk2.dts | 1 +
|
||||||
|
arch/arm/boot/dts/stm32mp157c.dtsi | 14 ++++++++++++++
|
||||||
|
3 files changed, 28 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
index 7e911f3..28017e4 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
@@ -287,6 +287,19 @@
|
||||||
|
/delete-property/dmas;
|
||||||
|
/delete-property/dma-names;
|
||||||
|
|
||||||
|
+ typec: stusb1600@28 {
|
||||||
|
+ compatible = "st,stusb1600";
|
||||||
|
+ reg = <0x28>;
|
||||||
|
+ status = "okay";
|
||||||
|
+
|
||||||
|
+ typec_con: connector {
|
||||||
|
+ compatible = "usb-c-connector";
|
||||||
|
+ label = "USB-C";
|
||||||
|
+ power-role = "sink";
|
||||||
|
+ power-opmode = "default";
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
pmic: stpmic@33 {
|
||||||
|
compatible = "st,stpmic1";
|
||||||
|
reg = <0x33>;
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||||
|
index c276c59..340e022 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||||
|
@@ -106,6 +106,7 @@
|
||||||
|
|
||||||
|
/* Wifi */
|
||||||
|
&sdmmc2 {
|
||||||
|
+ arm,primecell-periphid = <0x10153180>;
|
||||||
|
pinctrl-names = "default", "opendrain", "sleep";
|
||||||
|
pinctrl-0 = <&sdmmc2_b4_pins_a>;
|
||||||
|
pinctrl-1 = <&sdmmc2_b4_od_pins_a>;
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
index 4de499e..b09ef8b 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
@@ -892,6 +892,8 @@
|
||||||
|
|
||||||
|
compatible = "st,stm32-sai-sub-a";
|
||||||
|
reg = <0x4 0x1c>;
|
||||||
|
+ clocks = <&rcc SAI1_K>;
|
||||||
|
+ clock-names = "sai_ck";
|
||||||
|
dmas = <&dmamux1 87 0x400 0x01>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
@@ -900,6 +902,8 @@
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
compatible = "st,stm32-sai-sub-b";
|
||||||
|
reg = <0x24 0x1c>;
|
||||||
|
+ clocks = <&rcc SAI1_K>;
|
||||||
|
+ clock-names = "sai_ck";
|
||||||
|
dmas = <&dmamux1 88 0x400 0x01>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
@@ -919,6 +923,8 @@
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
compatible = "st,stm32-sai-sub-a";
|
||||||
|
reg = <0x4 0x1c>;
|
||||||
|
+ clocks = <&rcc SAI2_K>;
|
||||||
|
+ clock-names = "sai_ck";
|
||||||
|
dmas = <&dmamux1 89 0x400 0x01>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
@@ -927,6 +933,8 @@
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
compatible = "st,stm32-sai-sub-b";
|
||||||
|
reg = <0x24 0x1c>;
|
||||||
|
+ clocks = <&rcc SAI2_K>;
|
||||||
|
+ clock-names = "sai_ck";
|
||||||
|
dmas = <&dmamux1 90 0x400 0x01>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
@@ -946,6 +954,8 @@
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
compatible = "st,stm32-sai-sub-a";
|
||||||
|
reg = <0x04 0x1c>;
|
||||||
|
+ clocks = <&rcc SAI3_K>;
|
||||||
|
+ clock-names = "sai_ck";
|
||||||
|
dmas = <&dmamux1 113 0x400 0x01>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
@@ -954,6 +964,8 @@
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
compatible = "st,stm32-sai-sub-b";
|
||||||
|
reg = <0x24 0x1c>;
|
||||||
|
+ clocks = <&rcc SAI3_K>;
|
||||||
|
+ clock-names = "sai_ck";
|
||||||
|
dmas = <&dmamux1 114 0x400 0x01>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
@@ -1442,6 +1454,8 @@
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
compatible = "st,stm32-sai-sub-b";
|
||||||
|
reg = <0x24 0x1c>;
|
||||||
|
+ clocks = <&rcc SAI4_K>;
|
||||||
|
+ clock-names = "sai_ck";
|
||||||
|
dmas = <&dmamux1 100 0x400 0x01>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
From 449bea3af472f64774547738478ca3b2cfa91cae Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Mon, 14 Jan 2019 17:20:30 +0100
|
||||||
|
Subject: [PATCH 55/55] ARM stm32mp1 r0 rc4 hotfix-w903.1 DEFCONFIG
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/configs/fragment-02-multiv7_addons.config | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
index 38c5562..ddf15a9 100644
|
||||||
|
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
@@ -346,6 +346,8 @@ CONFIG_USB_CONFIGFS=y
|
||||||
|
#
|
||||||
|
# USB Physical Layer drivers
|
||||||
|
#
|
||||||
|
+CONFIG_TYPEC=y
|
||||||
|
+CONFIG_TYPEC_STUSB=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Platform Support
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,554 @@
|
||||||
|
From b6678ec426d7dbc5248a2d98c0c2c7a5b55e4d5f Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Wed, 16 Jan 2019 17:51:05 +0100
|
||||||
|
Subject: [PATCH 56/58] ARM stm32mp1 r0 rc4 hotfix w903.3 DRIVERS
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/clk/clk-stm32mp1.c | 142 ++++++++++++++++++++--------------
|
||||||
|
drivers/i2c/busses/i2c-stm32f7.c | 33 +++++++-
|
||||||
|
drivers/irqchip/irq-stm32-exti.c | 160 +++++++++++++++++++++++++--------------
|
||||||
|
kernel/power/suspend.c | 1 -
|
||||||
|
4 files changed, 218 insertions(+), 118 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
|
||||||
|
index 7eccaa1..56d7b86 100644
|
||||||
|
--- a/drivers/clk/clk-stm32mp1.c
|
||||||
|
+++ b/drivers/clk/clk-stm32mp1.c
|
||||||
|
@@ -2215,8 +2215,8 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
|
||||||
|
|
||||||
|
static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||||
|
/* Oscillator divider */
|
||||||
|
- DIV(NO_ID, "clk-hsi-div", "clk-hsi", 0, RCC_HSICFGR, 0, 2,
|
||||||
|
- CLK_DIVIDER_READ_ONLY),
|
||||||
|
+ DIV(NO_ID, "clk-hsi-div", "clk-hsi", CLK_DIVIDER_POWER_OF_TWO,
|
||||||
|
+ RCC_HSICFGR, 0, 2, CLK_DIVIDER_READ_ONLY),
|
||||||
|
|
||||||
|
/* External / Internal Oscillators */
|
||||||
|
SGATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0),
|
||||||
|
@@ -2517,11 +2517,10 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||||
|
CLK_SET_RATE_NO_REPARENT,
|
||||||
|
_NO_GATE,
|
||||||
|
_MMUX(M_ETHCK),
|
||||||
|
- _DIV(RCC_ETHCKSELR, 4, 4, CLK_DIVIDER_ALLOW_ZERO, NULL)),
|
||||||
|
+ _DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)),
|
||||||
|
|
||||||
|
/* RTC clock */
|
||||||
|
- SDIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 7,
|
||||||
|
- CLK_DIVIDER_ALLOW_ZERO),
|
||||||
|
+ SDIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 6, 0),
|
||||||
|
|
||||||
|
COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE |
|
||||||
|
CLK_SET_RATE_PARENT,
|
||||||
|
@@ -2724,52 +2723,53 @@ static struct sreg clock_gating[] = {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct smux {
|
||||||
|
- const char *name;
|
||||||
|
- struct clk *clk;
|
||||||
|
- struct clk *clkp;
|
||||||
|
+ u32 clk_id;
|
||||||
|
+ u32 mux_id;
|
||||||
|
+ struct clk_hw *hw;
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define KER_SRC(_clk_name)\
|
||||||
|
+#define KER_SRC(_clk_id, _mux_id)\
|
||||||
|
{\
|
||||||
|
- .name = _clk_name,\
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-struct smux _mux_kernel[] = {
|
||||||
|
- KER_SRC("sdmmc1_k"),
|
||||||
|
- KER_SRC("spi2_k"),
|
||||||
|
- KER_SRC("spi4_k"),
|
||||||
|
- KER_SRC("i2c1_k"),
|
||||||
|
- KER_SRC("i2c3_k"),
|
||||||
|
- KER_SRC("lptim2_k"),
|
||||||
|
- KER_SRC("lptim3_k"),
|
||||||
|
- KER_SRC("usart2_k"),
|
||||||
|
- KER_SRC("usart3_k"),
|
||||||
|
- KER_SRC("uart7_k"),
|
||||||
|
- KER_SRC("sai1_k"),
|
||||||
|
- KER_SRC("ethck_k"),
|
||||||
|
- KER_SRC("i2c4_k"),
|
||||||
|
- KER_SRC("rng2_k"),
|
||||||
|
- KER_SRC("sdmmc3_k"),
|
||||||
|
- KER_SRC("fmc_k"),
|
||||||
|
- KER_SRC("qspi_k"),
|
||||||
|
- KER_SRC("usbphy_k"),
|
||||||
|
- KER_SRC("usbo_k"),
|
||||||
|
- KER_SRC("spdif_k"),
|
||||||
|
- KER_SRC("spi1_k"),
|
||||||
|
- KER_SRC("cec_k"),
|
||||||
|
- KER_SRC("lptim1_k"),
|
||||||
|
- KER_SRC("uart6_k"),
|
||||||
|
- KER_SRC("fdcan_k"),
|
||||||
|
- KER_SRC("sai2_k"),
|
||||||
|
- KER_SRC("sai3_k"),
|
||||||
|
- KER_SRC("sai4_k"),
|
||||||
|
- KER_SRC("adc12_k"),
|
||||||
|
- KER_SRC("dsi_k"),
|
||||||
|
- KER_SRC("ck_per"),
|
||||||
|
- KER_SRC("rng1_k"),
|
||||||
|
- KER_SRC("stgen_k"),
|
||||||
|
- KER_SRC("usart1_k"),
|
||||||
|
- KER_SRC("spi6_k"),
|
||||||
|
+ .clk_id = _clk_id,\
|
||||||
|
+ .mux_id = _mux_id,\
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct smux _mux_kernel[M_LAST] = {
|
||||||
|
+ KER_SRC(SDMMC1_K, M_SDMMC12),
|
||||||
|
+ KER_SRC(SDMMC3_K, M_SDMMC3),
|
||||||
|
+ KER_SRC(FMC_K, M_FMC),
|
||||||
|
+ KER_SRC(QSPI_K, M_QSPI),
|
||||||
|
+ KER_SRC(RNG1_K, M_RNG1),
|
||||||
|
+ KER_SRC(RNG2_K, M_RNG2),
|
||||||
|
+ KER_SRC(USBPHY_K, M_USBPHY),
|
||||||
|
+ KER_SRC(USBO_K, M_USBO),
|
||||||
|
+ KER_SRC(STGEN_K, M_STGEN),
|
||||||
|
+ KER_SRC(SPDIF_K, M_SPDIF),
|
||||||
|
+ KER_SRC(SPI1_K, M_SPI1),
|
||||||
|
+ KER_SRC(SPI2_K, M_SPI23),
|
||||||
|
+ KER_SRC(SPI4_K, M_SPI45),
|
||||||
|
+ KER_SRC(SPI6_K, M_SPI6),
|
||||||
|
+ KER_SRC(CEC_K, M_CEC),
|
||||||
|
+ KER_SRC(I2C1_K, M_I2C12),
|
||||||
|
+ KER_SRC(I2C3_K, M_I2C35),
|
||||||
|
+ KER_SRC(I2C4_K, M_I2C46),
|
||||||
|
+ KER_SRC(LPTIM1_K, M_LPTIM1),
|
||||||
|
+ KER_SRC(LPTIM2_K, M_LPTIM23),
|
||||||
|
+ KER_SRC(LPTIM4_K, M_LPTIM45),
|
||||||
|
+ KER_SRC(USART1_K, M_USART1),
|
||||||
|
+ KER_SRC(USART2_K, M_UART24),
|
||||||
|
+ KER_SRC(USART3_K, M_UART35),
|
||||||
|
+ KER_SRC(USART6_K, M_USART6),
|
||||||
|
+ KER_SRC(UART7_K, M_UART78),
|
||||||
|
+ KER_SRC(SAI1_K, M_SAI1),
|
||||||
|
+ KER_SRC(SAI2_K, M_SAI2),
|
||||||
|
+ KER_SRC(SAI3_K, M_SAI3),
|
||||||
|
+ KER_SRC(SAI4_K, M_SAI4),
|
||||||
|
+ KER_SRC(DSI_K, M_DSI),
|
||||||
|
+ KER_SRC(FDCAN_K, M_FDCAN),
|
||||||
|
+ KER_SRC(ADC12_K, M_ADC12),
|
||||||
|
+ KER_SRC(ETHCK_K, M_ETHCK),
|
||||||
|
+ KER_SRC(CK_PER, M_CKPER),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sreg pll_clock[] = {
|
||||||
|
@@ -2861,22 +2861,52 @@ static void stm32mp1_restore_pll(struct sreg *sreg, int size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void stm32mp1_backup_mux(struct smux *smux, int size)
|
||||||
|
+static void stm32mp1_backup_mux(struct device_node *np,
|
||||||
|
+ struct smux *smux, int size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
+ struct of_phandle_args clkspec;
|
||||||
|
+
|
||||||
|
+ clkspec.np = np;
|
||||||
|
+ clkspec.args_count = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
- smux[i].clk = __clk_lookup(smux[i].name);
|
||||||
|
- smux[i].clkp = clk_get_parent(smux[i].clk);
|
||||||
|
+ clkspec.args[0] = smux[i].clk_id;
|
||||||
|
+ smux[i].hw = __clk_get_hw(of_clk_get_from_provider(&clkspec));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stm32mp1_restore_mux(struct smux *smux, int size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
+ struct clk_hw *hw, *hwp1, *hwp2;
|
||||||
|
+ struct mux_cfg *mux;
|
||||||
|
+ u8 idx;
|
||||||
|
|
||||||
|
- for (i = 0; i < size; i++)
|
||||||
|
- clk_set_parent_force(smux[i].clk, smux[i].clkp);
|
||||||
|
+ /* These MUX are glitch free.
|
||||||
|
+ * Then we have to restore mux thru clock framework
|
||||||
|
+ * to be sure that CLK_OPS_PARENT_ENABLE will be exploited
|
||||||
|
+ */
|
||||||
|
+ for (i = 0; i < M_LAST; i++) {
|
||||||
|
+ /* get parent strored in clock framework */
|
||||||
|
+ hw = smux[i].hw;
|
||||||
|
+ hwp1 = clk_hw_get_parent(hw);
|
||||||
|
+
|
||||||
|
+ /* Get parent corresponding to mux register */
|
||||||
|
+ mux = ker_mux_cfg[smux[i].mux_id].mux;
|
||||||
|
+ idx = readl_relaxed(rcc_base + mux->reg_off) >> mux->shift;
|
||||||
|
+ idx &= (BIT(mux->width) - 1);
|
||||||
|
+ hwp2 = clk_hw_get_parent_by_index(hw, idx);
|
||||||
|
+
|
||||||
|
+ /* check if parent from mux & clock framework are differents */
|
||||||
|
+ if (hwp1 != hwp2) {
|
||||||
|
+ /* update first clock framework with the true parent */
|
||||||
|
+ clk_set_parent(hw->clk, hwp2->clk);
|
||||||
|
+
|
||||||
|
+ /* Restore now new parent */
|
||||||
|
+ clk_set_parent(hw->clk, hwp1->clk);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RCC_BIT_HSI 0
|
||||||
|
@@ -2900,9 +2930,6 @@ static int stm32mp1_clk_suspend(void)
|
||||||
|
/* Save clock gating regs */
|
||||||
|
stm32mp1_backup_sreg(clock_gating, ARRAY_SIZE(clock_gating));
|
||||||
|
|
||||||
|
- /* Save kernel clock regs */
|
||||||
|
- stm32mp1_backup_mux(_mux_kernel, ARRAY_SIZE(_mux_kernel));
|
||||||
|
-
|
||||||
|
/* Enable ck_xxx_ker clocks if ck_xxx was on */
|
||||||
|
reg = readl_relaxed(rcc_base + RCC_OCENSETR) & RCC_CK_OSC_MASK;
|
||||||
|
writel_relaxed(reg << 1, rcc_base + RCC_OCENSETR);
|
||||||
|
@@ -2970,6 +2997,9 @@ static int stm32_rcc_init_pwr(struct device_node *np)
|
||||||
|
|
||||||
|
SMC(STM32_SVC_RCC, STM32_WRITE, RCC_SREQCLRR, RCC_STOP_MASK);
|
||||||
|
|
||||||
|
+ /* Prepare kernel clock source backup */
|
||||||
|
+ stm32mp1_backup_mux(np, _mux_kernel, ARRAY_SIZE(_mux_kernel));
|
||||||
|
+
|
||||||
|
register_syscore_ops(&stm32mp1_clk_ops);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
|
||||||
|
index ac30aea..3af2637 100644
|
||||||
|
--- a/drivers/i2c/busses/i2c-stm32f7.c
|
||||||
|
+++ b/drivers/i2c/busses/i2c-stm32f7.c
|
||||||
|
@@ -978,6 +978,26 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
|
||||||
|
cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
|
||||||
|
f7_msg->read_write = I2C_SMBUS_READ;
|
||||||
|
break;
|
||||||
|
+ case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||||
|
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
|
||||||
|
+ dev_err(dev, "Invalid block %s size %d\n",
|
||||||
|
+ f7_msg->read_write == I2C_SMBUS_READ ?
|
||||||
|
+ "read" : "write",
|
||||||
|
+ data->block[0]);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (f7_msg->read_write) {
|
||||||
|
+ f7_msg->stop = false;
|
||||||
|
+ f7_msg->count = data->block[0];
|
||||||
|
+ cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
|
||||||
|
+ } else {
|
||||||
|
+ f7_msg->stop = true;
|
||||||
|
+ f7_msg->count = data->block[0] + 1;
|
||||||
|
+ for (i = 1; i <= data->block[0]; i++)
|
||||||
|
+ f7_msg->smbus_buf[i] = data->block[i];
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
dev_err(dev, "Unsupported smbus protocol %d\n", f7_msg->size);
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
@@ -986,7 +1006,8 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
|
||||||
|
f7_msg->buf = f7_msg->smbus_buf;
|
||||||
|
|
||||||
|
/* Configure PEC */
|
||||||
|
- if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK) {
|
||||||
|
+ if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK &&
|
||||||
|
+ f7_msg->size != I2C_SMBUS_I2C_BLOCK_DATA) {
|
||||||
|
cr1 |= STM32F7_I2C_CR1_PECEN;
|
||||||
|
cr2 |= STM32F7_I2C_CR2_PECBYTE;
|
||||||
|
if (!f7_msg->read_write)
|
||||||
|
@@ -1655,7 +1676,8 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check PEC */
|
||||||
|
- if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && read_write) {
|
||||||
|
+ if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK &&
|
||||||
|
+ size != I2C_SMBUS_I2C_BLOCK_DATA && read_write) {
|
||||||
|
ret = stm32f7_i2c_smbus_check_pec(i2c_dev);
|
||||||
|
if (ret)
|
||||||
|
goto pm_free;
|
||||||
|
@@ -1672,6 +1694,10 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||||
|
data->word = f7_msg->smbus_buf[0] |
|
||||||
|
(f7_msg->smbus_buf[1] << 8);
|
||||||
|
break;
|
||||||
|
+ case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||||
|
+ for (i = 0; i < data->block[0]; i++)
|
||||||
|
+ data->block[i + 1] = f7_msg->smbus_buf[i];
|
||||||
|
+ break;
|
||||||
|
case I2C_SMBUS_BLOCK_DATA:
|
||||||
|
case I2C_SMBUS_BLOCK_PROC_CALL:
|
||||||
|
for (i = 0; i <= f7_msg->smbus_buf[0]; i++)
|
||||||
|
@@ -1854,7 +1880,8 @@ static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
|
||||||
|
I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||||
|
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||||
|
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
|
||||||
|
- I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC;
|
||||||
|
+ I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC |
|
||||||
|
+ I2C_FUNC_SMBUS_I2C_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct i2c_algorithm stm32f7_i2c_algo = {
|
||||||
|
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
index 223ee2e..793be075a 100644
|
||||||
|
--- a/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
+++ b/drivers/irqchip/irq-stm32-exti.c
|
||||||
|
@@ -14,8 +14,10 @@
|
||||||
|
#include <linux/irqchip.h>
|
||||||
|
#include <linux/irqchip/chained_irq.h>
|
||||||
|
#include <linux/irqdomain.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_irq.h>
|
||||||
|
+#include <linux/of_platform.h>
|
||||||
|
#include <linux/syscore_ops.h>
|
||||||
|
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
@@ -37,12 +39,6 @@ struct stm32_exti_bank {
|
||||||
|
|
||||||
|
#define UNDEF_REG ~0
|
||||||
|
|
||||||
|
-enum stm32_exti_hwspinlock {
|
||||||
|
- HWSPINLOCK_UNKNOWN,
|
||||||
|
- HWSPINLOCK_NONE,
|
||||||
|
- HWSPINLOCK_READY,
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
struct stm32_desc_irq {
|
||||||
|
u32 exti;
|
||||||
|
u32 irq_parent;
|
||||||
|
@@ -69,8 +65,6 @@ struct stm32_exti_host_data {
|
||||||
|
void __iomem *base;
|
||||||
|
struct stm32_exti_chip_data *chips_data;
|
||||||
|
const struct stm32_exti_drv_data *drv_data;
|
||||||
|
- struct device_node *node;
|
||||||
|
- enum stm32_exti_hwspinlock hwlock_state;
|
||||||
|
struct hwspinlock *hwlock;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -285,49 +279,27 @@ static int stm32_exti_set_type(struct irq_data *d,
|
||||||
|
|
||||||
|
static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data)
|
||||||
|
{
|
||||||
|
- struct stm32_exti_host_data *host_data = chip_data->host_data;
|
||||||
|
- struct hwspinlock *hwlock;
|
||||||
|
- int id, ret = 0, timeout = 0;
|
||||||
|
-
|
||||||
|
- /* first time, check for hwspinlock availability */
|
||||||
|
- if (unlikely(host_data->hwlock_state == HWSPINLOCK_UNKNOWN)) {
|
||||||
|
- id = of_hwspin_lock_get_id(host_data->node, 0);
|
||||||
|
- if (id >= 0) {
|
||||||
|
- hwlock = hwspin_lock_request_specific(id);
|
||||||
|
- if (hwlock) {
|
||||||
|
- /* found valid hwspinlock */
|
||||||
|
- host_data->hwlock_state = HWSPINLOCK_READY;
|
||||||
|
- host_data->hwlock = hwlock;
|
||||||
|
- pr_debug("%s hwspinlock = %d\n", __func__, id);
|
||||||
|
- } else {
|
||||||
|
- host_data->hwlock_state = HWSPINLOCK_NONE;
|
||||||
|
- }
|
||||||
|
- } else if (id != -EPROBE_DEFER) {
|
||||||
|
- host_data->hwlock_state = HWSPINLOCK_NONE;
|
||||||
|
- } else {
|
||||||
|
- /* hwspinlock driver shall be ready at that stage */
|
||||||
|
- ret = -EPROBE_DEFER;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ int ret, timeout = 0;
|
||||||
|
|
||||||
|
- if (likely(host_data->hwlock_state == HWSPINLOCK_READY)) {
|
||||||
|
- /*
|
||||||
|
- * Use the x_raw API since we are under spin_lock protection.
|
||||||
|
- * Do not use the x_timeout API because we are under irq_disable
|
||||||
|
- * mode (see __setup_irq())
|
||||||
|
- */
|
||||||
|
- do {
|
||||||
|
- ret = hwspin_trylock_raw(host_data->hwlock);
|
||||||
|
- if (!ret)
|
||||||
|
- return 0;
|
||||||
|
-
|
||||||
|
- udelay(HWSPNLCK_RETRY_DELAY);
|
||||||
|
- timeout += HWSPNLCK_RETRY_DELAY;
|
||||||
|
- } while (timeout < HWSPNLCK_TIMEOUT);
|
||||||
|
-
|
||||||
|
- if (ret == -EBUSY)
|
||||||
|
- ret = -ETIMEDOUT;
|
||||||
|
- }
|
||||||
|
+ if (!chip_data->host_data->hwlock)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Use the x_raw API since we are under spin_lock protection.
|
||||||
|
+ * Do not use the x_timeout API because we are under irq_disable
|
||||||
|
+ * mode (see __setup_irq())
|
||||||
|
+ */
|
||||||
|
+ do {
|
||||||
|
+ ret = hwspin_trylock_raw(chip_data->host_data->hwlock);
|
||||||
|
+ if (!ret)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ udelay(HWSPNLCK_RETRY_DELAY);
|
||||||
|
+ timeout += HWSPNLCK_RETRY_DELAY;
|
||||||
|
+ } while (timeout < HWSPNLCK_TIMEOUT);
|
||||||
|
+
|
||||||
|
+ if (ret == -EBUSY)
|
||||||
|
+ ret = -ETIMEDOUT;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
pr_err("%s can't get hwspinlock (%d)\n", __func__, ret);
|
||||||
|
@@ -337,7 +309,7 @@ static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data)
|
||||||
|
|
||||||
|
static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data)
|
||||||
|
{
|
||||||
|
- if (likely(chip_data->host_data->hwlock_state == HWSPINLOCK_READY))
|
||||||
|
+ if (chip_data->host_data->hwlock)
|
||||||
|
hwspin_unlock_raw(chip_data->host_data->hwlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -710,8 +682,6 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
host_data->drv_data = dd;
|
||||||
|
- host_data->node = node;
|
||||||
|
- host_data->hwlock_state = HWSPINLOCK_UNKNOWN;
|
||||||
|
host_data->chips_data = kcalloc(dd->bank_nr,
|
||||||
|
sizeof(struct stm32_exti_chip_data),
|
||||||
|
GFP_KERNEL);
|
||||||
|
@@ -738,7 +708,8 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
|
||||||
|
|
||||||
|
static struct
|
||||||
|
stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||||
|
- u32 bank_idx)
|
||||||
|
+ u32 bank_idx,
|
||||||
|
+ struct device_node *node)
|
||||||
|
{
|
||||||
|
const struct stm32_exti_bank *stm32_bank;
|
||||||
|
struct stm32_exti_chip_data *chip_data;
|
||||||
|
@@ -758,7 +729,7 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||||
|
writel_relaxed(0, base + stm32_bank->imr_ofst);
|
||||||
|
writel_relaxed(0, base + stm32_bank->emr_ofst);
|
||||||
|
|
||||||
|
- pr_info("%pOF: bank%d\n", h_data->node, bank_idx);
|
||||||
|
+ pr_info("%pOF: bank%d\n", node, bank_idx);
|
||||||
|
|
||||||
|
return chip_data;
|
||||||
|
}
|
||||||
|
@@ -798,7 +769,7 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
struct stm32_exti_chip_data *chip_data;
|
||||||
|
|
||||||
|
stm32_bank = drv_data->exti_banks[i];
|
||||||
|
- chip_data = stm32_exti_chip_init(host_data, i);
|
||||||
|
+ chip_data = stm32_exti_chip_init(host_data, i, node);
|
||||||
|
|
||||||
|
gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
|
||||||
|
|
||||||
|
@@ -880,7 +851,7 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = 0; i < drv_data->bank_nr; i++)
|
||||||
|
- stm32_exti_chip_init(host_data, i);
|
||||||
|
+ stm32_exti_chip_init(host_data, i, node);
|
||||||
|
|
||||||
|
domain = irq_domain_add_hierarchy(parent_domain, 0,
|
||||||
|
drv_data->bank_nr * IRQS_PER_BANK,
|
||||||
|
@@ -938,6 +909,71 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Note : stm32_exti_probe() is called after stm32*_exti_of_init() */
|
||||||
|
+static int stm32_exti_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ int id, ret = 0;
|
||||||
|
+
|
||||||
|
+ id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
|
||||||
|
+
|
||||||
|
+ if (id == -EPROBE_DEFER)
|
||||||
|
+ /* hwspinlock framework not ready */
|
||||||
|
+ return -EPROBE_DEFER;
|
||||||
|
+
|
||||||
|
+ if (id == -ENOENT)
|
||||||
|
+ /* no hwspinlock defined (not an error, it is optional) */
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ if (id >= 0) {
|
||||||
|
+ stm32_host_data->hwlock = hwspin_lock_request_specific(id);
|
||||||
|
+ if (!stm32_host_data->hwlock) {
|
||||||
|
+ dev_err(&pdev->dev, "Failed to request hwspinlock\n");
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ dev_err(&pdev->dev, "Failed to get hwspinlock\n");
|
||||||
|
+ ret = id;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int stm32_exti_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ if (stm32_host_data->hwlock)
|
||||||
|
+ return hwspin_lock_free(stm32_host_data->hwlock);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct of_device_id stm32_exti_ids[] = {
|
||||||
|
+ { .compatible = "st,stm32mp1-exti", },
|
||||||
|
+ {},
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, stm32_exti_ids);
|
||||||
|
+
|
||||||
|
+static struct platform_driver stm32_exti_driver = {
|
||||||
|
+ .probe = stm32_exti_probe,
|
||||||
|
+ .remove = stm32_exti_remove,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "stm32_exti",
|
||||||
|
+ .of_match_table = stm32_exti_ids,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init stm32_exti_arch_init(void)
|
||||||
|
+{
|
||||||
|
+ return platform_driver_register(&stm32_exti_driver);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __exit stm32_exti_arch_exit(void)
|
||||||
|
+{
|
||||||
|
+ return platform_driver_unregister(&stm32_exti_driver);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+arch_initcall(stm32_exti_arch_init);
|
||||||
|
+module_exit(stm32_exti_arch_exit);
|
||||||
|
+
|
||||||
|
static int __init stm32f4_exti_of_init(struct device_node *np,
|
||||||
|
struct device_node *parent)
|
||||||
|
{
|
||||||
|
@@ -957,7 +993,15 @@ IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);
|
||||||
|
static int __init stm32mp1_exti_of_init(struct device_node *np,
|
||||||
|
struct device_node *parent)
|
||||||
|
{
|
||||||
|
- return stm32_exti_hierarchy_init(&stm32mp1_drv_data, np, parent);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = stm32_exti_hierarchy_init(&stm32mp1_drv_data, np, parent);
|
||||||
|
+
|
||||||
|
+ /* Clear the OF_POPULATED flag so that stm32_exti_probe can be called */
|
||||||
|
+ if (!ret)
|
||||||
|
+ of_node_clear_flag(np, OF_POPULATED);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
IRQCHIP_DECLARE(stm32mp1_exti, "st,stm32mp1-exti", stm32mp1_exti_of_init);
|
||||||
|
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
|
||||||
|
index 0bd595a..64f6aec 100644
|
||||||
|
--- a/kernel/power/suspend.c
|
||||||
|
+++ b/kernel/power/suspend.c
|
||||||
|
@@ -36,7 +36,6 @@
|
||||||
|
#include "power.h"
|
||||||
|
|
||||||
|
const char * const pm_labels[] = {
|
||||||
|
- [PM_SUSPEND_TO_IDLE] = "freeze",
|
||||||
|
[PM_SUSPEND_STANDBY] = "standby",
|
||||||
|
[PM_SUSPEND_MEM] = "mem",
|
||||||
|
};
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
From f30f869d9bb396c6981fc2800149c373d21586de Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Wed, 16 Jan 2019 17:52:31 +0100
|
||||||
|
Subject: [PATCH 57/58] ARM stm32mp1 r0 rc4 hotfix w903.3 DEVICETREE
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 30 ++++++++++++++++++++++++++++++
|
||||||
|
arch/arm/boot/dts/stm32mp157a-dk1.dts | 12 +++++++++++-
|
||||||
|
arch/arm/boot/dts/stm32mp157c-dk2.dts | 2 +-
|
||||||
|
arch/arm/boot/dts/stm32mp157c-ed1.dts | 2 +-
|
||||||
|
4 files changed, 43 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||||
|
index 183d7ba..474e7e3 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||||
|
@@ -1413,6 +1413,36 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ uart7_pins_a: uart7-0 {
|
||||||
|
+ pins1 {
|
||||||
|
+ pinmux = <STM32_PINMUX('E', 8, AF7)>; /* USART7_TX */
|
||||||
|
+ bias-disable;
|
||||||
|
+ drive-push-pull;
|
||||||
|
+ slew-rate = <0>;
|
||||||
|
+ };
|
||||||
|
+ pins2 {
|
||||||
|
+ pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
|
||||||
|
+ bias-disable;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ uart7_idle_pins_a: uart7-idle-0 {
|
||||||
|
+ pins1 {
|
||||||
|
+ pinmux = <STM32_PINMUX('E', 8, ANALOG)>; /* USART7_TX */
|
||||||
|
+ };
|
||||||
|
+ pins2 {
|
||||||
|
+ pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
|
||||||
|
+ bias-disable;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ uart7_sleep_pins_a: uart7-sleep-0 {
|
||||||
|
+ pins {
|
||||||
|
+ pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* USART7_TX */
|
||||||
|
+ <STM32_PINMUX('E', 7, ANALOG)>; /* USART7_RX */
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
usart2_pins_a: usart2-0 {
|
||||||
|
pins1 {
|
||||||
|
pinmux = <STM32_PINMUX('D', 5, AF7)>, /* USART2_TX */
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
index 28017e4..467c226 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
@@ -20,6 +20,8 @@
|
||||||
|
aliases {
|
||||||
|
ethernet0 = ðernet0;
|
||||||
|
serial0 = &uart4;
|
||||||
|
+ serial1 = &usart3;
|
||||||
|
+ serial2 = &uart7;
|
||||||
|
};
|
||||||
|
|
||||||
|
chosen {
|
||||||
|
@@ -310,7 +312,7 @@
|
||||||
|
|
||||||
|
st,main-control-register = <0x04>;
|
||||||
|
st,vin-control-register = <0xc0>;
|
||||||
|
- st,usb-control-register = <0x30>;
|
||||||
|
+ st,usb-control-register = <0x20>;
|
||||||
|
|
||||||
|
regulators {
|
||||||
|
compatible = "st,stpmic1-regulators";
|
||||||
|
@@ -671,6 +673,14 @@
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
+&uart7 {
|
||||||
|
+ pinctrl-names = "default", "sleep", "idle";
|
||||||
|
+ pinctrl-0 = <&uart7_pins_a>;
|
||||||
|
+ pinctrl-1 = <&uart7_sleep_pins_a>;
|
||||||
|
+ pinctrl-2 = <&uart7_idle_pins_a>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
&usart3 {
|
||||||
|
pinctrl-names = "default", "sleep", "idle";
|
||||||
|
pinctrl-0 = <&usart3_pins_b>;
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||||
|
index 340e022..4da15cd 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||||
|
@@ -14,7 +14,7 @@
|
||||||
|
compatible = "st,stm32mp157c-dk2", "st,stm32mp157";
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
- serial1 = &usart2;
|
||||||
|
+ serial3 = &usart2;
|
||||||
|
};
|
||||||
|
|
||||||
|
wifi_pwrseq: wifi-pwrseq {
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||||
|
index cf2750e..6d49f21 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||||
|
@@ -188,7 +188,7 @@
|
||||||
|
|
||||||
|
st,main-control-register = <0x04>;
|
||||||
|
st,vin-control-register = <0xc0>;
|
||||||
|
- st,usb-control-register = <0x30>;
|
||||||
|
+ st,usb-control-register = <0x20>;
|
||||||
|
|
||||||
|
regulators {
|
||||||
|
compatible = "st,stpmic1-regulators";
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
From 2cfb67b0a4403e68016a50c1302da9a8eeb15a6b Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Wed, 16 Jan 2019 17:53:15 +0100
|
||||||
|
Subject: [PATCH 58/58] ARM stm32mp1 r0 rc4 hotfix w903.3 DEFCONFIG
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/configs/fragment-02-multiv7_addons.config | 3 ---
|
||||||
|
1 file changed, 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
index ddf15a9..7b489e4 100644
|
||||||
|
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||||
|
@@ -123,9 +123,6 @@ CONFIG_CMA_SIZE_MBYTES=128
|
||||||
|
#
|
||||||
|
# LPDDR & LPDDR2 PCM memory drivers
|
||||||
|
#
|
||||||
|
-CONFIG_OF_RESOLVE=y
|
||||||
|
-CONFIG_OF_OVERLAY=y
|
||||||
|
-CONFIG_OF_CONFIGFS=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Misc devices
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,927 @@
|
||||||
|
From dbfd12db19506dc6d598c11d72aa0fb81c41aa82 Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Thu, 24 Jan 2019 10:51:36 +0100
|
||||||
|
Subject: [PATCH 59/60] ARM stm32mp1 r0 rc4 hotfix w904.3 DRIVERS
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/dma/stm32-dma.c | 4 +
|
||||||
|
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c | 64 +++++------
|
||||||
|
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 51 ++++++---
|
||||||
|
drivers/remoteproc/stm32_rproc.c | 21 ++--
|
||||||
|
drivers/tty/serial/stm32-usart.c | 8 ++
|
||||||
|
drivers/tty/serial/stm32-usart.h | 2 +-
|
||||||
|
drivers/usb/dwc2/core.h | 29 +++++
|
||||||
|
drivers/usb/dwc2/debugfs.c | 1 +
|
||||||
|
drivers/usb/dwc2/gadget.c | 133 +++++++++++++++++++++--
|
||||||
|
drivers/usb/dwc2/hcd.c | 3 -
|
||||||
|
drivers/usb/dwc2/hcd.h | 2 +-
|
||||||
|
drivers/usb/dwc2/hcd_queue.c | 19 ++--
|
||||||
|
drivers/usb/dwc2/hw.h | 17 +++
|
||||||
|
drivers/usb/dwc2/params.c | 18 ++-
|
||||||
|
14 files changed, 294 insertions(+), 78 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
|
||||||
|
index 1f9d606..5abfa4f 100644
|
||||||
|
--- a/drivers/dma/stm32-dma.c
|
||||||
|
+++ b/drivers/dma/stm32-dma.c
|
||||||
|
@@ -1242,6 +1242,7 @@ static int stm32_dma_mdma_prep_slave_sg(struct stm32_dma_chan *chan,
|
||||||
|
dev_err(chan2dev(chan),
|
||||||
|
"max buf size = %d bytes\n",
|
||||||
|
chan->sram_size);
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
goto free_alloc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@@ -1939,6 +1940,8 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||||
|
dev_dbg(&pdev->dev, "SRAM pool: %zu KiB\n",
|
||||||
|
gen_pool_size(dmadev->sram_pool) / 1024);
|
||||||
|
|
||||||
|
+ dma_set_max_seg_size(&pdev->dev, STM32_DMA_ALIGNED_MAX_DATA_ITEMS);
|
||||||
|
+
|
||||||
|
dma_cap_set(DMA_SLAVE, dd->cap_mask);
|
||||||
|
dma_cap_set(DMA_PRIVATE, dd->cap_mask);
|
||||||
|
dma_cap_set(DMA_CYCLIC, dd->cap_mask);
|
||||||
|
@@ -1959,6 +1962,7 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||||
|
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
||||||
|
dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
|
||||||
|
dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
|
||||||
|
+ dd->copy_align = DMAENGINE_ALIGN_32_BYTES;
|
||||||
|
dd->max_burst = STM32_DMA_MAX_BURST;
|
||||||
|
dd->descriptor_reuse = true;
|
||||||
|
dd->dev = &pdev->dev;
|
||||||
|
diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||||
|
index a76d03a..ee7486b 100644
|
||||||
|
--- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||||
|
+++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||||
|
@@ -254,24 +254,12 @@ static int otm8009a_init_sequence(struct otm8009a *ctx)
|
||||||
|
static int otm8009a_disable(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
struct otm8009a *ctx = panel_to_otm8009a(panel);
|
||||||
|
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||||
|
- int ret;
|
||||||
|
|
||||||
|
if (!ctx->enabled)
|
||||||
|
return 0; /* This is not an issue so we return 0 here */
|
||||||
|
|
||||||
|
backlight_disable(ctx->bl_dev);
|
||||||
|
|
||||||
|
- ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||||
|
- if (ret)
|
||||||
|
- return ret;
|
||||||
|
-
|
||||||
|
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||||
|
- if (ret)
|
||||||
|
- return ret;
|
||||||
|
-
|
||||||
|
- msleep(120);
|
||||||
|
-
|
||||||
|
ctx->enabled = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -280,16 +268,23 @@ static int otm8009a_disable(struct drm_panel *panel)
|
||||||
|
static int otm8009a_unprepare(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
struct otm8009a *ctx = panel_to_otm8009a(panel);
|
||||||
|
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
if (!ctx->prepared)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- if (ctx->reset_gpio) {
|
||||||
|
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||||
|
- msleep(20);
|
||||||
|
- }
|
||||||
|
+ ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
|
||||||
|
- regulator_disable(ctx->supply);
|
||||||
|
+ msleep(10);
|
||||||
|
+
|
||||||
|
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ msleep(120);
|
||||||
|
|
||||||
|
ctx->prepared = false;
|
||||||
|
|
||||||
|
@@ -304,20 +299,6 @@ static int otm8009a_prepare(struct drm_panel *panel)
|
||||||
|
if (ctx->prepared)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- ret = regulator_enable(ctx->supply);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- DRM_ERROR("failed to enable supply: %d\n", ret);
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (ctx->reset_gpio) {
|
||||||
|
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||||
|
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||||
|
- msleep(20);
|
||||||
|
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||||
|
- msleep(100);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
ret = otm8009a_init_sequence(ctx);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
@@ -475,6 +456,20 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ret = regulator_enable(ctx->supply);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ DRM_ERROR("failed to enable supply: %d\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ctx->reset_gpio) {
|
||||||
|
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||||
|
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||||
|
+ msleep(20);
|
||||||
|
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||||
|
+ msleep(100);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -485,6 +480,13 @@ static int otm8009a_remove(struct mipi_dsi_device *dsi)
|
||||||
|
mipi_dsi_detach(dsi);
|
||||||
|
drm_panel_remove(&ctx->panel);
|
||||||
|
|
||||||
|
+ if (ctx->reset_gpio) {
|
||||||
|
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||||
|
+ msleep(20);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ regulator_disable(ctx->supply);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
|
||||||
|
index a373651..7b37f97 100644
|
||||||
|
--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
|
||||||
|
+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
|
||||||
|
@@ -305,6 +305,7 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct dw_mipi_dsi_stm *dsi;
|
||||||
|
+ struct clk *pclk;
|
||||||
|
struct resource *res;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
@@ -335,23 +336,13 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||||
|
if (IS_ERR(dsi->pllref_clk)) {
|
||||||
|
ret = PTR_ERR(dsi->pllref_clk);
|
||||||
|
dev_err(dev, "Unable to get pll reference clock: %d\n", ret);
|
||||||
|
- regulator_disable(dsi->vdd_supply);
|
||||||
|
- return ret;
|
||||||
|
+ goto err_clk_get;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(dsi->pllref_clk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
|
||||||
|
- regulator_disable(dsi->vdd_supply);
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
|
||||||
|
- if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {
|
||||||
|
- dev_err(dev, "bad dsi hardware version\n");
|
||||||
|
- clk_disable_unprepare(dsi->pllref_clk);
|
||||||
|
- regulator_disable(dsi->vdd_supply);
|
||||||
|
- return -ENODEV;
|
||||||
|
+ goto err_clk_get;
|
||||||
|
}
|
||||||
|
|
||||||
|
dw_mipi_dsi_stm_plat_data.base = dsi->base;
|
||||||
|
@@ -361,13 +352,43 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
|
dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data);
|
||||||
|
if (IS_ERR(dsi->dsi)) {
|
||||||
|
+ ret = PTR_ERR(dsi->dsi);
|
||||||
|
DRM_ERROR("Failed to initialize mipi dsi host\n");
|
||||||
|
- regulator_disable(dsi->vdd_supply);
|
||||||
|
- clk_disable_unprepare(dsi->pllref_clk);
|
||||||
|
- return PTR_ERR(dsi->dsi);
|
||||||
|
+ goto err_probe;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pclk = devm_clk_get(dev, "pclk");
|
||||||
|
+ if (IS_ERR(pclk)) {
|
||||||
|
+ ret = PTR_ERR(pclk);
|
||||||
|
+ dev_err(dev, "Unable to get peripheral clock: %d\n", ret);
|
||||||
|
+ goto err_probe;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = clk_prepare_enable(pclk);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(dev, "%s: Failed to enable peripheral clk\n", __func__);
|
||||||
|
+ goto err_probe;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
|
||||||
|
+ clk_disable_unprepare(pclk);
|
||||||
|
+
|
||||||
|
+ if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {
|
||||||
|
+ ret = -ENODEV;
|
||||||
|
+ dev_err(dev, "bad dsi hardware version\n");
|
||||||
|
+ goto err_probe;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
+
|
||||||
|
+err_probe:
|
||||||
|
+ clk_disable_unprepare(dsi->pllref_clk);
|
||||||
|
+
|
||||||
|
+err_clk_get:
|
||||||
|
+ regulator_disable(dsi->vdd_supply);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_mipi_dsi_stm_remove(struct platform_device *pdev)
|
||||||
|
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
|
||||||
|
index 1d2be11..1827c25 100644
|
||||||
|
--- a/drivers/remoteproc/stm32_rproc.c
|
||||||
|
+++ b/drivers/remoteproc/stm32_rproc.c
|
||||||
|
@@ -104,10 +104,12 @@ static int stm32_rproc_da_to_pa(struct rproc *rproc, u64 da, phys_addr_t *pa)
|
||||||
|
da >= p_mem->dev_addr + p_mem->size)
|
||||||
|
continue;
|
||||||
|
*pa = da - p_mem->dev_addr + p_mem->bus_addr;
|
||||||
|
- dev_err(rproc->dev.parent, "da %llx to pa %#x\n", da, *pa);
|
||||||
|
+ dev_dbg(rproc->dev.parent, "da %llx to pa %#x\n", da, *pa);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ dev_err(rproc->dev.parent, "can't translate da %llx\n", da);
|
||||||
|
+
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -657,20 +659,21 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev)
|
||||||
|
|
||||||
|
if (of_property_read_bool(np, "early-booted")) {
|
||||||
|
rproc->early_boot = true;
|
||||||
|
-
|
||||||
|
err = of_property_read_u32(np, "rsc-address", &rsc_da);
|
||||||
|
- if (!err) {
|
||||||
|
- err = of_property_read_u32(np, "rsc-size",
|
||||||
|
- &ddata->rsc_len);
|
||||||
|
+ if (err)
|
||||||
|
+ /* no optional rsc table found */
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
- if (err) {
|
||||||
|
- dev_err(dev, "resource table size required as address defined\n");
|
||||||
|
- return err;
|
||||||
|
- }
|
||||||
|
+ err = of_property_read_u32(np, "rsc-size", &ddata->rsc_len);
|
||||||
|
+ if (err) {
|
||||||
|
+ dev_err(dev, "resource table size required as address defined\n");
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
err = stm32_rproc_da_to_pa(rproc, rsc_da, &rsc_pa);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
+
|
||||||
|
ddata->rsc_va = ioremap_wc(rsc_pa, ddata->rsc_len);
|
||||||
|
if (IS_ERR_OR_NULL(ddata->rsc_va)) {
|
||||||
|
dev_err(dev, "Unable to map memory region: %pa+%zx\n",
|
||||||
|
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
|
||||||
|
index d606eb5..6fc57fc 100644
|
||||||
|
--- a/drivers/tty/serial/stm32-usart.c
|
||||||
|
+++ b/drivers/tty/serial/stm32-usart.c
|
||||||
|
@@ -250,8 +250,16 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded)
|
||||||
|
ofs->icr);
|
||||||
|
port->icount.overrun++;
|
||||||
|
} else if (sr & USART_SR_PE) {
|
||||||
|
+ if (ofs->icr != UNDEF_REG)
|
||||||
|
+ writel_relaxed(USART_ICR_PECF,
|
||||||
|
+ port->membase +
|
||||||
|
+ ofs->icr);
|
||||||
|
port->icount.parity++;
|
||||||
|
} else if (sr & USART_SR_FE) {
|
||||||
|
+ if (ofs->icr != UNDEF_REG)
|
||||||
|
+ writel_relaxed(USART_ICR_FECF,
|
||||||
|
+ port->membase +
|
||||||
|
+ ofs->icr);
|
||||||
|
port->icount.frame++;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
|
||||||
|
index f1f5c1c..53d7e7b 100644
|
||||||
|
--- a/drivers/tty/serial/stm32-usart.h
|
||||||
|
+++ b/drivers/tty/serial/stm32-usart.h
|
||||||
|
@@ -241,7 +241,7 @@ struct stm32_usart_info stm32h7_info = {
|
||||||
|
|
||||||
|
/* USART_ICR */
|
||||||
|
#define USART_ICR_PECF BIT(0) /* F7 */
|
||||||
|
-#define USART_ICR_FFECF BIT(1) /* F7 */
|
||||||
|
+#define USART_ICR_FECF BIT(1) /* F7 */
|
||||||
|
#define USART_ICR_NCF BIT(2) /* F7 */
|
||||||
|
#define USART_ICR_ORECF BIT(3) /* F7 */
|
||||||
|
#define USART_ICR_IDLECF BIT(4) /* F7 */
|
||||||
|
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
|
||||||
|
index 4c1736f..3d8fa58 100644
|
||||||
|
--- a/drivers/usb/dwc2/core.h
|
||||||
|
+++ b/drivers/usb/dwc2/core.h
|
||||||
|
@@ -393,6 +393,20 @@ enum dwc2_ep0_state {
|
||||||
|
* 0 - No
|
||||||
|
* 1 - Yes
|
||||||
|
* @hird_threshold: Value of BESL or HIRD Threshold.
|
||||||
|
+ * @ref_clk_per: Indicates in terms of pico seconds the period
|
||||||
|
+ * of ref_clk.
|
||||||
|
+ * 62500 - 16MHz
|
||||||
|
+ * 58823 - 17MHz
|
||||||
|
+ * 52083 - 19.2MHz
|
||||||
|
+ * 50000 - 20MHz
|
||||||
|
+ * 41666 - 24MHz
|
||||||
|
+ * 33333 - 30MHz (default)
|
||||||
|
+ * 25000 - 40MHz
|
||||||
|
+ * @sof_cnt_wkup_alert: Indicates in term of number of SOF's after which
|
||||||
|
+ * the controller should generate an interrupt if the
|
||||||
|
+ * device had been in L1 state until that period.
|
||||||
|
+ * This is used by SW to initiate Remote WakeUp in the
|
||||||
|
+ * controller so as to sync to the uF number from the host.
|
||||||
|
* @activate_stm_fs_transceiver: Activate internal transceiver using GGPIO
|
||||||
|
* register.
|
||||||
|
* 0 - Deactivate the transceiver (default)
|
||||||
|
@@ -426,6 +440,9 @@ enum dwc2_ep0_state {
|
||||||
|
* back to DWC2_SPEED_PARAM_HIGH while device is gone.
|
||||||
|
* 0 - No (default)
|
||||||
|
* 1 - Yes
|
||||||
|
+ * @service_interval: Enable service interval based scheduling.
|
||||||
|
+ * 0 - No
|
||||||
|
+ * 1 - Yes
|
||||||
|
*
|
||||||
|
* The following parameters may be specified when starting the module. These
|
||||||
|
* parameters define how the DWC_otg controller should be configured. A
|
||||||
|
@@ -471,6 +488,7 @@ struct dwc2_core_params {
|
||||||
|
bool lpm_clock_gating;
|
||||||
|
bool besl;
|
||||||
|
bool hird_threshold_en;
|
||||||
|
+ bool service_interval;
|
||||||
|
u8 hird_threshold;
|
||||||
|
bool activate_stm_fs_transceiver;
|
||||||
|
bool activate_stm_id_vb_detection;
|
||||||
|
@@ -479,6 +497,10 @@ struct dwc2_core_params {
|
||||||
|
u32 max_transfer_size;
|
||||||
|
u32 ahbcfg;
|
||||||
|
|
||||||
|
+ /* GREFCLK parameters */
|
||||||
|
+ u32 ref_clk_per;
|
||||||
|
+ u16 sof_cnt_wkup_alert;
|
||||||
|
+
|
||||||
|
/* Host parameters */
|
||||||
|
bool host_dma;
|
||||||
|
bool dma_desc_enable;
|
||||||
|
@@ -618,6 +640,10 @@ struct dwc2_core_params {
|
||||||
|
* FIFO sizing is enabled 16 to 32768
|
||||||
|
* Actual maximum value is autodetected and also
|
||||||
|
* the default.
|
||||||
|
+ * @service_interval_mode: For enabling service interval based scheduling in the
|
||||||
|
+ * controller.
|
||||||
|
+ * 0 - Disable
|
||||||
|
+ * 1 - Enable
|
||||||
|
*/
|
||||||
|
struct dwc2_hw_params {
|
||||||
|
unsigned op_mode:3;
|
||||||
|
@@ -648,6 +674,7 @@ struct dwc2_hw_params {
|
||||||
|
unsigned utmi_phy_data_width:2;
|
||||||
|
unsigned lpm_mode:1;
|
||||||
|
unsigned ipg_isoc_en:1;
|
||||||
|
+ unsigned service_interval_mode:1;
|
||||||
|
u32 snpsid;
|
||||||
|
u32 dev_ep_dirs;
|
||||||
|
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
|
||||||
|
@@ -1372,6 +1399,7 @@ int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg);
|
||||||
|
int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
|
||||||
|
int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
|
||||||
|
void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg);
|
||||||
|
+void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg);
|
||||||
|
#else
|
||||||
|
static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
|
||||||
|
{ return 0; }
|
||||||
|
@@ -1406,6 +1434,7 @@ static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
||||||
|
static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
|
||||||
|
{ return 0; }
|
||||||
|
static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {}
|
||||||
|
+static inline void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
|
||||||
|
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c
|
||||||
|
index 22d015b..7f62f4c 100644
|
||||||
|
--- a/drivers/usb/dwc2/debugfs.c
|
||||||
|
+++ b/drivers/usb/dwc2/debugfs.c
|
||||||
|
@@ -701,6 +701,7 @@ static int params_show(struct seq_file *seq, void *v)
|
||||||
|
print_param(seq, p, besl);
|
||||||
|
print_param(seq, p, hird_threshold_en);
|
||||||
|
print_param(seq, p, hird_threshold);
|
||||||
|
+ print_param(seq, p, service_interval);
|
||||||
|
print_param(seq, p, host_dma);
|
||||||
|
print_param(seq, p, g_dma);
|
||||||
|
print_param(seq, p, g_dma_desc);
|
||||||
|
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
|
||||||
|
index 220c0f9..55ef3cc 100644
|
||||||
|
--- a/drivers/usb/dwc2/gadget.c
|
||||||
|
+++ b/drivers/usb/dwc2/gadget.c
|
||||||
|
@@ -123,6 +123,24 @@ static inline void dwc2_gadget_incr_frame_num(struct dwc2_hsotg_ep *hs_ep)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * dwc2_gadget_dec_frame_num_by_one - Decrements the targeted frame number
|
||||||
|
+ * by one.
|
||||||
|
+ * @hs_ep: The endpoint.
|
||||||
|
+ *
|
||||||
|
+ * This function used in service interval based scheduling flow to calculate
|
||||||
|
+ * descriptor frame number filed value. For service interval mode frame
|
||||||
|
+ * number in descriptor should point to last (u)frame in the interval.
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+static inline void dwc2_gadget_dec_frame_num_by_one(struct dwc2_hsotg_ep *hs_ep)
|
||||||
|
+{
|
||||||
|
+ if (hs_ep->target_frame)
|
||||||
|
+ hs_ep->target_frame -= 1;
|
||||||
|
+ else
|
||||||
|
+ hs_ep->target_frame = DSTS_SOFFN_LIMIT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* dwc2_hsotg_en_gsint - enable one or more of the general interrupt
|
||||||
|
* @hsotg: The device state
|
||||||
|
* @ints: A bitmask of the interrupts to enable
|
||||||
|
@@ -228,6 +246,27 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * dwc2_gadget_wkup_alert_handler - Handler for WKUP_ALERT interrupt
|
||||||
|
+ *
|
||||||
|
+ * @hsotg: Programming view of the DWC_otg controller
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg)
|
||||||
|
+{
|
||||||
|
+ u32 gintsts2;
|
||||||
|
+ u32 gintmsk2;
|
||||||
|
+
|
||||||
|
+ gintsts2 = dwc2_readl(hsotg, GINTSTS2);
|
||||||
|
+ gintmsk2 = dwc2_readl(hsotg, GINTMSK2);
|
||||||
|
+
|
||||||
|
+ if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) {
|
||||||
|
+ dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__);
|
||||||
|
+ dwc2_set_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
|
||||||
|
+ dwc2_set_bit(hsotg, DCTL, DCTL_RMTWKUPSIG);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode
|
||||||
|
* TX FIFOs
|
||||||
|
*
|
||||||
|
@@ -2812,6 +2851,23 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)
|
||||||
|
if (using_desc_dma(hsotg)) {
|
||||||
|
hs_ep->target_frame = hsotg->frame_number;
|
||||||
|
dwc2_gadget_incr_frame_num(hs_ep);
|
||||||
|
+
|
||||||
|
+ /* In service interval mode target_frame must
|
||||||
|
+ * be set to last (u)frame of the service interval.
|
||||||
|
+ */
|
||||||
|
+ if (hsotg->params.service_interval) {
|
||||||
|
+ /* Set target_frame to the first (u)frame of
|
||||||
|
+ * the service interval
|
||||||
|
+ */
|
||||||
|
+ hs_ep->target_frame &= ~hs_ep->interval + 1;
|
||||||
|
+
|
||||||
|
+ /* Set target_frame to the last (u)frame of
|
||||||
|
+ * the service interval
|
||||||
|
+ */
|
||||||
|
+ dwc2_gadget_incr_frame_num(hs_ep);
|
||||||
|
+ dwc2_gadget_dec_frame_num_by_one(hs_ep);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
dwc2_gadget_start_isoc_ddma(hs_ep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@@ -3127,6 +3183,7 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
|
||||||
|
hsotg->connected = 0;
|
||||||
|
hsotg->test_mode = 0;
|
||||||
|
|
||||||
|
+ /* all endpoints should be shutdown */
|
||||||
|
for (ep = 0; ep < hsotg->num_of_eps; ep++) {
|
||||||
|
if (hsotg->eps_in[ep])
|
||||||
|
kill_all_requests(hsotg, hsotg->eps_in[ep],
|
||||||
|
@@ -3177,6 +3234,7 @@ static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
|
||||||
|
GINTSTS_PTXFEMP | \
|
||||||
|
GINTSTS_RXFLVL)
|
||||||
|
|
||||||
|
+static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
|
||||||
|
/**
|
||||||
|
* dwc2_hsotg_core_init - issue softreset to the core
|
||||||
|
* @hsotg: The device state
|
||||||
|
@@ -3191,13 +3249,23 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
||||||
|
u32 val;
|
||||||
|
u32 usbcfg;
|
||||||
|
u32 dcfg = 0;
|
||||||
|
+ int ep;
|
||||||
|
|
||||||
|
/* Kill any ep0 requests as controller will be reinitialized */
|
||||||
|
kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
|
||||||
|
|
||||||
|
- if (!is_usb_reset)
|
||||||
|
+ if (!is_usb_reset) {
|
||||||
|
if (dwc2_core_reset(hsotg, true))
|
||||||
|
return;
|
||||||
|
+ } else {
|
||||||
|
+ /* all endpoints should be shutdown */
|
||||||
|
+ for (ep = 1; ep < hsotg->num_of_eps; ep++) {
|
||||||
|
+ if (hsotg->eps_in[ep])
|
||||||
|
+ dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
|
||||||
|
+ if (hsotg->eps_out[ep])
|
||||||
|
+ dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we must now enable ep0 ready for host detection and then
|
||||||
|
@@ -3312,6 +3380,10 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
||||||
|
dwc2_set_bit(hsotg, DIEPMSK, DIEPMSK_BNAININTRMSK);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Enable Service Interval mode if supported */
|
||||||
|
+ if (using_desc_dma(hsotg) && hsotg->params.service_interval)
|
||||||
|
+ dwc2_set_bit(hsotg, DCTL, DCTL_SERVICE_INTERVAL_SUPPORTED);
|
||||||
|
+
|
||||||
|
dwc2_writel(hsotg, 0, DAINTMSK);
|
||||||
|
|
||||||
|
dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
|
||||||
|
@@ -3368,6 +3440,10 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
||||||
|
/* configure the core to support LPM */
|
||||||
|
dwc2_gadget_init_lpm(hsotg);
|
||||||
|
|
||||||
|
+ /* program GREFCLK register if needed */
|
||||||
|
+ if (using_desc_dma(hsotg) && hsotg->params.service_interval)
|
||||||
|
+ dwc2_gadget_program_ref_clk(hsotg);
|
||||||
|
+
|
||||||
|
/* must be at-least 3ms to allow bus to see disconnect */
|
||||||
|
mdelay(3);
|
||||||
|
|
||||||
|
@@ -3676,6 +3752,10 @@ static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
|
||||||
|
if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
|
||||||
|
goto irq_retry;
|
||||||
|
|
||||||
|
+ /* Check WKUP_ALERT interrupt*/
|
||||||
|
+ if (hsotg->params.service_interval)
|
||||||
|
+ dwc2_gadget_wkup_alert_handler(hsotg);
|
||||||
|
+
|
||||||
|
spin_unlock(&hsotg->lock);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
@@ -3990,7 +4070,6 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
|
||||||
|
struct dwc2_hsotg *hsotg = hs_ep->parent;
|
||||||
|
int dir_in = hs_ep->dir_in;
|
||||||
|
int index = hs_ep->index;
|
||||||
|
- unsigned long flags;
|
||||||
|
u32 epctrl_reg;
|
||||||
|
u32 ctrl;
|
||||||
|
|
||||||
|
@@ -4008,8 +4087,6 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
|
||||||
|
|
||||||
|
epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
|
||||||
|
|
||||||
|
- spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
-
|
||||||
|
ctrl = dwc2_readl(hsotg, epctrl_reg);
|
||||||
|
|
||||||
|
if (ctrl & DXEPCTL_EPENA)
|
||||||
|
@@ -4032,10 +4109,22 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
|
||||||
|
hs_ep->fifo_index = 0;
|
||||||
|
hs_ep->fifo_size = 0;
|
||||||
|
|
||||||
|
- spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int dwc2_hsotg_ep_disable_lock(struct usb_ep *ep)
|
||||||
|
+{
|
||||||
|
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
|
||||||
|
+ struct dwc2_hsotg *hsotg = hs_ep->parent;
|
||||||
|
+ unsigned long flags;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
+ ret = dwc2_hsotg_ep_disable(ep);
|
||||||
|
+ spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* on_list - check request is on the given endpoint
|
||||||
|
* @ep: The endpoint to check.
|
||||||
|
@@ -4183,7 +4272,7 @@ static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
|
||||||
|
|
||||||
|
static const struct usb_ep_ops dwc2_hsotg_ep_ops = {
|
||||||
|
.enable = dwc2_hsotg_ep_enable,
|
||||||
|
- .disable = dwc2_hsotg_ep_disable,
|
||||||
|
+ .disable = dwc2_hsotg_ep_disable_lock,
|
||||||
|
.alloc_request = dwc2_hsotg_ep_alloc_request,
|
||||||
|
.free_request = dwc2_hsotg_ep_free_request,
|
||||||
|
.queue = dwc2_hsotg_ep_queue_lock,
|
||||||
|
@@ -4323,9 +4412,9 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
|
||||||
|
/* all endpoints should be shutdown */
|
||||||
|
for (ep = 1; ep < hsotg->num_of_eps; ep++) {
|
||||||
|
if (hsotg->eps_in[ep])
|
||||||
|
- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
|
||||||
|
+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
|
||||||
|
if (hsotg->eps_out[ep])
|
||||||
|
- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
|
||||||
|
+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
@@ -4773,9 +4862,9 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg)
|
||||||
|
|
||||||
|
for (ep = 0; ep < hsotg->num_of_eps; ep++) {
|
||||||
|
if (hsotg->eps_in[ep])
|
||||||
|
- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
|
||||||
|
+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
|
||||||
|
if (hsotg->eps_out[ep])
|
||||||
|
- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
|
||||||
|
+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -4942,8 +5031,32 @@ void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg)
|
||||||
|
val |= hsotg->params.lpm_clock_gating ? GLPMCFG_ENBLSLPM : 0;
|
||||||
|
val |= hsotg->params.hird_threshold << GLPMCFG_HIRD_THRES_SHIFT;
|
||||||
|
val |= hsotg->params.besl ? GLPMCFG_ENBESL : 0;
|
||||||
|
+ val |= GLPMCFG_LPM_ACCEPT_CTRL_ISOC;
|
||||||
|
dwc2_writel(hsotg, val, GLPMCFG);
|
||||||
|
dev_dbg(hsotg->dev, "GLPMCFG=0x%08x\n", dwc2_readl(hsotg, GLPMCFG));
|
||||||
|
+
|
||||||
|
+ /* Unmask WKUP_ALERT Interrupt */
|
||||||
|
+ if (hsotg->params.service_interval)
|
||||||
|
+ dwc2_set_bit(hsotg, GINTMSK2, GINTMSK2_WKUP_ALERT_INT_MSK);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * dwc2_gadget_program_ref_clk - Program GREFCLK register in device mode
|
||||||
|
+ *
|
||||||
|
+ * @hsotg: Programming view of DWC_otg controller
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg)
|
||||||
|
+{
|
||||||
|
+ u32 val = 0;
|
||||||
|
+
|
||||||
|
+ val |= GREFCLK_REF_CLK_MODE;
|
||||||
|
+ val |= hsotg->params.ref_clk_per << GREFCLK_REFCLKPER_SHIFT;
|
||||||
|
+ val |= hsotg->params.sof_cnt_wkup_alert <<
|
||||||
|
+ GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT;
|
||||||
|
+
|
||||||
|
+ dwc2_writel(hsotg, val, GREFCLK);
|
||||||
|
+ dev_dbg(hsotg->dev, "GREFCLK=0x%08x\n", dwc2_readl(hsotg, GREFCLK));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
|
||||||
|
index 12fa6c0..7f128b1 100644
|
||||||
|
--- a/drivers/usb/dwc2/hcd.c
|
||||||
|
+++ b/drivers/usb/dwc2/hcd.c
|
||||||
|
@@ -1309,14 +1309,11 @@ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg,
|
||||||
|
u32 remaining_count;
|
||||||
|
u32 byte_count;
|
||||||
|
u32 dword_count;
|
||||||
|
- u32 __iomem *data_fifo;
|
||||||
|
u32 *data_buf = (u32 *)chan->xfer_buf;
|
||||||
|
|
||||||
|
if (dbg_hc(chan))
|
||||||
|
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||||
|
|
||||||
|
- data_fifo = (u32 __iomem *)(hsotg->regs + HCFIFO(chan->hc_num));
|
||||||
|
-
|
||||||
|
remaining_count = chan->xfer_len - chan->xfer_count;
|
||||||
|
if (remaining_count > chan->max_packet)
|
||||||
|
byte_count = chan->max_packet;
|
||||||
|
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h
|
||||||
|
index 3f9bccc..c089ffa 100644
|
||||||
|
--- a/drivers/usb/dwc2/hcd.h
|
||||||
|
+++ b/drivers/usb/dwc2/hcd.h
|
||||||
|
@@ -366,7 +366,7 @@ struct dwc2_qh {
|
||||||
|
u32 desc_list_sz;
|
||||||
|
u32 *n_bytes;
|
||||||
|
struct timer_list unreserve_timer;
|
||||||
|
- struct timer_list wait_timer;
|
||||||
|
+ struct hrtimer wait_timer;
|
||||||
|
struct dwc2_tt *dwc_tt;
|
||||||
|
int ttport;
|
||||||
|
unsigned tt_buffer_dirty:1;
|
||||||
|
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
|
||||||
|
index 40839591..ea3aa64 100644
|
||||||
|
--- a/drivers/usb/dwc2/hcd_queue.c
|
||||||
|
+++ b/drivers/usb/dwc2/hcd_queue.c
|
||||||
|
@@ -59,7 +59,7 @@
|
||||||
|
#define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5))
|
||||||
|
|
||||||
|
/* If we get a NAK, wait this long before retrying */
|
||||||
|
-#define DWC2_RETRY_WAIT_DELAY (msecs_to_jiffies(1))
|
||||||
|
+#define DWC2_RETRY_WAIT_DELAY 1*1E6L
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dwc2_periodic_channel_available() - Checks that a channel is available for a
|
||||||
|
@@ -1464,10 +1464,12 @@ static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg,
|
||||||
|
* qh back to the "inactive" list, then queues transactions.
|
||||||
|
*
|
||||||
|
* @t: Pointer to wait_timer in a qh.
|
||||||
|
+ *
|
||||||
|
+ * Return: HRTIMER_NORESTART to not automatically restart this timer.
|
||||||
|
*/
|
||||||
|
-static void dwc2_wait_timer_fn(struct timer_list *t)
|
||||||
|
+static enum hrtimer_restart dwc2_wait_timer_fn(struct hrtimer *t)
|
||||||
|
{
|
||||||
|
- struct dwc2_qh *qh = from_timer(qh, t, wait_timer);
|
||||||
|
+ struct dwc2_qh *qh = container_of(t, struct dwc2_qh, wait_timer);
|
||||||
|
struct dwc2_hsotg *hsotg = qh->hsotg;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
@@ -1491,6 +1493,7 @@ static void dwc2_wait_timer_fn(struct timer_list *t)
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||||
|
+ return HRTIMER_NORESTART;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -1521,7 +1524,8 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
|
||||||
|
/* Initialize QH */
|
||||||
|
qh->hsotg = hsotg;
|
||||||
|
timer_setup(&qh->unreserve_timer, dwc2_unreserve_timer_fn, 0);
|
||||||
|
- timer_setup(&qh->wait_timer, dwc2_wait_timer_fn, 0);
|
||||||
|
+ hrtimer_init(&qh->wait_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||||
|
+ qh->wait_timer.function = &dwc2_wait_timer_fn;
|
||||||
|
qh->ep_type = ep_type;
|
||||||
|
qh->ep_is_in = ep_is_in;
|
||||||
|
|
||||||
|
@@ -1690,7 +1694,7 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||||
|
* won't do anything anyway, but we want it to finish before we free
|
||||||
|
* memory.
|
||||||
|
*/
|
||||||
|
- del_timer_sync(&qh->wait_timer);
|
||||||
|
+ hrtimer_cancel(&qh->wait_timer);
|
||||||
|
|
||||||
|
dwc2_host_put_tt_info(hsotg, qh->dwc_tt);
|
||||||
|
|
||||||
|
@@ -1716,6 +1720,7 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
u32 intr_mask;
|
||||||
|
+ ktime_t delay;
|
||||||
|
|
||||||
|
if (dbg_qh(qh))
|
||||||
|
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||||
|
@@ -1734,8 +1739,8 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||||
|
list_add_tail(&qh->qh_list_entry,
|
||||||
|
&hsotg->non_periodic_sched_waiting);
|
||||||
|
qh->wait_timer_cancel = false;
|
||||||
|
- mod_timer(&qh->wait_timer,
|
||||||
|
- jiffies + DWC2_RETRY_WAIT_DELAY + 1);
|
||||||
|
+ delay = ktime_set(0, DWC2_RETRY_WAIT_DELAY);
|
||||||
|
+ hrtimer_start(&qh->wait_timer, delay, HRTIMER_MODE_REL);
|
||||||
|
} else {
|
||||||
|
list_add_tail(&qh->qh_list_entry,
|
||||||
|
&hsotg->non_periodic_sched_inactive);
|
||||||
|
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
|
||||||
|
index 31f8c60..4980ecb 100644
|
||||||
|
--- a/drivers/usb/dwc2/hw.h
|
||||||
|
+++ b/drivers/usb/dwc2/hw.h
|
||||||
|
@@ -316,6 +316,7 @@
|
||||||
|
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14
|
||||||
|
#define GHWCFG4_ACG_SUPPORTED BIT(12)
|
||||||
|
#define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11)
|
||||||
|
+#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED BIT(10)
|
||||||
|
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0
|
||||||
|
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1
|
||||||
|
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2
|
||||||
|
@@ -336,6 +337,8 @@
|
||||||
|
#define GLPMCFG_SNDLPM BIT(24)
|
||||||
|
#define GLPMCFG_RETRY_CNT_MASK (0x7 << 21)
|
||||||
|
#define GLPMCFG_RETRY_CNT_SHIFT 21
|
||||||
|
+#define GLPMCFG_LPM_ACCEPT_CTRL_CONTROL BIT(21)
|
||||||
|
+#define GLPMCFG_LPM_ACCEPT_CTRL_ISOC BIT(22)
|
||||||
|
#define GLPMCFG_LPM_CHNL_INDX_MASK (0xf << 17)
|
||||||
|
#define GLPMCFG_LPM_CHNL_INDX_SHIFT 17
|
||||||
|
#define GLPMCFG_L1RESUMEOK BIT(16)
|
||||||
|
@@ -408,6 +411,19 @@
|
||||||
|
#define ADPCTL_PRB_DSCHRG_MASK (0x3 << 0)
|
||||||
|
#define ADPCTL_PRB_DSCHRG_SHIFT 0
|
||||||
|
|
||||||
|
+#define GREFCLK HSOTG_REG(0x0064)
|
||||||
|
+#define GREFCLK_REFCLKPER_MASK (0x1ffff << 15)
|
||||||
|
+#define GREFCLK_REFCLKPER_SHIFT 15
|
||||||
|
+#define GREFCLK_REF_CLK_MODE BIT(14)
|
||||||
|
+#define GREFCLK_SOF_CNT_WKUP_ALERT_MASK (0x3ff)
|
||||||
|
+#define GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT 0
|
||||||
|
+
|
||||||
|
+#define GINTMSK2 HSOTG_REG(0x0068)
|
||||||
|
+#define GINTMSK2_WKUP_ALERT_INT_MSK BIT(0)
|
||||||
|
+
|
||||||
|
+#define GINTSTS2 HSOTG_REG(0x006c)
|
||||||
|
+#define GINTSTS2_WKUP_ALERT_INT BIT(0)
|
||||||
|
+
|
||||||
|
#define HPTXFSIZ HSOTG_REG(0x100)
|
||||||
|
/* Use FIFOSIZE_* constants to access this register */
|
||||||
|
|
||||||
|
@@ -447,6 +463,7 @@
|
||||||
|
#define DCFG_DEVSPD_FS48 3
|
||||||
|
|
||||||
|
#define DCTL HSOTG_REG(0x804)
|
||||||
|
+#define DCTL_SERVICE_INTERVAL_SUPPORTED BIT(19)
|
||||||
|
#define DCTL_PWRONPRGDONE BIT(11)
|
||||||
|
#define DCTL_CGOUTNAK BIT(10)
|
||||||
|
#define DCTL_SGOUTNAK BIT(9)
|
||||||
|
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
|
||||||
|
index 7fef905..bdcabb1 100644
|
||||||
|
--- a/drivers/usb/dwc2/params.c
|
||||||
|
+++ b/drivers/usb/dwc2/params.c
|
||||||
|
@@ -71,6 +71,13 @@ static void dwc2_set_his_params(struct dwc2_hsotg *hsotg)
|
||||||
|
p->power_down = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void dwc2_set_s3c6400_params(struct dwc2_hsotg *hsotg)
|
||||||
|
+{
|
||||||
|
+ struct dwc2_core_params *p = &hsotg->params;
|
||||||
|
+
|
||||||
|
+ p->power_down = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg)
|
||||||
|
{
|
||||||
|
struct dwc2_core_params *p = &hsotg->params;
|
||||||
|
@@ -81,6 +88,7 @@ static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg)
|
||||||
|
p->host_perio_tx_fifo_size = 256;
|
||||||
|
p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
|
||||||
|
GAHBCFG_HBSTLEN_SHIFT;
|
||||||
|
+ p->power_down = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg)
|
||||||
|
@@ -110,6 +118,7 @@ static void dwc2_set_amlogic_params(struct dwc2_hsotg *hsotg)
|
||||||
|
p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI;
|
||||||
|
p->ahbcfg = GAHBCFG_HBSTLEN_INCR8 <<
|
||||||
|
GAHBCFG_HBSTLEN_SHIFT;
|
||||||
|
+ p->power_down = DWC2_POWER_DOWN_PARAM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg)
|
||||||
|
@@ -177,7 +186,8 @@ const struct of_device_id dwc2_of_match_table[] = {
|
||||||
|
{ .compatible = "lantiq,arx100-usb", .data = dwc2_set_ltq_params },
|
||||||
|
{ .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params },
|
||||||
|
{ .compatible = "snps,dwc2" },
|
||||||
|
- { .compatible = "samsung,s3c6400-hsotg" },
|
||||||
|
+ { .compatible = "samsung,s3c6400-hsotg",
|
||||||
|
+ .data = dwc2_set_s3c6400_params },
|
||||||
|
{ .compatible = "amlogic,meson8-usb",
|
||||||
|
.data = dwc2_set_amlogic_params },
|
||||||
|
{ .compatible = "amlogic,meson8b-usb",
|
||||||
|
@@ -330,9 +340,12 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg)
|
||||||
|
p->hird_threshold_en = true;
|
||||||
|
p->hird_threshold = 4;
|
||||||
|
p->ipg_isoc_en = false;
|
||||||
|
+ p->service_interval = false;
|
||||||
|
p->max_packet_count = hw->max_packet_count;
|
||||||
|
p->max_transfer_size = hw->max_transfer_size;
|
||||||
|
p->ahbcfg = GAHBCFG_HBSTLEN_INCR << GAHBCFG_HBSTLEN_SHIFT;
|
||||||
|
+ p->ref_clk_per = 33333;
|
||||||
|
+ p->sof_cnt_wkup_alert = 100;
|
||||||
|
|
||||||
|
if ((hsotg->dr_mode == USB_DR_MODE_HOST) ||
|
||||||
|
(hsotg->dr_mode == USB_DR_MODE_OTG)) {
|
||||||
|
@@ -628,6 +641,7 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg)
|
||||||
|
CHECK_BOOL(besl, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a));
|
||||||
|
CHECK_BOOL(hird_threshold_en, hsotg->params.lpm);
|
||||||
|
CHECK_RANGE(hird_threshold, 0, hsotg->params.besl ? 12 : 7, 0);
|
||||||
|
+ CHECK_BOOL(service_interval, hw->service_interval_mode);
|
||||||
|
CHECK_RANGE(max_packet_count,
|
||||||
|
15, hw->max_packet_count,
|
||||||
|
hw->max_packet_count);
|
||||||
|
@@ -816,6 +830,8 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
||||||
|
GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT;
|
||||||
|
hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED);
|
||||||
|
hw->ipg_isoc_en = !!(hwcfg4 & GHWCFG4_IPG_ISOC_SUPPORTED);
|
||||||
|
+ hw->service_interval_mode = !!(hwcfg4 &
|
||||||
|
+ GHWCFG4_SERVICE_INTERVAL_SUPPORTED);
|
||||||
|
|
||||||
|
/* fifo sizes */
|
||||||
|
hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >>
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
From 56b9c52ec61df693bd997e3ef1465230a6cb1834 Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Thu, 24 Jan 2019 10:52:11 +0100
|
||||||
|
Subject: [PATCH 60/60] ARM stm32mp1 r0 rc4 hotfix w904.3 DEVICETREE
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 43 +++++++++++++++++++++++++++++++
|
||||||
|
arch/arm/boot/dts/stm32mp157a-dk1.dts | 2 +-
|
||||||
|
arch/arm/boot/dts/stm32mp157c-dk2.dts | 4 +--
|
||||||
|
arch/arm/boot/dts/stm32mp157c-ed1.dts | 2 +-
|
||||||
|
arch/arm/boot/dts/stm32mp157c.dtsi | 22 +++++++---------
|
||||||
|
5 files changed, 57 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||||
|
index 474e7e3..6e4e5c9 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||||
|
@@ -1249,6 +1249,49 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ sdmmc2_b4_pins_b: sdmmc2-b4-1 {
|
||||||
|
+ pins1 {
|
||||||
|
+ pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
|
||||||
|
+ <STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
|
||||||
|
+ <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
|
||||||
|
+ <STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
|
||||||
|
+ <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
|
||||||
|
+ slew-rate = <1>;
|
||||||
|
+ drive-push-pull;
|
||||||
|
+ bias-disable;
|
||||||
|
+ };
|
||||||
|
+ pins2 {
|
||||||
|
+ pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
|
||||||
|
+ slew-rate = <2>;
|
||||||
|
+ drive-push-pull;
|
||||||
|
+ bias-disable;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 {
|
||||||
|
+ pins1 {
|
||||||
|
+ pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
|
||||||
|
+ <STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
|
||||||
|
+ <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
|
||||||
|
+ <STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
|
||||||
|
+ slew-rate = <1>;
|
||||||
|
+ drive-push-pull;
|
||||||
|
+ bias-disable;
|
||||||
|
+ };
|
||||||
|
+ pins2 {
|
||||||
|
+ pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
|
||||||
|
+ slew-rate = <2>;
|
||||||
|
+ drive-push-pull;
|
||||||
|
+ bias-disable;
|
||||||
|
+ };
|
||||||
|
+ pins3 {
|
||||||
|
+ pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
|
||||||
|
+ slew-rate = <1>;
|
||||||
|
+ drive-open-drain;
|
||||||
|
+ bias-disable;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
sdmmc2_d47_pins_a: sdmmc2-d47-0 {
|
||||||
|
pins {
|
||||||
|
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
index 467c226..e3a36d3 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||||
|
@@ -325,7 +325,7 @@
|
||||||
|
|
||||||
|
vddcore: buck1 {
|
||||||
|
regulator-name = "vddcore";
|
||||||
|
- regulator-min-microvolt = <800000>;
|
||||||
|
+ regulator-min-microvolt = <1200000>;
|
||||||
|
regulator-max-microvolt = <1350000>;
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-initial-mode = <0>;
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||||
|
index 4da15cd..20a86f1 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||||
|
@@ -108,8 +108,8 @@
|
||||||
|
&sdmmc2 {
|
||||||
|
arm,primecell-periphid = <0x10153180>;
|
||||||
|
pinctrl-names = "default", "opendrain", "sleep";
|
||||||
|
- pinctrl-0 = <&sdmmc2_b4_pins_a>;
|
||||||
|
- pinctrl-1 = <&sdmmc2_b4_od_pins_a>;
|
||||||
|
+ pinctrl-0 = <&sdmmc2_b4_pins_b>;
|
||||||
|
+ pinctrl-1 = <&sdmmc2_b4_od_pins_b>;
|
||||||
|
pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>;
|
||||||
|
non-removable;
|
||||||
|
st,neg-edge;
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||||
|
index 6d49f21..780c992 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||||
|
@@ -203,7 +203,7 @@
|
||||||
|
|
||||||
|
vddcore: buck1 {
|
||||||
|
regulator-name = "vddcore";
|
||||||
|
- regulator-min-microvolt = <800000>;
|
||||||
|
+ regulator-min-microvolt = <1200000>;
|
||||||
|
regulator-max-microvolt = <1350000>;
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-initial-mode = <0>;
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
index b09ef8b..694e6e0 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
@@ -430,8 +430,8 @@
|
||||||
|
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&rcc SPI2_K>;
|
||||||
|
resets = <&rcc SPI2_R>;
|
||||||
|
- dmas = <&dmamux1 39 0x400 0x05>,
|
||||||
|
- <&dmamux1 40 0x400 0x05>;
|
||||||
|
+ dmas = <&dmamux1 39 0x400 0x01>,
|
||||||
|
+ <&dmamux1 40 0x400 0x01>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
|
power-domains = <&pd_core>;
|
||||||
|
status = "disabled";
|
||||||
|
@@ -456,8 +456,8 @@
|
||||||
|
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&rcc SPI3_K>;
|
||||||
|
resets = <&rcc SPI3_R>;
|
||||||
|
- dmas = <&dmamux1 61 0x400 0x05>,
|
||||||
|
- <&dmamux1 62 0x400 0x05>;
|
||||||
|
+ dmas = <&dmamux1 61 0x400 0x01>,
|
||||||
|
+ <&dmamux1 62 0x400 0x01>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
|
power-domains = <&pd_core>;
|
||||||
|
status = "disabled";
|
||||||
|
@@ -756,8 +756,8 @@
|
||||||
|
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&rcc SPI1_K>;
|
||||||
|
resets = <&rcc SPI1_R>;
|
||||||
|
- dmas = <&dmamux1 37 0x400 0x05>,
|
||||||
|
- <&dmamux1 38 0x400 0x05>;
|
||||||
|
+ dmas = <&dmamux1 37 0x400 0x01>,
|
||||||
|
+ <&dmamux1 38 0x400 0x01>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
|
power-domains = <&pd_core>;
|
||||||
|
status = "disabled";
|
||||||
|
@@ -782,8 +782,8 @@
|
||||||
|
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&rcc SPI4_K>;
|
||||||
|
resets = <&rcc SPI4_R>;
|
||||||
|
- dmas = <&dmamux1 83 0x400 0x05>,
|
||||||
|
- <&dmamux1 84 0x400 0x05>;
|
||||||
|
+ dmas = <&dmamux1 83 0x400 0x01>,
|
||||||
|
+ <&dmamux1 84 0x400 0x01>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
|
power-domains = <&pd_core>;
|
||||||
|
status = "disabled";
|
||||||
|
@@ -870,8 +870,8 @@
|
||||||
|
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&rcc SPI5_K>;
|
||||||
|
resets = <&rcc SPI5_R>;
|
||||||
|
- dmas = <&dmamux1 85 0x400 0x05>,
|
||||||
|
- <&dmamux1 86 0x400 0x05>;
|
||||||
|
+ dmas = <&dmamux1 85 0x400 0x01>,
|
||||||
|
+ <&dmamux1 86 0x400 0x01>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
|
power-domains = <&pd_core>;
|
||||||
|
status = "disabled";
|
||||||
|
@@ -1770,7 +1770,6 @@
|
||||||
|
clocks = <&rcc USBH>;
|
||||||
|
resets = <&rcc USBH_R>;
|
||||||
|
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
- power-domains = <&pd_core>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1781,7 +1780,6 @@
|
||||||
|
resets = <&rcc USBH_R>;
|
||||||
|
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
companion = <&usbh_ohci>;
|
||||||
|
- power-domains = <&pd_core>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
From 5f558583046192d07b1718d6db15cef522fa0bce Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Mon, 28 Jan 2019 10:49:20 +0100
|
||||||
|
Subject: [PATCH 61/62] ARM stm32mp1 r0 rc4 hotfix w904.5 DRIVERS
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c | 38 ++++++++++++++----------
|
||||||
|
drivers/usb/dwc2/platform.c | 13 ++++++--
|
||||||
|
2 files changed, 33 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||||
|
index ee7486b..78a7e62 100644
|
||||||
|
--- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||||
|
+++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||||
|
@@ -284,7 +284,9 @@ static int otm8009a_unprepare(struct drm_panel *panel)
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
- msleep(120);
|
||||||
|
+ msleep(10);
|
||||||
|
+
|
||||||
|
+ regulator_disable(ctx->supply);
|
||||||
|
|
||||||
|
ctx->prepared = false;
|
||||||
|
|
||||||
|
@@ -299,6 +301,26 @@ static int otm8009a_prepare(struct drm_panel *panel)
|
||||||
|
if (ctx->prepared)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
+ if (ctx->reset_gpio) {
|
||||||
|
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||||
|
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ msleep(20);
|
||||||
|
+
|
||||||
|
+ ret = regulator_enable(ctx->supply);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ DRM_ERROR("failed to enable supply: %d\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ msleep(120);
|
||||||
|
+
|
||||||
|
+ if (ctx->reset_gpio) {
|
||||||
|
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||||
|
+ msleep(20);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = otm8009a_init_sequence(ctx);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
@@ -456,20 +478,6 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = regulator_enable(ctx->supply);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- DRM_ERROR("failed to enable supply: %d\n", ret);
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (ctx->reset_gpio) {
|
||||||
|
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||||
|
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||||
|
- msleep(20);
|
||||||
|
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||||
|
- msleep(100);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
|
||||||
|
index b2e5ddc..b80d046 100644
|
||||||
|
--- a/drivers/usb/dwc2/platform.c
|
||||||
|
+++ b/drivers/usb/dwc2/platform.c
|
||||||
|
@@ -568,13 +568,17 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||||
|
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
- if (dwc2_is_device_mode(dwc2))
|
||||||
|
- dwc2_hsotg_suspend(dwc2);
|
||||||
|
-
|
||||||
|
if (dwc2->params.activate_stm_id_vb_detection &&
|
||||||
|
!dwc2->params.force_b_session_valid) {
|
||||||
|
u32 ggpio;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Need to force the mode to the current mode to avoid Mode
|
||||||
|
+ * Mismatch Interrupt when ID and VBUS detection will be
|
||||||
|
+ * disabled
|
||||||
|
+ */
|
||||||
|
+ dwc2_force_mode(dwc2, dwc2_is_host_mode(dwc2));
|
||||||
|
+
|
||||||
|
ggpio = dwc2_readl(dwc2, GGPIO);
|
||||||
|
ggpio &= ~GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||||
|
ggpio &= ~GGPIO_STM32_OTG_GCCFG_VBDEN;
|
||||||
|
@@ -583,6 +587,9 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||||
|
regulator_disable(dwc2->usb33d);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (dwc2_is_device_mode(dwc2))
|
||||||
|
+ dwc2_hsotg_suspend(dwc2);
|
||||||
|
+
|
||||||
|
if (dwc2->ll_hw_enabled)
|
||||||
|
ret = __dwc2_lowlevel_hw_disable(dwc2);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
From 771fc61468f4af9f733beb9dbe070033ea2b826a Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Mon, 28 Jan 2019 10:49:58 +0100
|
||||||
|
Subject: [PATCH 62/62] ARM stm32mp1 r0 rc4 hotfix w904.5 DEVICETREE
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/stm32mp157c.dtsi | 1 -
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
index 694e6e0..9647119 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
@@ -1233,7 +1233,6 @@
|
||||||
|
g-tx-fifo-size = <128 128 64 64 64 64 32 32>;
|
||||||
|
dr_mode = "otg";
|
||||||
|
usb33d-supply = <&usb33>;
|
||||||
|
- power-domains = <&pd_core>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
From 67b204258838dd2c940d5b1508318b4890324a06 Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Tue, 29 Jan 2019 17:31:19 +0100
|
||||||
|
Subject: [PATCH 63/64] ARM stm32mp1 r0 rc4 hotfix w905.2 DRIVERS
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/dma/stm32-dma.c | 70 ++++++++++++++++++++++++++++++++++++---------
|
||||||
|
drivers/usb/dwc2/platform.c | 38 ++++++++++++++++++------
|
||||||
|
2 files changed, 87 insertions(+), 21 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
|
||||||
|
index 5abfa4f..dc3ba91 100644
|
||||||
|
--- a/drivers/dma/stm32-dma.c
|
||||||
|
+++ b/drivers/dma/stm32-dma.c
|
||||||
|
@@ -1675,37 +1675,81 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
|
||||||
|
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool stm32_dma_is_current_sg(struct stm32_dma_chan *chan)
|
||||||
|
+{
|
||||||
|
+ struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
|
||||||
|
+ struct stm32_dma_sg_req *sg_req;
|
||||||
|
+ u32 dma_scr, dma_smar, id;
|
||||||
|
+
|
||||||
|
+ id = chan->id;
|
||||||
|
+ dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id));
|
||||||
|
+
|
||||||
|
+ if (!(dma_scr & STM32_DMA_SCR_DBM))
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ sg_req = &chan->desc->sg_req[chan->next_sg];
|
||||||
|
+
|
||||||
|
+ if (dma_scr & STM32_DMA_SCR_CT) {
|
||||||
|
+ dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM0AR(id));
|
||||||
|
+ return (dma_smar == sg_req->chan_reg.dma_sm0ar);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(id));
|
||||||
|
+
|
||||||
|
+ return (dma_smar == sg_req->chan_reg.dma_sm1ar);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
|
||||||
|
struct stm32_dma_desc *desc,
|
||||||
|
u32 next_sg)
|
||||||
|
{
|
||||||
|
u32 modulo, burst_size;
|
||||||
|
- u32 residue = 0;
|
||||||
|
+ u32 residue;
|
||||||
|
+ u32 n_sg = next_sg;
|
||||||
|
+ struct stm32_dma_sg_req *sg_req = &chan->desc->sg_req[chan->next_sg];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Drain case */
|
||||||
|
if (chan->residue_after_drain)
|
||||||
|
return chan->residue_after_drain;
|
||||||
|
|
||||||
|
+ residue = stm32_dma_get_remaining_bytes(chan);
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
- * In cyclic mode, for the last period, residue = remaining bytes from
|
||||||
|
- * NDTR
|
||||||
|
+ * Calculate the residue means compute the descriptors
|
||||||
|
+ * information:
|
||||||
|
+ * - the sg currently transferred
|
||||||
|
+ * - the remaining position in this sg (NDTR).
|
||||||
|
+ *
|
||||||
|
+ * The issue is that a race condition can occur if DMA is
|
||||||
|
+ * running. DMA can have started to transfer the next sg before
|
||||||
|
+ * the position in sg is read. In this case the remaing position
|
||||||
|
+ * can correspond to the new sg position.
|
||||||
|
+ * The strategy implemented in the stm32 driver is to check the
|
||||||
|
+ * sg transition. If detected we can not trust the SxNDTR register value
|
||||||
|
+ * this register can not be up to date during the transition.
|
||||||
|
+ * in this case we can assume that the dma is at the beginning of next
|
||||||
|
+ * sg so we calculate the residue in consequence.
|
||||||
|
*/
|
||||||
|
- if (chan->desc->cyclic && next_sg == 0) {
|
||||||
|
- residue = stm32_dma_get_remaining_bytes(chan);
|
||||||
|
- goto end;
|
||||||
|
+
|
||||||
|
+ if (!stm32_dma_is_current_sg(chan)) {
|
||||||
|
+ n_sg++;
|
||||||
|
+ if (n_sg == chan->desc->num_sgs)
|
||||||
|
+ n_sg = 0;
|
||||||
|
+ residue = sg_dma_len(&sg_req->stm32_sgl_req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * For all other periods in cyclic mode, and in sg mode,
|
||||||
|
- * residue = remaining bytes from NDTR + remaining periods/sg to be
|
||||||
|
- * transferred
|
||||||
|
+ * In cyclic mode, for the last period, residue = remaining bytes
|
||||||
|
+ * from NDTR
|
||||||
|
+ * else for all other periods in cyclic mode, and in sg mode,
|
||||||
|
+ * residue = remaining bytes from NDTR + remaining
|
||||||
|
+ * periods/sg to be transferred
|
||||||
|
*/
|
||||||
|
- for (i = next_sg; i < desc->num_sgs; i++)
|
||||||
|
- residue += sg_dma_len(&desc->sg_req[i].stm32_sgl_req);
|
||||||
|
- residue += stm32_dma_get_remaining_bytes(chan);
|
||||||
|
+ if (!chan->desc->cyclic || n_sg != 0)
|
||||||
|
+ for (i = n_sg; i < desc->num_sgs; i++)
|
||||||
|
+ residue += sg_dma_len(&desc->sg_req[i].stm32_sgl_req);
|
||||||
|
|
||||||
|
-end:
|
||||||
|
if (!chan->mem_burst)
|
||||||
|
return residue;
|
||||||
|
|
||||||
|
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
|
||||||
|
index b80d046..7e6960c 100644
|
||||||
|
--- a/drivers/usb/dwc2/platform.c
|
||||||
|
+++ b/drivers/usb/dwc2/platform.c
|
||||||
|
@@ -568,16 +568,35 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||||
|
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
+ if (dwc2_is_device_mode(dwc2))
|
||||||
|
+ dwc2_hsotg_suspend(dwc2);
|
||||||
|
+
|
||||||
|
if (dwc2->params.activate_stm_id_vb_detection &&
|
||||||
|
!dwc2->params.force_b_session_valid) {
|
||||||
|
- u32 ggpio;
|
||||||
|
+ u32 ggpio, gotgctl;
|
||||||
|
+ int is_host = dwc2_is_host_mode(dwc2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to force the mode to the current mode to avoid Mode
|
||||||
|
- * Mismatch Interrupt when ID and VBUS detection will be
|
||||||
|
- * disabled
|
||||||
|
+ * Mismatch Interrupt when ID detection will be disabled.
|
||||||
|
*/
|
||||||
|
- dwc2_force_mode(dwc2, dwc2_is_host_mode(dwc2));
|
||||||
|
+ dwc2_force_mode(dwc2, is_host);
|
||||||
|
+
|
||||||
|
+ if (!is_host) {
|
||||||
|
+ gotgctl = dwc2_readl(dwc2, GOTGCTL);
|
||||||
|
+ /*
|
||||||
|
+ * We're about to disable Vbus detection hw before low
|
||||||
|
+ * power mode entry. Then an undesired disconnect
|
||||||
|
+ * interrupt may occur which is racy with low power
|
||||||
|
+ * (low-level hw disable). Then check valid session
|
||||||
|
+ * to force B-peripheral session value.
|
||||||
|
+ */
|
||||||
|
+ if (gotgctl & GOTGCTL_BSESVLD) {
|
||||||
|
+ gotgctl |= GOTGCTL_BVALOVAL;
|
||||||
|
+ gotgctl |= GOTGCTL_BVALOEN;
|
||||||
|
+ dwc2_writel(dwc2, gotgctl, GOTGCTL);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
ggpio = dwc2_readl(dwc2, GGPIO);
|
||||||
|
ggpio &= ~GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||||
|
@@ -587,9 +606,6 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||||
|
regulator_disable(dwc2->usb33d);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (dwc2_is_device_mode(dwc2))
|
||||||
|
- dwc2_hsotg_suspend(dwc2);
|
||||||
|
-
|
||||||
|
if (dwc2->ll_hw_enabled)
|
||||||
|
ret = __dwc2_lowlevel_hw_disable(dwc2);
|
||||||
|
|
||||||
|
@@ -612,7 +628,7 @@ static int __maybe_unused dwc2_resume(struct device *dev)
|
||||||
|
|
||||||
|
if (dwc2->params.activate_stm_id_vb_detection &&
|
||||||
|
!dwc2->params.force_b_session_valid) {
|
||||||
|
- u32 ggpio;
|
||||||
|
+ u32 ggpio, gotgctl;
|
||||||
|
|
||||||
|
ret = regulator_enable(dwc2->usb33d);
|
||||||
|
if (ret)
|
||||||
|
@@ -625,6 +641,12 @@ static int __maybe_unused dwc2_resume(struct device *dev)
|
||||||
|
|
||||||
|
/* ID/VBUS detection startup time */
|
||||||
|
usleep_range(5000, 7000);
|
||||||
|
+
|
||||||
|
+ /* Unconditionally clear B-Session Valid override */
|
||||||
|
+ gotgctl = dwc2_readl(dwc2, GOTGCTL);
|
||||||
|
+ gotgctl &= ~GOTGCTL_BVALOVAL;
|
||||||
|
+ gotgctl &= ~GOTGCTL_BVALOEN;
|
||||||
|
+ dwc2_writel(dwc2, gotgctl, GOTGCTL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwc2->params.force_b_session_valid) {
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
From cad13a8b78d8d320394dbed545df8e47c199bbd1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: christophe montaud <christophe.montaud@st.com>
|
||||||
|
Date: Tue, 29 Jan 2019 17:31:53 +0100
|
||||||
|
Subject: [PATCH 64/64] ARM stm32mp1 r0 rc4 hotfix w905.2 DEVICETREE
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/stm32mp157c.dtsi | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
index 9647119..5581a1c 100644
|
||||||
|
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||||
|
@@ -58,6 +58,7 @@
|
||||||
|
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||||
|
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
|
||||||
|
interrupt-parent = <&intc>;
|
||||||
|
+ always-on;
|
||||||
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
|
|
@ -0,0 +1,389 @@
|
||||||
|
#
|
||||||
|
# systemd specific
|
||||||
|
#
|
||||||
|
CONFIG_TASKSTATS=y
|
||||||
|
CONFIG_TASK_DELAY_ACCT=y
|
||||||
|
CONFIG_TASK_XACCT=y
|
||||||
|
CONFIG_TASK_IO_ACCOUNTING=y
|
||||||
|
# CONFIG_CGROUP_DEBUG is not set
|
||||||
|
CONFIG_CGROUP_FREEZER=y
|
||||||
|
CONFIG_CGROUP_DEVICE=y
|
||||||
|
CONFIG_CPUSETS=y
|
||||||
|
CONFIG_CGROUP_CPUACCT=y
|
||||||
|
CONFIG_CGROUP_SCHED=y
|
||||||
|
CONFIG_BLK_CGROUP=y
|
||||||
|
CONFIG_AUTOFS4_FS=y
|
||||||
|
CONFIG_SYSV_FS=y
|
||||||
|
# CONFIG_SYSFS_DEPRECATED is not set
|
||||||
|
# CONFIG_SYSFS_DEPRECATED_V2 is not set
|
||||||
|
CONFIG_HOTPLUG=y
|
||||||
|
CONFIG_UEVENT_HELPER_PATH=""
|
||||||
|
CONFIG_UNIX=y
|
||||||
|
CONFIG_SYSFS=y
|
||||||
|
CONFIG_PROC_FS=y
|
||||||
|
CONFIG_TMPFS=y
|
||||||
|
CONFIG_INOTIFY_USER=y
|
||||||
|
CONFIG_SIGNALFD=y
|
||||||
|
CONFIG_TMPFS_POSIX_ACL=y
|
||||||
|
CONFIG_BLK_DEV_BSG=y
|
||||||
|
CONFIG_DEVTMPFS=y
|
||||||
|
CONFIG_DEVTMPFS_MOUNT=y
|
||||||
|
CONFIG_CGROUPS=y
|
||||||
|
CONFIG_CGROUP_NS=y
|
||||||
|
CONFIG_PROC_PID_CPUSET=y
|
||||||
|
CONFIG_RESOURCE_COUNTERS=y
|
||||||
|
CONFIG_FUSE_FS=y
|
||||||
|
CONFIG_TIMERFD=y
|
||||||
|
CONFIG_EPOLL=y
|
||||||
|
CONFIG_NET=y
|
||||||
|
CONFIG_FHANDLE=y
|
||||||
|
CONFIG_CRYPTO_USER_API_HASH=y
|
||||||
|
CONFIG_CRYPTO_HMAC=y
|
||||||
|
CONFIG_CRYPTO_SHA256=y
|
||||||
|
# CONFIG_FW_LOADER_USER_HELPER is not set
|
||||||
|
CONFIG_DMIID=y
|
||||||
|
CONFIG_NET_NS=y
|
||||||
|
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
|
||||||
|
CONFIG_USER_NS=y
|
||||||
|
CONFIG_IPV6=y
|
||||||
|
CONFIG_TMPFS_XATTR=y
|
||||||
|
CONFIG_TMPFS_POSIX_ACL=y
|
||||||
|
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||||
|
CONFIG_XFS_POSIX_ACL=y
|
||||||
|
CONFIG_BTRFS_FS_POSIX_ACL=y
|
||||||
|
CONFIG_CHECKPOINT_RESTORE=y
|
||||||
|
CONFIG_CGROUP_SCHED=y
|
||||||
|
CONFIG_FAIR_GROUP_SCHED=y
|
||||||
|
CONFIG_SECCOMP=y
|
||||||
|
CONFIG_CFS_BANDWIDTH=y
|
||||||
|
CONFIG_CGROUP_BPF=y
|
||||||
|
# CONFIG_RT_GROUP_SCHED is not set
|
||||||
|
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
|
||||||
|
# CONFIG_AUDIT is not set
|
||||||
|
CONFIG_BPF_SYSCALL=y
|
||||||
|
|
||||||
|
# -------------------------------------------
|
||||||
|
# IP Table
|
||||||
|
# -------------------------------------------
|
||||||
|
CONFIG_UNIX_DIAG=m
|
||||||
|
CONFIG_TLS=m
|
||||||
|
CONFIG_IP_MULTICAST=y
|
||||||
|
CONFIG_IP_ADVANCED_ROUTER=y
|
||||||
|
CONFIG_IP_FIB_TRIE_STATS=y
|
||||||
|
CONFIG_IP_MULTIPLE_TABLES=y
|
||||||
|
CONFIG_IP_ROUTE_MULTIPATH=y
|
||||||
|
CONFIG_IP_ROUTE_VERBOSE=y
|
||||||
|
CONFIG_NET_IPIP=m
|
||||||
|
CONFIG_NET_IPGRE_DEMUX=m
|
||||||
|
CONFIG_NET_IPGRE=m
|
||||||
|
CONFIG_NET_IPGRE_BROADCAST=y
|
||||||
|
CONFIG_IP_MROUTE=y
|
||||||
|
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
|
||||||
|
CONFIG_IP_PIMSM_V1=y
|
||||||
|
CONFIG_IP_PIMSM_V2=y
|
||||||
|
CONFIG_NET_IPVTI=m
|
||||||
|
CONFIG_NET_FOU_IP_TUNNELS=y
|
||||||
|
CONFIG_INET_AH=m
|
||||||
|
CONFIG_INET_ESP=m
|
||||||
|
CONFIG_INET_ESP_OFFLOAD=m
|
||||||
|
CONFIG_INET_IPCOMP=m
|
||||||
|
CONFIG_INET_XFRM_MODE_TRANSPORT=m
|
||||||
|
CONFIG_INET_XFRM_MODE_TUNNEL=m
|
||||||
|
CONFIG_INET_XFRM_MODE_BEET=m
|
||||||
|
CONFIG_INET_DIAG=m
|
||||||
|
CONFIG_INET_UDP_DIAG=m
|
||||||
|
CONFIG_INET_RAW_DIAG=mCONFIG_BPF_SYSCALL=y
|
||||||
|
CONFIG_INET_DIAG_DESTROY=y
|
||||||
|
CONFIG_TCP_CONG_ADVANCED=y
|
||||||
|
CONFIG_TCP_MD5SIG=y
|
||||||
|
CONFIG_IPV6=m
|
||||||
|
CONFIG_IPV6_ROUTE_INFO=y
|
||||||
|
CONFIG_INET6_ESP_OFFLOAD=m
|
||||||
|
CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
|
||||||
|
CONFIG_IPV6_VTI=m
|
||||||
|
CONFIG_IPV6_SIT_6RD=y
|
||||||
|
CONFIG_IPV6_GRE=m
|
||||||
|
CONFIG_IPV6_SUBTREES=y
|
||||||
|
CONFIG_IPV6_MROUTE=y
|
||||||
|
CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
|
||||||
|
CONFIG_IPV6_PIMSM_V2=y
|
||||||
|
CONFIG_IPV6_SEG6_LWTUNNEL=y
|
||||||
|
CONFIG_IPV6_SEG6_HMAC=y
|
||||||
|
CONFIG_NETWORK_SECMARK=y
|
||||||
|
CONFIG_NETWORK_PHY_TIMESTAMPING=y
|
||||||
|
CONFIG_NETFILTER=y
|
||||||
|
CONFIG_NF_CONNTRACK=m
|
||||||
|
CONFIG_NF_LOG_NETDEV=m
|
||||||
|
CONFIG_NF_CONNTRACK_SECMARK=y
|
||||||
|
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||||
|
CONFIG_NF_CONNTRACK_TIMEOUT=y
|
||||||
|
CONFIG_NF_CONNTRACK_TIMESTAMP=y
|
||||||
|
CONFIG_NF_CONNTRACK_AMANDA=m
|
||||||
|
CONFIG_NF_CONNTRACK_FTP=m
|
||||||
|
CONFIG_NF_CONNTRACK_H323=m
|
||||||
|
CONFIG_NF_CONNTRACK_IRC=m
|
||||||
|
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
|
||||||
|
CONFIG_NF_CONNTRACK_SNMP=m
|
||||||
|
CONFIG_NF_CONNTRACK_PPTP=m
|
||||||
|
CONFIG_NF_CONNTRACK_SIP=m
|
||||||
|
CONFIG_NF_CONNTRACK_TFTP=m
|
||||||
|
CONFIG_NF_CT_NETLINK=mCONFIG_BPF_SYSCALL=y
|
||||||
|
CONFIG_NF_CT_NETLINK_TIMEOUT=m
|
||||||
|
CONFIG_NF_CT_NETLINK_HELPER=m
|
||||||
|
CONFIG_NETFILTER_NETLINK_GLUE_CT=y
|
||||||
|
CONFIG_NF_TABLES=m
|
||||||
|
CONFIG_NF_TABLES_INET=m
|
||||||
|
CONFIG_NF_TABLES_NETDEV=m
|
||||||
|
CONFIG_NFT_EXTHDR=m
|
||||||
|
CONFIG_NFT_META=m
|
||||||
|
CONFIG_NFT_RT=m
|
||||||
|
CONFIG_NFT_NUMGEN=m
|
||||||
|
CONFIG_NFT_CT=m
|
||||||
|
CONFIG_NFT_SET_RBTREE=m
|
||||||
|
CONFIG_NFT_SET_HASH=m
|
||||||
|
CONFIG_NFT_SET_BITMAP=m
|
||||||
|
CONFIG_NFT_COUNTER=m
|
||||||
|
CONFIG_NFT_LOG=m
|
||||||
|
CONFIG_NFT_LIMIT=m
|
||||||
|
CONFIG_NFT_MASQ=m
|
||||||
|
CONFIG_NFT_REDIR=m
|
||||||
|
CONFIG_NFT_NAT=m
|
||||||
|
CONFIG_NFT_OBJREF=m
|
||||||
|
CONFIG_NFT_QUEUE=m
|
||||||
|
CONFIG_NFT_QUOTA=m
|
||||||
|
CONFIG_NFT_REJECT=m
|
||||||
|
CONFIG_NFT_HASH=m
|
||||||
|
CONFIG_NFT_DUP_NETDEV=m
|
||||||
|
CONFIG_NFT_FWD_NETDEV=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_HMARK=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_LED=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_LOG=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_TEE=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||||
|
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_BPF=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_CPU=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_DCCP=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_DSCP=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_ESP=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_HELPER=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_MAC=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_MARK=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_NFACCT=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_OSF=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_OWNER=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_POLICY=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_REALM=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_RECENT=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_SCTP=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_STATE=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_STRING=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_TIME=m
|
||||||
|
CONFIG_NETFILTER_XT_MATCH_U32=m
|
||||||
|
CONFIG_IP_SET=m
|
||||||
|
CONFIG_IP_VS=m
|
||||||
|
CONFIG_NF_CONNTRACK_IPV4=m
|
||||||
|
CONFIG_NF_SOCKET_IPV4=m
|
||||||
|
CONFIG_NFT_CHAIN_ROUTE_IPV4=m
|
||||||
|
CONFIG_NFT_DUP_IPV4=m
|
||||||
|
CONFIG_NFT_FIB_IPV4=m
|
||||||
|
CONFIG_NF_TABLES_ARP=m
|
||||||
|
CONFIG_NF_LOG_ARP=m
|
||||||
|
CONFIG_NFT_CHAIN_NAT_IPV4=m
|
||||||
|
CONFIG_NFT_MASQ_IPV4=m
|
||||||
|
CONFIG_NFT_REDIR_IPV4=m
|
||||||
|
CONFIG_IP_NF_IPTABLES=m
|
||||||
|
CONFIG_IP_NF_MATCH_AH=m
|
||||||
|
CONFIG_IP_NF_MATCH_ECN=m
|
||||||
|
CONFIG_IP_NF_MATCH_RPFILTER=m
|
||||||
|
CONFIG_IP_NF_MATCH_TTL=m
|
||||||
|
CONFIG_IP_NF_FILTER=m
|
||||||
|
CONFIG_IP_NF_TARGET_REJECT=m
|
||||||
|
CONFIG_IP_NF_TARGET_SYNPROXY=m
|
||||||
|
CONFIG_IP_NF_NAT=m
|
||||||
|
CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||||
|
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||||
|
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||||
|
CONFIG_IP_NF_MANGLE=m
|
||||||
|
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||||
|
CONFIG_IP_NF_TARGET_ECN=m
|
||||||
|
CONFIG_IP_NF_TARGET_TTL=m
|
||||||
|
CONFIG_IP_NF_RAW=m
|
||||||
|
CONFIG_IP_NF_ARPTABLES=m
|
||||||
|
CONFIG_IP_NF_ARPFILTER=m
|
||||||
|
CONFIG_IP_NF_ARP_MANGLE=m
|
||||||
|
CONFIG_NF_CONNTRACK_IPV6=m
|
||||||
|
CONFIG_NF_SOCKET_IPV6=m
|
||||||
|
CONFIG_NFT_CHAIN_ROUTE_IPV6=m
|
||||||
|
CONFIG_NFT_DUP_IPV6=m
|
||||||
|
CONFIG_NFT_FIB_IPV6=m
|
||||||
|
CONFIG_NFT_CHAIN_NAT_IPV6=m
|
||||||
|
CONFIG_NFT_MASQ_IPV6=m
|
||||||
|
CONFIG_NFT_REDIR_IPV6=m
|
||||||
|
CONFIG_IP6_NF_IPTABLES=m
|
||||||
|
CONFIG_IP6_NF_MATCH_AH=m
|
||||||
|
CONFIG_IP6_NF_MATCH_EUI64=m
|
||||||
|
CONFIG_IP6_NF_MATCH_FRAG=m
|
||||||
|
CONFIG_IP6_NF_MATCH_OPTS=m
|
||||||
|
CONFIG_IP6_NF_MATCH_HL=m
|
||||||
|
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
|
||||||
|
CONFIG_IP6_NF_MATCH_MH=m
|
||||||
|
CONFIG_IP6_NF_MATCH_RPFILTER=m
|
||||||
|
CONFIG_IP6_NF_MATCH_RT=m
|
||||||
|
CONFIG_IP6_NF_TARGET_HL=m
|
||||||
|
CONFIG_IP6_NF_FILTER=m
|
||||||
|
CONFIG_IP6_NF_TARGET_REJECT=m
|
||||||
|
CONFIG_IP6_NF_TARGET_SYNPROXY=m
|
||||||
|
CONFIG_IP6_NF_MANGLE=m
|
||||||
|
CONFIG_IP6_NF_RAW=m
|
||||||
|
CONFIG_IP6_NF_NAT=m
|
||||||
|
CONFIG_IP6_NF_TARGET_MASQUERADE=m
|
||||||
|
CONFIG_IP6_NF_TARGET_NPT=m
|
||||||
|
CONFIG_NF_TABLES_BRIDGE=m
|
||||||
|
CONFIG_NFT_BRIDGE_META=m
|
||||||
|
CONFIG_NFT_BRIDGE_REJECT=m
|
||||||
|
CONFIG_NF_LOG_BRIDGE=m
|
||||||
|
CONFIG_BRIDGE_NF_EBTABLES=m
|
||||||
|
CONFIG_BRIDGE_EBT_BROUTE=m
|
||||||
|
CONFIG_BRIDGE_EBT_T_FILTER=m
|
||||||
|
CONFIG_BRIDGE_EBT_T_NAT=m
|
||||||
|
CONFIG_BRIDGE_EBT_802_3=m
|
||||||
|
CONFIG_BRIDGE_EBT_AMONG=m
|
||||||
|
CONFIG_BRIDGE_EBT_ARP=m
|
||||||
|
CONFIG_BRIDGE_EBT_IP=m
|
||||||
|
CONFIG_BRIDGE_EBT_IP6=m
|
||||||
|
CONFIG_BRIDGE_EBT_LIMIT=m
|
||||||
|
CONFIG_BRIDGE_EBT_MARK=m
|
||||||
|
CONFIG_BRIDGE_EBT_PKTTYPE=m
|
||||||
|
CONFIG_BRIDGE_EBT_STP=m
|
||||||
|
CONFIG_BRIDGE_EBT_VLAN=m
|
||||||
|
CONFIG_BRIDGE_EBT_ARPREPLY=m
|
||||||
|
CONFIG_BRIDGE_EBT_DNAT=m
|
||||||
|
CONFIG_BRIDGE_EBT_MARK_T=m
|
||||||
|
CONFIG_BRIDGE_EBT_REDIRECT=m
|
||||||
|
CONFIG_BRIDGE_EBT_SNAT=m
|
||||||
|
CONFIG_BRIDGE_EBT_LOG=m
|
||||||
|
CONFIG_BRIDGE_EBT_NFLOG=m
|
||||||
|
CONFIG_L2TP=m
|
||||||
|
CONFIG_BRIDGE=m
|
||||||
|
CONFIG_VLAN_8021Q=m
|
||||||
|
CONFIG_VLAN_8021Q_GVRP=y
|
||||||
|
CONFIG_VLAN_8021Q_MVRP=y
|
||||||
|
CONFIG_LLC2=m
|
||||||
|
CONFIG_6LOWPAN=m
|
||||||
|
CONFIG_6LOWPAN_DEBUGFS=y
|
||||||
|
CONFIG_IEEE802154=m
|
||||||
|
CONFIG_NET_SCHED=y
|
||||||
|
CONFIG_NET_SCH_CBQ=m
|
||||||
|
CONFIG_NET_SCH_HTB=m
|
||||||
|
CONFIG_NET_SCH_HFSC=m
|
||||||
|
CONFIG_NET_SCH_PRIO=m
|
||||||
|
CONFIG_NET_SCH_MULTIQ=m
|
||||||
|
CONFIG_NET_SCH_RED=m
|
||||||
|
CONFIG_NET_SCH_SFB=m
|
||||||
|
CONFIG_NET_SCH_SFQ=m
|
||||||
|
CONFIG_NET_SCH_TEQL=m
|
||||||
|
CONFIG_NET_SCH_TBF=m
|
||||||
|
CONFIG_NET_SCH_GRED=m
|
||||||
|
CONFIG_NET_SCH_DSMARK=m
|
||||||
|
CONFIG_NET_SCH_NETEM=m
|
||||||
|
CONFIG_NET_SCH_DRR=m
|
||||||
|
CONFIG_NET_SCH_MQPRIO=m
|
||||||
|
CONFIG_NET_SCH_CHOKE=m
|
||||||
|
CONFIG_NET_SCH_QFQ=m
|
||||||
|
CONFIG_NET_SCH_CODEL=m
|
||||||
|
CONFIG_NET_SCH_FQ_CODEL=m
|
||||||
|
CONFIG_NET_SCH_FQ=m
|
||||||
|
CONFIG_NET_SCH_HHF=m
|
||||||
|
CONFIG_NET_SCH_PIE=m
|
||||||
|
CONFIG_NET_SCH_PLUG=m
|
||||||
|
CONFIG_NET_SCH_DEFAULT=y
|
||||||
|
CONFIG_NET_CLS_BASIC=m
|
||||||
|
CONFIG_NET_CLS_TCINDEX=m
|
||||||
|
CONFIG_NET_CLS_ROUTE4=m
|
||||||
|
CONFIG_NET_CLS_FW=m
|
||||||
|
CONFIG_NET_CLS_U32=m
|
||||||
|
CONFIG_CLS_U32_PERF=y
|
||||||
|
CONFIG_CLS_U32_MARK=y
|
||||||
|
CONFIG_NET_CLS_RSVP=m
|
||||||
|
CONFIG_NET_CLS_RSVP6=m
|
||||||
|
CONFIG_NET_CLS_FLOW=m
|
||||||
|
CONFIG_NET_CLS_CGROUP=m
|
||||||
|
CONFIG_NET_CLS_BPF=m
|
||||||
|
CONFIG_NET_CLS_FLOWER=m
|
||||||
|
CONFIG_NET_CLS_MATCHALL=m
|
||||||
|
CONFIG_NET_EMATCH=y
|
||||||
|
CONFIG_NET_EMATCH_CMP=m
|
||||||
|
CONFIG_NET_EMATCH_NBYTE=m
|
||||||
|
CONFIG_NET_EMATCH_U32=m
|
||||||
|
CONFIG_NET_EMATCH_META=m
|
||||||
|
CONFIG_NET_EMATCH_TEXT=m
|
||||||
|
CONFIG_NET_EMATCH_CANID=m
|
||||||
|
CONFIG_NET_CLS_ACT=y
|
||||||
|
CONFIG_NET_ACT_POLICE=m
|
||||||
|
CONFIG_NET_ACT_GACT=m
|
||||||
|
CONFIG_GACT_PROB=y
|
||||||
|
CONFIG_NET_ACT_MIRRED=m
|
||||||
|
CONFIG_NET_ACT_SAMPLE=m
|
||||||
|
CONFIG_NET_ACT_NAT=m
|
||||||
|
CONFIG_NET_ACT_PEDIT=m
|
||||||
|
CONFIG_NET_ACT_CSUM=m
|
||||||
|
CONFIG_NET_ACT_VLAN=m
|
||||||
|
CONFIG_NET_ACT_BPF=m
|
||||||
|
CONFIG_NET_ACT_SKBMOD=m
|
||||||
|
CONFIG_NET_ACT_IFE=m
|
||||||
|
CONFIG_NET_ACT_TUNNEL_KEY=m
|
||||||
|
CONFIG_NET_IFE_SKBMARK=m
|
||||||
|
CONFIG_NET_IFE_SKBPRIO=m
|
||||||
|
CONFIG_NET_IFE_SKBTCINDEX=m
|
||||||
|
CONFIG_NET_CLS_IND=y
|
||||||
|
CONFIG_DCB=y
|
||||||
|
CONFIG_BATMAN_ADV=m
|
||||||
|
CONFIG_BATMAN_ADV_BATMAN_V=y
|
||||||
|
CONFIG_BATMAN_ADV_DAT=y
|
||||||
|
CONFIG_BATMAN_ADV_NC=y
|
||||||
|
CONFIG_BATMAN_ADV_MCAST=y
|
||||||
|
CONFIG_BATMAN_ADV_DEBUG=y
|
||||||
|
CONFIG_OPENVSWITCH=m
|
||||||
|
CONFIG_VSOCKETS=m
|
||||||
|
CONFIG_VIRTIO_VSOCKETS=m
|
||||||
|
CONFIG_NETLINK_DIAG=m
|
||||||
|
CONFIG_NET_NSH=m
|
||||||
|
CONFIG_HSR=m
|
||||||
|
CONFIG_CGROUP_NET_PRIO=y
|
||||||
|
CONFIG_BPF_JIT=y
|
||||||
|
CONFIG_BT_6LOWPAN=m
|
||||||
|
CONFIG_MACVLAN=m
|
||||||
|
CONFIG_MACVTAP=m
|
||||||
|
CONFIG_TUN=m
|
||||||
|
CONFIG_TUN_VNET_CROSS_LE=y
|
||||||
|
CONFIG_VETH=m
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIG_TEE=y
|
||||||
|
CONFIG_OPTEE=y
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Allow to load kernel modules built with different kernel version
|
||||||
|
CONFIG_MODULE_FORCE_LOAD=y
|
||||||
|
CONFIG_MODVERSIONS=y
|
||||||
|
|
||||||
|
# Support of iks01a2
|
||||||
|
CONFIG_IIO_BUFFER=y
|
||||||
|
CONFIG_IIO_KFIFO_BUF=y
|
||||||
|
CONFIG_IIO_TRIGGERED_BUFFER=y
|
||||||
|
CONFIG_HTS221=y
|
||||||
|
CONFIG_IIO_ST_PRESS=m
|
||||||
|
CONFIG_IIO_ST_LSM6DSX=m
|
||||||
|
CONFIG_IIO_ST_LSM6DSX_I2C=m
|
||||||
|
|
||||||
|
|
@ -0,0 +1,346 @@
|
||||||
|
Compilation of kernel:
|
||||||
|
1. Pre-requisite
|
||||||
|
2. Initialise cross-compilation via SDK
|
||||||
|
3. Prepare kernel source code
|
||||||
|
4. Manage the kernel source code
|
||||||
|
5. Configure kernel source code
|
||||||
|
6. Compile kernel source code
|
||||||
|
7. Update software on board
|
||||||
|
|
||||||
|
1. Pre-requisite:
|
||||||
|
-----------------
|
||||||
|
OpenSTLinux SDK must be installed.
|
||||||
|
|
||||||
|
For kernel build, you need to install:
|
||||||
|
- libncurses and libncursesw dev package
|
||||||
|
Ubuntu: sudo apt-get install libncurses5-dev libncursesw5-dev
|
||||||
|
Fedora: sudo yum install ncurses-devel
|
||||||
|
- mkimage
|
||||||
|
Ubuntu: sudo apt-get install u-boot-tools
|
||||||
|
Fedora: sudo yum install u-boot-tools
|
||||||
|
|
||||||
|
Only if you like to have a git management of the code (see section 4
|
||||||
|
[Manage the kernel source code]):
|
||||||
|
- git:
|
||||||
|
Ubuntu: sudo apt-get install git-core gitk
|
||||||
|
Fedora: sudo yum install git
|
||||||
|
|
||||||
|
If you have never configured your git configuration, run the following commands:
|
||||||
|
$> git config --global user.name "your_name"
|
||||||
|
$> git config --global user.email "your_email@example.com"
|
||||||
|
|
||||||
|
2. Initialise cross-compilation via SDK:
|
||||||
|
----------------------------------------
|
||||||
|
Source SDK environment:
|
||||||
|
$> source <path to SDK>/environment-setup-cortexa9hf-neon-openstlinux_weston-linux-gnueabi
|
||||||
|
|
||||||
|
To verify if your cross-compilation environment has been put in place correctly,
|
||||||
|
run the following command:
|
||||||
|
$> set | grep CROSS
|
||||||
|
CROSS_COMPILE=arm-openstlinux_weston-linux-gnueabi-
|
||||||
|
|
||||||
|
Warning: the environment is valid only on the shell session where you have
|
||||||
|
sourced the SDK environment.
|
||||||
|
|
||||||
|
3. Prepare kernel source:
|
||||||
|
-------------------------
|
||||||
|
If you have the tarball and the list of patches, then you must extract the
|
||||||
|
tarball and apply the patches.
|
||||||
|
$> tar xfz <kernel source>.tar.gz
|
||||||
|
or
|
||||||
|
$> tar xfj <kernel source>.tar.bz2
|
||||||
|
or
|
||||||
|
$> tar xfJ <kernel source>.tar.xz
|
||||||
|
|
||||||
|
$> cd <directory to kernel source code>
|
||||||
|
NB: if you like to have a git management of the code, see section 4 [Manage the
|
||||||
|
kernel source code]
|
||||||
|
if there is some patch, please apply it on source code
|
||||||
|
$> for p in `ls -1 <path to patch>/*.patch`; do patch -p1 < $p; done
|
||||||
|
|
||||||
|
4. Manage the kernel source code:
|
||||||
|
---------------------------------
|
||||||
|
4.1 Setup kernel source code under git
|
||||||
|
--------------------------------------
|
||||||
|
If you like to have a better management of change made on kernel source, you can
|
||||||
|
use git.
|
||||||
|
|
||||||
|
* With the kernel source code extracted in the section 3 [Prepare kernel source]
|
||||||
|
$> cd <directory to kernel source code>
|
||||||
|
$> test -d .git || git init . && git add . && git commit -m "new kernel" && git gc
|
||||||
|
$> git checkout -b WORKING
|
||||||
|
Apply patches:
|
||||||
|
$> for p in `ls -1 <path to patch>/*.patch`; do git am $p; done
|
||||||
|
NB: this is the fastest way to get your kernel source code ready for development
|
||||||
|
|
||||||
|
Or
|
||||||
|
|
||||||
|
* With the kernel source code from the Linux kernel git repositories:
|
||||||
|
URL: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
|
||||||
|
Branch: ##GIT_BRANCH##
|
||||||
|
Revision: ##GIT_SRCREV##
|
||||||
|
|
||||||
|
$> git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
|
||||||
|
$> cd <kernel source>
|
||||||
|
$> git checkout -b WORKING ##GIT_SRCREV##
|
||||||
|
$> for p in `ls -1 <path to patch>/*.patch`; do git am $p; done
|
||||||
|
NB: this way is slightly slower than the tarball extraction but you get
|
||||||
|
advantage of all git history.
|
||||||
|
|
||||||
|
4.2 Predefined kernel version vs auto-generated kernel version:
|
||||||
|
---------------------------------------------------------------
|
||||||
|
If you are using git for managing your source code, kernel makefile get the SHA1
|
||||||
|
of current git and add it to kernel version number generated.
|
||||||
|
ex.: 4.9.23-g3e866b0 (kernel version + SHA1 of current git commit)
|
||||||
|
To bypass this auto-generation of kernel version number:
|
||||||
|
$> cd <directory to kernel source code>
|
||||||
|
$> echo "" > .scmversion
|
||||||
|
This file avoid to have a kernel version with SHA1:
|
||||||
|
- With scmversion file: 4.9.23
|
||||||
|
- Without scmversion file: 4.9.23-g3e866b0
|
||||||
|
This configuration allows to build new kernel from modified source code without
|
||||||
|
any issue when using the new kernel binary on target regarding any external
|
||||||
|
kernel module already available on target rootfs (as built without scmversion).
|
||||||
|
|
||||||
|
5. Configure kernel source code:
|
||||||
|
--------------------------------
|
||||||
|
There are two methods to configure and compile kernel source code:
|
||||||
|
- Inside kernel source tree directory
|
||||||
|
- Outside kernel source tree in a build directory
|
||||||
|
We highly preconized the build is a build directory method as:
|
||||||
|
- It avoids mixing files generated by the build with the source files inside
|
||||||
|
same directories
|
||||||
|
- To remove all the files generated by the build, it's enough to remove the
|
||||||
|
build directory
|
||||||
|
- You can build for different configurations in several build directories, e.g.:
|
||||||
|
1) build in "build_1" for a first kernel configuration
|
||||||
|
2) build in "build_2" for a second kernel configuration
|
||||||
|
Then this leaves the 2 images available for tests
|
||||||
|
|
||||||
|
* Configure on a build directory (different of kernel source code directory)
|
||||||
|
Here for example, build directory is located at the same level of kernel
|
||||||
|
source code
|
||||||
|
$> cd <directory to kernel source code>
|
||||||
|
$> mkdir -p ../build
|
||||||
|
$> make ARCH=arm O="$PWD/../build" multi_v7_defconfig fragment*.config
|
||||||
|
|
||||||
|
If there are some fragments, apply them
|
||||||
|
* manually one by one:
|
||||||
|
$> scripts/kconfig/merge_config.sh -m -r -O $PWD/../build $PWD/../build/.config ../fragment-01-xxx.config
|
||||||
|
$> scripts/kconfig/merge_config.sh -m -r -O $PWD/../build $PWD/../build/.config ../fragment-02-xxx.config
|
||||||
|
...
|
||||||
|
$> yes '' | make ARCH=arm oldconfig O="$PWD/../build"
|
||||||
|
* or, by loop:
|
||||||
|
$> for f in `ls -1 ../fragment*.config`; do scripts/kconfig/merge_config.sh -m -r -O $PWD/../build $PWD/../build/.config $f; done
|
||||||
|
$> yes '' | make ARCH=arm oldconfig O="$PWD/../build"
|
||||||
|
|
||||||
|
* Configure on the current source code directory
|
||||||
|
$> cd <directory to kernel source code>
|
||||||
|
$> make ARCH=arm multi_v7_defconfig fragment*.config
|
||||||
|
|
||||||
|
If there are some fragments, apply them
|
||||||
|
* manually one by one:
|
||||||
|
$> scripts/kconfig/merge_config.sh -m -r .config ../fragment-01-xxxx.config
|
||||||
|
$> scripts/kconfig/merge_config.sh -m -r .config ../fragment-02-xxxx.config
|
||||||
|
...
|
||||||
|
$> yes '' | make oldconfig
|
||||||
|
* or, by loop:
|
||||||
|
$> for f in `ls -1 ../fragment*.config`; do scripts/kconfig/merge_config.sh -m -r .config $f; done
|
||||||
|
$> yes '' | make ARCH=arm oldconfig
|
||||||
|
|
||||||
|
NB: Two types of fragments are provided:
|
||||||
|
* official fragments (fragment-xxx.config)
|
||||||
|
* optional fragments as example (optional-fragment-xxx.config) to add a
|
||||||
|
feature not enabled by default.
|
||||||
|
The order in which fragments are applied is determined by the number of the
|
||||||
|
fragment filename (fragment-001, fragment-002, e.g.).
|
||||||
|
Please pay special attention to the naming of your optional fragments to
|
||||||
|
ensure you select the right features.
|
||||||
|
|
||||||
|
6. Compile kernel source code:
|
||||||
|
------------------------------
|
||||||
|
You MUST compile from the directory on which the configuration has been done (i.e.
|
||||||
|
the directory which contains the '.config' file).
|
||||||
|
|
||||||
|
It's preconized to use the method with dedicated build directory for a better
|
||||||
|
managment of changes made on source code (as all build artifacts will be located
|
||||||
|
inside the dedicated build directory).
|
||||||
|
|
||||||
|
* Compile and install on a build directory (different of kernel source code directory)
|
||||||
|
$> cd <directory to kernel source code>
|
||||||
|
* Build kernel images (uImage and vmlinux) and device tree (dtbs)
|
||||||
|
$> make ARCH=arm uImage vmlinux dtbs LOADADDR=0xC2000040 O="$PWD/../build"
|
||||||
|
* Build kernel module
|
||||||
|
$> make ARCH=arm modules O="$PWD/../build"
|
||||||
|
* Generate output build artifacts
|
||||||
|
$> make ARCH=arm INSTALL_MOD_PATH="$PWD/../build/install_artifact" modules_install O="$PWD/../build"
|
||||||
|
$> mkdir -p $PWD/../build/install_artifact/boot/
|
||||||
|
$> cp $PWD/../build/arch/arm/boot/uImage $PWD/../build/install_artifact/boot/
|
||||||
|
$> cp $PWD/../build/arch/arm/boot/dts/st*.dtb $PWD/../build/install_artifact/boot/
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
$> cd <build directory>
|
||||||
|
* Build kernel images (uImage and vmlinux) and device tree (dtbs)
|
||||||
|
$> make ARCH=arm uImage vmlinux dtbs LOADADDR=0xC2000040
|
||||||
|
* Build kernel module
|
||||||
|
$> make ARCH=arm modules
|
||||||
|
* Generate output build artifacts
|
||||||
|
$> make ARCH=arm INSTALL_MOD_PATH="$PWD/../build/install_artifact" modules_install
|
||||||
|
$> mkdir -p $PWD/../build/install_artifact/boot/
|
||||||
|
$> cp $PWD/../build/arch/arm/boot/uImage $PWD/../build/install_artifact/boot/
|
||||||
|
$> cp $PWD/../build/arch/arm/boot/dts/st*.dtb $PWD/../build/install_artifact/boot/
|
||||||
|
|
||||||
|
* Compile and install on the current source code directory
|
||||||
|
$> cd <directory to kernel source code>
|
||||||
|
* Build kernel images (uImage and vmlinux) and device tree (dtbs)
|
||||||
|
$> make ARCH=arm uImage vmlinux dtbs LOADADDR=0xC2000040
|
||||||
|
* Build kernel module
|
||||||
|
$> make ARCH=arm modules
|
||||||
|
* Generate output build artifacts
|
||||||
|
$> make ARCH=arm INSTALL_MOD_PATH="$PWD/install_artifact" modules_install
|
||||||
|
$> mkdir -p $PWD/install_artifact/boot/
|
||||||
|
$> cp $PWD/arch/arm/boot/uImage $PWD/install_artifact/boot/
|
||||||
|
$> cp $PWD/arch/arm/boot/dts/st*.dtb $PWD/install_artifact/boot/
|
||||||
|
|
||||||
|
7. Update software on board:
|
||||||
|
----------------------------
|
||||||
|
7.1. Partitioning of binaries:
|
||||||
|
------------------------------
|
||||||
|
* Bootfs:
|
||||||
|
Bootfs contains the kernel and the devicetree.
|
||||||
|
* Rootfs:
|
||||||
|
Rootfs contains the external kernel modules.
|
||||||
|
Please refer to User guide for more details.
|
||||||
|
|
||||||
|
7.2. Update via network:
|
||||||
|
------------------------
|
||||||
|
* kernel + devicetree
|
||||||
|
$> cd <path to install_artifact dir>/install_artifact
|
||||||
|
$> ssh root@<ip of board> mount <device corresponding to bootfs> /boot
|
||||||
|
$> scp -r boot/* root@<ip of board>:/boot/
|
||||||
|
$> ssh root@<ip of board> umount /boot
|
||||||
|
|
||||||
|
* kernel modules
|
||||||
|
$> cd <path to install_artifact dir>/install_artifact
|
||||||
|
Remove the link on install_artifact/lib/modules/<kernel version>/
|
||||||
|
$> rm lib/modules/<kernel version>/source lib/modules/<kernel version>/build
|
||||||
|
Optionally, strip kernel modules (to reduce the size of each kernel modules)
|
||||||
|
$> find . -name "*.ko" | xargs $STRIP --strip-debug --remove-section=.comment --remove-section=.note --preserve-dates
|
||||||
|
|
||||||
|
Copy kernel modules:
|
||||||
|
$> scp -r lib/modules/* root@<ip of board>:/lib/modules/
|
||||||
|
|
||||||
|
Generate a list of module dependencies (modules.dep) and a list of symbols
|
||||||
|
provided by modules (modules.symbols):
|
||||||
|
$> ssh root@<ip of board> /sbin/depmod -a
|
||||||
|
Synchronize data on disk with memory
|
||||||
|
$> ssh root@<ip of board> sync
|
||||||
|
Reboot the board in order to take update into account
|
||||||
|
$> ssh root@<ip of board> reboot
|
||||||
|
|
||||||
|
7.3. Update via SDCARD on your Linux PC:
|
||||||
|
----------------------------------------
|
||||||
|
* kernel + devicetree
|
||||||
|
$> cd <path to install_artifact dir>/install_artifact
|
||||||
|
Verify sdcard are mounted on your Linux PC: /media/$USER/bootfs
|
||||||
|
$> cp -r boot/* /media/$USER/bootfs/
|
||||||
|
Depending of your Linux configuration, you may call the command under sudo
|
||||||
|
$> sudo cp -r boot/* /media/$USER/bootfs/
|
||||||
|
Don't forget to unmount properly sdcard
|
||||||
|
|
||||||
|
* kernel modules
|
||||||
|
$> cd <path to install_artifact dir>/install_artifact
|
||||||
|
Remove the link on install_artifact/lib/modules/<kernel version>/
|
||||||
|
$> rm lib/modules/<kernel version>/source lib/modules/<kernel version>/build
|
||||||
|
Optionally, strip kernel modules (to reduce the size of each kernel modules)
|
||||||
|
$> find . -name "*.ko" | xargs $STRIP --strip-debug --remove-section=.comment --remove-section=.note --preserve-dates
|
||||||
|
|
||||||
|
Verify sdcard are mounted on your Linux PC: /media/$USER/rootfs
|
||||||
|
Copy kernel modules:
|
||||||
|
$> cp -r lib/modules/* /media/$USER/rootfs/lib/modules/
|
||||||
|
Depending of your Linux configuration, you may call the command under sudo
|
||||||
|
$> sudo cp -r lib/modules/* /media/$USER/rootfs/lib/modules/
|
||||||
|
Don't forget to unmount properly sdcard
|
||||||
|
|
||||||
|
Generate a list of module dependencies (modules.dep) and a list of symbols
|
||||||
|
provided by modules (modules.symbols):
|
||||||
|
$> ssh root@<ip of board> depmod -a
|
||||||
|
Synchronize data on disk with memory
|
||||||
|
$> ssh root@<ip of board> sync
|
||||||
|
Reboot the board in order to take update into account
|
||||||
|
$> ssh root@<ip of board> reboot
|
||||||
|
|
||||||
|
7.4. Update via SDCARD on your BOARD (via U-Boot):
|
||||||
|
--------------------------------------------------
|
||||||
|
You MUST configure first, via U-Boot, the board into usb mass storage:
|
||||||
|
* Plug the SDCARD on Board.
|
||||||
|
* Start the board and stop on U-boot shell:
|
||||||
|
Hit any key to stop autoboot: 0
|
||||||
|
STM32MP>
|
||||||
|
* plug an USB cable between the PC and the board via USB OTG port.
|
||||||
|
* On U-Boot shell, call the usb mass storage functionnality:
|
||||||
|
STM32MP> ums 0 mmc 0
|
||||||
|
ums <USB controller> <dev type: mmc|usb> <dev[:part]>
|
||||||
|
Example:
|
||||||
|
For SDCARD: ums 0 mmc 0
|
||||||
|
For USB Disk: ums 0 usb 0
|
||||||
|
|
||||||
|
* kernel + devicetree
|
||||||
|
$> cd <path to install_artifact dir>/install_artifact
|
||||||
|
Remove the link on install_artifact/lib/modules/<kernel version>/
|
||||||
|
$> rm lib/modules/<kernel version>/source lib/modules/<kernel version>/build
|
||||||
|
Optionally, strip kernel modules (to reduce the size of each kernel modules)
|
||||||
|
$> find . -name "*.ko" | xargs $STRIP --strip-debug --remove-section=.comment --remove-section=.note --preserve-dates
|
||||||
|
|
||||||
|
Verify sdcard mount point are mounted on your Linux PC: /media/$USER/bootfs
|
||||||
|
$> cp -r boot/* /media/$USER/bootfs/
|
||||||
|
Depending of your Linux configuration, you may call the command under sudo
|
||||||
|
$> sudo cp -rf boot/* /media/$USER/bootfs/
|
||||||
|
Don't forget to unmount properly sdcard
|
||||||
|
Warning: kernel and device tree file name must be aligned between
|
||||||
|
extlinux.conf file and file system.
|
||||||
|
|
||||||
|
* kernel modules
|
||||||
|
$> cd <path to install_artifact dir>/install_artifact
|
||||||
|
Remove the link on install_artifact/lib/modules/<kernel version>/
|
||||||
|
$> rm lib/modules/<kernel version>/source lib/modules/<kernel version>/build
|
||||||
|
Optionally, strip kernel modules (to reduce the size of each kernel modules)
|
||||||
|
$> find . -name "*.ko" | xargs $STRIP --strip-debug --remove-section=.comment --remove-section=.note --preserve-dates
|
||||||
|
|
||||||
|
Verify sdcard mount point are mounted on your Linux PC: /media/$USER/rootfs
|
||||||
|
Copy kernel modules:
|
||||||
|
$> cp -rf lib/modules/* /media/$USER/rootfs/lib/modules/
|
||||||
|
Depending of your Linux configuration, you may call the command under sudo
|
||||||
|
$> sudo cp -r lib/modules/* /media/$USER/rootfs/lib/modules/
|
||||||
|
Don't forget to unmount properly sdcard
|
||||||
|
|
||||||
|
At next runtime, don't forget to generate a list of module dependencies
|
||||||
|
(modules.dep) and a list of symbols provided by modules (modules.symbols):
|
||||||
|
$on board> depmod -a
|
||||||
|
Synchronize data on disk with memory
|
||||||
|
$on board> sync
|
||||||
|
Reboot the board in order to take update into account
|
||||||
|
$on board> reboot
|
||||||
|
|
||||||
|
8. Useful information:
|
||||||
|
----------------------
|
||||||
|
* How to re-generate kernel database on board:
|
||||||
|
$on board> depmod -a
|
||||||
|
(don't forget to synchronize the filesystem before to reboot)
|
||||||
|
$on board> sync
|
||||||
|
|
||||||
|
* How to see the list of external kernel modules loaded:
|
||||||
|
$on board> lsmod
|
||||||
|
|
||||||
|
* How to see information about kernel module:
|
||||||
|
$on board> modinfo ./install_artifact/lib/modules/<kernel version>/kernel/drivers/leds/led-class-flash.ko
|
||||||
|
Example usage:
|
||||||
|
filename: <build directory>./install_artifact/lib/modules/4.9.23-g3e866b0/kernel/drivers/leds/led-class-flash.ko
|
||||||
|
license: GPL v2
|
||||||
|
description: LED Flash class interface
|
||||||
|
author: Jacek Anaszewski <j.anaszewski@samsung.com>
|
||||||
|
depends:
|
||||||
|
intree: Y
|
||||||
|
vermagic: 4.9.23-g3e866b0 SMP mod_unload ARMv7 p2v8
|
||||||
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
SUMMARY = "Linux STM32MP Kernel"
|
||||||
|
SECTION = "kernel"
|
||||||
|
LICENSE = "GPLv2"
|
||||||
|
LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
|
||||||
|
|
||||||
|
include linux-stm32mp.inc
|
||||||
|
|
||||||
|
SRC_URI = "https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.9.tar.xz"
|
||||||
|
SRC_URI[md5sum] = "d7e09d6be85ec8548c73e8713531e958"
|
||||||
|
SRC_URI[sha256sum] = "fc116cc6829c73944215d3b3ac0fc368dde9e8235b456744afffde001269dbf2"
|
||||||
|
|
||||||
|
SRC_URI += " \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0001-ARM-stm32mp1-r0-rc1-MACHINE.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0002-ARM-stm32mp1-r0-rc1-CLOCK.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0003-ARM-stm32mp1-r0-rc1-DMA.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0004-ARM-stm32mp1-r0-rc1-I2C.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0005-ARM-stm32mp1-r0-rc1-IIO.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0006-ARM-stm32mp1-r0-rc1-IRQ-Mailbox.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0007-ARM-stm32mp1-r0-rc1-INPUT-TTY.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0008-ARM-stm32mp1-r0-rc1-MFD.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0009-ARM-stm32mp1-r0-rc1-MMC-MTD.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0010-ARM-stm32mp1-r0-rc1-ETH.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0011-ARM-stm32mp1-r0-rc1-NVMEM.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0012-ARM-stm32mp1-r0-rc1-PINCTRL-PWM-RESET-RTC.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0013-ARM-stm32mp1-r0-rc1-REMOTEPROC-RPMSG.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0014-ARM-stm32mp1-r0-rc1-WATCHDOG.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0015-ARM-stm32mp1-r0-rc1-MISC.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0016-ARM-stm32mp1-r0-rc1-DEVICETREE.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0017-ARM-stm32mp1-r0-rc1-DEFCONFIG.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0018-ARM-stm32mp1-r0-rc2-DRM-KMS.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0019-ARM-stm32mp1-r0-rc2-SOUND.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0020-ARM-stm32mp1-r0-rc2-MEDIA.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0021-ARM-stm32mp1-r0-rc2-PINCTRL.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0022-ARM-stm32mp1-r0-rc2-MFD-IRQ.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0023-ARM-stm32mp1-r0-rc2-USB.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0024-ARM-stm32mp1-r0-rc2-THERMAL.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0025-ARM-stm32mp1-r0-rc2-REMOTEPROC.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0026-ARM-stm32mp1-r0-rc2-NET.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0027-ARM-stm32mp1-r0-rc2-HWCLK-SPI.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0028-ARM-stm32mp1-r0-rc2-MMC.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0029-ARM-stm32mp1-r0-rc2-HWSPINLOCK-IIO-I2C.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0030-ARM-stm32mp1-r0-rc2-DEVICETREE.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0031-ARM-stm32mp1-r0-rc2-DEFCONFIG.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0032-ARM-stm32mp1-r0-rc3-DMA.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0033-ARM-stm32mp1-r0-rc3-DISPLAY.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0034-ARM-stm32mp1-r0-rc3-ETH.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0035-ARM-stm32mp1-r0-rc3-IIO.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0036-ARM-stm32mp1-r0-rc3-INPUT-TTY.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0037-ARM-stm32mp1-r0-rc3-IRQ-Mailbox.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0038-ARM-stm32mp1-r0-rc3-MEDIA.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0039-ARM-stm32mp1-r0-rc3-MMC-MTD.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0040-ARM-stm32mp1-r0-rc3-PINCTRL-PWM-RESET-RTC.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0041-ARM-stm32mp1-r0-rc3-REMOTEPROC-RPMSG.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0042-ARM-stm32mp1-r0-rc3-SOUND.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0043-ARM-stm32mp1-r0-rc3-MISC.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0044-ARM-stm32mp1-r0-rc3-DEVICETREE.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0045-ARM-stm32mp1-r0-rc3-DEFCONFIG.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0046-ARM-stm32mp1-r0-rc4-MMC-MTD.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0047-ARM-stm32mp1-r0-rc4-PINCTRL-PWM-RESET-RTC.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0048-ARM-stm32mp1-r0-rc4-REMOTEPROC-RPMSG.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0049-ARM-stm32mp1-r0-rc4-SOUND.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0050-ARM-stm32mp1-r0-rc4-USB.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0051-ARM-stm32mp1-r0-rc4-DEVICETREE.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0052-ARM-stm32mp1-r0-rc4-DEFCONFIG.patch \
|
||||||
|
\
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0053-ARM-stm32mp1-r0-rc4-hotfix-w903.1-DRIVERS.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0054-ARM-stm32mp1-r0-rc4-hotfix-w903.1-DEVICETREE.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0055-ARM-stm32mp1-r0-rc4-hotfix-w903.1-DEFCONFIG.patch \
|
||||||
|
\
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0056-ARM-stm32mp1-r0-rc4-hotfix-w903.3-DRIVERS.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0057-ARM-stm32mp1-r0-rc4-hotfix-w903.3-DEVICETREE.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0058-ARM-stm32mp1-r0-rc4-hotfix-w903.3-DEFCONFIG.patch \
|
||||||
|
\
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0059-ARM-stm32mp1-r0-rc4-hotfix-w904.3-DRIVERS.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0060-ARM-stm32mp1-r0-rc4-hotfix-w904.3-DEVICETREE.patch \
|
||||||
|
\
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0061-ARM-stm32mp1-r0-rc4-hotfix-w904.5-DRIVERS.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0062-ARM-stm32mp1-r0-rc4-hotfix-w904.5-DEVICETREE.patch \
|
||||||
|
\
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0063-ARM-stm32mp1-r0-rc4-hotfix-w905.2-DRIVERS.patch \
|
||||||
|
file://${LINUX_VERSION}/4.19.9/0064-ARM-stm32mp1-r0-rc4-hotfix-w905.2-DEVICETREE.patch \
|
||||||
|
"
|
||||||
|
|
||||||
|
LINUX_VERSION = "4.19"
|
||||||
|
|
||||||
|
PV = "${LINUX_VERSION}"
|
||||||
|
|
||||||
|
S = "${WORKDIR}/linux-4.19.9"
|
||||||
|
|
||||||
|
# ---------------------------------
|
||||||
|
# Configure devupstream class usage
|
||||||
|
# ---------------------------------
|
||||||
|
BBCLASSEXTEND = "devupstream:target"
|
||||||
|
|
||||||
|
SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/linux.git;protocol=https;branch=v${LINUX_VERSION}-stm32mp"
|
||||||
|
SRCREV_class-devupstream = "196201973b7048ccf75aa63ac3c3673f8b6ee1c1"
|
||||||
|
|
||||||
|
# ---------------------------------
|
||||||
|
# Configure default preference to manage dynamic selection between tarball and github
|
||||||
|
# ---------------------------------
|
||||||
|
STM32MP_SOURCE_SELECTION ?= "tarball"
|
||||||
|
|
||||||
|
DEFAULT_PREFERENCE = "${@bb.utils.contains('STM32MP_SOURCE_SELECTION', 'github', '-1', '1', d)}"
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# Defconfig
|
||||||
|
#
|
||||||
|
KERNEL_DEFCONFIG = "multi_v7_defconfig"
|
||||||
|
KERNEL_CONFIG_FRAGMENTS = "${@bb.utils.contains('KERNEL_DEFCONFIG', 'multi_v7_defconfig', '${S}/arch/arm/configs/fragment-01-multiv7_cleanup.config', '', d)}"
|
||||||
|
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('KERNEL_DEFCONFIG', 'multi_v7_defconfig', '${S}/arch/arm/configs/fragment-02-multiv7_addons.config', '', d)}"
|
||||||
|
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${WORKDIR}/fragments/4.19/fragment-03-systemd.config', '', d)} "
|
||||||
|
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('COMBINED_FEATURES', 'optee', '${WORKDIR}/fragments/4.19/fragment-04-optee.config', '', d)}"
|
||||||
|
KERNEL_CONFIG_FRAGMENTS += "${WORKDIR}/fragments/4.19/fragment-05-modules.config"
|
||||||
|
|
||||||
|
SRC_URI += "file://4.19/fragment-03-systemd.config;subdir=fragments"
|
||||||
|
SRC_URI += "file://4.19/fragment-04-optee.config;subdir=fragments"
|
||||||
|
SRC_URI += "file://4.19/fragment-05-modules.config;subdir=fragments"
|
||||||
|
# Don't forget to add/del for devupstream
|
||||||
|
SRC_URI_append_class-devupstream = " file://4.19/fragment-03-systemd.config;subdir=fragments "
|
||||||
|
SRC_URI_append_class-devupstream = " file://4.19/fragment-04-optee.config;subdir=fragments "
|
||||||
|
SRC_URI_append_class-devupstream = " file://4.19/fragment-05-modules.config;subdir=fragments "
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# Kernel Args
|
||||||
|
#
|
||||||
|
KERNEL_EXTRA_ARGS += "LOADADDR=${ST_KERNEL_LOADADDR}"
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# Archiver
|
||||||
|
#
|
||||||
|
inherit archiver
|
||||||
|
ARCHIVER_MODE[src] = "${@'original' if d.getVar('ST_ARCHIVER_ENABLE') == '1' else ''}"
|
||||||
|
SRC_URI =+ "file://README.HOW_TO.txt"
|
||||||
|
|
||||||
|
inherit archiver_stm32mp_clean
|
||||||
Loading…
Reference in New Issue