LINUX-STM32MP: update to v2.0.0 (v5.4-stm32mp-r1)

Change-Id: I30e1aa3ee0f28b3dc27e5899956719b8fe7b43a4
This commit is contained in:
Priouzeau Christophe 2020-02-03 15:03:57 +01:00 committed by Romuald JEANNE
parent 4b72bbe010
commit 032589bd75
58 changed files with 37036 additions and 57549 deletions

View File

@ -2,7 +2,7 @@ COMPATIBLE_MACHINE = "(stm32mpcommon)"
inherit kernel
DEPENDS += "openssl-native util-linux-native"
DEPENDS += "openssl-native util-linux-native libyaml-native"
B = "${WORKDIR}/build"
# Configure build dir for externalsrc class usage through devtool
@ -14,6 +14,21 @@ FILESEXTRAPATHS_prepend := "${THISDIR}:"
# -------------------------------------------------------------
# Do not deploy kernel module with specfic tarball
MODULE_TARBALL_DEPLOY = "0"
do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/kernel"
#---------------------------------------------------------------
# Module kernel signature
KERNEL_SIGN_ENABLE ?= "0"
EXTRA_OEMAKE += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', 'INSTALL_MOD_STRIP=1','')}"
#
# Force task order for link creation
#
python () {
d.appendVarFlag("do_unpack", "postfuncs", " do_symlink_kernsrc")
}
do_symlink_kernsrc[noexec] = "1"
# ---------------------------------------------------------------------
# Defconfig
@ -65,6 +80,11 @@ do_configure_prepend() {
do_install_append() {
# Install KERNEL_IMAGETYPE for kernel-imagebootfs package
install -m 0644 ${KERNEL_OUTPUT_DIR}/${KERNEL_IMAGETYPE} ${D}/${KERNEL_IMAGEDEST}
if ${@bb.utils.contains('MACHINE_FEATURES','gpu','true','false',d)}; then
# when ACCEPT_EULA are filled
echo "blacklist etnaviv" > ${D}/${sysconfdir}/modprobe.d/blacklist.conf
fi
}
# ---------------------------------------------------------------------
@ -79,3 +99,4 @@ 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}"
FILES_${KERNEL_PACKAGE_NAME}-modules += "${sysconfdir}/modprobe.d"

View File

@ -1,82 +0,0 @@
From 72d1b59c3ca272dd153ebd350ef9e403dac3db59 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:38 +0100
Subject: [PATCH 01/31] ARM stm32mp1 r3 MACHINE
---
arch/arm/mach-integrator/integrator_cp.c | 2 --
arch/arm/mach-stm32/Kconfig | 5 +----
arch/arm/mach-versatile/versatile_dt.c | 4 ----
3 files changed, 1 insertion(+), 10 deletions(-)
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-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
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,
};
/*
--
2.7.4

View File

@ -1,39 +0,0 @@
From bcd539392e9bc23b9b47250eacf84907dd993089 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:39 +0100
Subject: [PATCH 04/31] ARM stm32mp1 r3 BLUETOOTH CHAR
---
drivers/bluetooth/hci_bcm.c | 3 ++-
drivers/char/hw_random/stm32-rng.c | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 59e5fc5..c553235 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -1324,7 +1324,8 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
if (!bcmdev->shutdown) {
dev_warn(&serdev->dev,
"No reset resource, using default baud rate\n");
- bcmdev->oper_speed = bcmdev->init_speed;
+ if (!bcmdev->oper_speed)
+ bcmdev->oper_speed = bcmdev->init_speed;
}
err = bcm_gpio_set_power(bcmdev, false);
diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 37b338a..0ef5b6a 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -161,6 +161,7 @@ static int stm32_rng_probe(struct platform_device *ofdev)
#endif
priv->rng.read = stm32_rng_read,
priv->rng.priv = (unsigned long) dev;
+ priv->rng.quality = 900;
pm_runtime_set_autosuspend_delay(dev, 100);
pm_runtime_use_autosuspend(dev);
--
2.7.4

View File

@ -1,203 +0,0 @@
From 7aa67bec68104aebb6a182e12cbfd62dfa81a5d3 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:40 +0100
Subject: [PATCH 08/31] ARM stm32mp1 r3 GPIO
---
drivers/gpio/gpiolib-of.c | 5 +++++
drivers/gpio/gpiolib.c | 50 ++++++++++++++++++++++++++++-------------
drivers/gpio/gpiolib.h | 2 ++
include/dt-bindings/gpio/gpio.h | 6 +++++
include/linux/gpio/machine.h | 2 ++
include/linux/of_gpio.h | 2 ++
6 files changed, 51 insertions(+), 16 deletions(-)
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index e0f149b..a8cba78 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -281,6 +281,11 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
if (of_flags & OF_GPIO_TRANSITORY)
*flags |= GPIO_TRANSITORY;
+ if (of_flags & OF_GPIO_PULL_UP)
+ *flags |= GPIO_PULL_UP;
+ if (of_flags & OF_GPIO_PULL_DOWN)
+ *flags |= GPIO_PULL_DOWN;
+
return desc;
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index a24f13d..aa750f9 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2537,6 +2537,14 @@ EXPORT_SYMBOL_GPL(gpiochip_free_own_desc);
* rely on gpio_request() having been called beforehand.
*/
+static int gpio_set_config(struct gpio_chip *gc, unsigned offset,
+ enum pin_config_param mode)
+{
+ unsigned long config = { PIN_CONF_PACKED(mode, 0) };
+
+ return gc->set_config ? gc->set_config(gc, offset, config) : -ENOTSUPP;
+}
+
/**
* gpiod_direction_input - set the GPIO direction to input
* @desc: GPIO to set to input
@@ -2573,20 +2581,19 @@ int gpiod_direction_input(struct gpio_desc *desc)
if (status == 0)
clear_bit(FLAG_IS_OUT, &desc->flags);
+ if (test_bit(FLAG_PULL_UP, &desc->flags))
+ gpio_set_config(chip, gpio_chip_hwgpio(desc),
+ PIN_CONFIG_BIAS_PULL_UP);
+ else if (test_bit(FLAG_PULL_DOWN, &desc->flags))
+ gpio_set_config(chip, gpio_chip_hwgpio(desc),
+ PIN_CONFIG_BIAS_PULL_DOWN);
+
trace_gpio_direction(desc_to_gpio(desc), 1, status);
return status;
}
EXPORT_SYMBOL_GPL(gpiod_direction_input);
-static int gpio_set_drive_single_ended(struct gpio_chip *gc, unsigned offset,
- enum pin_config_param mode)
-{
- unsigned long config = { PIN_CONF_PACKED(mode, 0) };
-
- return gc->set_config ? gc->set_config(gc, offset, config) : -ENOTSUPP;
-}
-
static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value)
{
struct gpio_chip *gc = desc->gdev->chip;
@@ -2672,8 +2679,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
gc = desc->gdev->chip;
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
/* First see if we can enable open drain in hardware */
- ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
- PIN_CONFIG_DRIVE_OPEN_DRAIN);
+ ret = gpio_set_config(gc, gpio_chip_hwgpio(desc),
+ PIN_CONFIG_DRIVE_OPEN_DRAIN);
if (!ret)
goto set_output_value;
/* Emulate open drain by not actively driving the line high */
@@ -2683,8 +2690,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
}
}
else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
- ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
- PIN_CONFIG_DRIVE_OPEN_SOURCE);
+ ret = gpio_set_config(gc, gpio_chip_hwgpio(desc),
+ PIN_CONFIG_DRIVE_OPEN_SOURCE);
if (!ret)
goto set_output_value;
/* Emulate open source by not actively driving the line low */
@@ -2693,8 +2700,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
goto set_output_flag;
}
} else {
- gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
- PIN_CONFIG_DRIVE_PUSH_PULL);
+ gpio_set_config(gc, gpio_chip_hwgpio(desc),
+ PIN_CONFIG_DRIVE_PUSH_PULL);
}
set_output_value:
@@ -2737,7 +2744,7 @@ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
}
config = pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE, debounce);
- return chip->set_config(chip, gpio_chip_hwgpio(desc), config);
+ return gpio_set_config(chip, gpio_chip_hwgpio(desc), config);
}
EXPORT_SYMBOL_GPL(gpiod_set_debounce);
@@ -2774,7 +2781,7 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE,
!transitory);
gpio = gpio_chip_hwgpio(desc);
- rc = chip->set_config(chip, gpio, packed);
+ rc = gpio_set_config(chip, gpio, packed);
if (rc == -ENOTSUPP) {
dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO %d\n",
gpio);
@@ -3908,6 +3915,17 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
if (lflags & GPIO_OPEN_SOURCE)
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+ if ((lflags & GPIO_PULL_UP) && (lflags & GPIO_PULL_DOWN)) {
+ gpiod_err(desc,
+ "both pull-up and pull-down enabled, invalid configuration\n");
+ return -EINVAL;
+ }
+
+ if (lflags & GPIO_PULL_UP)
+ set_bit(FLAG_PULL_UP, &desc->flags);
+ else if (lflags & GPIO_PULL_DOWN)
+ set_bit(FLAG_PULL_DOWN, &desc->flags);
+
status = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY));
if (status < 0)
return status;
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index a7e49fef..34d2650 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -216,6 +216,8 @@ struct gpio_desc {
#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */
#define FLAG_TRANSITORY 12 /* GPIO may lose value in sleep or reset */
+#define FLAG_PULL_UP 13 /* GPIO has pull up enabled */
+#define FLAG_PULL_DOWN 14 /* GPIO has pull down enabled */
/* Connection label */
const char *label;
diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
index 2cc10ae..c029467 100644
--- a/include/dt-bindings/gpio/gpio.h
+++ b/include/dt-bindings/gpio/gpio.h
@@ -33,4 +33,10 @@
#define GPIO_PERSISTENT 0
#define GPIO_TRANSITORY 8
+/* Bit 4 express pull up */
+#define GPIO_PULL_UP 16
+
+/* Bit 5 express pull down */
+#define GPIO_PULL_DOWN 32
+
#endif
diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h
index daa44ea..69673be 100644
--- a/include/linux/gpio/machine.h
+++ b/include/linux/gpio/machine.h
@@ -12,6 +12,8 @@ enum gpio_lookup_flags {
GPIO_OPEN_SOURCE = (1 << 2),
GPIO_PERSISTENT = (0 << 3),
GPIO_TRANSITORY = (1 << 3),
+ GPIO_PULL_UP = (1 << 4),
+ GPIO_PULL_DOWN = (1 << 5),
};
/**
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 163b79e..f9737de 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -28,6 +28,8 @@ enum of_gpio_flags {
OF_GPIO_SINGLE_ENDED = 0x2,
OF_GPIO_OPEN_DRAIN = 0x4,
OF_GPIO_TRANSITORY = 0x8,
+ OF_GPIO_PULL_UP = 0x10,
+ OF_GPIO_PULL_DOWN = 0x20,
};
#ifdef CONFIG_OF_GPIO
--
2.7.4

View File

@ -1,249 +0,0 @@
From da8d8b897bc61f58b87237394c4a9ff4f89e906d Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:40 +0100
Subject: [PATCH 09/31] ARM stm32mp1 r3 HWSPINLOCK
---
drivers/hwspinlock/Kconfig | 9 ++
drivers/hwspinlock/Makefile | 1 +
drivers/hwspinlock/hwspinlock_core.c | 15 ++--
drivers/hwspinlock/stm32_hwspinlock.c | 164 ++++++++++++++++++++++++++++++++++
4 files changed, 182 insertions(+), 7 deletions(-)
create mode 100644 drivers/hwspinlock/stm32_hwspinlock.c
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/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
index 2bad40d..287e1b3 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -333,6 +333,9 @@ int of_hwspin_lock_get_id(struct device_node *np, int index)
if (ret)
return ret;
+ if (!of_device_is_available(args.np))
+ return -ENOENT;
+
/* Find the hwspinlock device: we need its base_id */
ret = -EPROBE_DEFER;
rcu_read_lock();
@@ -742,13 +745,11 @@ struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
/* sanity check (this shouldn't happen) */
WARN_ON(hwlock_to_id(hwlock) != id);
- /* make sure this hwspinlock is unused */
- ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
- if (ret == 0) {
- pr_warn("hwspinlock %u is already in use\n", id);
- hwlock = NULL;
- goto out;
- }
+ /*
+ * We intentionally do not check for the HWSPINLOCK_UNUSED tag as
+ * we want to share HWSPINLOCK between several devices. This is safe
+ * since the lock/unlock requests are called under &hwlock->lock control
+ */
/* mark as used and power up */
ret = __hwspin_lock_request(hwlock);
diff --git a/drivers/hwspinlock/stm32_hwspinlock.c b/drivers/hwspinlock/stm32_hwspinlock.c
new file mode 100644
index 0000000..b9b9b99
--- /dev/null
+++ b/drivers/hwspinlock/stm32_hwspinlock.c
@@ -0,0 +1,164 @@
+// 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/delay.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 void stm32_hwspinlock_relax(struct hwspinlock *lock)
+{
+ ndelay(50);
+}
+
+static const struct hwspinlock_ops stm32_hwspinlock_ops = {
+ .trylock = stm32_hwspinlock_trylock,
+ .unlock = stm32_hwspinlock_unlock,
+ .relax = stm32_hwspinlock_relax,
+};
+
+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>");
--
2.7.4

View File

@ -1,496 +0,0 @@
From 61b384e5eaed6c1ef9342e7216ffd2376e0f611d Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:43 +0100
Subject: [PATCH 16/31] ARM stm32mp1 r3 NET
---
drivers/net/ethernet/stmicro/stmmac/common.h | 2 +-
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 167 +++++++++++++++++----
drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 45 +++++-
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 6 +
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 5 +
.../net/wireless/broadcom/brcm80211/brcmutil/d11.c | 3 -
8 files changed, 191 insertions(+), 42 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index b069b3a..272b9ca6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -261,7 +261,7 @@ struct stmmac_safety_stats {
#define STMMAC_COAL_TX_TIMER 1000
#define STMMAC_MAX_COAL_TX_TICK 100000
#define STMMAC_TX_MAX_FRAMES 256
-#define STMMAC_TX_FRAMES 1
+#define STMMAC_TX_FRAMES 25
/* Packets types */
enum packets_types {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index 7e2e79d..dd45026 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,14 +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 */
- u32 mode_reg; /* MAC glue-logic mode register */
+ int eth_clk_sel_reg;
+ int eth_ref_clk_sel_reg;
+ int irq_pwr_wakeup;
+ u32 mode_reg; /* MAC glue-logic mode register */
struct regmap *regmap;
u32 speed;
const struct stm32_ops *ops;
@@ -98,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->int_phyclk) {
+ 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->int_phyclk)
+ 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)
@@ -130,19 +194,22 @@ 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:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
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;
@@ -153,6 +220,11 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
return -EINVAL;
}
+ /* Need to update PMCCLRR (clear register) */
+ regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
+ dwmac->ops->syscfg_eth_mask);
+
+ /* Update PMCSETR (set register) */
return regmap_update_bits(dwmac->regmap, reg,
dwmac->ops->syscfg_eth_mask, val);
}
@@ -232,35 +304,65 @@ 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;
- 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);
}
- /* 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;
}
- return 0;
+ err = 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->irq_pwr_wakeup == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ 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");
+ 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 +428,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;
}
@@ -341,8 +449,9 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
return ret;
clk_disable_unprepare(dwmac->clk_tx);
- clk_disable_unprepare(dwmac->syscfg_clk);
- if (dwmac->int_phyclk)
+ if (dwmac->syscfg_clk)
+ clk_disable_unprepare(dwmac->syscfg_clk);
+ if (dwmac->clk_eth_ck)
clk_disable_unprepare(dwmac->clk_eth_ck);
return ret;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
index 49f5687..5b35071 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
@@ -22,7 +22,7 @@ int dwmac4_dma_reset(void __iomem *ioaddr)
/* DMA SW reset */
value |= DMA_BUS_MODE_SFT_RESET;
writel(value, ioaddr + DMA_BUS_MODE);
- limit = 10;
+ limit = 100;
while (limit--) {
if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
break;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 014fe93..ccb512f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2713,6 +2713,8 @@ static int stmmac_release(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
u32 chan;
+ stmmac_disable_all_queues(priv);
+
if (priv->eee_enabled)
del_timer_sync(&priv->eee_ctrl_timer);
@@ -2724,8 +2726,6 @@ static int stmmac_release(struct net_device *dev)
stmmac_stop_all_queues(priv);
- stmmac_disable_all_queues(priv);
-
for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
del_timer_sync(&priv->tx_queue[chan].txtimer);
@@ -4501,14 +4501,13 @@ int stmmac_suspend(struct device *dev)
if (!ndev || !netif_running(ndev))
return 0;
- if (ndev->phydev)
- phy_stop(ndev->phydev);
+ /* call carrier off first to avoid false dev_watchdog timeouts */
+ netif_carrier_off(ndev);
mutex_lock(&priv->lock);
netif_device_detach(ndev);
stmmac_stop_all_queues(priv);
-
stmmac_disable_all_queues(priv);
/* Stop TX/RX DMA */
@@ -4532,6 +4531,10 @@ int stmmac_suspend(struct device *dev)
priv->oldlink = false;
priv->speed = SPEED_UNKNOWN;
priv->oldduplex = DUPLEX_UNKNOWN;
+
+ if (ndev->phydev)
+ phy_stop(ndev->phydev);
+
return 0;
}
EXPORT_SYMBOL_GPL(stmmac_suspend);
@@ -4572,6 +4575,7 @@ int stmmac_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
if (!netif_running(ndev))
return 0;
@@ -4601,11 +4605,32 @@ int stmmac_resume(struct device *dev)
netif_device_attach(ndev);
+ if (ndev->phydev)
+ phy_start(ndev->phydev);
+
mutex_lock(&priv->lock);
stmmac_reset_queues_param(priv);
- stmmac_clear_descriptors(priv);
+ /* Stop TX/RX DMA and clear the descriptors */
+ stmmac_stop_all_dma(priv);
+
+ /* Release and free the Rx/Tx resources */
+ free_dma_desc_resources(priv);
+
+ ret = alloc_dma_desc_resources(priv);
+ if (ret < 0) {
+ netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n",
+ __func__);
+ goto dma_desc_error;
+ }
+
+ ret = init_dma_desc_rings(ndev, GFP_KERNEL);
+ if (ret < 0) {
+ netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n",
+ __func__);
+ goto init_error;
+ }
stmmac_hw_setup(ndev, false);
stmmac_init_tx_coalesce(priv);
@@ -4617,10 +4642,14 @@ int stmmac_resume(struct device *dev)
mutex_unlock(&priv->lock);
+ return 0;
+init_error:
+ free_dma_desc_resources(priv);
+dma_desc_error:
if (ndev->phydev)
- phy_start(ndev->phydev);
+ phy_disconnect(ndev->phydev);
- return 0;
+ return -1;
}
EXPORT_SYMBOL_GPL(stmmac_resume);
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;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
index ffa243e..55974a4 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
@@ -496,6 +496,11 @@ int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid)
brcmf_dbg(TRACE, "reqid=%llu\n", reqid);
pi = ifp_to_pno(ifp);
+
+ /* No PNO reqeuset */
+ if (!pi->n_reqs)
+ return 0;
+
err = brcmf_pno_remove_request(pi, reqid);
if (err)
return err;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c
index eb5db94..e7584b8 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c
@@ -193,9 +193,6 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
}
break;
case BRCMU_CHSPEC_D11AC_BW_160:
- ch->bw = BRCMU_CHAN_BW_160;
- ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
- BRCMU_CHSPEC_D11AC_SB_SHIFT);
switch (ch->sb) {
case BRCMU_CHAN_SB_LLL:
ch->control_ch_num -= CH_70MHZ_APART;
--
2.7.4

View File

@ -1,377 +0,0 @@
From a658fa1ee69e4b233cde37442c25523238b0d001 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:43 +0100
Subject: [PATCH 17/31] ARM stm32mp1 r3 NVMEM
---
drivers/nvmem/Kconfig | 10 ++
drivers/nvmem/Makefile | 2 +
drivers/nvmem/core.c | 74 +++++++++++++++
drivers/nvmem/stm32-romem.c | 203 +++++++++++++++++++++++++++++++++++++++++
include/linux/nvmem-consumer.h | 14 +++
5 files changed, 303 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 30c0407..e5808b8f 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -1246,6 +1246,80 @@ 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_cell_read_u8() - Read a cell value as an u8
+ *
+ * @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_u8(struct device *dev, const char *cell_id, u8 *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_u8);
+
+/**
* 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..34b388c
--- /dev/null
+++ b/drivers/nvmem/stm32-romem.c
@@ -0,0 +1,203 @@
+// 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
+
+/* 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;
+};
+
+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) {
+ 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));
+ 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 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.size = cfg->size;
+ priv->cfg.reg_read = stm32_bsec_read;
+ priv->cfg.reg_write = stm32_bsec_write;
+ }
+
+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg));
+}
+
+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,
+ .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..c97f1e9 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -39,6 +39,8 @@ 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);
+int nvmem_cell_read_u8(struct device *dev, const char *cell_id, u8 *val);
/* direct nvmem device read/write interface */
struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
@@ -95,6 +97,18 @@ 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 int nvmem_cell_read_u8(struct device *dev,
+ const char *cell_id, u8 *val)
+{
+ return -EOPNOTSUPP;
+}
+
static inline struct nvmem_device *nvmem_device_get(struct device *dev,
const char *name)
{
--
2.7.4

View File

@ -1,276 +0,0 @@
From eb8e18ef550744ca51256b8cd1dc3cf09b7596e4 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:45 +0100
Subject: [PATCH 22/31] ARM stm32mp1 r3 RTC
---
drivers/rtc/Kconfig | 1 +
drivers/rtc/rtc-stm32.c | 119 ++++++++++++++++++++++++++++++++++++
include/dt-bindings/rtc/rtc-stm32.h | 13 ++++
3 files changed, 133 insertions(+)
create mode 100644 include/dt-bindings/rtc/rtc-stm32.h
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 7d7be60..6e201ff 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1770,6 +1770,7 @@ config RTC_DRV_R7301
config RTC_DRV_STM32
tristate "STM32 RTC"
select REGMAP_MMIO
+ depends on COMMON_CLK
depends on ARCH_STM32 || COMPILE_TEST
help
If you say yes here you get support for the STM32 On-Chip
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index 8e6c9b3..8ab3586 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -6,6 +6,7 @@
#include <linux/bcd.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/iopoll.h>
#include <linux/ioport.h>
#include <linux/mfd/syscon.h>
@@ -15,6 +16,8 @@
#include <linux/regmap.h>
#include <linux/rtc.h>
+#include <dt-bindings/rtc/rtc-stm32.h>
+
#define DRIVER_NAME "stm32_rtc"
/* STM32_RTC_TR bit fields */
@@ -39,6 +42,12 @@
#define STM32_RTC_CR_FMT BIT(6)
#define STM32_RTC_CR_ALRAE BIT(8)
#define STM32_RTC_CR_ALRAIE BIT(12)
+#define STM32_RTC_CR_COSEL BIT(19)
+#define STM32_RTC_CR_OSEL_SHIFT 21
+#define STM32_RTC_CR_OSEL GENMASK(22, 21)
+#define STM32_RTC_CR_COE BIT(23)
+#define STM32_RTC_CR_TAMPOE BIT(26)
+#define STM32_RTC_CR_OUT2EN BIT(31)
/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
#define STM32_RTC_ISR_ALRAWF BIT(0)
@@ -75,6 +84,11 @@
/* STM32_RTC_SR/_SCR bit fields */
#define STM32_RTC_SR_ALRA BIT(0)
+/* STM32_RTC_CFGR bit fields */
+#define STM32_RTC_CFGR_OUT2_RMP BIT(0)
+#define STM32_RTC_CFGR_LSCOEN_OUT1 1
+#define STM32_RTC_CFGR_LSCOEN_OUT2_RMP 2
+
/* STM32_RTC_VERR bit fields */
#define STM32_RTC_VERR_MINREV_SHIFT 0
#define STM32_RTC_VERR_MINREV GENMASK(3, 0)
@@ -101,6 +115,7 @@ struct stm32_rtc_registers {
u16 wpr;
u16 sr;
u16 scr;
+ u16 cfgr;
u16 verr;
};
@@ -115,6 +130,7 @@ struct stm32_rtc_data {
bool has_pclk;
bool need_dbp;
bool has_wakeirq;
+ bool has_lsco;
};
struct stm32_rtc {
@@ -128,8 +144,87 @@ struct stm32_rtc {
const struct stm32_rtc_data *data;
int irq_alarm;
int wakeirq_alarm;
+ int lsco;
+ struct clk *clk_lsco;
};
+/*
+ * -------------------------------------------------------------------------
+ * | TAMPOE | OSEL[1:0] | COE | OUT2EN | RTC_OUT1 | RTC_OUT2 |
+ * | | | | | | or RTC_OUT2_RMP |
+ * |-------------------------------------------------------------------------|
+ * | 0 | 00 | 0 | 0 or 1 | - | - |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 | 00 | 1 | 0 | CALIB | - |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 or 1 | !=00 | 0 | 0 | TAMPALRM | - |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 | 00 | 1 | 1 | - | CALIB |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 or 1 | !=00 | 0 | 1 | - | TAMPALRM |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 or 1 | !=00 | 1 | 1 | TAMPALRM | CALIB |
+ * -------------------------------------------------------------------------
+ */
+static int stm32_rtc_clk_lsco_check_availability(struct stm32_rtc *rtc)
+{
+ struct stm32_rtc_registers regs = rtc->data->regs;
+ unsigned int cr = readl_relaxed(rtc->base + regs.cr);
+ unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
+ unsigned int calib = STM32_RTC_CR_COE;
+ unsigned int tampalrm = STM32_RTC_CR_TAMPOE | STM32_RTC_CR_OSEL;
+
+ switch (rtc->lsco) {
+ case RTC_OUT1:
+ if ((!(cr & STM32_RTC_CR_OUT2EN) &&
+ ((cr & calib) || cr & tampalrm)) ||
+ ((cr & calib) && (cr & tampalrm)))
+ return -EBUSY;
+ break;
+ case RTC_OUT2_RMP:
+ if ((cr & STM32_RTC_CR_OUT2EN) &&
+ (cfgr & STM32_RTC_CFGR_OUT2_RMP) &&
+ ((cr & calib) || (cr & tampalrm)))
+ return -EBUSY;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (clk_get_rate(rtc->rtc_ck) != 32768)
+ return -ERANGE;
+
+ return 0;
+}
+
+static int stm32_rtc_clk_lsco_register(struct platform_device *pdev)
+{
+ struct stm32_rtc *rtc = platform_get_drvdata(pdev);
+ struct stm32_rtc_registers regs = rtc->data->regs;
+ u8 lscoen;
+ int ret;
+
+ ret = stm32_rtc_clk_lsco_check_availability(rtc);
+ if (ret)
+ return ret;
+
+ lscoen = (rtc->lsco == RTC_OUT1) ? STM32_RTC_CFGR_LSCOEN_OUT1 :
+ STM32_RTC_CFGR_LSCOEN_OUT2_RMP;
+
+ rtc->clk_lsco = clk_register_gate(&pdev->dev, "rtc_lsco",
+ __clk_get_name(rtc->rtc_ck),
+ CLK_IGNORE_UNUSED | CLK_IS_CRITICAL,
+ rtc->base + regs.cfgr, lscoen,
+ 0, NULL);
+ if (IS_ERR(rtc->clk_lsco))
+ return PTR_ERR(rtc->clk_lsco);
+
+ of_clk_add_provider(pdev->dev.of_node,
+ of_clk_src_simple_get, rtc->clk_lsco);
+
+ return 0;
+}
+
static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
{
const struct stm32_rtc_registers *regs = &rtc->data->regs;
@@ -552,6 +647,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {
.has_pclk = false,
.need_dbp = true,
.has_wakeirq = false,
+ .has_lsco = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -562,6 +658,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {
.wpr = 0x24,
.sr = 0x0C, /* set to ISR offset to ease alarm management */
.scr = UNDEF_REG,
+ .cfgr = UNDEF_REG,
.verr = UNDEF_REG,
},
.events = {
@@ -574,6 +671,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = {
.has_pclk = true,
.need_dbp = true,
.has_wakeirq = false,
+ .has_lsco = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -584,6 +682,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = {
.wpr = 0x24,
.sr = 0x0C, /* set to ISR offset to ease alarm management */
.scr = UNDEF_REG,
+ .cfgr = UNDEF_REG,
.verr = UNDEF_REG,
},
.events = {
@@ -605,6 +704,7 @@ static const struct stm32_rtc_data stm32mp1_data = {
.has_pclk = true,
.need_dbp = false,
.has_wakeirq = true,
+ .has_lsco = true,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -615,6 +715,7 @@ static const struct stm32_rtc_data stm32mp1_data = {
.wpr = 0x24,
.sr = 0x50,
.scr = 0x5C,
+ .cfgr = 0x60,
.verr = 0x3F4,
},
.events = {
@@ -821,6 +922,21 @@ static int stm32_rtc_probe(struct platform_device *pdev)
goto err;
}
+ if (rtc->data->has_lsco) {
+ ret = of_property_read_s32(pdev->dev.of_node,
+ "st,lsco", &rtc->lsco);
+ if (!ret) {
+ ret = stm32_rtc_clk_lsco_register(pdev);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "LSCO clock registration failed: %d\n",
+ ret);
+ } else {
+ rtc->lsco = ret;
+ dev_dbg(&pdev->dev, "No LSCO clock: %d\n", ret);
+ }
+ }
+
/*
* If INITS flag is reset (calendar year field set to 0x00), calendar
* must be initialized
@@ -857,6 +973,9 @@ static int stm32_rtc_remove(struct platform_device *pdev)
const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int cr;
+ if (!IS_ERR_OR_NULL(rtc->clk_lsco))
+ clk_unregister_gate(rtc->clk_lsco);
+
/* Disable interrupts */
stm32_rtc_wpr_unlock(rtc);
cr = readl_relaxed(rtc->base + regs->cr);
diff --git a/include/dt-bindings/rtc/rtc-stm32.h b/include/dt-bindings/rtc/rtc-stm32.h
new file mode 100644
index 0000000..4373c4d
--- /dev/null
+++ b/include/dt-bindings/rtc/rtc-stm32.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides constants for STM32_RTC bindings.
+ */
+
+#ifndef _DT_BINDINGS_RTC_RTC_STM32_H
+#define _DT_BINDINGS_RTC_RTC_STM32_H
+
+#define RTC_OUT1 0
+#define RTC_OUT2 1
+#define RTC_OUT2_RMP 2
+
+#endif
--
2.7.4

View File

@ -1,658 +0,0 @@
From 62a47162dba55286160a68ac2b46d405142b2830 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Mon, 9 Dec 2019 12:26:14 +0100
Subject: [PATCH 23/31] ARM stm32mp1 r3 SOC
---
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/st/Kconfig | 17 +++
drivers/soc/st/Makefile | 2 +
drivers/soc/st/stm32_hdp.c | 242 ++++++++++++++++++++++++++++++++++++
drivers/soc/st/stm32_pm_domain.c | 212 +++++++++++++++++++++++++++++++
include/dt-bindings/soc/stm32-hdp.h | 108 ++++++++++++++++
7 files changed, 583 insertions(+)
create mode 100644 drivers/soc/st/Kconfig
create mode 100644 drivers/soc/st/Makefile
create mode 100644 drivers/soc/st/stm32_hdp.c
create mode 100644 drivers/soc/st/stm32_pm_domain.c
create mode 100644 include/dt-bindings/soc/stm32-hdp.h
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 f0d46b1..d2c3147 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..8ab6049
--- /dev/null
+++ b/drivers/soc/st/Kconfig
@@ -0,0 +1,17 @@
+if ARCH_STM32
+
+config STM32_PM_DOMAINS
+ bool "STM32 PM domains"
+ depends on MACH_STM32MP157
+ select PM_GENERIC_DOMAINS
+ default y if MACH_STM32MP157
+
+config STM32_HDP
+ bool "STMicroelectronics STM32MP157 Hardware Debug Port (HDP) pin control"
+ depends on MACH_STM32MP157
+ default n if MACH_STM32MP157
+ help
+ The Hardware Debug Port allows the observation of internal signals. By using multiplexers,
+ up to 16 signals for each of 8-bit output can be observed.
+
+endif # ARCH_STM32
diff --git a/drivers/soc/st/Makefile b/drivers/soc/st/Makefile
new file mode 100644
index 0000000..85905b7
--- /dev/null
+++ b/drivers/soc/st/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_STM32_PM_DOMAINS) += stm32_pm_domain.o
+obj-$(CONFIG_STM32_HDP) += stm32_hdp.o
diff --git a/drivers/soc/st/stm32_hdp.c b/drivers/soc/st/stm32_hdp.c
new file mode 100644
index 0000000..6408ac6
--- /dev/null
+++ b/drivers/soc/st/stm32_hdp.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Christophe Roullier <christophe.roullier@st.com>
+ * for STMicroelectronics.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+
+#define HDP_CTRL_ENABLE 1
+#define HDP_CTRL_DISABLE 0
+
+enum {
+ HDP_CTRL = 0,
+ HDP_MUX = 0x4,
+ HDP_VAL = 0x10,
+ HDP_GPOSET = 0x14,
+ HDP_GPOCLR = 0x18,
+ HDP_GPOVAL = 0x1c,
+ HDP_VERR = 0x3f4,
+ HDP_IPIDR = 0x3f8,
+ HDP_SIDR = 0x3fc
+} HDP_register_offsets;
+
+struct data_priv {
+ struct clk *clk;
+ int clk_is_enabled;
+ struct dentry *pwr_dentry;
+ unsigned char __iomem *hdp_membase;
+ unsigned int hdp_ctrl;
+ unsigned int hdp_mux;
+};
+
+/* enable/disable */
+static int stm32_hdp_enable_set(void *data, int val)
+{
+ struct data_priv *e = (struct data_priv *)data;
+
+ if (!e->clk)
+ return -EPERM;
+
+ if (val == 1) {
+ if (clk_prepare_enable(e->clk) < 0) {
+ pr_err("Failed to enable HDP clock\n");
+ return -EPERM;
+ }
+ e->clk_is_enabled = 1;
+ } else {
+ clk_disable_unprepare(e->clk);
+ e->clk_is_enabled = 0;
+ }
+ return 0;
+}
+
+static int stm32_hdp_fops_set(void *data, u64 val)
+{
+ unsigned char __iomem *addr = (unsigned char __iomem *)data;
+
+ writel_relaxed(val, addr);
+
+ return 0;
+}
+
+static int stm32_hdp_fops_get(void *data, u64 *val)
+{
+ unsigned char __iomem *addr = (unsigned char __iomem *)data;
+
+ *val = readl_relaxed(addr);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(stm32_hdp_fops, stm32_hdp_fops_get,
+ stm32_hdp_fops_set, "0x%llx\n");
+
+int stm32_hdp_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+
+ struct data_priv *data;
+ struct dentry *r;
+
+ int ret;
+ const __be32 *getmuxing;
+ u32 muxing, version;
+
+ if (!np)
+ return -ENODEV;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(struct data_priv), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->hdp_membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data->hdp_membase))
+ return PTR_ERR(data->hdp_membase);
+
+ /* Get HDP clocks */
+ data->clk = devm_clk_get(dev, "hdp");
+ if (IS_ERR(data->clk)) {
+ dev_err(dev, "No HDP CK clock provided...\n");
+ return PTR_ERR(data->clk);
+ }
+
+ /* Enable clock */
+ ret = stm32_hdp_enable_set(data, 1);
+ if (ret != 0)
+ return ret;
+
+ getmuxing = of_get_property(np, "muxing-hdp", NULL);
+ if (!getmuxing) {
+ dev_err(dev,
+ "no muxing-hdp property in node\n");
+ /* Disable clock */
+ ret = stm32_hdp_enable_set(data, 0);
+ if (ret != 0)
+ return ret;
+
+ return -EINVAL;
+ }
+
+ /* add hdp directory */
+ r = debugfs_create_dir("hdp", NULL);
+ if (!r) {
+ dev_err(dev, "Unable to create HDP debugFS\n");
+ /* Disable clock */
+ ret = stm32_hdp_enable_set(data, 0);
+ if (ret != 0)
+ return ret;
+
+ return -ENODEV;
+ }
+
+ debugfs_create_file("ctrl", 0644, r,
+ data->hdp_membase + HDP_CTRL, &stm32_hdp_fops);
+ debugfs_create_file("mux", 0644, r,
+ data->hdp_membase + HDP_MUX, &stm32_hdp_fops);
+ debugfs_create_file("val", 0644, r,
+ data->hdp_membase + HDP_VAL, &stm32_hdp_fops);
+ debugfs_create_file("gposet", 0644, r,
+ data->hdp_membase + HDP_GPOSET, &stm32_hdp_fops);
+ debugfs_create_file("gpoclr", 0644, r,
+ data->hdp_membase + HDP_GPOCLR, &stm32_hdp_fops);
+ debugfs_create_file("gpoval", 0644, r,
+ data->hdp_membase + HDP_GPOVAL, &stm32_hdp_fops);
+
+ /* Enable HDP */
+ writel(HDP_CTRL_ENABLE, data->hdp_membase + HDP_CTRL);
+
+ /* HDP Multiplexing */
+ muxing = of_read_number(getmuxing,
+ of_n_addr_cells(np));
+
+ writel(muxing, data->hdp_membase + HDP_MUX);
+
+ platform_set_drvdata(pdev, data);
+
+ /* Get Majeur, Minor version */
+ version = readl(data->hdp_membase + HDP_VERR);
+
+ dev_info(dev, "STM32 HDP version %d.%d initialized\n",
+ version >> 4, version & 0x0F);
+
+ return 0;
+}
+
+static int stm32_hdp_remove(struct platform_device *pdev)
+{
+ struct data_priv *data = platform_get_drvdata(pdev);
+
+ /* Disable HDP */
+ writel(HDP_CTRL_DISABLE, data->hdp_membase + HDP_CTRL);
+
+ if (data->clk) {
+ if (data->clk_is_enabled)
+ clk_disable_unprepare(data->clk);
+ }
+
+ pr_info("driver STM32 HDP removed\n");
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int stm32_hdp_suspend(struct device *dev)
+{
+ struct data_priv *data = dev_get_drvdata(dev);
+
+ data->hdp_ctrl = readl_relaxed(data->hdp_membase + HDP_CTRL);
+ data->hdp_mux = readl_relaxed(data->hdp_membase + HDP_MUX);
+
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static int stm32_hdp_resume(struct device *dev)
+{
+ struct data_priv *data = dev_get_drvdata(dev);
+
+ writel_relaxed(data->hdp_ctrl, data->hdp_membase + HDP_CTRL);
+ writel_relaxed(data->hdp_mux, data->hdp_membase + HDP_MUX);
+
+ pinctrl_pm_select_default_state(dev);
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(stm32_hdp_pm_ops,
+ stm32_hdp_suspend,
+ stm32_hdp_resume);
+
+static const struct of_device_id hdp_match[] = {
+ { .compatible = "st,stm32mp1-hdp",},
+ { }
+};
+MODULE_DEVICE_TABLE(of, hdp_match);
+
+static struct platform_driver hdp_driver = {
+ .probe = stm32_hdp_probe,
+ .remove = stm32_hdp_remove,
+ .driver = {
+ .name = "hdp",
+ .of_match_table = hdp_match,
+ .pm = &stm32_hdp_pm_ops,
+ },
+};
+
+module_platform_driver(hdp_driver);
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/include/dt-bindings/soc/stm32-hdp.h b/include/dt-bindings/soc/stm32-hdp.h
new file mode 100644
index 0000000..d986653
--- /dev/null
+++ b/include/dt-bindings/soc/stm32-hdp.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Roullier Christophe <christophe.roullier@st.com>
+ * for STMicroelectronics.
+ */
+
+#ifndef _DT_BINDINGS_STM32_HDP_H
+#define _DT_BINDINGS_STM32_HDP_H
+
+#define STM32_HDP(port, value) ((value) << ((port) * 4))
+
+/* define HDP Pins number*/
+#define HDP0_PWR_PWRWAKE_SYS 0
+#define HDP0_CM4_SLEEPDEEP 1
+#define HDP0_PWR_STDBY_WKUP 2
+#define HDP0_PWR_ENCOMP_VDDCORE 3
+#define HDP0_BSEC_OUT_SEC_NIDEN 4
+#define HDP0_RCC_CM4_SLEEPDEEP 6
+#define HDP0_GPU_DBG7 7
+#define HDP0_DDRCTRL_LP_REQ 8
+#define HDP0_PWR_DDR_RET_ENABLE_N 9
+#define HDP0_GPOVAL_0 15
+
+#define HDP1_PWR_PWRWAKE_MCU 0
+#define HDP1_CM4_HALTED 1
+#define HDP1_CA7_NAXIERRIRQ 2
+#define HDP1_PWR_OKIN_MR 3
+#define HDP1_BSEC_OUT_SEC_DBGEN 4
+#define HDP1_EXTI_SYS_WAKEUP 5
+#define HDP1_RCC_PWRDS_MPU 6
+#define HDP1_GPU_DBG6 7
+#define HDP1_DDRCTRL_DFI_CTRLUPD_REQ 8
+#define HDP1_DDRCTRL_CACTIVE_DDRC_ASR 9
+#define HDP1_GPOVAL_1 15
+
+#define HDP2_PWR_PWRWAKE_MPU 0
+#define HDP2_CM4_RXEV 1
+#define HDP2_CA7_NPMUIRQ1 2
+#define HDP2_CA7_NFIQOUT1 3
+#define HDP2_BSEC_IN_RSTCORE_N 4
+#define HDP2_EXTI_C2_WAKEUP 5
+#define HDP2_RCC_PWRDS_MCU 6
+#define HDP2_GPU_DBG5 7
+#define HDP2_DDRCTRL_DFI_INIT_COMPLETE 8
+#define HDP2_DDRCTRL_PERF_OP_IS_REFRESH 9
+#define HDP2_DDRCTRL_GSKP_DFI_LP_REQ 10
+#define HDP2_GPOVAL_2 15
+
+#define HDP3_PWR_SEL_VTH_VDD_CORE 0
+#define HDP3_CM4_TXEV 1
+#define HDP3_CA7_NPMUIRQ0 2
+#define HDP3_CA7_NFIQOUT0 3
+#define HDP3_BSEC_OUT_SEC_DFTLOCK 4
+#define HDP3_EXTI_C1_WAKEUP 5
+#define HDP3_RCC_PWRDS_SYS 6
+#define HDP3_GPU_DBG4 7
+#define HDP3_DDRCTRL_STAT_DDRC_REG_SELREF_TYPE0 8
+#define HDP3_DDRCTRL_CACTIVE_1 9
+#define HDP3_GPOVAL_3 15
+
+#define HDP4_PWR_PDDS 0
+#define HDP4_CM4_SLEEPING 1
+#define HDP4_CA7_NRESET1 2
+#define HDP4_CA7_NIRQOUT1 3
+#define HDP4_BSEC_OUT_SEC_DFTEN 4
+#define HDP4_BSEC_OUT_SEC_DBGSWENABLE 5
+#define HDP4_ETH_OUT_PMT_INTR_O 6
+#define HDP4_GPU_DBG3 7
+#define HDP4_DDRCTRL_STAT_DDRC_REG_SELREF_TYPE1 8
+#define HDP4_DDRCTRL_CACTIVE_0 9
+#define HDP4_GPOVAL_4 15
+
+#define HDP5_CA7_STANDBYWFIL2 0
+#define HDP5_PWR_VTH_VDDCORE_ACK 1
+#define HDP5_CA7_NRESET0 2
+#define HDP5_CA7_NIRQOUT0 3
+#define HDP5_BSEC_IN_PWROK 4
+#define HDP5_BSEC_OUT_SEC_DEVICEEN 5
+#define HDP5_ETH_OUT_LPI_INTR_O 6
+#define HDP5_GPU_DBG2 7
+#define HDP5_DDRCTRL_CACTIVE_DDRC 8
+#define HDP5_DDRCTRL_WR_CREDIT_CNT 9
+#define HDP5_GPOVAL_5 15
+
+#define HDP6_CA7_STANDBYWFI1 0
+#define HDP6_CA7_STANDBYWFE1 1
+#define HDP6_CA7_EVENT0 2
+#define HDP6_CA7_DBGACK1 3
+#define HDP6_BSEC_OUT_SEC_SPNIDEN 5
+#define HDP6_ETH_OUT_MAC_SPEED_O1 6
+#define HDP6_GPU_DBG1 7
+#define HDP6_DDRCTRL_CSYSACK_DDRC 8
+#define HDP6_DDRCTRL_LPR_CREDIT_CNT 9
+#define HDP6_GPOVAL_6 15
+
+#define HDP7_CA7_STANDBYWFI0 0
+#define HDP7_CA7_STANDBYWFE0 1
+#define HDP7_CA7_DBGACK0 3
+#define HDP7_BSEC_OUT_FUSE_OK 4
+#define HDP7_BSEC_OUT_SEC_SPIDEN 5
+#define HDP7_ETH_OUT_MAC_SPEED_O0 6
+#define HDP7_GPU_DBG0 7
+#define HDP7_DDRCTRL_CSYSREQ_DDRC 8
+#define HDP7_DDRCTRL_HPR_CREDIT_CNT 9
+#define HDP7_GPOVAL_7 15
+
+#endif /* _DT_BINDINGS_STM32_HDP_H */
--
2.7.4

View File

@ -1,689 +0,0 @@
From 69f90684b9d271fe91b53862b3a760d91b0fe7e4 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:46 +0100
Subject: [PATCH 25/31] ARM stm32mp1 r3 THERMAL
---
drivers/thermal/Kconfig | 2 +-
drivers/thermal/Makefile | 2 +-
drivers/thermal/st/Kconfig | 14 +
drivers/thermal/st/Makefile | 1 +
drivers/thermal/st/stm_thermal.c | 604 +++++++++++++++++++++++++++++++++++++++
5 files changed, 621 insertions(+), 2 deletions(-)
create mode 100644 drivers/thermal/st/stm_thermal.c
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..8cafc37
--- /dev/null
+++ b/drivers/thermal/st/stm_thermal.c
@@ -0,0 +1,604 @@
+// 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_ICIFR_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)
+
+/* DTS_ITENR register mask definitions */
+#define ITENR_MASK (GENMASK(2, 0) | GENMASK(6, 4))
+/* DTS_ICIFR register mask definitions */
+#define ICIFR_MASK (GENMASK(2, 0) | GENMASK(6, 4))
+
+/* Less significant bit position definitions */
+#define TS1_T0_POS 16
+#define TS1_HITTHD_POS 16
+#define TS1_LITTHD_POS 0
+#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 30000 /* 30 celsius */
+#define TS1_T0_VAL1 110000 /* 110 celsius */
+#define NO_HW_TRIG 0
+#define SAMPLING_TIME 15
+
+struct stm_thermal_sensor {
+ struct device *dev;
+ struct thermal_zone_device *th_dev;
+ enum thermal_device_mode mode;
+ struct clk *clk;
+ int irq;
+ void __iomem *base;
+ int t0, fmt0, ramp_coeff;
+ int low_en, high_en;
+};
+
+static void stm_thermal_disable_irq(struct stm_thermal_sensor *sensor)
+{
+ u32 itenr;
+
+ /* Disable IT generation */
+ itenr = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
+ itenr &= ~ITENR_MASK;
+ writel_relaxed(itenr, sensor->base + DTS_ITENR_OFFSET);
+}
+
+static void stm_thermal_set_irq_state(struct stm_thermal_sensor *sensor)
+{
+ u32 itenr;
+
+ dev_dbg(sensor->dev, "low:%d high:%d\n", sensor->low_en,
+ sensor->high_en);
+
+ /* Disable IT generation for low and high thresholds */
+ itenr = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
+ itenr &= ~(LOW_THRESHOLD | HIGH_THRESHOLD);
+
+ if (sensor->low_en)
+ itenr |= HIGH_THRESHOLD;
+
+ if (sensor->high_en)
+ itenr |= LOW_THRESHOLD;
+
+ /* Enable interrupts */
+ writel_relaxed(itenr, sensor->base + DTS_ITENR_OFFSET);
+}
+
+static irqreturn_t stm_thermal_alarm_irq_thread(int irq, void *sdata)
+{
+ struct stm_thermal_sensor *sensor = sdata;
+
+ dev_dbg(sensor->dev, "sr:%d\n",
+ readl_relaxed(sensor->base + DTS_SR_OFFSET));
+
+ stm_thermal_disable_irq(sensor);
+
+ thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED);
+
+ stm_thermal_set_irq_state(sensor);
+
+ /* Acknoledge all DTS irqs */
+ writel_relaxed(ICIFR_MASK, sensor->base + DTS_ICIFR_OFFSET);
+
+ 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);
+
+ sensor->mode = THERMAL_DEVICE_ENABLED;
+
+ return 0;
+}
+
+static int stm_sensor_power_off(struct stm_thermal_sensor *sensor)
+{
+ u32 value;
+
+ sensor->mode = THERMAL_DEVICE_DISABLED;
+
+ /* 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;
+
+ /* calculate divider for maximum 1MHz PCLK */
+ prescaler = clk_freq / ONE_MHZ + 1;
+
+ 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) & HSREF_CLK_DIV_MASK;
+
+ /* 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;
+
+ /* Figure out the CLK_PTAT frequency for a given temperature */
+ freqM = ((temp - sensor->t0) * sensor->ramp_coeff) / 1000 +
+ sensor->fmt0;
+
+ /* Figure out the threshold sample number */
+ *th = clk_get_rate(sensor->clk) * SAMPLING_TIME / freqM;
+ if (!*th)
+ return -EINVAL;
+
+ dev_dbg(sensor->dev, "freqM=%d Hz, threshold=0x%x", freqM, *th);
+
+ 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 periods;
+ int freqM, ret;
+
+ if (sensor->mode != THERMAL_DEVICE_ENABLED)
+ return -EAGAIN;
+
+ /* Retrieve the number of periods sampled */
+ ret = readl_relaxed_poll_timeout(sensor->base + DTS_DR_OFFSET, periods,
+ (periods & TS1_MFREQ_MASK),
+ STARTUP_TIME, POLL_TIMEOUT);
+ if (ret)
+ return ret;
+
+ /* Figure out the CLK_PTAT frequency */
+ freqM = (clk_get_rate(sensor->clk) * SAMPLING_TIME) / periods;
+ if (!freqM)
+ return -EINVAL;
+
+ /* Figure out the temperature in mili celsius */
+ *temp = (freqM - sensor->fmt0) * 1000 / sensor->ramp_coeff + sensor->t0;
+
+ dev_dbg(sensor->dev, "periods=0x%x t=%d mC", periods, *temp);
+
+ return 0;
+}
+
+static int stm_thermal_set_trips(void *data, int low, int high)
+{
+ struct stm_thermal_sensor *sensor = data;
+ u32 itr1, th;
+ int ret;
+
+ dev_dbg(sensor->dev, "set trips %d <--> %d\n", low, high);
+
+ /* Erase threshold content */
+ itr1 = readl_relaxed(sensor->base + DTS_ITR1_OFFSET);
+ itr1 &= ~(TS1_LITTHD_MASK | TS1_HITTHD_MASK);
+
+ /*
+ * Disable low-temp if "low" is too small. As per thermal framework
+ * API, we use -INT_MAX rather than INT_MIN.
+ */
+
+ if (low > -INT_MAX) {
+ sensor->low_en = 1;
+ /* add 0.5 of hysteresis due to measurement error */
+ ret = stm_thermal_calculate_threshold(sensor, low - 500, &th);
+ if (ret)
+ return ret;
+
+ itr1 |= (TS1_HITTHD_MASK & (th << TS1_HITTHD_POS));
+ } else {
+ sensor->low_en = 0;
+ }
+
+ /* Disable high-temp if "high" is too big. */
+ if (high < INT_MAX) {
+ sensor->high_en = 1;
+ ret = stm_thermal_calculate_threshold(sensor, high, &th);
+ if (ret)
+ return ret;
+
+ itr1 |= (TS1_LITTHD_MASK & (th << TS1_LITTHD_POS));
+ } else {
+ sensor->high_en = 0;
+ }
+
+ /* Write new threshod values*/
+ writel_relaxed(itr1, sensor->base + DTS_ITR1_OFFSET);
+
+ 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,
+ NULL, 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;
+ }
+
+ dev_dbg(dev, "%s: thermal IRQ registered", __func__);
+
+ return 0;
+}
+
+static int stm_thermal_sensor_off(struct stm_thermal_sensor *sensor)
+{
+ int ret;
+
+ stm_thermal_disable_irq(sensor);
+
+ 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;
+
+ 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;
+
+ return 0;
+
+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;
+
+ 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;
+
+ ret = stm_sensor_power_on(sensor);
+ if (ret)
+ return ret;
+
+ thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED);
+ stm_thermal_set_irq_state(sensor);
+
+ 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,
+ .set_trips = stm_thermal_set_trips,
+};
+
+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;
+ void __iomem *base;
+ int ret;
+
+ 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);
+ }
+
+ stm_thermal_disable_irq(sensor);
+
+ /* Clear irq flags */
+ writel_relaxed(ICIFR_MASK, sensor->base + DTS_ICIFR_OFFSET);
+
+ /* Configure and enable HW sensor */
+ ret = stm_thermal_prepare(sensor);
+ if (ret) {
+ dev_err(&pdev->dev, "Error preprare sensor: %d\n", ret);
+ return ret;
+ }
+
+ ret = stm_sensor_power_on(sensor);
+ if (ret) {
+ dev_err(&pdev->dev, "Error power on sensor: %d\n", 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;
+ }
+
+ /* Register IRQ into GIC */
+ ret = stm_register_irq(sensor);
+ if (ret)
+ goto err_tz;
+
+ stm_thermal_set_irq_state(sensor);
+
+ /*
+ * 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;
+
+ 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

View File

@ -1,361 +0,0 @@
From 918e6c75e00bcae7481c4560ebbca237d991b2c0 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:48 +0100
Subject: [PATCH 27/31] ARM stm32mp1 r3 WATCHDOG
---
drivers/watchdog/Kconfig | 12 ++++
drivers/watchdog/Makefile | 1 +
drivers/watchdog/stm32_iwdg.c | 83 ++++++++++++++++--------
drivers/watchdog/stpmic1_wdt.c | 140 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 211 insertions(+), 25 deletions(-)
create mode 100644 drivers/watchdog/stpmic1_wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index b165c46..9790eca 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/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index e00e3b3..56a3ffd 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -34,18 +34,10 @@
#define KR_KEY_EWA 0x5555 /* write access enable */
#define KR_KEY_DWA 0x0000 /* write access disable */
-/* IWDG_PR register bit values */
-#define PR_4 0x00 /* prescaler set to 4 */
-#define PR_8 0x01 /* prescaler set to 8 */
-#define PR_16 0x02 /* prescaler set to 16 */
-#define PR_32 0x03 /* prescaler set to 32 */
-#define PR_64 0x04 /* prescaler set to 64 */
-#define PR_128 0x05 /* prescaler set to 128 */
-#define PR_256 0x06 /* prescaler set to 256 */
+#define PR_SHIFT 2
/* IWDG_RLR register values */
-#define RLR_MIN 0x07C /* min value supported by reload register */
-#define RLR_MAX 0xFFF /* max value supported by reload register */
+#define RLR_MAX GENMASK(11, 0) /* max value of reload register */
/* IWDG_SR register bit mask */
#define FLAG_PVU BIT(0) /* Watchdog prescaler value update */
@@ -55,15 +47,28 @@
#define TIMEOUT_US 100000
#define SLEEP_US 1000
-#define HAS_PCLK true
+struct stm32_iwdg_data {
+ bool has_pclk;
+ u32 max_prescaler;
+};
+
+static const struct stm32_iwdg_data stm32_iwdg_data = {
+ .has_pclk = false,
+ .max_prescaler = 256,
+};
+
+static const struct stm32_iwdg_data stm32mp1_iwdg_data = {
+ .has_pclk = true,
+ .max_prescaler = 1024,
+};
struct stm32_iwdg {
struct watchdog_device wdd;
+ const struct stm32_iwdg_data *data;
void __iomem *regs;
struct clk *clk_lsi;
struct clk *clk_pclk;
unsigned int rate;
- bool has_pclk;
};
static inline u32 reg_read(void __iomem *base, u32 reg)
@@ -80,21 +85,30 @@ static int stm32_iwdg_start(struct watchdog_device *wdd)
{
struct stm32_iwdg *wdt = watchdog_get_drvdata(wdd);
u32 val = FLAG_PVU | FLAG_RVU;
- u32 reload;
+ u32 timeout, presc, iwdg_rlr, iwdg_pr;
int ret;
dev_dbg(wdd->parent, "%s\n", __func__);
- /* prescaler fixed to 256 */
- reload = clamp_t(unsigned int, ((wdd->timeout * wdt->rate) / 256) - 1,
- RLR_MIN, RLR_MAX);
+ timeout = clamp_t(unsigned int, wdd->timeout,
+ wdd->min_timeout, wdd->max_hw_heartbeat_ms / 1000);
+
+ if (timeout != wdd->timeout)
+ dev_warn(wdd->parent, "timeout skrinked to %d\n", timeout);
+
+ presc = DIV_ROUND_UP(timeout * wdt->rate, RLR_MAX + 1);
+
+ /* The prescaler is align on power of 2 and start at 2 ^ PR_SHIFT. */
+ presc = roundup_pow_of_two(presc);
+ iwdg_pr = presc <= 1 << PR_SHIFT ? 0 : ilog2(presc) - PR_SHIFT;
+ iwdg_rlr = ((timeout * wdt->rate) / presc) - 1;
/* enable write access */
reg_write(wdt->regs, IWDG_KR, KR_KEY_EWA);
/* set prescaler & reload registers */
- reg_write(wdt->regs, IWDG_PR, PR_256); /* prescaler fix to 256 */
- reg_write(wdt->regs, IWDG_RLR, reload);
+ reg_write(wdt->regs, IWDG_PR, iwdg_pr);
+ reg_write(wdt->regs, IWDG_RLR, iwdg_rlr);
reg_write(wdt->regs, IWDG_KR, KR_KEY_ENABLE);
/* wait for the registers to be updated (max 100ms) */
@@ -150,7 +164,7 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev,
}
/* optional peripheral clock */
- if (wdt->has_pclk) {
+ if (wdt->data->has_pclk) {
wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(wdt->clk_pclk)) {
dev_err(&pdev->dev, "Unable to get pclk clock\n");
@@ -191,8 +205,8 @@ static const struct watchdog_ops stm32_iwdg_ops = {
};
static const struct of_device_id stm32_iwdg_of_match[] = {
- { .compatible = "st,stm32-iwdg", .data = (void *)!HAS_PCLK },
- { .compatible = "st,stm32mp1-iwdg", .data = (void *)HAS_PCLK },
+ { .compatible = "st,stm32-iwdg", .data = &stm32_iwdg_data },
+ { .compatible = "st,stm32mp1-iwdg", .data = &stm32mp1_iwdg_data },
{ /* end node */ }
};
MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
@@ -206,14 +220,14 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
int ret;
match = of_match_device(stm32_iwdg_of_match, &pdev->dev);
- if (!match)
+ if (!match || !match->data)
return -ENODEV;
wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
if (!wdt)
return -ENOMEM;
- wdt->has_pclk = match->data;
+ wdt->data = match->data;
/* This is the timer base. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -231,8 +245,9 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
wdd = &wdt->wdd;
wdd->info = &stm32_iwdg_info;
wdd->ops = &stm32_iwdg_ops;
- wdd->min_timeout = ((RLR_MIN + 1) * 256) / wdt->rate;
- wdd->max_hw_heartbeat_ms = ((RLR_MAX + 1) * 256 * 1000) / wdt->rate;
+ wdd->min_timeout = 1;
+ wdd->max_hw_heartbeat_ms = ((RLR_MAX + 1) * wdt->data->max_prescaler *
+ 1000) / wdt->rate;
wdd->parent = &pdev->dev;
watchdog_set_drvdata(wdd, wdt);
@@ -243,6 +258,24 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
dev_warn(&pdev->dev,
"unable to set timeout value, using default\n");
+ /*
+ * In case of CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED is set
+ * (Means U-Boot/bootloaders leaves the watchdog running)
+ * When we get here we should make a decision to prevent
+ * any side effects before user space daemon will take care of it.
+ * The best option, taking into consideration that there is no
+ * way to read values back from hardware, is to enforce watchdog
+ * being run with deterministic values.
+ */
+ if (IS_ENABLED(CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED)) {
+ ret = stm32_iwdg_start(wdd);
+ if (ret)
+ return ret;
+
+ /* Make sure the watchdog is serviced */
+ set_bit(WDOG_HW_RUNNING, &wdd->status);
+ }
+
ret = watchdog_register_device(wdd);
if (ret) {
dev_err(&pdev->dev, "failed to register watchdog device\n");
diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c
new file mode 100644
index 0000000..45d0c54
--- /dev/null
+++ b/drivers/watchdog/stpmic1_wdt.c
@@ -0,0 +1,140 @@
+// 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)
+{
+ struct device *dev = &pdev->dev;
+ int ret;
+ struct stpmic1 *pmic;
+ struct stpmic1_wdt *wdt;
+
+ if (!dev->parent)
+ return -EINVAL;
+
+ pmic = dev_get_drvdata(dev->parent);
+ if (!pmic)
+ return -EINVAL;
+
+ wdt = devm_kzalloc(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.parent = dev;
+
+ wdt->wdtdev.timeout = PMIC_WDT_DEFAULT_TIMEOUT;
+ watchdog_init_timeout(&wdt->wdtdev, 0, dev);
+
+ watchdog_set_nowayout(&wdt->wdtdev, nowayout);
+ watchdog_set_drvdata(&wdt->wdtdev, wdt);
+
+ ret = devm_watchdog_register_device(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

View File

@ -1,253 +0,0 @@
From 9166e19abab21450a32288379f5fb55f44e7a340 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:49 +0100
Subject: [PATCH 29/31] ARM stm32mp1 r2.4 MISC
---
Documentation/remoteproc.txt | 23 ++++++++++++++++++++
arch/arm/Kconfig.debug | 49 ++++++++++++++++++++++++++++++++++++++++--
arch/arm/include/debug/stm32.S | 43 ++++++++++++++++++++++++++++++++++++
include/linux/amba/mmci.h | 11 ++--------
include/media/v4l2-fwnode.h | 2 ++
kernel/power/suspend.c | 1 -
6 files changed, 117 insertions(+), 12 deletions(-)
create mode 100644 arch/arm/include/debug/stm32.S
diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
index 77fb03a..bec2177 100644
--- a/Documentation/remoteproc.txt
+++ b/Documentation/remoteproc.txt
@@ -353,3 +353,26 @@ Of course, RSC_VDEV resource entries are only good enough for static
allocation of virtio devices. Dynamic allocations will also be made possible
using the rpmsg bus (similar to how we already do dynamic allocations of
rpmsg channels; read more about it in rpmsg.txt).
+
+8. System Resource Manager (SRM)
+
+Since some resources are shared (directly or not) between the processors, a
+processor cannot manage such resources without potentially impacting the other
+processors : as an example, if a processor changes the frequency of a clock, the
+frequency of another clock managed by another processor may be updated too.
+
+The System Resource Manager prevents such resource conflicts between the
+processors : it reserves and initializes the system resources of the peripherals
+assigned to a remote processor.
+
+As of today the following resources are controlled by the SRM:
+- clocks
+- gpios (pinctrl)
+- regulators (power supplies)
+
+The SRM is implemented as an 'rproc_subdev' and registered to remoteproc_core.
+Unlike the virtio device (vdev), the SRM subdev is probed *before* the rproc
+boots, ensuring the availability of the resources before the remoteproc starts.
+
+The resources handled by the SRM are defined in the DeviceTree: please read
+Documentation/devicetree/bindings/remoteproc/rproc-srm.txt for details.
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index bee0ba1..b402db6 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1191,6 +1191,42 @@ choice
If unsure, say N.
+ config STM32F4_DEBUG_UART
+ bool "Use STM32F4 UART for low-level debug"
+ depends on ARCH_STM32 && ARM_SINGLE_ARMV7M
+ 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, but another UART instance can be selected by modifying
+ CONFIG_DEBUG_UART_PHYS.
+
+ If unsure, say N.
+
+ config STM32F7_DEBUG_UART
+ bool "Use STM32F7 UART for low-level debug"
+ depends on ARCH_STM32 && ARM_SINGLE_ARMV7M
+ 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, but another UART instance can be selected by modifying
+ CONFIG_DEBUG_UART_PHYS.
+
+ If unsure, say N.
+
+ config STM32MP1_DEBUG_UART
+ bool "Use STM32MP1 UART for low-level debug"
+ depends on ARCH_STM32 && ARCH_MULTI_V7
+ select DEBUG_STM32_UART
+ help
+ Say Y here if you want kernel low-level debugging support
+ on STM32MP1 based platforms, wich default UART is wired on
+ UART4, but another UART instance can be selected by modifying
+ CONFIG_DEBUG_UART_PHYS and CONFIG_DEBUG_UART_VIRT.
+
+ 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
@@ -1475,6 +1511,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
@@ -1524,6 +1564,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
@@ -1587,6 +1628,8 @@ config DEBUG_UART_PHYS
default 0x3e000000 if DEBUG_BCM_KONA_UART
default 0x3f201000 if DEBUG_BCM2836
default 0x4000e400 if DEBUG_LL_UART_EFM32
+ default 0x40010000 if STM32MP1_DEBUG_UART
+ default 0x40011000 if STM32F4_DEBUG_UART || STM32F7_DEBUG_UART
default 0x40028000 if DEBUG_AT91_SAMV7_USART1
default 0x40081000 if DEBUG_LPC18XX_UART0
default 0x40090000 if DEBUG_LPC32XX
@@ -1681,10 +1724,12 @@ config DEBUG_UART_PHYS
DEBUG_S3C64XX_UART || \
DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
- DEBUG_AT91_UART
+ DEBUG_AT91_UART || STM32F4_DEBUG_UART || \
+ STM32F7_DEBUG_UART || STM32MP1_DEBUG_UART
config DEBUG_UART_VIRT
hex "Virtual base address of debug UART"
+ default 0xfe010000 if STM32MP1_DEBUG_UART
default 0xc881f000 if DEBUG_RV1108_UART2
default 0xc8821000 if DEBUG_RV1108_UART1
default 0xc8912000 if DEBUG_RV1108_UART0
@@ -1797,7 +1842,7 @@ config DEBUG_UART_VIRT
DEBUG_S3C64XX_UART || \
DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
- DEBUG_AT91_UART
+ DEBUG_AT91_UART || STM32MP1_DEBUG_UART
config DEBUG_UART_8250_SHIFT
int "Register offset shift for the 8250 debug UART"
diff --git a/arch/arm/include/debug/stm32.S b/arch/arm/include/debug/stm32.S
new file mode 100644
index 0000000..3353a81
--- /dev/null
+++ b/arch/arm/include/debug/stm32.S
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics SA 2017 - All Rights Reserved
+ * Author: Gerald Baeza <gerald.baeza@st.com> for STMicroelectronics.
+ */
+
+#ifdef CONFIG_STM32F4_DEBUG_UART
+#define STM32_USART_SR_OFF 0x00
+#define STM32_USART_TDR_OFF 0x04
+#endif
+
+#if defined(CONFIG_STM32F7_DEBUG_UART) || defined(CONFIG_STM32MP1_DEBUG_UART)
+#define STM32_USART_SR_OFF 0x1C
+#define STM32_USART_TDR_OFF 0x28
+#endif
+
+#define STM32_USART_TC (1 << 6) /* Tx complete */
+#define STM32_USART_TXE (1 << 7) /* Tx data reg empty */
+
+.macro addruart, rp, rv, tmp
+ ldr \rp, =CONFIG_DEBUG_UART_PHYS @ physical base
+#if defined(CONFIG_MMU)
+ ldr \rv, =CONFIG_DEBUG_UART_VIRT @ virt base
+#else
+ ldr \rv, =CONFIG_DEBUG_UART_PHYS @ same as physical base
+#endif
+.endm
+
+.macro senduart,rd,rx
+ strb \rd, [\rx, #STM32_USART_TDR_OFF]
+.endm
+
+.macro waituart,rd,rx
+1001: ldr \rd, [\rx, #(STM32_USART_SR_OFF)] @ Read Status Register
+ tst \rd, #STM32_USART_TXE @ TXE = 1 = tx empty
+ beq 1001b
+.endm
+
+.macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #(STM32_USART_SR_OFF)] @ Read Status Register
+ tst \rd, #STM32_USART_TC @ TC = 1 = tx complete
+ beq 1001b
+.endm
diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h
index da8357b..c92ebc3 100644
--- a/include/linux/amba/mmci.h
+++ b/include/linux/amba/mmci.h
@@ -18,20 +18,13 @@
* mask into a value to be binary (or set some other custom bits
* in MMCIPWR) or:ed and written into the MMCIPWR register of the
* block. May also control external power based on the power_mode.
- * @status: if no GPIO read function was given to the block in
- * gpio_wp (below) this function will be called to determine
- * whether a card is present in the MMC slot or not
- * @gpio_wp: read this GPIO pin to see if the card is write protected
- * @gpio_cd: read this GPIO pin to detect card insertion
- * @cd_invert: true if the gpio_cd pin value is active low
+ * @status: if no GPIO line was given to the block in this function will
+ * be called to determine whether a card is present in the MMC slot or not
*/
struct mmci_platform_data {
unsigned int ocr_mask;
int (*ios_handler)(struct device *, struct mmc_ios *);
unsigned int (*status)(struct device *);
- int gpio_wp;
- int gpio_cd;
- bool cd_invert;
};
#endif
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;
};
/**
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

View File

@ -0,0 +1,58 @@
From fda596ab13299af0f9cebfa8f9bde2827b02a2b3 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:36:29 +0200
Subject: [PATCH 01/23] ARM-stm32mp1-r1-MACHINE
---
arch/arm/kernel/time.c | 2 ++
arch/arm/mach-stm32/Kconfig | 1 +
arch/arm/mach-stm32/board-dt.c | 2 ++
3 files changed, 5 insertions(+)
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index b996b2cf0..dddc7ebf4 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -9,6 +9,7 @@
* reading the RTC at bootup, etc...
*/
#include <linux/clk-provider.h>
+#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/errno.h>
#include <linux/export.h>
@@ -107,5 +108,6 @@ void __init time_init(void)
of_clk_init(NULL);
#endif
timer_probe();
+ tick_setup_hrtimer_broadcast();
}
}
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
index 57699bd8f..8f9fd1da9 100644
--- a/arch/arm/mach-stm32/Kconfig
+++ b/arch/arm/mach-stm32/Kconfig
@@ -46,6 +46,7 @@ if ARCH_MULTI_V7
config MACH_STM32MP157
bool "STMicroelectronics STM32MP157"
select ARM_ERRATA_814220
+ select REGULATOR
default y
endif # ARMv7-A
diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c
index 011d57b48..8e06a9442 100644
--- a/arch/arm/mach-stm32/board-dt.c
+++ b/arch/arm/mach-stm32/board-dt.c
@@ -17,6 +17,8 @@ static const char *const stm32_compat[] __initconst = {
"st,stm32f746",
"st,stm32f769",
"st,stm32h743",
+ "st,stm32mp151",
+ "st,stm32mp153",
"st,stm32mp157",
NULL
};
--
2.17.1

View File

@ -1,21 +1,22 @@
From 704a13efcc696fa4d151b741e0882f4c42eef870 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Thu, 30 Jan 2020 15:28:05 +0100
Subject: [PATCH 02/31] ARM stm32mp1 r3 CPUFREQ
From 14bcead6b5ca532f85cffadab2753cc044002f86 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:37:04 +0200
Subject: [PATCH 02/23] ARM-stm32mp1-r1-CPUFREQ
---
drivers/cpufreq/Kconfig.arm | 7 +++
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
drivers/cpufreq/stm32-cpufreq.c | 99 ++++++++++++++++++++++++++++++++++++
4 files changed, 108 insertions(+)
drivers/cpufreq/Kconfig.arm | 7 ++
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
drivers/cpufreq/stm32-cpufreq.c | 101 +++++++++++++++++++++++++++
drivers/opp/core.c | 11 ++-
5 files changed, 120 insertions(+), 1 deletion(-)
create mode 100644 drivers/cpufreq/stm32-cpufreq.c
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 0cd8eb7..b950d5a 100644
index a905796f7..b2beb1708 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -255,6 +255,13 @@ config ARM_STI_CPUFREQ
@@ -295,6 +295,13 @@ config ARM_STI_CPUFREQ
this config option if you wish to add CPUFreq support for STi based
SoCs.
@ -30,22 +31,22 @@ index 0cd8eb7..b950d5a 100644
bool
depends on CPUFREQ_DT && ARCH_TANGO
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index c1ffeab..c15b4f7 100644
index 9a9f5ccd1..6139d2aeb 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ) += scmi-cpufreq.o
@@ -80,6 +80,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ) += scmi-cpufreq.o
obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o
obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o
+obj-$(CONFIG_ARM_STM32_CPUFREQ) += stm32-cpufreq.o
obj-$(CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM) += sun50i-cpufreq-nvmem.o
obj-$(CONFIG_ARM_TANGO_CPUFREQ) += tango-cpufreq.o
obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o
obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index fe14c57..d61a02a 100644
index bca8d1f47..7ac5715e4 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -121,6 +121,7 @@ static const struct of_device_id blacklist[] __initconst = {
@@ -131,6 +131,7 @@ static const struct of_device_id blacklist[] __initconst = {
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
@ -55,10 +56,10 @@ index fe14c57..d61a02a 100644
diff --git a/drivers/cpufreq/stm32-cpufreq.c b/drivers/cpufreq/stm32-cpufreq.c
new file mode 100644
index 0000000..f4a41e0
index 000000000..35fb3520d
--- /dev/null
+++ b/drivers/cpufreq/stm32-cpufreq.c
@@ -0,0 +1,99 @@
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
@ -115,7 +116,9 @@ index 0000000..f4a41e0
+ priv->opps = dev_pm_opp_set_supported_hw(cpu_dev, &supported_hw, 1);
+ if (IS_ERR(priv->opps)) {
+ ret = PTR_ERR(priv->opps);
+ dev_err(&pdev->dev, "Failed to set supported opp: %d\n", ret);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to set supported opp: %d\n",
+ ret);
+ return ret;
+ }
+
@ -158,6 +161,37 @@ index 0000000..f4a41e0
+MODULE_DESCRIPTION("STM32 CPU freq driver");
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 9ff0538ee..1974bf21f 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -980,9 +980,14 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
opp_table->clk = clk_get(dev, NULL);
if (IS_ERR(opp_table->clk)) {
ret = PTR_ERR(opp_table->clk);
- if (ret != -EPROBE_DEFER)
+ if (ret != -EPROBE_DEFER) {
dev_dbg(dev, "%s: Couldn't find clock: %d\n", __func__,
ret);
+ }
+ else {
+ kfree(opp_table);
+ return ERR_PTR(-EPROBE_DEFER);
+ }
}
BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head);
@@ -1443,6 +1448,10 @@ struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev,
struct opp_table *opp_table;
opp_table = dev_pm_opp_get_opp_table(dev);
+
+ if (PTR_ERR(opp_table) == -EPROBE_DEFER)
+ return opp_table;
+
if (!opp_table)
return ERR_PTR(-ENOMEM);
--
2.7.4
2.17.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,231 @@
From 31ac3e358c9c6303d58c3f24fe33b6924a56bddd Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:39:52 +0200
Subject: [PATCH 04/23] ARM-stm32mp1-r1-RNG-DEBUG-NVMEM
---
arch/arm/Kconfig.debug | 42 +++++++++++++++++++++++++-----
arch/arm/include/debug/stm32.S | 9 +++----
drivers/char/hw_random/stm32-rng.c | 5 +++-
drivers/nvmem/core.c | 37 ++++++++++++++++++++++++++
include/linux/nvmem-consumer.h | 7 +++++
5 files changed, 88 insertions(+), 12 deletions(-)
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 8bcbd0cd7..3357e294a 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1201,23 +1201,49 @@ choice
config STM32F4_DEBUG_UART
bool "Use STM32F4 UART for low-level debug"
- depends on ARCH_STM32
+ depends on MACH_STM32F429 || MACH_STM32F469
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.
+ USART1, but another UART instance can be selected by modifying
+ CONFIG_DEBUG_UART_PHYS.
If unsure, say N.
config STM32F7_DEBUG_UART
bool "Use STM32F7 UART for low-level debug"
- depends on ARCH_STM32
+ depends on MACH_STM32F746 || MACH_STM32F769
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.
+ USART1, but another UART instance can be selected by modifying
+ CONFIG_DEBUG_UART_PHYS.
+
+ If unsure, say N.
+
+ config STM32H7_DEBUG_UART
+ bool "Use STM32H7 UART for low-level debug"
+ depends on MACH_STM32H743
+ select DEBUG_STM32_UART
+ help
+ Say Y here if you want kernel low-level debugging support
+ on STM32H7 based platforms, which default UART is wired on
+ USART1, but another UART instance can be selected by modifying
+ CONFIG_DEBUG_UART_PHYS.
+
+ If unsure, say N.
+
+ config STM32MP1_DEBUG_UART
+ bool "Use STM32MP1 UART for low-level debug"
+ depends on MACH_STM32MP157
+ select DEBUG_STM32_UART
+ help
+ Say Y here if you want kernel low-level debugging support
+ on STM32MP1 based platforms, wich default UART is wired on
+ UART4, but another UART instance can be selected by modifying
+ CONFIG_DEBUG_UART_PHYS and CONFIG_DEBUG_UART_VIRT.
If unsure, say N.
@@ -1619,6 +1645,9 @@ config DEBUG_UART_PHYS
default 0x3e000000 if DEBUG_BCM_KONA_UART
default 0x3f201000 if DEBUG_BCM2836
default 0x4000e400 if DEBUG_LL_UART_EFM32
+ default 0x40010000 if STM32MP1_DEBUG_UART
+ default 0x40011000 if STM32F4_DEBUG_UART || STM32F7_DEBUG_UART || \
+ STM32H7_DEBUG_UART
default 0x40028000 if DEBUG_AT91_SAMV7_USART1
default 0x40081000 if DEBUG_LPC18XX_UART0
default 0x40090000 if DEBUG_LPC32XX
@@ -1713,7 +1742,7 @@ config DEBUG_UART_PHYS
DEBUG_S3C64XX_UART || \
DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
- DEBUG_AT91_UART
+ DEBUG_AT91_UART || DEBUG_STM32_UART
config DEBUG_UART_VIRT
hex "Virtual base address of debug UART"
@@ -1779,6 +1808,7 @@ config DEBUG_UART_VIRT
default 0xfcfe8600 if DEBUG_BCM63XX_UART
default 0xfd000000 if DEBUG_SPEAR3XX || DEBUG_SPEAR13XX
default 0xfd883000 if DEBUG_ALPINE_UART0
+ default 0xfe010000 if STM32MP1_DEBUG_UART
default 0xfe017000 if DEBUG_MMP_UART2
default 0xfe018000 if DEBUG_MMP_UART3
default 0xfe100000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART
@@ -1823,7 +1853,7 @@ config DEBUG_UART_VIRT
DEBUG_S3C64XX_UART || \
DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
- DEBUG_AT91_UART
+ DEBUG_AT91_UART || DEBUG_STM32_UART
config DEBUG_UART_8250_SHIFT
int "Register offset shift for the 8250 debug UART"
diff --git a/arch/arm/include/debug/stm32.S b/arch/arm/include/debug/stm32.S
index 1abb32f68..6446e4692 100644
--- a/arch/arm/include/debug/stm32.S
+++ b/arch/arm/include/debug/stm32.S
@@ -4,14 +4,13 @@
* Author: Gerald Baeza <gerald.baeza@st.com> for STMicroelectronics.
*/
-#define STM32_UART_BASE 0x40011000 /* USART1 */
-
#ifdef CONFIG_STM32F4_DEBUG_UART
#define STM32_USART_SR_OFF 0x00
#define STM32_USART_TDR_OFF 0x04
#endif
-#ifdef CONFIG_STM32F7_DEBUG_UART
+#if defined(CONFIG_STM32F7_DEBUG_UART) || (CONFIG_STM32H7_DEBUG_UART) || \
+ defined(CONFIG_STM32MP1_DEBUG_UART)
#define STM32_USART_SR_OFF 0x1C
#define STM32_USART_TDR_OFF 0x28
#endif
@@ -20,8 +19,8 @@
#define STM32_USART_TXE (1 << 7) /* Tx data reg empty */
.macro addruart, rp, rv, tmp
- ldr \rp, =STM32_UART_BASE @ physical base
- ldr \rv, =STM32_UART_BASE @ virt base /* NoMMU */
+ ldr \rp, =CONFIG_DEBUG_UART_PHYS @ physical base
+ ldr \rv, =CONFIG_DEBUG_UART_VIRT @ virt base
.endm
.macro senduart,rd,rx
diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 38324c2dd..a25c4b5c3 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -135,7 +135,10 @@ static int stm32_rng_probe(struct platform_device *ofdev)
return PTR_ERR(priv->clk);
priv->rst = devm_reset_control_get(&ofdev->dev, NULL);
- if (!IS_ERR(priv->rst)) {
+ if (IS_ERR(priv->rst)) {
+ if (PTR_ERR(priv->rst) != -ENOENT)
+ return PTR_ERR(priv->rst);
+ } else {
reset_control_assert(priv->rst);
udelay(2);
reset_control_deassert(priv->rst);
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 960542dea..8105fe423 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -1080,6 +1080,43 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
}
EXPORT_SYMBOL_GPL(nvmem_cell_write);
+/**
+ * nvmem_cell_read_u8() - Read a cell value as an u8
+ *
+ * @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_u8(struct device *dev, const char *cell_id, u8 *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_u8);
+
/**
* nvmem_cell_read_u16() - Read a cell value as an u16
*
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 5c17cb733..c3c53a63e 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -61,6 +61,7 @@ void nvmem_cell_put(struct nvmem_cell *cell);
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_u8(struct device *dev, const char *cell_id, u8 *val);
int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val);
int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val);
@@ -123,6 +124,12 @@ static inline int nvmem_cell_write(struct nvmem_cell *cell,
return -EOPNOTSUPP;
}
+static inline int nvmem_cell_read_u8(struct device *dev,
+ const char *cell_id, u8 *val)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int nvmem_cell_read_u16(struct device *dev,
const char *cell_id, u16 *val)
{
--
2.17.1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,253 @@
From 9e9f45cd3d4887d9af58da15e627443838da1645 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:41:46 +0200
Subject: [PATCH 08/23] ARM-stm32mp1-r1-HWSPINLOCK
---
Documentation/hwspinlock.txt | 10 ++-
drivers/hwspinlock/hwspinlock_core.c | 82 ++++++++++++++++++------
drivers/hwspinlock/hwspinlock_internal.h | 2 +
3 files changed, 73 insertions(+), 21 deletions(-)
diff --git a/Documentation/hwspinlock.txt b/Documentation/hwspinlock.txt
index 6f03713b7..605bd2dc8 100644
--- a/Documentation/hwspinlock.txt
+++ b/Documentation/hwspinlock.txt
@@ -54,9 +54,11 @@ Should be called from a process context (might sleep).
struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
Assign a specific hwspinlock id and return its address, or NULL
-if that hwspinlock is already in use. Usually board code will
-be calling this function in order to reserve specific hwspinlock
-ids for predefined purposes.
+if that hwspinlock is already in use and not shared. If that specific
+hwspinlock is declared as shared, it can be requested and used by
+several users.
+Usually board code will be calling this function in order to reserve
+specific hwspinlock ids for predefined purposes.
Should be called from a process context (might sleep).
@@ -449,11 +451,13 @@ of which represents a single hardware lock::
* struct hwspinlock - this struct represents a single hwspinlock instance
* @bank: the hwspinlock_device structure which owns this lock
* @lock: initialized and used by hwspinlock core
+ * @refcount: number of users (when shared)
* @priv: private data, owned by the underlying platform-specific hwspinlock drv
*/
struct hwspinlock {
struct hwspinlock_device *bank;
spinlock_t lock;
+ unsigned int refcount;
void *priv;
};
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
index 8862445aa..ac76631c7 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -29,6 +29,8 @@
/* radix tree tags */
#define HWSPINLOCK_UNUSED (0) /* tags an hwspinlock as unused */
+#define HWSPINLOCK_EXCLUSIVE (1) /* tags an hwspinlock as exclusive */
+#define HWSPINLOCK_SHARED (2) /* tags an hwspinlock as shared */
/*
* A radix tree is used to maintain the available hwspinlock instances.
@@ -308,7 +310,7 @@ EXPORT_SYMBOL_GPL(__hwspin_unlock);
* @hwlock_spec: hwlock specifier as found in the device tree
*
* This is a simple translation function, suitable for hwspinlock platform
- * drivers that only has a lock specifier length of 1.
+ * drivers that only has a lock specifier length of 1 or 2.
*
* Returns a relative index of the lock within a specified bank on success,
* or -EINVAL on invalid specifier cell count.
@@ -316,7 +318,8 @@ EXPORT_SYMBOL_GPL(__hwspin_unlock);
static inline int
of_hwspin_lock_simple_xlate(const struct of_phandle_args *hwlock_spec)
{
- if (WARN_ON(hwlock_spec->args_count != 1))
+ if (WARN_ON(hwlock_spec->args_count != 1 &&
+ hwlock_spec->args_count != 2))
return -EINVAL;
return hwlock_spec->args[0];
@@ -339,11 +342,12 @@ of_hwspin_lock_simple_xlate(const struct of_phandle_args *hwlock_spec)
int of_hwspin_lock_get_id(struct device_node *np, int index)
{
struct of_phandle_args args;
- struct hwspinlock *hwlock;
+ struct hwspinlock *hwlock, *tmp;
struct radix_tree_iter iter;
void **slot;
int id;
int ret;
+ unsigned int tag;
ret = of_parse_phandle_with_args(np, "hwlocks", "#hwlock-cells", index,
&args);
@@ -383,6 +387,37 @@ int of_hwspin_lock_get_id(struct device_node *np, int index)
}
id += hwlock->bank->base_id;
+ /* Set the EXCLUSIVE / SHARED tag */
+ if (args.args_count == 2 && args.args[1]) {
+ /* Tag SHARED unless already tagged EXCLUSIVE */
+ if (radix_tree_tag_get(&hwspinlock_tree, id,
+ HWSPINLOCK_EXCLUSIVE)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ tag = HWSPINLOCK_SHARED;
+ } else {
+ /* Tag EXCLUSIVE unless already tagged SHARED */
+ if (radix_tree_tag_get(&hwspinlock_tree, id,
+ HWSPINLOCK_SHARED)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ tag = HWSPINLOCK_EXCLUSIVE;
+ }
+
+ /* mark this hwspinlock */
+ hwlock = radix_tree_lookup(&hwspinlock_tree, id);
+ if (!hwlock) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tmp = radix_tree_tag_set(&hwspinlock_tree, id, tag);
+
+ /* self-sanity check which should never fail */
+ WARN_ON(tmp != hwlock);
+
out:
of_node_put(args.np);
return ret ? ret : id;
@@ -505,6 +540,7 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
spin_lock_init(&hwlock->lock);
hwlock->bank = bank;
+ hwlock->refcount = 0;
ret = hwspin_lock_register_single(hwlock, base_id + i);
if (ret)
@@ -647,7 +683,7 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock)
{
struct device *dev = hwlock->bank->dev;
struct hwspinlock *tmp;
- int ret;
+ int ret, id;
/* prevent underlying implementation from being removed */
if (!try_module_get(dev->driver->owner)) {
@@ -664,13 +700,18 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock)
return ret;
}
+ /* update shareable refcount */
+ id = hwlock_to_id(hwlock);
+ if (radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_SHARED) &&
+ hwlock->refcount++)
+ goto out;
+
/* mark hwspinlock as used, should not fail */
- tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock_to_id(hwlock),
- HWSPINLOCK_UNUSED);
+ tmp = radix_tree_tag_clear(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
/* self-sanity check that should never fail */
WARN_ON(tmp != hwlock);
-
+out:
return ret;
}
@@ -764,9 +805,9 @@ struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
/* sanity check (this shouldn't happen) */
WARN_ON(hwlock_to_id(hwlock) != id);
- /* make sure this hwspinlock is unused */
- ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
- if (ret == 0) {
+ /* make sure this hwspinlock is unused or shareable */
+ if (!radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_SHARED) &&
+ !radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED)) {
pr_warn("hwspinlock %u is already in use\n", id);
hwlock = NULL;
goto out;
@@ -799,7 +840,7 @@ int hwspin_lock_free(struct hwspinlock *hwlock)
{
struct device *dev;
struct hwspinlock *tmp;
- int ret;
+ int ret, id;
if (!hwlock) {
pr_err("invalid hwlock\n");
@@ -810,30 +851,35 @@ int hwspin_lock_free(struct hwspinlock *hwlock)
mutex_lock(&hwspinlock_tree_lock);
/* make sure the hwspinlock is used */
- ret = radix_tree_tag_get(&hwspinlock_tree, hwlock_to_id(hwlock),
- HWSPINLOCK_UNUSED);
+ id = hwlock_to_id(hwlock);
+ ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
if (ret == 1) {
dev_err(dev, "%s: hwlock is already free\n", __func__);
dump_stack();
ret = -EINVAL;
- goto out;
+ goto unlock;
}
/* notify the underlying device that power is not needed */
ret = pm_runtime_put(dev);
if (ret < 0)
- goto out;
+ goto unlock;
+
+ /* update shareable refcount */
+ if (radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_SHARED) &&
+ --hwlock->refcount)
+ goto put;
/* mark this hwspinlock as available */
- tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock),
- HWSPINLOCK_UNUSED);
+ tmp = radix_tree_tag_set(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
/* sanity check (this shouldn't happen) */
WARN_ON(tmp != hwlock);
+put:
module_put(dev->driver->owner);
-out:
+unlock:
mutex_unlock(&hwspinlock_tree_lock);
return ret;
}
diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h
index 9eb6bd020..c808e116c 100644
--- a/drivers/hwspinlock/hwspinlock_internal.h
+++ b/drivers/hwspinlock/hwspinlock_internal.h
@@ -35,11 +35,13 @@ struct hwspinlock_ops {
* struct hwspinlock - this struct represents a single hwspinlock instance
* @bank: the hwspinlock_device structure which owns this lock
* @lock: initialized and used by hwspinlock core
+ * @refcount: number of users (when shared)
* @priv: private data, owned by the underlying platform-specific hwspinlock drv
*/
struct hwspinlock {
struct hwspinlock_device *bank;
spinlock_t lock;
+ unsigned int refcount;
void *priv;
};
--
2.17.1

View File

@ -0,0 +1,471 @@
From 835fe45ed0a3c0ef8cb2b74a900d227a124b4761 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:44:22 +0200
Subject: [PATCH 11/23] ARM-stm32mp1-r1-RESET-RTC-WATCHDOG
---
drivers/reset/reset-stm32mp1.c | 83 +++++++++++------
drivers/rtc/Kconfig | 1 +
drivers/rtc/rtc-stm32.c | 159 +++++++++++++++++++++++++++------
drivers/watchdog/stm32_iwdg.c | 6 +-
4 files changed, 192 insertions(+), 57 deletions(-)
diff --git a/drivers/reset/reset-stm32mp1.c b/drivers/reset/reset-stm32mp1.c
index b221a2804..daf0e26b2 100644
--- a/drivers/reset/reset-stm32mp1.c
+++ b/drivers/reset/reset-stm32mp1.c
@@ -4,14 +4,21 @@
* Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
*/
+#include <dt-bindings/reset/stm32mp1-resets.h>
+#include <linux/arm-smccc.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
+#include <linux/slab.h>
-#define CLR_OFFSET 0x4
+#define STM32MP1_RESET_ID_MASK GENMASK(15, 0)
+
+#define CLR_OFFSET 0x4
struct stm32_reset_data {
struct reset_controller_dev rcdev;
@@ -79,37 +86,57 @@ static const struct of_device_id stm32_reset_dt_ids[] = {
{ /* sentinel */ },
};
-static int stm32_reset_probe(struct platform_device *pdev)
+static void __init stm32mp1_reset_init(struct device_node *np)
{
- struct device *dev = &pdev->dev;
- struct stm32_reset_data *data;
- void __iomem *membase;
- struct resource *res;
-
- data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ void __iomem *base;
+ const struct of_device_id *match;
+ struct stm32_reset_data *data = NULL;
+ int ret;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("%pOFn: unable to map resource", np);
+ of_node_put(np);
+ return;
+ }
+
+ match = of_match_node(stm32_reset_dt_ids, np);
+ if (!match) {
+ pr_err("%s: match data not found\n", __func__);
+ goto err;
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- membase = devm_ioremap_resource(dev, res);
- if (IS_ERR(membase))
- return PTR_ERR(membase);
+ goto err;
- data->membase = membase;
+ data->membase = base;
data->rcdev.owner = THIS_MODULE;
- data->rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE;
data->rcdev.ops = &stm32_reset_ops;
- data->rcdev.of_node = dev->of_node;
-
- return devm_reset_controller_register(dev, &data->rcdev);
+ data->rcdev.of_node = np;
+ data->rcdev.nr_resets = STM32MP1_RESET_ID_MASK;
+
+ ret = reset_controller_register(&data->rcdev);
+ if (!ret)
+ return;
+
+err:
+ pr_err("stm32mp1 reset failed to initialize\n");
+ if (data)
+ kfree(data);
+ if (base)
+ iounmap(base);
+ of_node_put(np);
}
-static struct platform_driver stm32_reset_driver = {
- .probe = stm32_reset_probe,
- .driver = {
- .name = "stm32mp1-reset",
- .of_match_table = stm32_reset_dt_ids,
- },
-};
-
-builtin_platform_driver(stm32_reset_driver);
+/*
+ * RCC reset and clock drivers bind to the same RCC node.
+ * Register RCC reset driver at init through clock of table,
+ * clock driver for RCC will register at probe time.
+ */
+static void __init stm32mp1_reset_of_init_drv(struct device_node *np)
+{
+ of_node_clear_flag(np, OF_POPULATED);
+ stm32mp1_reset_init(np);
+}
+OF_DECLARE_1(clk, stm32mp1_rcc, "st,stm32mp1-rcc", stm32mp1_reset_of_init_drv);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index c5b980414..d590b4205 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1862,6 +1862,7 @@ config RTC_DRV_R7301
config RTC_DRV_STM32
tristate "STM32 RTC"
select REGMAP_MMIO
+ depends on COMMON_CLK
depends on ARCH_STM32 || COMPILE_TEST
help
If you say yes here you get support for the STM32 On-Chip
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index 2999e33a7..5bfe655c5 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -6,6 +6,8 @@
#include <linux/bcd.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/errno.h>
#include <linux/iopoll.h>
#include <linux/ioport.h>
#include <linux/mfd/syscon.h>
@@ -15,6 +17,8 @@
#include <linux/regmap.h>
#include <linux/rtc.h>
+#include <dt-bindings/rtc/rtc-stm32.h>
+
#define DRIVER_NAME "stm32_rtc"
/* STM32_RTC_TR bit fields */
@@ -39,6 +43,12 @@
#define STM32_RTC_CR_FMT BIT(6)
#define STM32_RTC_CR_ALRAE BIT(8)
#define STM32_RTC_CR_ALRAIE BIT(12)
+#define STM32_RTC_CR_COSEL BIT(19)
+#define STM32_RTC_CR_OSEL_SHIFT 21
+#define STM32_RTC_CR_OSEL GENMASK(22, 21)
+#define STM32_RTC_CR_COE BIT(23)
+#define STM32_RTC_CR_TAMPOE BIT(26)
+#define STM32_RTC_CR_OUT2EN BIT(31)
/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
#define STM32_RTC_ISR_ALRAWF BIT(0)
@@ -75,6 +85,11 @@
/* STM32_RTC_SR/_SCR bit fields */
#define STM32_RTC_SR_ALRA BIT(0)
+/* STM32_RTC_CFGR bit fields */
+#define STM32_RTC_CFGR_OUT2_RMP BIT(0)
+#define STM32_RTC_CFGR_LSCOEN_OUT1 1
+#define STM32_RTC_CFGR_LSCOEN_OUT2_RMP 2
+
/* STM32_RTC_VERR bit fields */
#define STM32_RTC_VERR_MINREV_SHIFT 0
#define STM32_RTC_VERR_MINREV GENMASK(3, 0)
@@ -101,6 +116,7 @@ struct stm32_rtc_registers {
u16 wpr;
u16 sr;
u16 scr;
+ u16 cfgr;
u16 verr;
};
@@ -114,7 +130,7 @@ struct stm32_rtc_data {
void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags);
bool has_pclk;
bool need_dbp;
- bool has_wakeirq;
+ bool has_lsco;
};
struct stm32_rtc {
@@ -127,9 +143,87 @@ struct stm32_rtc {
struct clk *rtc_ck;
const struct stm32_rtc_data *data;
int irq_alarm;
- int wakeirq_alarm;
+ int lsco;
+ struct clk *clk_lsco;
};
+/*
+ * -------------------------------------------------------------------------
+ * | TAMPOE | OSEL[1:0] | COE | OUT2EN | RTC_OUT1 | RTC_OUT2 |
+ * | | | | | | or RTC_OUT2_RMP |
+ * |-------------------------------------------------------------------------|
+ * | 0 | 00 | 0 | 0 or 1 | - | - |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 | 00 | 1 | 0 | CALIB | - |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 or 1 | !=00 | 0 | 0 | TAMPALRM | - |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 | 00 | 1 | 1 | - | CALIB |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 or 1 | !=00 | 0 | 1 | - | TAMPALRM |
+ * |--------|-----------|-----|--------|------------------|------------------|
+ * | 0 or 1 | !=00 | 1 | 1 | TAMPALRM | CALIB |
+ * -------------------------------------------------------------------------
+ */
+static int stm32_rtc_clk_lsco_check_availability(struct stm32_rtc *rtc)
+{
+ struct stm32_rtc_registers regs = rtc->data->regs;
+ unsigned int cr = readl_relaxed(rtc->base + regs.cr);
+ unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
+ unsigned int calib = STM32_RTC_CR_COE;
+ unsigned int tampalrm = STM32_RTC_CR_TAMPOE | STM32_RTC_CR_OSEL;
+
+ switch (rtc->lsco) {
+ case RTC_OUT1:
+ if ((!(cr & STM32_RTC_CR_OUT2EN) &&
+ ((cr & calib) || cr & tampalrm)) ||
+ ((cr & calib) && (cr & tampalrm)))
+ return -EBUSY;
+ break;
+ case RTC_OUT2_RMP:
+ if ((cr & STM32_RTC_CR_OUT2EN) &&
+ (cfgr & STM32_RTC_CFGR_OUT2_RMP) &&
+ ((cr & calib) || (cr & tampalrm)))
+ return -EBUSY;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (clk_get_rate(rtc->rtc_ck) != 32768)
+ return -ERANGE;
+
+ return 0;
+}
+
+static int stm32_rtc_clk_lsco_register(struct platform_device *pdev)
+{
+ struct stm32_rtc *rtc = platform_get_drvdata(pdev);
+ struct stm32_rtc_registers regs = rtc->data->regs;
+ u8 lscoen;
+ int ret;
+
+ ret = stm32_rtc_clk_lsco_check_availability(rtc);
+ if (ret)
+ return ret;
+
+ lscoen = (rtc->lsco == RTC_OUT1) ? STM32_RTC_CFGR_LSCOEN_OUT1 :
+ STM32_RTC_CFGR_LSCOEN_OUT2_RMP;
+
+ rtc->clk_lsco = clk_register_gate(&pdev->dev, "rtc_lsco",
+ __clk_get_name(rtc->rtc_ck),
+ CLK_IGNORE_UNUSED | CLK_IS_CRITICAL,
+ rtc->base + regs.cfgr, lscoen,
+ 0, NULL);
+ if (IS_ERR(rtc->clk_lsco))
+ return PTR_ERR(rtc->clk_lsco);
+
+ of_clk_add_provider(pdev->dev.of_node,
+ of_clk_src_simple_get, rtc->clk_lsco);
+
+ return 0;
+}
+
static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
{
const struct stm32_rtc_registers *regs = &rtc->data->regs;
@@ -547,7 +641,7 @@ static void stm32_rtc_clear_events(struct stm32_rtc *rtc,
static const struct stm32_rtc_data stm32_rtc_data = {
.has_pclk = false,
.need_dbp = true,
- .has_wakeirq = false,
+ .has_lsco = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -558,6 +652,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {
.wpr = 0x24,
.sr = 0x0C, /* set to ISR offset to ease alarm management */
.scr = UNDEF_REG,
+ .cfgr = UNDEF_REG,
.verr = UNDEF_REG,
},
.events = {
@@ -569,7 +664,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {
static const struct stm32_rtc_data stm32h7_rtc_data = {
.has_pclk = true,
.need_dbp = true,
- .has_wakeirq = false,
+ .has_lsco = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -580,6 +675,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = {
.wpr = 0x24,
.sr = 0x0C, /* set to ISR offset to ease alarm management */
.scr = UNDEF_REG,
+ .cfgr = UNDEF_REG,
.verr = UNDEF_REG,
},
.events = {
@@ -600,7 +696,7 @@ static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc,
static const struct stm32_rtc_data stm32mp1_data = {
.has_pclk = true,
.need_dbp = false,
- .has_wakeirq = true,
+ .has_lsco = true,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -611,6 +707,7 @@ static const struct stm32_rtc_data stm32mp1_data = {
.wpr = 0x24,
.sr = 0x50,
.scr = 0x5C,
+ .cfgr = 0x60,
.verr = 0x3F4,
},
.events = {
@@ -738,13 +835,15 @@ static int stm32_rtc_probe(struct platform_device *pdev)
} else {
rtc->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(rtc->pclk)) {
- dev_err(&pdev->dev, "no pclk clock");
+ if (PTR_ERR(rtc->pclk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "no pclk clock");
return PTR_ERR(rtc->pclk);
}
rtc->rtc_ck = devm_clk_get(&pdev->dev, "rtc_ck");
}
if (IS_ERR(rtc->rtc_ck)) {
- dev_err(&pdev->dev, "no rtc_ck clock");
+ if (PTR_ERR(rtc->pclk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "no rtc_ck clock");
return PTR_ERR(rtc->rtc_ck);
}
@@ -781,19 +880,12 @@ static int stm32_rtc_probe(struct platform_device *pdev)
}
ret = device_init_wakeup(&pdev->dev, true);
- if (rtc->data->has_wakeirq) {
- rtc->wakeirq_alarm = platform_get_irq(pdev, 1);
- if (rtc->wakeirq_alarm > 0) {
- ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
- rtc->wakeirq_alarm);
- } else {
- ret = rtc->wakeirq_alarm;
- if (rtc->wakeirq_alarm == -EPROBE_DEFER)
- goto err;
- }
- }
if (ret)
- dev_warn(&pdev->dev, "alarm can't wake up the system: %d", ret);
+ goto err;
+
+ ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm);
+ if (ret)
+ goto err;
platform_set_drvdata(pdev, rtc);
@@ -816,6 +908,21 @@ static int stm32_rtc_probe(struct platform_device *pdev)
goto err;
}
+ if (rtc->data->has_lsco) {
+ ret = of_property_read_s32(pdev->dev.of_node,
+ "st,lsco", &rtc->lsco);
+ if (!ret) {
+ ret = stm32_rtc_clk_lsco_register(pdev);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "LSCO clock registration failed: %d\n",
+ ret);
+ } else {
+ rtc->lsco = ret;
+ dev_dbg(&pdev->dev, "No LSCO clock: %d\n", ret);
+ }
+ }
+
/*
* If INITS flag is reset (calendar year field set to 0x00), calendar
* must be initialized
@@ -852,6 +959,9 @@ static int stm32_rtc_remove(struct platform_device *pdev)
const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int cr;
+ if (!IS_ERR_OR_NULL(rtc->clk_lsco))
+ clk_unregister_gate(rtc->clk_lsco);
+
/* Disable interrupts */
stm32_rtc_wpr_unlock(rtc);
cr = readl_relaxed(rtc->base + regs->cr);
@@ -881,9 +991,6 @@ static int stm32_rtc_suspend(struct device *dev)
if (rtc->data->has_pclk)
clk_disable_unprepare(rtc->pclk);
- if (device_may_wakeup(dev))
- return enable_irq_wake(rtc->irq_alarm);
-
return 0;
}
@@ -902,15 +1009,13 @@ static int stm32_rtc_resume(struct device *dev)
if (ret < 0)
return ret;
- if (device_may_wakeup(dev))
- return disable_irq_wake(rtc->irq_alarm);
-
return ret;
}
#endif
-static SIMPLE_DEV_PM_OPS(stm32_rtc_pm_ops,
- stm32_rtc_suspend, stm32_rtc_resume);
+static const struct dev_pm_ops stm32_rtc_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_rtc_suspend, stm32_rtc_resume)
+};
static struct platform_driver stm32_rtc_driver = {
.probe = stm32_rtc_probe,
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index 25188d6bb..1b71c205c 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -163,7 +163,8 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev,
wdt->clk_lsi = devm_clk_get(dev, "lsi");
if (IS_ERR(wdt->clk_lsi)) {
- dev_err(dev, "Unable to get lsi clock\n");
+ if (PTR_ERR(wdt->clk_lsi) != -EPROBE_DEFER)
+ dev_err(dev, "Unable to get lsi clock\n");
return PTR_ERR(wdt->clk_lsi);
}
@@ -171,7 +172,8 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev,
if (wdt->data->has_pclk) {
wdt->clk_pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(wdt->clk_pclk)) {
- dev_err(dev, "Unable to get pclk clock\n");
+ if (PTR_ERR(wdt->clk_pclk) != -EPROBE_DEFER)
+ dev_err(dev, "Unable to get pclk clock\n");
return PTR_ERR(wdt->clk_pclk);
}
--
2.17.1

View File

@ -0,0 +1,716 @@
From f811efe3cbe842a78d98740c0a0a8e1b7c0181b0 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:45:15 +0200
Subject: [PATCH 13/23] ARM-stm32mp1-r1-MFD
---
drivers/mfd/Kconfig | 10 +
drivers/mfd/Makefile | 1 +
drivers/mfd/stm32-pwr.c | 400 +++++++++++++++++++++++++++++++
drivers/mfd/stm32-timers.c | 36 ++-
drivers/mfd/stmfx.c | 22 +-
drivers/mfd/stpmic1.c | 6 +
drivers/mfd/wm8994-core.c | 21 ++
include/linux/mfd/stm32-timers.h | 12 +-
include/linux/mfd/stmfx.h | 1 +
include/linux/mfd/wm8994/pdata.h | 6 +
10 files changed, 494 insertions(+), 21 deletions(-)
create mode 100644 drivers/mfd/stm32-pwr.c
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 43169f25d..48ef1822a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1955,6 +1955,16 @@ config MFD_STPMIC1
To compile this driver as a module, choose M here: the
module will be called stpmic1.
+config MFD_STM32MP1_PWR
+ bool "STM32MP1 wake-up pins"
+ depends on MACH_STM32MP157
+ default y
+ help
+ Select this option to enable STM32 PWR Wake-up pins driver.
+
+ This driver provides interruptions that can be used to wake-up from
+ suspend.
+
config MFD_STMFX
tristate "Support for STMicroelectronics Multi-Function eXpander (STMFX)"
depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c1067ea46..11acfa1bf 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -249,6 +249,7 @@ obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o
obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
+obj-$(CONFIG_MFD_STM32MP1_PWR) += stm32-pwr.o
obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o
obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o
obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
diff --git a/drivers/mfd/stm32-pwr.c b/drivers/mfd/stm32-pwr.c
new file mode 100644
index 000000000..48ca8b474
--- /dev/null
+++ b/drivers/mfd/stm32-pwr.c
@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/gpio.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <asm/exception.h>
+
+#define NB_WAKEUPPINS 6
+
+#define STM32_SVC_PWR 0x82001001
+#define STM32_WRITE 0x1
+#define STM32_SET_BITS 0x2
+#define STM32_CLEAR_BITS 0x3
+
+#define PWR_WKUP_OFFSET 0x20
+// PWR Registers
+#define WKUPCR 0x0
+#define WKUPFR 0x4
+#define MPUWKUPENR 0x8
+
+#define WKUP_FLAGS_MASK GENMASK(5, 0)
+
+// WKUPCR bits definition
+#define WKUP_EDGE_SHIFT 8
+#define WKUP_PULL_SHIFT 16
+#define WKUP_PULL_MASK GENMASK(1, 0)
+
+enum wkup_pull_setting {
+ WKUP_NO_PULL = 0,
+ WKUP_PULL_UP,
+ WKUP_PULL_DOWN,
+ WKUP_PULL_RESERVED
+};
+
+#define SMC(class, op, offset, val) do { \
+ struct arm_smccc_res res; \
+ arm_smccc_smc(class, op, PWR_WKUP_OFFSET + (offset), val, \
+ 0, 0, 0, 0, &res); \
+} while (0) \
+
+struct stm32_pwr_data {
+ struct device *dev;
+ void __iomem *base; /* IO Memory base address */
+ struct irq_domain *domain; /* Domain for this controller */
+ int irq; /* Parent interrupt */
+ u32 masked; /* IRQ is masked */
+ u32 wake; /* IRQ is wake on */
+ u32 pending; /* IRQ has been received while wake on*/
+ struct gpio_desc *gpio[NB_WAKEUPPINS];
+};
+
+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);
+ SMC(STM32_SVC_PWR, STM32_SET_BITS, WKUPCR, BIT(d->hwirq));
+}
+
+static void stm32_pwr_irq_set_enable(struct irq_data *d)
+{
+ struct stm32_pwr_data *priv = d->domain->host_data;
+
+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
+ if (!(priv->masked & BIT(d->hwirq)) || (priv->wake & BIT(d->hwirq)))
+ SMC(STM32_SVC_PWR, STM32_SET_BITS, MPUWKUPENR, BIT(d->hwirq));
+ else
+ SMC(STM32_SVC_PWR, STM32_CLEAR_BITS, MPUWKUPENR, 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);
+ priv->masked |= BIT(d->hwirq);
+ stm32_pwr_irq_set_enable(d);
+}
+
+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);
+ priv->masked &= ~BIT(d->hwirq);
+ stm32_pwr_irq_set_enable(d);
+}
+
+static int stm32_pwr_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ struct stm32_pwr_data *priv = d->domain->host_data;
+ struct irq_data *parent = irq_get_irq_data(priv->irq);
+
+ dev_dbg(priv->dev, "irq:%lu on:%d\n", d->hwirq, on);
+ if (on) {
+ priv->wake |= BIT(d->hwirq);
+ } else {
+ priv->wake &= ~BIT(d->hwirq);
+ priv->pending &= ~BIT(d->hwirq);
+ }
+ stm32_pwr_irq_set_enable(d);
+
+ if (parent->chip && parent->chip->irq_set_wake)
+ return parent->chip->irq_set_wake(parent, on);
+
+ return 0;
+}
+
+static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+ struct stm32_pwr_data *priv = d->domain->host_data;
+ int pin_id = d->hwirq;
+ u32 wkupcr;
+ int en;
+
+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
+
+ en = readl_relaxed(priv->base + MPUWKUPENR) & BIT(pin_id);
+ /* reference manual request to disable the wakeup pin while
+ * changing the edge detection setting
+ */
+ if (en)
+ stm32_pwr_irq_mask(d);
+
+ wkupcr = readl_relaxed(priv->base + WKUPCR);
+ switch (flow_type & IRQ_TYPE_SENSE_MASK) {
+ case IRQF_TRIGGER_FALLING:
+ wkupcr |= (1 << (WKUP_EDGE_SHIFT + pin_id));
+ break;
+ case IRQF_TRIGGER_RISING:
+ wkupcr &= ~(1 << (WKUP_EDGE_SHIFT + pin_id));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr);
+
+ if (en)
+ stm32_pwr_irq_unmask(d);
+
+ return 0;
+}
+
+#ifdef CONFIG_SMP
+static int stm32_pwr_set_affinity_parent(struct irq_data *data,
+ const struct cpumask *dest, bool force)
+{
+ struct stm32_pwr_data *priv = data->domain->host_data;
+ struct irq_data *parent = irq_get_irq_data(priv->irq);
+
+ if (parent->chip && parent->chip->irq_set_affinity)
+ return parent->chip->irq_set_affinity(parent, dest, force);
+
+ return IRQ_SET_MASK_OK_DONE;
+}
+#endif
+
+static int stm32_pwr_irq_request_resources(struct irq_data *d)
+{
+ struct stm32_pwr_data *priv = d->domain->host_data;
+ struct gpio_desc *gpio;
+ int ret;
+
+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
+ gpio = gpiod_get_index(priv->dev, "wakeup", d->hwirq, GPIOD_IN);
+ if (IS_ERR(gpio)) {
+ ret = PTR_ERR(gpio);
+ dev_err(priv->dev, "Failed to get wakeup gpio: %d", ret);
+ return ret;
+ }
+ priv->gpio[d->hwirq] = gpio;
+ return 0;
+}
+
+static void stm32_pwr_irq_release_resources(struct irq_data *d)
+{
+ struct stm32_pwr_data *priv = d->domain->host_data;
+
+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
+ gpiod_put(priv->gpio[d->hwirq]);
+}
+
+static struct irq_chip stm32_pwr_irq_chip = {
+ .name = "stm32-pwr-irq",
+ .irq_ack = stm32_pwr_irq_ack,
+ .irq_mask = stm32_pwr_irq_mask,
+ .irq_unmask = stm32_pwr_irq_unmask,
+ .irq_set_type = stm32_pwr_irq_set_type,
+ .irq_set_wake = stm32_pwr_irq_set_wake,
+ .irq_request_resources = stm32_pwr_irq_request_resources,
+ .irq_release_resources = stm32_pwr_irq_release_resources,
+#ifdef CONFIG_SMP
+ .irq_set_affinity = stm32_pwr_set_affinity_parent,
+#endif
+};
+
+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);
+
+ if (config >= WKUP_PULL_RESERVED) {
+ 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;
+}
+
+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)
+{
+ if (WARN_ON(intsize < 3)) {
+ pr_err("%s: bad irq config parameters\n", __func__);
+ return -EINVAL;
+ }
+
+ *out_hwirq = intspec[0];
+ *out_type = intspec[1] & (IRQ_TYPE_SENSE_MASK);
+
+ 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 = {
+ .alloc = stm32_pwr_alloc,
+ .xlate = stm32_pwr_xlate,
+ .free = irq_domain_free_irqs_common,
+};
+
+/*
+ * Handler for the cascaded IRQ.
+ */
+static void stm32_pwr_handle_irq(struct irq_desc *desc)
+{
+ struct stm32_pwr_data *priv = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ u32 wkupfr, wkupenr, i;
+
+ chained_irq_enter(chip, 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))) {
+ struct irq_desc *d;
+
+ d = irq_to_desc(irq_find_mapping(priv->domain, i));
+
+ if (priv->wake & BIT(i)) {
+ dev_dbg(priv->dev,
+ "irq %d while wake enabled\n", i);
+ priv->pending |= BIT(i);
+ }
+
+ dev_dbg(priv->dev, "handle wkup irq:%d\n", i);
+ handle_edge_irq(d);
+ }
+ }
+ chained_irq_exit(chip, desc);
+}
+
+static int __maybe_unused stm32_pwr_suspend(struct device *dev)
+{
+ struct stm32_pwr_data *priv = dev_get_drvdata(dev);
+
+ pr_debug("suspend");
+ if (priv->pending != 0)
+ return -EBUSY;
+
+ return 0;
+}
+
+static const struct dev_pm_ops stm32_pwr_pm = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_pwr_suspend, NULL)
+};
+
+static int stm32_pwr_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct stm32_pwr_data *priv;
+ struct device_node *np = dev->of_node;
+ struct resource *res;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ priv->dev = dev;
+ dev_set_drvdata(dev, priv);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->base)) {
+ dev_err(dev, "Unable to map registers\n");
+ return PTR_ERR(priv->base);
+ }
+
+ /* Disable all wake-up pins */
+ SMC(STM32_SVC_PWR, STM32_WRITE, MPUWKUPENR, 0);
+ /* Clear all interrupts flags */
+ SMC(STM32_SVC_PWR, STM32_SET_BITS, WKUPCR, WKUP_FLAGS_MASK);
+
+ 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__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = irq_of_parse_and_map(np, 0);
+ if (ret < 0) {
+ dev_err(dev, "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);
+
+ of_node_clear_flag(np, OF_POPULATED);
+
+ return 0;
+
+out_domain:
+ irq_domain_remove(priv->domain);
+out:
+ return ret;
+}
+
+static int stm32_pwr_remove(struct platform_device *pdev)
+{
+ struct stm32_pwr_data *priv = dev_get_drvdata(&pdev->dev);
+
+ irq_domain_remove(priv->domain);
+ return 0;
+}
+
+static const struct of_device_id stm32_pwr_ids[] = {
+ { .compatible = "st,stm32mp1-pwr", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, stm32_pwr_ids);
+
+static struct platform_driver stm32_pwr_driver = {
+ .probe = stm32_pwr_probe,
+ .remove = stm32_pwr_remove,
+ .driver = {
+ .name = "stm32_pwr",
+ .of_match_table = stm32_pwr_ids,
+ .pm = &stm32_pwr_pm,
+ },
+};
+
+static int __init stm32_pwr_init(void)
+{
+ return platform_driver_register(&stm32_pwr_driver);
+}
+
+static void __exit stm32_pwr_exit(void)
+{
+ return platform_driver_unregister(&stm32_pwr_driver);
+}
+
+arch_initcall(stm32_pwr_init);
+module_exit(stm32_pwr_exit);
diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c
index efcd4b980..65a160a26 100644
--- a/drivers/mfd/stm32-timers.c
+++ b/drivers/mfd/stm32-timers.c
@@ -167,26 +167,36 @@ static void stm32_timers_get_arr_size(struct stm32_timers *ddata)
regmap_write(ddata->regmap, TIM_ARR, 0x0);
}
-static void stm32_timers_dma_probe(struct device *dev,
- struct stm32_timers *ddata)
+static int stm32_timers_dma_probe(struct device *dev,
+ struct stm32_timers *ddata)
{
int i;
+ int ret = 0;
char name[4];
init_completion(&ddata->dma.completion);
mutex_init(&ddata->dma.lock);
- /* Optional DMA support: get valid DMA channel(s) or NULL */
+ /* Optional DMA support but report if an existing one fails */
for (i = STM32_TIMERS_DMA_CH1; i <= STM32_TIMERS_DMA_CH4; i++) {
snprintf(name, ARRAY_SIZE(name), "ch%1d", i + 1);
- ddata->dma.chans[i] = dma_request_slave_channel(dev, name);
+ ddata->dma.chans[i] = dma_request_chan(dev, name);
}
- ddata->dma.chans[STM32_TIMERS_DMA_UP] =
- dma_request_slave_channel(dev, "up");
- ddata->dma.chans[STM32_TIMERS_DMA_TRIG] =
- dma_request_slave_channel(dev, "trig");
- ddata->dma.chans[STM32_TIMERS_DMA_COM] =
- dma_request_slave_channel(dev, "com");
+ ddata->dma.chans[STM32_TIMERS_DMA_UP] = dma_request_chan(dev, "up");
+ ddata->dma.chans[STM32_TIMERS_DMA_TRIG] = dma_request_chan(dev, "trig");
+ ddata->dma.chans[STM32_TIMERS_DMA_COM] = dma_request_chan(dev, "com");
+
+ for (i = STM32_TIMERS_DMA_CH1; i < STM32_TIMERS_MAX_DMAS; i++) {
+ if (IS_ERR(ddata->dma.chans[i])) {
+ /* Save the first error code to return */
+ if (PTR_ERR(ddata->dma.chans[i]) != -ENODEV && !ret)
+ ret = PTR_ERR(ddata->dma.chans[i]);
+
+ ddata->dma.chans[i] = NULL;
+ }
+ }
+
+ return ret;
}
static void stm32_timers_dma_remove(struct device *dev,
@@ -230,7 +240,11 @@ static int stm32_timers_probe(struct platform_device *pdev)
stm32_timers_get_arr_size(ddata);
- stm32_timers_dma_probe(dev, ddata);
+ ret = stm32_timers_dma_probe(dev, ddata);
+ if (ret) {
+ stm32_timers_dma_remove(dev, ddata);
+ return ret;
+ }
platform_set_drvdata(pdev, ddata);
diff --git a/drivers/mfd/stmfx.c b/drivers/mfd/stmfx.c
index 857991cb3..711979afd 100644
--- a/drivers/mfd/stmfx.c
+++ b/drivers/mfd/stmfx.c
@@ -287,14 +287,21 @@ static int stmfx_irq_init(struct i2c_client *client)
ret = regmap_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN, irqoutpin);
if (ret)
- return ret;
+ goto irq_exit;
ret = devm_request_threaded_irq(stmfx->dev, client->irq,
NULL, stmfx_irq_handler,
irqtrigger | IRQF_ONESHOT,
"stmfx", stmfx);
if (ret)
- stmfx_irq_exit(client);
+ goto irq_exit;
+
+ stmfx->irq = client->irq;
+
+ return 0;
+
+irq_exit:
+ stmfx_irq_exit(client);
return ret;
}
@@ -481,6 +488,8 @@ static int stmfx_suspend(struct device *dev)
if (ret)
return ret;
+ disable_irq(stmfx->irq);
+
if (stmfx->vdd)
return regulator_disable(stmfx->vdd);
@@ -501,6 +510,13 @@ static int stmfx_resume(struct device *dev)
}
}
+ /* Reset STMFX - supply has been stopped during suspend */
+ ret = stmfx_chip_reset(stmfx);
+ if (ret) {
+ dev_err(stmfx->dev, "Failed to reset chip: %d\n", ret);
+ return ret;
+ }
+
ret = regmap_raw_write(stmfx->map, STMFX_REG_SYS_CTRL,
&stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl));
if (ret)
@@ -517,6 +533,8 @@ static int stmfx_resume(struct device *dev)
if (ret)
return ret;
+ enable_irq(stmfx->irq);
+
return 0;
}
#endif
diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c
index 7dfbe8906..766c3217f 100644
--- a/drivers/mfd/stpmic1.c
+++ b/drivers/mfd/stpmic1.c
@@ -170,6 +170,9 @@ static int stpmic1_suspend(struct device *dev)
disable_irq(pmic_dev->irq);
+ if (device_may_wakeup(dev))
+ enable_irq_wake(pmic_dev->irq);
+
return 0;
}
@@ -183,6 +186,9 @@ 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);
return 0;
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 1e9fe7d92..b110c8ac1 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -7,6 +7,7 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -185,6 +186,12 @@ static int wm8994_resume(struct device *dev)
if (!wm8994->suspended)
return 0;
+ /*
+ * LDO1/2 minimum cycle time is 36ms according to codec specification
+ * Wait before enabling regulator to make sure we fit this requirement
+ */
+ msleep(40);
+
ret = regulator_bulk_enable(wm8994->num_supplies,
wm8994->supplies);
if (ret != 0) {
@@ -300,6 +307,20 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
pdata->csnaddr_pd = of_property_read_bool(np, "wlf,csnaddr-pd");
+
+ 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/stm32-timers.h b/include/linux/mfd/stm32-timers.h
index 067d14655..f8db83aed 100644
--- a/include/linux/mfd/stm32-timers.h
+++ b/include/linux/mfd/stm32-timers.h
@@ -70,14 +70,11 @@
#define TIM_CCER_CC4E BIT(12) /* Capt/Comp 4 out Ena */
#define TIM_CCER_CC4P BIT(13) /* Capt/Comp 4 Polarity */
#define TIM_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12))
-#define TIM_BDTR_BKE BIT(12) /* Break input enable */
-#define TIM_BDTR_BKP BIT(13) /* Break input polarity */
+#define TIM_BDTR_BKE(x) BIT(12 + (x) * 12) /* Break input enable */
+#define TIM_BDTR_BKP(x) BIT(13 + (x) * 12) /* Break input polarity */
#define TIM_BDTR_AOE BIT(14) /* Automatic Output Enable */
#define TIM_BDTR_MOE BIT(15) /* Main Output Enable */
-#define TIM_BDTR_BKF (BIT(16) | BIT(17) | BIT(18) | BIT(19))
-#define TIM_BDTR_BK2F (BIT(20) | BIT(21) | BIT(22) | BIT(23))
-#define TIM_BDTR_BK2E BIT(24) /* Break 2 input enable */
-#define TIM_BDTR_BK2P BIT(25) /* Break 2 input polarity */
+#define TIM_BDTR_BKF(x) (0xf << (16 + (x) * 4))
#define TIM_DCR_DBA GENMASK(4, 0) /* DMA base addr */
#define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */
@@ -87,8 +84,7 @@
#define TIM_CR2_MMS2_SHIFT 20
#define TIM_SMCR_TS_SHIFT 4
#define TIM_BDTR_BKF_MASK 0xF
-#define TIM_BDTR_BKF_SHIFT 16
-#define TIM_BDTR_BK2F_SHIFT 20
+#define TIM_BDTR_BKF_SHIFT(x) (16 + (x) * 4)
enum stm32_timers_dmas {
STM32_TIMERS_DMA_CH1,
diff --git a/include/linux/mfd/stmfx.h b/include/linux/mfd/stmfx.h
index 3c6798367..744dce639 100644
--- a/include/linux/mfd/stmfx.h
+++ b/include/linux/mfd/stmfx.h
@@ -109,6 +109,7 @@ struct stmfx {
struct device *dev;
struct regmap *map;
struct regulator *vdd;
+ int irq;
struct irq_domain *irq_domain;
struct mutex lock; /* IRQ bus lock */
u8 irq_src;
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index 81e7dcbd9..addb2fede 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -231,6 +231,12 @@ struct wm8994_pdata {
* GPIO for the IRQ pin if host only supports edge triggering
*/
int irq_gpio;
+
+ /* MCLK1 clock provider */
+ struct clk *mclk1;
+
+ /* MCLK2 clock provider */
+ struct clk *mclk2;
};
#endif
--
2.17.1

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

View File

@ -0,0 +1,679 @@
From 9ce7cf9f5ce6b3fe1370be07d989eabaf0afb25a Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:47:45 +0200
Subject: [PATCH 18/23] ARM-stm32mp1-r1-SOUND
---
sound/soc/codecs/Kconfig | 2 +-
sound/soc/codecs/cs42l51.c | 17 ++++--
sound/soc/codecs/wm8994.c | 80 +++++++++++++++++++++++--
sound/soc/stm/stm32_i2s.c | 75 +++++++++++++++++-------
sound/soc/stm/stm32_sai.c | 26 ++++++---
sound/soc/stm/stm32_sai_sub.c | 21 ++++---
sound/soc/stm/stm32_spdifrx.c | 107 +++++++++++++++++++++-------------
7 files changed, 241 insertions(+), 87 deletions(-)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 229cc89f8..e5d231a63 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1395,7 +1395,7 @@ config SND_SOC_WM8993
tristate
config SND_SOC_WM8994
- tristate
+ tristate "Wolfson Microelectronics WM8994 codec"
config SND_SOC_WM8995
tristate
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 55408c8fc..01a4d93e1 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -174,6 +174,7 @@ static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component, CS42L51_POWER_CTL1,
CS42L51_POWER_CTL1_PDN, 0);
+ msleep(20);
break;
}
@@ -214,12 +215,10 @@ static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = {
SND_SOC_DAPM_ADC_E("Right ADC", "Right HiFi Capture",
CS42L51_POWER_CTL1, 2, 1,
cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
- SND_SOC_DAPM_DAC_E("Left DAC", "Left HiFi Playback",
- CS42L51_POWER_CTL1, 5, 1,
- cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
- SND_SOC_DAPM_DAC_E("Right DAC", "Right HiFi Playback",
- CS42L51_POWER_CTL1, 6, 1,
- cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_DAC_E("Left DAC", NULL, CS42L51_POWER_CTL1, 5, 1,
+ cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_DAC_E("Right DAC", NULL, CS42L51_POWER_CTL1, 6, 1,
+ cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
/* analog/mic */
SND_SOC_DAPM_INPUT("AIN1L"),
@@ -255,6 +254,12 @@ static const struct snd_soc_dapm_route cs42l51_routes[] = {
{"HPL", NULL, "Left DAC"},
{"HPR", NULL, "Right DAC"},
+ {"Right DAC", NULL, "DAC Mux"},
+ {"Left DAC", NULL, "DAC Mux"},
+
+ {"DAC Mux", "Direct PCM", "Playback"},
+ {"DAC Mux", "DSP PCM", "Playback"},
+
{"Left ADC", NULL, "Left PGA"},
{"Right ADC", NULL, "Right PGA"},
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index d5fb7f5dd..a166ab1f3 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -7,6 +7,7 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -840,6 +841,42 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int mclk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(comp);
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
+ struct clk *mclk = pdata->mclk1;
+ int ret, mclk_id = 0;
+
+ if (!strncmp(w->name, "MCLK2", 5)) {
+ mclk_id = 1;
+ mclk = pdata->mclk2;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dev_dbg(comp->dev, "Enable master clock %s\n",
+ mclk_id ? "MCLK2" : "MCLK1");
+
+ ret = clk_prepare_enable(mclk);
+ if (ret < 0) {
+ dev_err(comp->dev, "Failed to enable clock: %d\n", ret);
+ return ret;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ dev_dbg(comp->dev, "Disable master clock %s\n",
+ mclk_id ? "MCLK2" : "MCLK1");
+ clk_disable_unprepare(mclk);
+ break;
+ }
+
+ return 0;
+}
+
static void vmid_reference(struct snd_soc_component *component)
{
struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
@@ -1157,7 +1194,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))
@@ -1776,6 +1812,16 @@ static const struct snd_soc_dapm_widget wm8994_specific_dapm_widgets[] = {
SND_SOC_DAPM_MUX("AIF3ADC Mux", SND_SOC_NOPM, 0, 0, &wm8994_aif3adc_mux),
};
+static const struct snd_soc_dapm_widget wm8994_mclk1_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("MCLK1", SND_SOC_NOPM, 0, 0, mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget wm8994_mclk2_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("MCLK2", SND_SOC_NOPM, 0, 0, mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
static const struct snd_soc_dapm_widget wm8958_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("AIF3", WM8994_POWER_MANAGEMENT_6, 5, 1, NULL, 0),
SND_SOC_DAPM_MUX("Mono PCM Out Mux", SND_SOC_NOPM, 0, 0, &mono_pcm_out_mux),
@@ -2000,10 +2046,10 @@ static const struct snd_soc_dapm_route wm8994_lateclk_intercon[] = {
};
static const struct snd_soc_dapm_route wm8994_revd_intercon[] = {
- { "AIF1DACDAT", NULL, "AIF2DACDAT" },
- { "AIF2DACDAT", NULL, "AIF1DACDAT" },
- { "AIF1ADCDAT", NULL, "AIF2ADCDAT" },
- { "AIF2ADCDAT", NULL, "AIF1ADCDAT" },
+// { "AIF1DACDAT", NULL, "AIF2DACDAT" },
+// { "AIF2DACDAT", NULL, "AIF1DACDAT" },
+// { "AIF1ADCDAT", NULL, "AIF2ADCDAT" },
+// { "AIF2ADCDAT", NULL, "AIF1ADCDAT" },
{ "MICBIAS1", NULL, "CLK_SYS" },
{ "MICBIAS1", NULL, "MICBIAS Supply" },
{ "MICBIAS2", NULL, "CLK_SYS" },
@@ -2377,11 +2423,26 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
{
struct snd_soc_component *component = dai->component;
struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int i;
+ /*
+ * Simple card provides unconditionnaly clock_id = 0.
+ * Workaround to select master clock for aif1/2
+ */
switch (dai->id) {
case 1:
+ if (pdata->mclk1)
+ clk_id = WM8994_SYSCLK_MCLK1;
+ else if (pdata->mclk2)
+ clk_id = WM8994_SYSCLK_MCLK2;
+ break;
case 2:
+ if (pdata->mclk2)
+ clk_id = WM8994_SYSCLK_MCLK2;
+ else if (pdata->mclk1)
+ clk_id = WM8994_SYSCLK_MCLK1;
break;
default:
@@ -3991,6 +4052,7 @@ static int wm8994_component_probe(struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
struct wm8994 *control = dev_get_drvdata(component->dev->parent);
+ struct wm8994_pdata *pdata = &control->pdata;
struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
unsigned int reg;
int ret, i;
@@ -4274,6 +4336,14 @@ static int wm8994_component_probe(struct snd_soc_component *component)
ARRAY_SIZE(wm8994_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets,
ARRAY_SIZE(wm8994_specific_dapm_widgets));
+ if (pdata->mclk1)
+ snd_soc_dapm_new_controls(dapm, wm8994_mclk1_dapm_widgets,
+ ARRAY_SIZE(wm8994_mclk1_dapm_widgets));
+
+ if (pdata->mclk2)
+ snd_soc_dapm_new_controls(dapm, wm8994_mclk2_dapm_widgets,
+ ARRAY_SIZE(wm8994_mclk2_dapm_widgets));
+
if (control->revision < 4) {
snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets,
ARRAY_SIZE(wm8994_lateclk_revd_widgets));
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 3e7226a53..7c4d63c33 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -831,25 +831,33 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
/* Get clocks */
i2s->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(i2s->pclk)) {
- dev_err(&pdev->dev, "Could not get pclk\n");
+ if (PTR_ERR(i2s->pclk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Could not get pclk: %ld\n",
+ PTR_ERR(i2s->pclk));
return PTR_ERR(i2s->pclk);
}
i2s->i2sclk = devm_clk_get(&pdev->dev, "i2sclk");
if (IS_ERR(i2s->i2sclk)) {
- dev_err(&pdev->dev, "Could not get i2sclk\n");
+ if (PTR_ERR(i2s->i2sclk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Could not get i2sclk: %ld\n",
+ PTR_ERR(i2s->i2sclk));
return PTR_ERR(i2s->i2sclk);
}
i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k");
if (IS_ERR(i2s->x8kclk)) {
- dev_err(&pdev->dev, "missing x8k parent clock\n");
+ if (PTR_ERR(i2s->x8kclk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Could not get x8k parent clock: %ld\n",
+ PTR_ERR(i2s->x8kclk));
return PTR_ERR(i2s->x8kclk);
}
i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k");
if (IS_ERR(i2s->x11kclk)) {
- dev_err(&pdev->dev, "missing x11k parent clock\n");
+ if (PTR_ERR(i2s->x11kclk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Could not get x11k parent clock: %ld\n",
+ PTR_ERR(i2s->x11kclk));
return PTR_ERR(i2s->x11kclk);
}
@@ -866,12 +874,24 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
}
/* Reset */
- rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
- if (!IS_ERR(rst)) {
- reset_control_assert(rst);
- udelay(2);
- reset_control_deassert(rst);
+ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(rst)) {
+ if (PTR_ERR(rst) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Reset controller error %ld\n",
+ PTR_ERR(rst));
+ return PTR_ERR(rst);
}
+ reset_control_assert(rst);
+ udelay(2);
+ reset_control_deassert(rst);
+
+ return 0;
+}
+
+static int stm32_i2s_remove(struct platform_device *pdev)
+{
+ snd_dmaengine_pcm_unregister(&pdev->dev);
+ snd_soc_unregister_component(&pdev->dev);
return 0;
}
@@ -903,48 +923,62 @@ static int stm32_i2s_probe(struct platform_device *pdev)
i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk",
i2s->base, i2s->regmap_conf);
if (IS_ERR(i2s->regmap)) {
- dev_err(&pdev->dev, "regmap init failed\n");
+ if (PTR_ERR(i2s->regmap) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Regmap init error %ld\n",
+ PTR_ERR(i2s->regmap));
return PTR_ERR(i2s->regmap);
}
- ret = devm_snd_soc_register_component(&pdev->dev, &stm32_i2s_component,
- i2s->dai_drv, 1);
- if (ret)
+ ret = snd_dmaengine_pcm_register(&pdev->dev, &stm32_i2s_pcm_config, 0);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "PCM DMA register error %d\n", ret);
return ret;
+ }
- ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
- &stm32_i2s_pcm_config, 0);
- if (ret)
+ ret = snd_soc_register_component(&pdev->dev, &stm32_i2s_component,
+ i2s->dai_drv, 1);
+ if (ret) {
+ snd_dmaengine_pcm_unregister(&pdev->dev);
return ret;
+ }
/* Set SPI/I2S in i2s mode */
ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD);
if (ret)
- return ret;
+ goto error;
ret = regmap_read(i2s->regmap, STM32_I2S_IPIDR_REG, &val);
if (ret)
- return ret;
+ goto error;
if (val == I2S_IPIDR_NUMBER) {
ret = regmap_read(i2s->regmap, STM32_I2S_HWCFGR_REG, &val);
if (ret)
- return ret;
+ goto error;
if (!FIELD_GET(I2S_HWCFGR_I2S_SUPPORT_MASK, val)) {
dev_err(&pdev->dev,
"Device does not support i2s mode\n");
- return -EPERM;
+ ret = -EPERM;
+ goto error;
}
ret = regmap_read(i2s->regmap, STM32_I2S_VERR_REG, &val);
+ if (ret)
+ goto error;
dev_dbg(&pdev->dev, "I2S version: %lu.%lu registered\n",
FIELD_GET(I2S_VERR_MAJ_MASK, val),
FIELD_GET(I2S_VERR_MIN_MASK, val));
}
+ return ret;
+
+error:
+ stm32_i2s_remove(pdev);
+
return ret;
}
@@ -981,6 +1015,7 @@ static struct platform_driver stm32_i2s_driver = {
.pm = &stm32_i2s_pm_ops,
},
.probe = stm32_i2s_probe,
+ .remove = stm32_i2s_remove,
};
module_platform_driver(stm32_i2s_driver);
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index ef4273361..820ae27e7 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -174,20 +174,26 @@ static int stm32_sai_probe(struct platform_device *pdev)
if (!STM_SAI_IS_F4(sai)) {
sai->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(sai->pclk)) {
- dev_err(&pdev->dev, "missing bus clock pclk\n");
+ if (PTR_ERR(sai->pclk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "missing bus clock pclk: %ld\n",
+ PTR_ERR(sai->pclk));
return PTR_ERR(sai->pclk);
}
}
sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k");
if (IS_ERR(sai->clk_x8k)) {
- dev_err(&pdev->dev, "missing x8k parent clock\n");
+ if (PTR_ERR(sai->clk_x8k) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "missing x8k parent clock: %ld\n",
+ PTR_ERR(sai->clk_x8k));
return PTR_ERR(sai->clk_x8k);
}
sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k");
if (IS_ERR(sai->clk_x11k)) {
- dev_err(&pdev->dev, "missing x11k parent clock\n");
+ if (PTR_ERR(sai->clk_x11k) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "missing x11k parent clock: %ld\n",
+ PTR_ERR(sai->clk_x11k));
return PTR_ERR(sai->clk_x11k);
}
@@ -197,12 +203,16 @@ static int stm32_sai_probe(struct platform_device *pdev)
return sai->irq;
/* reset */
- rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
- if (!IS_ERR(rst)) {
- reset_control_assert(rst);
- udelay(2);
- reset_control_deassert(rst);
+ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(rst)) {
+ if (PTR_ERR(rst) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Reset controller error %ld\n",
+ PTR_ERR(rst));
+ return PTR_ERR(rst);
}
+ reset_control_assert(rst);
+ udelay(2);
+ reset_control_deassert(rst);
/* Enable peripheral clock to allow register access */
ret = clk_prepare_enable(sai->pclk);
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 10eb4b8e8..be25715b4 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -1380,7 +1380,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
sai->regmap = devm_regmap_init_mmio(&pdev->dev, base,
sai->regmap_config);
if (IS_ERR(sai->regmap)) {
- dev_err(&pdev->dev, "Failed to initialize MMIO\n");
+ if (PTR_ERR(sai->regmap) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Regmap init error %ld\n",
+ PTR_ERR(sai->regmap));
return PTR_ERR(sai->regmap);
}
@@ -1471,7 +1473,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
of_node_put(args.np);
sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
if (IS_ERR(sai->sai_ck)) {
- dev_err(&pdev->dev, "Missing kernel clock sai_ck\n");
+ if (PTR_ERR(sai->sai_ck) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Missing kernel clock sai_ck: %ld\n",
+ PTR_ERR(sai->sai_ck));
return PTR_ERR(sai->sai_ck);
}
@@ -1543,21 +1547,22 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
return ret;
}
+ if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+ conf = &stm32_sai_pcm_config_spdif;
+
ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
if (ret) {
- dev_err(&pdev->dev, "Could not register pcm dma\n");
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "PCM DMA register error %d\n", ret);
return ret;
}
ret = snd_soc_register_component(&pdev->dev, &stm32_component,
&sai->cpu_dai_drv, 1);
if (ret)
- return ret;
+ snd_dmaengine_pcm_unregister(&pdev->dev);
- if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
- conf = &stm32_sai_pcm_config_spdif;
-
- return 0;
+ return ret;
}
static int stm32_sai_sub_remove(struct platform_device *pdev)
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index e53fb4bd6..1bfa3b2ba 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -353,6 +353,8 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK | SPDIFRX_CR_RXSTEO;
cr_mask = cr;
+ cr |= SPDIFRX_CR_NBTRSET(SPDIFRX_NBTR_63);
+ cr_mask |= SPDIFRX_CR_NBTR_MASK;
cr |= SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_SYNC);
cr_mask |= SPDIFRX_CR_SPDIFEN_MASK;
ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR,
@@ -404,7 +406,9 @@ static int stm32_spdifrx_dma_ctrl_register(struct device *dev,
spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl");
if (IS_ERR(spdifrx->ctrl_chan)) {
- dev_err(dev, "dma_request_slave_channel failed\n");
+ if (PTR_ERR(spdifrx->ctrl_chan) != -EPROBE_DEFER)
+ dev_err(dev, "dma_request_slave_channel error %ld\n",
+ PTR_ERR(spdifrx->ctrl_chan));
return PTR_ERR(spdifrx->ctrl_chan);
}
@@ -665,7 +669,7 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid)
struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid;
struct platform_device *pdev = spdifrx->pdev;
unsigned int cr, mask, sr, imr;
- unsigned int flags;
+ unsigned int flags, sync_state;
int err = 0, err_xrun = 0;
regmap_read(spdifrx->regmap, STM32_SPDIFRX_SR, &sr);
@@ -725,11 +729,23 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid)
}
if (err) {
- /* SPDIFRX in STATE_STOP. Disable SPDIFRX to clear errors */
+ regmap_read(spdifrx->regmap, STM32_SPDIFRX_CR, &cr);
+ sync_state = FIELD_GET(SPDIFRX_CR_SPDIFEN_MASK, cr) &&
+ SPDIFRX_SPDIFEN_SYNC;
+
+ /* SPDIFRX is in STATE_STOP. Disable SPDIFRX to clear errors */
cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE);
regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR,
SPDIFRX_CR_SPDIFEN_MASK, cr);
+ /* If SPDIFRX was in STATE_SYNC, retry synchro */
+ if (sync_state) {
+ cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_SYNC);
+ regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR,
+ SPDIFRX_CR_SPDIFEN_MASK, cr);
+ return IRQ_HANDLED;
+ }
+
spin_lock(&spdifrx->irq_lock);
if (spdifrx->substream)
snd_pcm_stop(spdifrx->substream,
@@ -915,7 +931,9 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev,
spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk");
if (IS_ERR(spdifrx->kclk)) {
- dev_err(&pdev->dev, "Could not get kclk\n");
+ if (PTR_ERR(spdifrx->kclk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Could not get kclk: %ld\n",
+ PTR_ERR(spdifrx->kclk));
return PTR_ERR(spdifrx->kclk);
}
@@ -926,6 +944,22 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev,
return 0;
}
+static int stm32_spdifrx_remove(struct platform_device *pdev)
+{
+ struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev);
+
+ if (spdifrx->ctrl_chan)
+ dma_release_channel(spdifrx->ctrl_chan);
+
+ if (spdifrx->dmab)
+ snd_dma_free_pages(spdifrx->dmab);
+
+ snd_dmaengine_pcm_unregister(&pdev->dev);
+ snd_soc_unregister_component(&pdev->dev);
+
+ return 0;
+}
+
static int stm32_spdifrx_probe(struct platform_device *pdev)
{
struct stm32_spdifrx_data *spdifrx;
@@ -953,7 +987,9 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
spdifrx->base,
spdifrx->regmap_conf);
if (IS_ERR(spdifrx->regmap)) {
- dev_err(&pdev->dev, "Regmap init failed\n");
+ if (PTR_ERR(spdifrx->regmap) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Regmap init error %ld\n",
+ PTR_ERR(spdifrx->regmap));
return PTR_ERR(spdifrx->regmap);
}
@@ -964,37 +1000,46 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
return ret;
}
- rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
- if (!IS_ERR(rst)) {
- reset_control_assert(rst);
- udelay(2);
- reset_control_deassert(rst);
+ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(rst)) {
+ if (PTR_ERR(rst) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Reset controller error %ld\n",
+ PTR_ERR(rst));
+ return PTR_ERR(rst);
}
+ reset_control_assert(rst);
+ udelay(2);
+ reset_control_deassert(rst);
- ret = devm_snd_soc_register_component(&pdev->dev,
- &stm32_spdifrx_component,
- stm32_spdifrx_dai,
- ARRAY_SIZE(stm32_spdifrx_dai));
- if (ret)
+ pcm_config = &stm32_spdifrx_pcm_config;
+ ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "PCM DMA register error %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_register_component(&pdev->dev,
+ &stm32_spdifrx_component,
+ stm32_spdifrx_dai,
+ ARRAY_SIZE(stm32_spdifrx_dai));
+ if (ret) {
+ snd_dmaengine_pcm_unregister(&pdev->dev);
return ret;
+ }
ret = stm32_spdifrx_dma_ctrl_register(&pdev->dev, spdifrx);
if (ret)
goto error;
- pcm_config = &stm32_spdifrx_pcm_config;
- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0);
- if (ret) {
- dev_err(&pdev->dev, "PCM DMA register returned %d\n", ret);
- goto error;
- }
-
ret = regmap_read(spdifrx->regmap, STM32_SPDIFRX_IDR, &idr);
if (ret)
goto error;
if (idr == SPDIFRX_IPIDR_NUMBER) {
ret = regmap_read(spdifrx->regmap, STM32_SPDIFRX_VERR, &ver);
+ if (ret)
+ goto error;
dev_dbg(&pdev->dev, "SPDIFRX version: %lu.%lu registered\n",
FIELD_GET(SPDIFRX_VERR_MAJ_MASK, ver),
@@ -1004,27 +1049,11 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
return ret;
error:
- if (!IS_ERR(spdifrx->ctrl_chan))
- dma_release_channel(spdifrx->ctrl_chan);
- if (spdifrx->dmab)
- snd_dma_free_pages(spdifrx->dmab);
+ stm32_spdifrx_remove(pdev);
return ret;
}
-static int stm32_spdifrx_remove(struct platform_device *pdev)
-{
- struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev);
-
- if (spdifrx->ctrl_chan)
- dma_release_channel(spdifrx->ctrl_chan);
-
- if (spdifrx->dmab)
- snd_dma_free_pages(spdifrx->dmab);
-
- return 0;
-}
-
MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids);
#ifdef CONFIG_PM_SLEEP
--
2.17.1

View File

@ -0,0 +1,213 @@
From 21d34047c11667042371bf23d89f168be4eb607d Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:48:07 +0200
Subject: [PATCH 19/23] ARM-stm32mp1-r1-MISC
---
CONTRIBUTING.md | 30 ++++++++++++++++++++++++
drivers/block/loop.c | 49 ++++++++++++++++++++++++++++-----------
include/linux/pm_wakeup.h | 10 ++++++++
tools/perf/util/srcline.c | 16 ++++++++++++-
4 files changed, 91 insertions(+), 14 deletions(-)
create mode 100644 CONTRIBUTING.md
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..3d1bacd78
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,30 @@
+# Contributing guide
+
+This document serves as a checklist before contributing to this repository. It includes links to read up on if topics are unclear to you.
+
+This guide mainly focuses on the proper use of Git.
+
+## 1. Issues
+
+STM32MPU projects do not activate "Github issues" feature for the time being. If you need to report an issue or question about this project deliverables, you can report them using [ ST Support Center ](https://my.st.com/ols#/ols/newrequest) or [ ST Community MPU Forum ](https://community.st.com/s/topic/0TO0X0000003u2AWAQ/stm32-mpus).
+
+## 2. Pull Requests
+
+STMicrolectronics is happy to receive contributions from the community, based on an initial Contributor License Agreement (CLA) procedure.
+
+* If you are an individual writing original source code and you are sure **you own the intellectual property**, then you need to sign an Individual CLA (https://cla.st.com).
+* If you work for a company that wants also to allow you to contribute with your work, your company needs to provide a Corporate CLA (https://cla.st.com) mentioning your GitHub account name.
+* If you are not sure that a CLA (Individual or Corporate) has been signed for your GitHub account you can check here (https://cla.st.com).
+
+Please note that:
+* The Corporate CLA will always take precedence over the Individual CLA.
+* One CLA submission is sufficient, for any project proposed by STMicroelectronics.
+
+__How to proceed__
+
+* We recommend to fork the project in your GitHub account to further develop your contribution. Please use the latest commit version.
+* Please, submit one Pull Request for one new feature or proposal. This will ease the analysis and final merge if accepted.
+
+__Note__
+
+Merge will not be done directly in GitHub but it will need first to follow internal integration process before public deliver in a standard release. The Pull request will stay open until it is merged and delivered.
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index ef6e25185..6831ab725 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -427,11 +427,12 @@ static int lo_fallocate(struct loop_device *lo, struct request *rq, loff_t pos,
* information.
*/
struct file *file = lo->lo_backing_file;
+ struct request_queue *q = lo->lo_queue;
int ret;
mode |= FALLOC_FL_KEEP_SIZE;
- if ((!file->f_op->fallocate) || lo->lo_encrypt_key_size) {
+ if (!blk_queue_discard(q)) {
ret = -EOPNOTSUPP;
goto out;
}
@@ -461,7 +462,7 @@ static void lo_complete_rq(struct request *rq)
if (!cmd->use_aio || cmd->ret < 0 || cmd->ret == blk_rq_bytes(rq) ||
req_op(rq) != REQ_OP_READ) {
if (cmd->ret < 0)
- ret = BLK_STS_IOERR;
+ ret = errno_to_blk_status(cmd->ret);
goto end_io;
}
@@ -863,28 +864,47 @@ static void loop_config_discard(struct loop_device *lo)
struct inode *inode = file->f_mapping->host;
struct request_queue *q = lo->lo_queue;
+ /*
+ * If the backing device is a block device, mirror its zeroing
+ * capability. Set the discard sectors to the block device's zeroing
+ * capabilities because loop discards result in blkdev_issue_zeroout(),
+ * not blkdev_issue_discard(). This maintains consistent behavior with
+ * file-backed loop devices: discarded regions read back as zero.
+ */
+ if (S_ISBLK(inode->i_mode) && !lo->lo_encrypt_key_size) {
+ struct request_queue *backingq;
+
+ backingq = bdev_get_queue(inode->i_bdev);
+ blk_queue_max_discard_sectors(q,
+ backingq->limits.max_write_zeroes_sectors);
+
+ blk_queue_max_write_zeroes_sectors(q,
+ backingq->limits.max_write_zeroes_sectors);
+
/*
* We use punch hole to reclaim the free space used by the
* image a.k.a. discard. However we do not support discard if
* encryption is enabled, because it may give an attacker
* useful information.
*/
- if ((!file->f_op->fallocate) ||
- lo->lo_encrypt_key_size) {
+ } else if (!file->f_op->fallocate || lo->lo_encrypt_key_size) {
q->limits.discard_granularity = 0;
q->limits.discard_alignment = 0;
blk_queue_max_discard_sectors(q, 0);
blk_queue_max_write_zeroes_sectors(q, 0);
- blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q);
- return;
- }
- q->limits.discard_granularity = inode->i_sb->s_blocksize;
- q->limits.discard_alignment = 0;
+ } else {
+ q->limits.discard_granularity = inode->i_sb->s_blocksize;
+ q->limits.discard_alignment = 0;
+
+ blk_queue_max_discard_sectors(q, UINT_MAX >> 9);
+ blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9);
+ }
- blk_queue_max_discard_sectors(q, UINT_MAX >> 9);
- blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9);
- blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
+ if (q->limits.max_write_zeroes_sectors)
+ blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
+ else
+ blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q);
}
static void loop_unprepare_queue(struct loop_device *lo)
@@ -1950,7 +1970,10 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
failed:
/* complete non-aio request */
if (!cmd->use_aio || ret) {
- cmd->ret = ret ? -EIO : 0;
+ if (ret == -EOPNOTSUPP)
+ cmd->ret = ret;
+ else
+ cmd->ret = ret ? -EIO : 0;
blk_mq_complete_request(rq);
}
}
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
index 661efa029..faee74f36 100644
--- a/include/linux/pm_wakeup.h
+++ b/include/linux/pm_wakeup.h
@@ -79,6 +79,11 @@ static inline bool device_may_wakeup(struct device *dev)
return dev->power.can_wakeup && !!dev->power.wakeup;
}
+static inline bool device_wakeup_path(struct device *dev)
+{
+ return !!dev->power.wakeup_path;
+}
+
static inline void device_set_wakeup_path(struct device *dev)
{
dev->power.wakeup_path = true;
@@ -165,6 +170,11 @@ static inline bool device_may_wakeup(struct device *dev)
return dev->power.can_wakeup && dev->power.should_wakeup;
}
+static inline bool device_wakeup_path(struct device *dev)
+{
+ return false;
+}
+
static inline void device_set_wakeup_path(struct device *dev) {}
static inline void __pm_stay_awake(struct wakeup_source *ws) {}
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index 6ccf6f6d0..5b7d6c16d 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -193,16 +193,30 @@ static void find_address_in_section(bfd *abfd, asection *section, void *data)
bfd_vma pc, vma;
bfd_size_type size;
struct a2l_data *a2l = data;
+ flagword flags;
if (a2l->found)
return;
- if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
+#ifdef bfd_get_section_flags
+ flags = bfd_get_section_flags(abfd, section);
+#else
+ flags = bfd_section_flags(section);
+#endif
+ if ((flags & SEC_ALLOC) == 0)
return;
pc = a2l->addr;
+#ifdef bfd_get_section_vma
vma = bfd_get_section_vma(abfd, section);
+#else
+ vma = bfd_section_vma(section);
+#endif
+#ifdef bfd_get_section_size
size = bfd_get_section_size(section);
+#else
+ size = bfd_section_size(section);
+#endif
if (pc < vma || pc >= vma + size)
return;
--
2.17.1

View File

@ -1,22 +1,22 @@
From 62cd375deb0762da00fbfce0f211a02404f5ab54 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:53 +0100
Subject: [PATCH 31/31] ARM stm32mp1 r3 DEFCONFIG
From c85af400114b9a862a0e9df538d00e1eb42d0028 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:50:29 +0200
Subject: [PATCH 21/23] ARM-stm32mp1-r1-CONFIG
---
.../arm/configs/fragment-01-multiv7_cleanup.config | 69 +++
arch/arm/configs/fragment-02-multiv7_addons.config | 508 +++++++++++++++++++++
arch/arm/configs/multi_v7_defconfig | 1 +
3 files changed, 578 insertions(+)
.../fragment-01-multiv7_cleanup.config | 152 +++++++
.../configs/fragment-02-multiv7_addons.config | 420 ++++++++++++++++++
arch/arm/configs/multi_v7_defconfig | 1 +
3 files changed, 573 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
index 000000000..76dd83cf0
--- /dev/null
+++ b/arch/arm/configs/fragment-01-multiv7_cleanup.config
@@ -0,0 +1,69 @@
@@ -0,0 +1,152 @@
+#
+# CPU Core family selection
+#
@ -35,6 +35,7 @@ index 0000000..22f6ffb
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
@ -82,47 +83,10 @@ index 0000000..22f6ffb
+# 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..e68bb1e
--- /dev/null
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
@@ -0,0 +1,508 @@
+#
+# General setup
+#
+CONFIG_POSIX_MQUEUE=y
+CONFIG_USELIB=y
+CONFIG_FUTEX=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
+#
@ -133,128 +97,29 @@ index 0000000..e68bb1e
+#
+# Kernel Features
+#
+CONFIG_SCHED_MC=y
+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
+
+#
+# CPU Power Management
+#
+#
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_EFI 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
+#
+CONFIG_BT_RTL=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTUSB_RTL=y
+#
+# 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
+#
+
+#
+# Misc devices
+#
+CONFIG_SRAM=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_CHR_DEV_SG=y
+
+#
+# MII PHY device drivers
+#
+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
+#
+
+#
+# Character devices
+#
+CONFIG_SERIAL_NONSTANDARD=y
+
+#
+# Serial drivers
+#
+# 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
@ -279,28 +144,183 @@ index 0000000..e68bb1e
+# CONFIG_I2C_SLAVE_EEPROM is not set
+
+#
+# STMicroelectronics STMPE Interface Drivers
+#
+# CONFIG_REGULATOR_WM8994 is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_POWER_AVS is not set
+# CONFIG_POWER_SUPPLY is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_SCHED_DEBUG 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 000000000..62c0de302
--- /dev/null
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
@@ -0,0 +1,420 @@
+#
+# General setup
+#
+CONFIG_POSIX_MQUEUE=y
+CONFIG_USELIB=y
+CONFIG_FUTEX=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
+
+#
+# Kernel Features
+#
+CONFIG_SCHED_MC=y
+CONFIG_MCPM=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_FORCE_MAX_ZONEORDER=12
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# CPU Power Management
+#
+#
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+
+
+#
+# Floating point emulation
+#
+CONFIG_VFP=y
+
+#
+# Networking options
+#
+CONFIG_DNS_RESOLVER=y
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_M_CAN=y
+CONFIG_CAN_M_CAN_PLATFORM=y
+
+#
+# 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
+#
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+
+#
+# Misc devices
+#
+CONFIG_SRAM=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_CHR_DEV_SG=y
+
+#
+# MII PHY device drivers
+#
+
+#
+# Input Device Drivers
+#
+
+#
+# Touchscreen drivers
+#
+CONFIG_TOUCHSCREEN_EDT_FT5X06=y
+CONFIG_TOUCHSCREEN_GOODIX=y
+
+#
+# Character devices
+#
+CONFIG_SERIAL_NONSTANDARD=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_STM32=y
+CONFIG_SPI_STM32_QSPI=y
+
+#
+# Pin controllers
+#
+CONFIG_PINCTRL_STMFX=y
+
+#
+# Memory mapped GPIO drivers
+#
+
+#
+# Memory Technology Device (MTD) support
+#
+
+CONFIG_MTD_SPI_NAND=y
+
+#
+# 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
@ -312,12 +332,11 @@ index 0000000..e68bb1e
+# STMicroelectronics thermal drivers
+#
+
+
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+
+#
+# Sonics Silicon Backplane
@ -329,9 +348,9 @@ index 0000000..e68bb1e
+CONFIG_PROTECTION_CONSUMER=y
+
+#
+# STMicroelectronics STMPE Interface Drivers
+# Regulator drivers
+#
+# CONFIG_REGULATOR_WM8994 is not set
+CONFIG_REGULATOR_STM32_PWR=y
+
+#
+# Multimedia core support
@ -343,14 +362,10 @@ index 0000000..e68bb1e
+CONFIG_VIDEO_STM32_HDMI_CEC=m
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+
+#
+# Camera sensor devices
+#
+CONFIG_VIDEO_OV5640=y
+CONFIG_VIDEO_OV5640=m
+CONFIG_VIDEO_ST_MIPID02=m
+
+#
+# Graphics support
@ -372,7 +387,7 @@ index 0000000..e68bb1e
+#
+# Display Interface Bridges
+#
+CONFIG_VIDEO_ADV7511=y
+CONFIG_DRM_I2C_ADV7511=y
+CONFIG_DRM_SII902X=y
+
+#
@ -410,7 +425,6 @@ index 0000000..e68bb1e
+CONFIG_SND_SOC_DMIC=y
+CONFIG_SND_SOC_CS42L42=y
+CONFIG_SND_SOC_CS42L51_I2C=y
+
+#
+# USB Device Class drivers
+#
@ -421,12 +435,6 @@ index 0000000..e68bb1e
+#
+
+#
+# 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
+#
+CONFIG_USB_CONFIGFS=y
@ -457,7 +465,6 @@ index 0000000..e68bb1e
+# File systems
+#
+CONFIG_OVERLAY_FS=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+CONFIG_JFFS2_FS=y
+
+#
@ -484,7 +491,6 @@ index 0000000..e68bb1e
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_PREEMPT=y
+
+#
@ -495,6 +501,9 @@ index 0000000..e68bb1e
+#
+CONFIG_KEYS=y
+
+CONFIG_CRYPTO_DEV_STM32_CRC=y
+CONFIG_CRYPTO_DEV_STM32_HASH=y
+CONFIG_CRYPTO_DEV_STM32_CRYP=y
+
+#
+# Library routines
@ -502,61 +511,35 @@ index 0000000..e68bb1e
+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 HSEM
+#
+CONFIG_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_STM32=y
+
+#
+# STM32 IPCC
+#
+CONFIG_STM32_IPCC=y
+
+#
+# STM32 RPROC
+#
+CONFIG_REMOTEPROC=y
+CONFIG_STM32_RPROC=y
+CONFIG_RPMSG_VIRTIO=y
+
+#
+# RPMSG_TTY
+#
+CONFIG_RPMSG_VIRTIO=y
@ -569,26 +552,27 @@ index 0000000..e68bb1e
+CONFIG_SAMPLE_RPMSG_CLIENT=m
+
+#
+# STM32 RPROC
+# STM32 TIMER
+#
+# CONFIG_MAILBOX is not set
+CONFIG_REMOTEPROC=y
+CONFIG_STM32_RPROC=y
+CONFIG_RPMSG_VIRTIO=y
+CONFIG_MFD_STM32_TIMERS=y
+CONFIG_IIO_STM32_TIMER_TRIGGER=y
+CONFIG_PWM_STM32=y
+CONFIG_COUNTER=y
+CONFIG_STM32_TIMER_CNT=y
+
+#
+# Cryptographic
+# STM32 LPTIMER
+#
+CONFIG_CRYPTO_DEV_STM32_CRC=y
+CONFIG_CRYPTO_DEV_STM32_HASH=y
+CONFIG_CRYPTO_DEV_STM32_CRYP=y
+CONFIG_MFD_STM32_LPTIMER=y
+CONFIG_PWM_STM32_LP=y
+CONFIG_IIO_STM32_LPTIMER_TRIGGER=y
+CONFIG_STM32_LPTIMER_CNT=y
+
+#
+# STM32 ADC
+#
+CONFIG_STM32_ADC_CORE=y
+CONFIG_STM32_ADC=y
+CONFIG_STM32_ADC_TEMP=y
+
+#
+# STM32 DAC
@ -596,22 +580,33 @@ index 0000000..e68bb1e
+CONFIG_STM32_DAC=y
+
+#
+# STM32 HSEM
+# STM32 VREFBUF
+#
+CONFIG_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_STM32=y
+CONFIG_REGULATOR_STM32_VREFBUF=y
+
+#
+# SCMI
+#
+CONFIG_ARM_SCMI_PROTOCOL=y
+CONFIG_COMMON_CLK_SCMI=y
+CONFIG_ARM_SMC_MBOX=y
+
+#
+# TTY
+#
+CONFIG_LEGACY_PTY_COUNT=8
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index fc33444..ac1e50b 100644
index e4c8def9a..4231ad37e 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -946,6 +946,7 @@ CONFIG_PHY_DM816X_USB=m
CONFIG_OMAP_USB2=y
CONFIG_TI_PIPE3=y
@@ -1038,6 +1038,7 @@ CONFIG_TI_PIPE3=y
CONFIG_TWL4030_USB=m
CONFIG_MESON_MX_EFUSE=m
CONFIG_ROCKCHIP_EFUSE=m
+CONFIG_STM32_DDR_PMU=y
CONFIG_NVMEM_IMX_OCOTP=y
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_NVMEM_VF610_OCOTP=y
--
2.7.4
2.17.1

View File

@ -0,0 +1,24 @@
From 65ad7ed110b25b333679e5084fb82db0d5a15a6c Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Fri, 10 Apr 2020 14:50:46 +0200
Subject: [PATCH 22/23] ARM-stm32mp1-r1-POWER
---
kernel/power/suspend.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 27f149f5d..4581702e8 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -34,7 +34,6 @@
#include "power.h"
const char * const pm_labels[] = {
- [PM_SUSPEND_TO_IDLE] = "freeze",
[PM_SUSPEND_STANDBY] = "standby",
[PM_SUSPEND_MEM] = "mem",
};
--
2.17.1

View File

@ -1,20 +1,20 @@
From 6b4eeb6fe243c0c077a9b9ce4f631a5310f7b058 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Fri, 8 Nov 2019 16:52:43 +0100
Subject: [PATCH 18/31] ARM stm32mp1 r3 PERF
From cc23b579a850b77f33f331fe854a4d52910ed0d1 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Tue, 9 Jun 2020 13:06:44 +0200
Subject: [PATCH 23/23] ARM-stm32mp1-r1-PERF
---
Documentation/perf/stm32-ddr-pmu.txt | 41 +++
drivers/perf/Kconfig | 6 +
drivers/perf/Makefile | 1 +
drivers/perf/stm32_ddr_pmu.c | 505 +++++++++++++++++++++++++++++++++++
drivers/perf/stm32_ddr_pmu.c | 505 +++++++++++++++++++++++++++
4 files changed, 553 insertions(+)
create mode 100644 Documentation/perf/stm32-ddr-pmu.txt
create mode 100644 drivers/perf/stm32_ddr_pmu.c
diff --git a/Documentation/perf/stm32-ddr-pmu.txt b/Documentation/perf/stm32-ddr-pmu.txt
new file mode 100644
index 0000000..d5b35b3
index 000000000..d5b35b326
--- /dev/null
+++ b/Documentation/perf/stm32-ddr-pmu.txt
@@ -0,0 +1,41 @@
@ -60,10 +60,10 @@ index 0000000..d5b35b3
+ $ cat /sys/bus/event_source/devices/ddrperfm/bandwidth
+ Read = 403, Write = 239, Read & Write = 642 (MB/s)
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 08ebaf7..57e8f6c 100644
index 09ae8a970..2c5041314 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -87,6 +87,12 @@ config QCOM_L3_PMU
@@ -105,6 +105,12 @@ config QCOM_L3_PMU
Adds the L3 cache PMU into the perf events subsystem for
monitoring L3 cache events.
@ -73,23 +73,24 @@ index 08ebaf7..57e8f6c 100644
+ help
+ Support for STM32 DDR performance monitor (DDRPERFM).
+
config XGENE_PMU
depends on ARCH_XGENE
bool "APM X-Gene SoC PMU"
config THUNDERX2_PMU
tristate "Cavium ThunderX2 SoC PMU UNCORE"
depends on ARCH_THUNDER2 && ARM64 && ACPI && NUMA
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index b3902bd..04f7f64 100644
index 2ebb4de17..fd3368c1b 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -7,5 +7,6 @@ obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.o
@@ -9,6 +9,7 @@ obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o
obj-$(CONFIG_HISI_PMU) += hisilicon/
obj-$(CONFIG_QCOM_L2_PMU) += qcom_l2_pmu.o
obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o
+obj-$(CONFIG_STM32_DDR_PMU) += stm32_ddr_pmu.o
obj-$(CONFIG_THUNDERX2_PMU) += thunderx2_pmu.o
obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o
obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o
diff --git a/drivers/perf/stm32_ddr_pmu.c b/drivers/perf/stm32_ddr_pmu.c
new file mode 100644
index 0000000..4f30f6f
index 000000000..4f30f6f8b
--- /dev/null
+++ b/drivers/perf/stm32_ddr_pmu.c
@@ -0,0 +1,505 @@
@ -599,5 +600,5 @@ index 0000000..4f30f6f
+MODULE_AUTHOR("Gerald Baeza <gerald.baeza@st.com>");
+MODULE_LICENSE("GPL v2");
--
2.7.4
2.17.1

View File

@ -13,3 +13,9 @@ CONFIG_IIO_ST_LSM6DSX_I2C=m
# support of event emulation
CONFIG_INPUT_UINPUT=m
# USBIP
CONFIG_USBIP_CORE=m
CONFIG_USBIP_HOST=m
# CONFIG_USBIP_DEBUG is not set

View File

@ -0,0 +1,10 @@
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_SHA256=y
CONFIG_MODULE_SIG_ALL=y
# CONFIG_MODULE_SIG_FORCE is not set
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
# CONFIG_MODULE_SIG_SHA1 is not set
# CONFIG_MODULE_SIG_SHA224 is not set
CONFIG_MODULE_SIG_SHA256=y
# CONFIG_MODULE_SIG_SHA384 is not set
# CONFIG_MODULE_SIG_SHA512 is not set

View File

@ -12,12 +12,15 @@ Compilation of kernel:
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
- libncurses and libncursesw dev package libyaml-dev
Ubuntu: sudo apt-get install libncurses5-dev libncursesw5-dev libyaml-dev
Fedora: sudo yum install ncurses-devel libyaml-devel
- mkimage
Ubuntu: sudo apt-get install u-boot-tools
Fedora: sudo yum install u-boot-tools
- yaml (check dts)
Ubuntu: sudo apt-get install libyaml-dev
Fedora: sudo yum install libyaml-devel
Only if you like to have a git management of the code (see section 4
[Manage the kernel source code]):
@ -26,18 +29,18 @@ Only if you like to have a git management of the code (see section 4
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"
$ 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-cortexa7t2hf-neon-vfpv4-openstlinux_weston-linux-gnueabi
$ source <path to SDK>/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-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-
$ set | grep CROSS
CROSS_COMPILE=arm-ostl-linux-gnueabi-
Warning: the environment is valid only on the shell session where you have
sourced the SDK environment.
@ -46,18 +49,14 @@ sourced the SDK environment.
-------------------------
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
$> tar xfJ linux-##PV##.tar.xz
A new directory containing kernel standard source code will be created, go into it:
$> cd <directory to kernel source code>
$> cd linux-##PV##
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
$> for p in `ls -1 ../*.patch`; do patch -p1 < $p; done
4. Manage the kernel source code:
---------------------------------
@ -67,11 +66,11 @@ 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
$ 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
$ 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
@ -81,10 +80,10 @@ Or
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
$ 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.
@ -94,8 +93,8 @@ 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
$ 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
@ -121,33 +120,33 @@ We highly preconized the build is a build directory method as:
* 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>
$ 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
$ 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"
$ 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
$ 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
$ 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
$ 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
$ 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)
@ -168,7 +167,7 @@ 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>
$ 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
@ -181,28 +180,34 @@ inside the dedicated build directory).
or
$> cd <build directory>
$ cd <build directory>
* Build kernel images (uImage and vmlinux) and device tree (dtbs)
$> make ARCH=arm uImage vmlinux dtbs LOADADDR=0xC2000040
$ make ARCH=arm uImage vmlinux dtbs LOADADDR=0xC2000040
* Build kernel module
$> make ARCH=arm modules
$ 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/
$ 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>
$ cd <directory to kernel source code>
* Build kernel images (uImage and vmlinux) and device tree (dtbs)
$> make ARCH=arm uImage vmlinux dtbs LOADADDR=0xC2000040
$ make ARCH=arm uImage vmlinux dtbs LOADADDR=0xC2000040
* Build kernel module
$> make ARCH=arm modules
$ 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/
$ 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/
Generated files are :
#> $PWD/install_artifact/boot/uImage
#> $PWD/install_artifact/boot/<stm32-boards>.dtb
7. Update software on board:
----------------------------
@ -217,63 +222,63 @@ Please refer to User guide for more details.
7.2. Update via network:
------------------------
* kernel + devicetree
$> cd <path to install_artifact dir>/install_artifact
$ cd <path to install_artifact dir>/install_artifact
if bootfs are not monted on target, mount it
$> ssh root@<ip of board> df to see if there is a partition mounted on /boot
$ ssh root@<ip of board> df to see if there is a partition mounted on /boot
else
$> 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
$ 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
$ 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
$ 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
$ 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/
$ 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
$ ssh root@<ip of board> /sbin/depmod -a
Synchronize data on disk with memory
$> ssh root@<ip of board> sync
$ ssh root@<ip of board> sync
Reboot the board in order to take update into account
$> ssh root@<ip of board> reboot
$ 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
$ 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/
$ 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/
$ sudo cp -r boot/* /media/$USER/bootfs/
Don't forget to unmount properly sdcard
* kernel modules
$> cd <path to install_artifact dir>/install_artifact
$ 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
$ 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
$ 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/
$ 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/
$ 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
$ ssh root@<ip of board> depmod -a
Synchronize data on disk with memory
$> ssh root@<ip of board> sync
$ ssh root@<ip of board> sync
Reboot the board in order to take update into account
$> ssh root@<ip of board> reboot
$ ssh root@<ip of board> reboot
7.4. Update via SDCARD on your BOARD (via U-Boot):
--------------------------------------------------
@ -291,32 +296,32 @@ For SDCARD: ums 0 mmc 0
For USB Disk: ums 0 usb 0
* kernel + devicetree
$> cd <path to install_artifact dir>/install_artifact
$ 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
$ 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
$ 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/
$ 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/
$ 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
$ 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
$ 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
$ 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/
$ 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/
$ 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
@ -338,13 +343,13 @@ For USB Disk: ums 0 usb 0
$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
$on board> modinfo /lib/modules/5.4.31/kernel/drivers/leds/led-class-flash.ko
filename: /lib/modules/5.4.31/kernel/drivers/leds/led-class-flash.ko
license: GPL v2
description: LED Flash class interface
author: Jacek Anaszewski <j.anaszewski@samsung.com>
depends:
depends:
intree: Y
vermagic: 4.9.23-g3e866b0 SMP mod_unload ARMv7 p2v8
name: led_class_flash
vermagic: 5.4.31 SMP preempt mod_unload modversions ARMv7 p2v8

View File

@ -1,95 +0,0 @@
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.94.tar.xz"
SRC_URI[md5sum] = "3f5621e9b463a3574618f3edfe438e4a"
SRC_URI[sha256sum] = "c62a10a75a7c4213e41287040e7c7509b7d42117d6830feb7dfe505949fa7467"
SRC_URI += " \
file://${LINUX_VERSION}/4.19.94/0001-ARM-stm32mp1-r3-MACHINE.patch \
file://${LINUX_VERSION}/4.19.94/0002-ARM-stm32mp1-r3-CPUFREQ.patch \
file://${LINUX_VERSION}/4.19.94/0003-ARM-stm32mp1-r3-CRYPTO.patch \
file://${LINUX_VERSION}/4.19.94/0004-ARM-stm32mp1-r3-BLUETOOTH-CHAR.patch \
file://${LINUX_VERSION}/4.19.94/0005-ARM-stm32mp1-r3-CLOCK.patch \
file://${LINUX_VERSION}/4.19.94/0006-ARM-stm32mp1-r3-DMA.patch \
file://${LINUX_VERSION}/4.19.94/0007-ARM-stm32mp1-r3-DRM.patch \
file://${LINUX_VERSION}/4.19.94/0008-ARM-stm32mp1-r3-GPIO.patch \
file://${LINUX_VERSION}/4.19.94/0009-ARM-stm32mp1-r3-HWSPINLOCK.patch \
file://${LINUX_VERSION}/4.19.94/0010-ARM-stm32mp1-r3-HWTRACING-I2C.patch \
file://${LINUX_VERSION}/4.19.94/0011-ARM-stm32mp1-r3-IIO.patch \
file://${LINUX_VERSION}/4.19.94/0012-ARM-stm32mp1-r3-INPUT-IRQ-Mailbox.patch \
file://${LINUX_VERSION}/4.19.94/0013-ARM-stm32mp1-r3-MEDIA.patch \
file://${LINUX_VERSION}/4.19.94/0014-ARM-stm32mp1-r3-MFD.patch \
file://${LINUX_VERSION}/4.19.94/0015-ARM-stm32mp1-r3-MMC-MTD.patch \
file://${LINUX_VERSION}/4.19.94/0016-ARM-stm32mp1-r3-NET.patch \
file://${LINUX_VERSION}/4.19.94/0017-ARM-stm32mp1-r3-NVMEM.patch \
file://${LINUX_VERSION}/4.19.94/0018-ARM-stm32mp1-r3-PERF.patch \
file://${LINUX_VERSION}/4.19.94/0019-ARM-stm32mp1-r3-PHY-PINCTRL-PWM.patch \
file://${LINUX_VERSION}/4.19.94/0020-ARM-stm32mp1-r3-REGULATOR.patch \
file://${LINUX_VERSION}/4.19.94/0021-ARM-stm32mp1-r3-REMOTEPROC-RPMSG-RESET.patch \
file://${LINUX_VERSION}/4.19.94/0022-ARM-stm32mp1-r3-RTC.patch \
file://${LINUX_VERSION}/4.19.94/0023-ARM-stm32mp1-r3-SOC.patch \
file://${LINUX_VERSION}/4.19.94/0024-ARM-stm32mp1-r3-SPI.patch \
file://${LINUX_VERSION}/4.19.94/0025-ARM-stm32mp1-r3-THERMAL.patch \
file://${LINUX_VERSION}/4.19.94/0026-ARM-stm32mp1-r3-TTY-USB.patch \
file://${LINUX_VERSION}/4.19.94/0027-ARM-stm32mp1-r3-WATCHDOG.patch \
file://${LINUX_VERSION}/4.19.94/0028-ARM-stm32mp1-r3-SOUND.patch \
file://${LINUX_VERSION}/4.19.94/0029-ARM-stm32mp1-r2.4-MISC.patch \
file://${LINUX_VERSION}/4.19.94/0030-ARM-stm32mp1-r3-DEVICETREE.patch \
file://${LINUX_VERSION}/4.19.94/0031-ARM-stm32mp1-r3-DEFCONFIG.patch \
"
LINUX_VERSION = "4.19"
PV = "${LINUX_VERSION}"
S = "${WORKDIR}/linux-4.19.94"
# ---------------------------------
# Configure devupstream class usage
# ---------------------------------
BBCLASSEXTEND = "devupstream:target"
SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/linux.git;protocol=https;branch=v${LINUX_VERSION}-stm32mp;name=linux"
SRCREV_class-devupstream = "1cb30cb5ffc29a53ec2031b6a29878ddd266516c"
SRCREV_FORMAT_class-devupstream = "linux"
PV_class-devupstream = "${LINUX_VERSION}+github+${SRCPV}"
# ---------------------------------
# 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)}"
# ---------------------------------
# Configure archiver use
# ---------------------------------
include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'linux-stm32mp-archiver.inc','')}
# -------------------------------------------------------------
# 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_class-devupstream += " file://4.19/fragment-03-systemd.config;subdir=fragments "
SRC_URI_class-devupstream += " file://4.19/fragment-04-optee.config;subdir=fragments "
SRC_URI_class-devupstream += " file://4.19/fragment-05-modules.config;subdir=fragments "
# -------------------------------------------------------------
# Kernel Args
#
KERNEL_EXTRA_ARGS += "LOADADDR=${ST_KERNEL_LOADADDR}"

View File

@ -0,0 +1,89 @@
SUMMARY = "Linux STM32MP Kernel"
SECTION = "kernel"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
include linux-stm32mp.inc
LINUX_VERSION = "5.4"
LINUX_SUBVERSION = "31"
SRC_URI = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}.tar.xz;name=kernel"
SRC_URI[kernel.sha256sum] = "a11083f8f809887f6a0f8d4467532385b99418f17998fe6e837807491c276eeb"
SRC_URI += " \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0001-ARM-stm32mp1-r1-MACHINE.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0002-ARM-stm32mp1-r1-CPUFREQ.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0003-ARM-stm32mp1-r1-CRYPTO.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0004-ARM-stm32mp1-r1-RNG-DEBUG-NVMEM.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0005-ARM-stm32mp1-r1-CLOCK.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0006-ARM-stm32mp1-r1-DMA.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0007-ARM-stm32mp1-r1-DRM.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0008-ARM-stm32mp1-r1-HWSPINLOCK.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0009-ARM-stm32mp1-r1-I2C-IIO-IRQCHIP.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0010-ARM-stm32mp1-r1-MAILBOX-REMOTEPROC-RPMSG.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0011-ARM-stm32mp1-r1-RESET-RTC-WATCHDOG.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0012-ARM-stm32mp1-r1-MEDIA-SOC-THERMAL.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0013-ARM-stm32mp1-r1-MFD.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0014-ARM-stm32mp1-r1-MMC-NAND.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0015-ARM-stm32mp1-r1-NET-TTY.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0016-ARM-stm32mp1-r1-PHY-USB.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0017-ARM-stm32mp1-r1-PINCTRL-REGULATOR-SPI-PWM.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0018-ARM-stm32mp1-r1-SOUND.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0019-ARM-stm32mp1-r1-MISC.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0020-ARM-stm32mp1-r1-DEVICETREE.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0021-ARM-stm32mp1-r1-CONFIG.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0022-ARM-stm32mp1-r1-POWER.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0023-ARM-stm32mp1-r1-PERF.patch \
"
PV = "${LINUX_VERSION}.${LINUX_SUBVERSION}"
S = "${WORKDIR}/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}"
# ---------------------------------
# Configure devupstream class usage
# ---------------------------------
#BBCLASSEXTEND = "devupstream:target"
#SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/linux.git;protocol=https;branch=v${LINUX_VERSION}-stm32mp;name=linux"
#SRCREV_class-devupstream = "196201973b7048ccf75aa63ac3c3673f8b6ee1c1"
#SRCREV_FORMAT_class-devupstream = "linux"
#PV_class-devupstream = "${LINUX_VERSION}+github+${SRCPV}"
# ---------------------------------
# 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)}"
# ---------------------------------
# Configure archiver use
# ---------------------------------
include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'linux-stm32mp-archiver.inc','')}
# -------------------------------------------------------------
# Defconfig
#
KERNEL_DEFCONFIG = "defconfig"
KERNEL_CONFIG_FRAGMENTS = "${@bb.utils.contains('KERNEL_DEFCONFIG', 'defconfig', '${S}/arch/arm/configs/fragment-01-multiv7_cleanup.config', '', d)}"
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('KERNEL_DEFCONFIG', 'defconfig', '${S}/arch/arm/configs/fragment-02-multiv7_addons.config', '', d)}"
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${WORKDIR}/fragments/5.4/fragment-03-systemd.config', '', d)} "
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('COMBINED_FEATURES', 'optee', '${WORKDIR}/fragments/5.4/fragment-04-optee.config', '', d)}"
KERNEL_CONFIG_FRAGMENTS += "${WORKDIR}/fragments/5.4/fragment-05-modules.config"
KERNEL_CONFIG_FRAGMENTS += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', '${WORKDIR}/fragments/5.4/fragment-06-signature.config','')} "
SRC_URI += "file://${LINUX_VERSION}/fragment-03-systemd.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-04-optee.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-05-modules.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-06-signature.config;subdir=fragments"
# Don't forget to add/del for devupstream
#SRC_URI_class-devupstream += " file://${LINUX_VERSION}/fragment-03-systemd.config;subdir=fragments "
#SRC_URI_class-devupstream += " file://${LINUX_VERSION}/fragment-04-optee.config;subdir=fragments "
#SRC_URI_class-devupstream += " file://${LINUX_VERSION}/fragment-05-modules.config;subdir=fragments "
# -------------------------------------------------------------
# Kernel Args
#
KERNEL_EXTRA_ARGS += "LOADADDR=${ST_KERNEL_LOADADDR}"