KERNEL: v1.1.0 update
Signed-off-by: Christophe Priouzeau <christophe.priouzeau@st.com>
This commit is contained in:
parent
7bc347c769
commit
3d3a8be098
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Archiver Configuration
|
||||
#
|
||||
SRC_URI_append = " file://README.HOW_TO.txt "
|
||||
|
||||
inherit archiver
|
||||
ARCHIVER_MODE[src] = "original"
|
||||
|
||||
inherit archiver_stm32mp_clean
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
From 747a93a65dc5e3761539c365a272186f0b7fca08 Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:11:59 +0200
|
||||
Subject: [PATCH 01/30] ARM stm32mp1 r2 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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,61 @@
|
|||
From 613535e3904f7615aff655384c65cd897312e3b0 Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:11:59 +0200
|
||||
Subject: [PATCH 03/30] ARM stm32mp1 r2 BLUETOOTH CHAR
|
||||
|
||||
---
|
||||
drivers/bluetooth/hci_bcm.c | 3 ++-
|
||||
drivers/char/hw_random/stm32-rng.c | 9 +++++++++
|
||||
2 files changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
|
||||
index 8001323..31da580 100644
|
||||
--- a/drivers/bluetooth/hci_bcm.c
|
||||
+++ b/drivers/bluetooth/hci_bcm.c
|
||||
@@ -1299,7 +1299,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 042860d..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);
|
||||
@@ -169,6 +170,13 @@ static int stm32_rng_probe(struct platform_device *ofdev)
|
||||
return devm_hwrng_register(dev, &priv->rng);
|
||||
}
|
||||
|
||||
+static int stm32_rng_remove(struct platform_device *ofdev)
|
||||
+{
|
||||
+ pm_runtime_disable(&ofdev->dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_PM
|
||||
static int stm32_rng_runtime_suspend(struct device *dev)
|
||||
{
|
||||
@@ -210,6 +218,7 @@ static struct platform_driver stm32_rng_driver = {
|
||||
.of_match_table = stm32_rng_match,
|
||||
},
|
||||
.probe = stm32_rng_probe,
|
||||
+ .remove = stm32_rng_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(stm32_rng_driver);
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
From 2eae46b85e51f0b995ddfdd6176501d4a6cf1520 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:15:45 +0100
|
||||
Subject: [PATCH 02/52] ARM: stm32mp1-r0-rc1: CLOCK
|
||||
From 787309b96cc3eb1ed824dff1a9814d88a437bebb Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:11:59 +0200
|
||||
Subject: [PATCH 04/30] ARM stm32mp1 r2 CLOCK
|
||||
|
||||
---
|
||||
drivers/clk/clk-stm32mp1.c | 1022 ++++++++++++++++++++++++++---
|
||||
drivers/clk/clk-stm32mp1.c | 1061 ++++++++++++++++++++++++++---
|
||||
drivers/clk/clk.c | 24 +-
|
||||
include/dt-bindings/clock/stm32mp1-clks.h | 3 -
|
||||
include/linux/clk.h | 1 +
|
||||
4 files changed, 968 insertions(+), 82 deletions(-)
|
||||
4 files changed, 1004 insertions(+), 85 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
|
||||
index a907555..50d739a 100644
|
||||
index a907555..fba9626 100644
|
||||
--- a/drivers/clk/clk-stm32mp1.c
|
||||
+++ b/drivers/clk/clk-stm32mp1.c
|
||||
@@ -5,15 +5,22 @@
|
||||
|
|
@ -37,7 +37,15 @@ index a907555..50d739a 100644
|
|||
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
|
||||
@@ -101,6 +108,10 @@ static DEFINE_SPINLOCK(rlock);
|
||||
@@ -45,6 +52,7 @@ static DEFINE_SPINLOCK(rlock);
|
||||
#define RCC_AHB5ENSETR 0x210
|
||||
#define RCC_AHB6ENSETR 0x218
|
||||
#define RCC_AHB6LPENSETR 0x318
|
||||
+#define RCC_MLAHBENSETR 0xA38
|
||||
#define RCC_RCK12SELR 0x28
|
||||
#define RCC_RCK3SELR 0x820
|
||||
#define RCC_RCK4SELR 0x824
|
||||
@@ -101,6 +109,10 @@ static DEFINE_SPINLOCK(rlock);
|
||||
#define RCC_TIMG2PRER 0x82C
|
||||
#define RCC_RTCDIVR 0x44
|
||||
#define RCC_DBGCFGR 0x80C
|
||||
|
|
@ -48,7 +56,7 @@ index a907555..50d739a 100644
|
|||
|
||||
#define RCC_CLR 0x4
|
||||
|
||||
@@ -121,7 +132,7 @@ static const char * const cpu_src[] = {
|
||||
@@ -121,7 +133,7 @@ static const char * const cpu_src[] = {
|
||||
};
|
||||
|
||||
static const char * const axi_src[] = {
|
||||
|
|
@ -57,7 +65,7 @@ index a907555..50d739a 100644
|
|||
};
|
||||
|
||||
static const char * const per_src[] = {
|
||||
@@ -225,19 +236,19 @@ static const char * const usart6_src[] = {
|
||||
@@ -225,19 +237,19 @@ static const char * const usart6_src[] = {
|
||||
};
|
||||
|
||||
static const char * const fdcan_src[] = {
|
||||
|
|
@ -81,7 +89,7 @@ index a907555..50d739a 100644
|
|||
};
|
||||
|
||||
static const char * const dsi_src[] = {
|
||||
@@ -269,7 +280,7 @@ static const struct clk_div_table axi_div_table[] = {
|
||||
@@ -269,7 +281,7 @@ static const struct clk_div_table axi_div_table[] = {
|
||||
static const struct clk_div_table mcu_div_table[] = {
|
||||
{ 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
|
||||
{ 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 },
|
||||
|
|
@ -90,7 +98,7 @@ index a907555..50d739a 100644
|
|||
{ 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 },
|
||||
{ 0 },
|
||||
};
|
||||
@@ -356,17 +367,20 @@ struct stm32_gate_cfg {
|
||||
@@ -356,17 +368,20 @@ struct stm32_gate_cfg {
|
||||
struct gate_cfg *gate;
|
||||
struct stm32_mgate *mgate;
|
||||
const struct clk_ops *ops;
|
||||
|
|
@ -111,7 +119,7 @@ index a907555..50d739a 100644
|
|||
};
|
||||
|
||||
/* STM32 Composite clock */
|
||||
@@ -376,6 +390,11 @@ struct stm32_composite_cfg {
|
||||
@@ -376,6 +391,11 @@ struct stm32_composite_cfg {
|
||||
const struct stm32_mux_cfg *mux;
|
||||
};
|
||||
|
||||
|
|
@ -123,7 +131,7 @@ index a907555..50d739a 100644
|
|||
static struct clk_hw *
|
||||
_clk_hw_register_gate(struct device *dev,
|
||||
struct clk_hw_onecell_data *clk_data,
|
||||
@@ -592,6 +611,9 @@ clk_stm32_register_gate_ops(struct device *dev,
|
||||
@@ -592,6 +612,9 @@ clk_stm32_register_gate_ops(struct device *dev,
|
||||
if (cfg->ops)
|
||||
init.ops = cfg->ops;
|
||||
|
||||
|
|
@ -133,7 +141,7 @@ index a907555..50d739a 100644
|
|||
hw = _get_stm32_gate(base, cfg, lock);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@@ -630,6 +652,9 @@ clk_stm32_register_composite(struct device *dev,
|
||||
@@ -630,6 +653,9 @@ clk_stm32_register_composite(struct device *dev,
|
||||
|
||||
if (cfg->mux->ops)
|
||||
mux_ops = cfg->mux->ops;
|
||||
|
|
@ -143,7 +151,7 @@ index a907555..50d739a 100644
|
|||
}
|
||||
}
|
||||
|
||||
@@ -641,6 +666,9 @@ clk_stm32_register_composite(struct device *dev,
|
||||
@@ -641,6 +667,9 @@ clk_stm32_register_composite(struct device *dev,
|
||||
|
||||
if (cfg->div->ops)
|
||||
div_ops = cfg->div->ops;
|
||||
|
|
@ -153,7 +161,7 @@ index a907555..50d739a 100644
|
|||
}
|
||||
}
|
||||
|
||||
@@ -652,6 +680,9 @@ clk_stm32_register_composite(struct device *dev,
|
||||
@@ -652,6 +681,9 @@ clk_stm32_register_composite(struct device *dev,
|
||||
|
||||
if (cfg->gate->ops)
|
||||
gate_ops = cfg->gate->ops;
|
||||
|
|
@ -163,7 +171,7 @@ index a907555..50d739a 100644
|
|||
}
|
||||
}
|
||||
|
||||
@@ -1193,7 +1224,8 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
@@ -1193,7 +1225,8 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
.func = _clk_stm32_register_gate,\
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +181,7 @@ index a907555..50d739a 100644
|
|||
(&(struct stm32_gate_cfg) {\
|
||||
&(struct gate_cfg) {\
|
||||
.reg_off = _gate_offset,\
|
||||
@@ -1202,6 +1234,7 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
@@ -1202,6 +1235,7 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
},\
|
||||
.mgate = _mgate,\
|
||||
.ops = _ops,\
|
||||
|
|
@ -181,7 +189,7 @@ index a907555..50d739a 100644
|
|||
})
|
||||
|
||||
#define _STM32_MGATE(_mgate)\
|
||||
@@ -1209,11 +1242,11 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
@@ -1209,11 +1243,11 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
|
||||
#define _GATE(_gate_offset, _gate_bit_idx, _gate_flags)\
|
||||
_STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags,\
|
||||
|
|
@ -195,7 +203,7 @@ index a907555..50d739a 100644
|
|||
|
||||
#define _MGATE_MP1(_mgate)\
|
||||
.gate = &per_gate_cfg[_mgate]
|
||||
@@ -1227,7 +1260,7 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
@@ -1227,7 +1261,7 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
_STM32_MGATE(_mgate))
|
||||
|
||||
#define _STM32_DIV(_div_offset, _div_shift, _div_width,\
|
||||
|
|
@ -204,7 +212,7 @@ index a907555..50d739a 100644
|
|||
.div = &(struct stm32_div_cfg) {\
|
||||
&(struct div_cfg) {\
|
||||
.reg_off = _div_offset,\
|
||||
@@ -1237,13 +1270,14 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
@@ -1237,13 +1271,14 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
.table = _div_table,\
|
||||
},\
|
||||
.ops = _ops,\
|
||||
|
|
@ -221,7 +229,7 @@ index a907555..50d739a 100644
|
|||
.mux = &(struct stm32_mux_cfg) {\
|
||||
&(struct mux_cfg) {\
|
||||
.reg_off = _offset,\
|
||||
@@ -1254,10 +1288,11 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
@@ -1254,10 +1289,11 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
},\
|
||||
.mmux = _mmux,\
|
||||
.ops = _ops,\
|
||||
|
|
@ -234,7 +242,7 @@ index a907555..50d739a 100644
|
|||
|
||||
#define _MMUX(_mmux) .mux = &ker_mux_cfg[_mmux]
|
||||
|
||||
@@ -1286,10 +1321,513 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
@@ -1286,10 +1322,513 @@ _clk_stm32_register_composite(struct device *dev,
|
||||
MGATE_MP1(_id, _name, _parent, _flags, _mgate)
|
||||
|
||||
#define KCLK(_id, _name, _parents, _flags, _mgate, _mmux)\
|
||||
|
|
@ -478,7 +486,7 @@ index a907555..50d739a 100644
|
|||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct clk_divider *divider = to_clk_divider(hw);
|
||||
+ unsigned int value;
|
||||
+ int value;
|
||||
+ unsigned long flags = 0;
|
||||
+ u32 val;
|
||||
+
|
||||
|
|
@ -752,7 +760,15 @@ index a907555..50d739a 100644
|
|||
|
||||
enum {
|
||||
G_SAI1,
|
||||
@@ -1408,7 +1946,7 @@ enum {
|
||||
@@ -1401,6 +1940,7 @@ enum {
|
||||
G_CRYP1,
|
||||
G_HASH1,
|
||||
G_BKPSRAM,
|
||||
+ G_DDRPERFM,
|
||||
|
||||
G_LAST
|
||||
};
|
||||
@@ -1408,7 +1948,7 @@ enum {
|
||||
static struct stm32_mgate mp1_mgate[G_LAST];
|
||||
|
||||
#define _K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags,\
|
||||
|
|
@ -761,7 +777,7 @@ index a907555..50d739a 100644
|
|||
[_id] = {\
|
||||
&(struct gate_cfg) {\
|
||||
.reg_off = _gate_offset,\
|
||||
@@ -1417,15 +1955,24 @@ static struct stm32_mgate mp1_mgate[G_LAST];
|
||||
@@ -1417,15 +1957,24 @@ static struct stm32_mgate mp1_mgate[G_LAST];
|
||||
},\
|
||||
.mgate = _mgate,\
|
||||
.ops = _ops,\
|
||||
|
|
@ -788,7 +804,11 @@ index a907555..50d739a 100644
|
|||
|
||||
/* Peripheral gates */
|
||||
static struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
|
||||
@@ -1490,17 +2037,17 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
|
||||
@@ -1487,20 +2036,21 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
|
||||
K_GATE(G_STGENRO, RCC_APB4ENSETR, 20, 0),
|
||||
K_MGATE(G_USBPHY, RCC_APB4ENSETR, 16, 0),
|
||||
K_GATE(G_IWDG2, RCC_APB4ENSETR, 15, 0),
|
||||
+ K_GATE(G_DDRPERFM, RCC_APB4ENSETR, 8, 0),
|
||||
K_MGATE(G_DSI, RCC_APB4ENSETR, 4, 0),
|
||||
K_MGATE(G_LTDC, RCC_APB4ENSETR, 0, 0),
|
||||
|
||||
|
|
@ -817,7 +837,7 @@ index a907555..50d739a 100644
|
|||
|
||||
K_MGATE(G_SDMMC3, RCC_AHB2ENSETR, 16, 0),
|
||||
K_MGATE(G_USBO, RCC_AHB2ENSETR, 8, 0),
|
||||
@@ -1529,11 +2076,11 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
|
||||
@@ -1529,11 +2079,11 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
|
||||
K_GATE(G_GPIOB, RCC_AHB4ENSETR, 1, 0),
|
||||
K_GATE(G_GPIOA, RCC_AHB4ENSETR, 0, 0),
|
||||
|
||||
|
|
@ -834,7 +854,7 @@ index a907555..50d739a 100644
|
|||
|
||||
K_GATE(G_USBH, RCC_AHB6ENSETR, 24, 0),
|
||||
K_GATE(G_CRC1, RCC_AHB6ENSETR, 20, 0),
|
||||
@@ -1541,12 +2088,15 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
|
||||
@@ -1541,12 +2091,15 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
|
||||
K_MGATE(G_SDMMC1, RCC_AHB6ENSETR, 16, 0),
|
||||
K_MGATE(G_QSPI, RCC_AHB6ENSETR, 14, 0),
|
||||
K_MGATE(G_FMC, RCC_AHB6ENSETR, 12, 0),
|
||||
|
|
@ -850,7 +870,7 @@ index a907555..50d739a 100644
|
|||
K_GATE(G_ETHSTP, RCC_AHB6LPENSETR, 11, 0),
|
||||
};
|
||||
|
||||
@@ -1591,7 +2141,7 @@ enum {
|
||||
@@ -1591,7 +2144,7 @@ enum {
|
||||
|
||||
static struct stm32_mmux ker_mux[M_LAST];
|
||||
|
||||
|
|
@ -859,7 +879,7 @@ index a907555..50d739a 100644
|
|||
[_id] = {\
|
||||
&(struct mux_cfg) {\
|
||||
.reg_off = _offset,\
|
||||
@@ -1602,15 +2152,24 @@ static struct stm32_mmux ker_mux[M_LAST];
|
||||
@@ -1602,15 +2155,24 @@ static struct stm32_mmux ker_mux[M_LAST];
|
||||
},\
|
||||
.mmux = _mmux,\
|
||||
.ops = _ops,\
|
||||
|
|
@ -886,7 +906,7 @@ index a907555..50d739a 100644
|
|||
|
||||
static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
|
||||
/* Kernel multi mux */
|
||||
@@ -1626,7 +2185,7 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
|
||||
@@ -1626,7 +2188,7 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
|
||||
K_MMUX(M_UART78, RCC_UART78CKSELR, 0, 3, 0),
|
||||
K_MMUX(M_SAI1, RCC_SAI1CKSELR, 0, 3, 0),
|
||||
K_MMUX(M_ETHCK, RCC_ETHCKSELR, 0, 2, 0),
|
||||
|
|
@ -895,7 +915,7 @@ index a907555..50d739a 100644
|
|||
|
||||
/* Kernel simple mux */
|
||||
K_MUX(M_RNG2, RCC_RNG2CKSELR, 0, 2, 0),
|
||||
@@ -1647,10 +2206,10 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
|
||||
@@ -1647,23 +2209,24 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
|
||||
K_MUX(M_ADC12, RCC_ADCCKSELR, 0, 2, 0),
|
||||
K_MUX(M_DSI, RCC_DSICKSELR, 0, 1, 0),
|
||||
K_MUX(M_CKPER, RCC_CPERCKSELR, 0, 2, 0),
|
||||
|
|
@ -910,8 +930,11 @@ index a907555..50d739a 100644
|
|||
};
|
||||
|
||||
static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
@@ -1659,11 +2218,12 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
CLK_DIVIDER_READ_ONLY),
|
||||
/* Oscillator divider */
|
||||
- DIV(NO_ID, "clk-hsi-div", "clk-hsi", 0, RCC_HSICFGR, 0, 2,
|
||||
- CLK_DIVIDER_READ_ONLY),
|
||||
+ DIV(NO_ID, "clk-hsi-div", "clk-hsi", CLK_DIVIDER_POWER_OF_TWO,
|
||||
+ RCC_HSICFGR, 0, 2, CLK_DIVIDER_READ_ONLY),
|
||||
|
||||
/* External / Internal Oscillators */
|
||||
- GATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0),
|
||||
|
|
@ -928,7 +951,7 @@ index a907555..50d739a 100644
|
|||
|
||||
FIXED_FACTOR(CK_HSE_DIV2, "clk-hse-div2", "ck_hse", 0, 1, 2),
|
||||
|
||||
@@ -1685,24 +2245,24 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
@@ -1685,24 +2248,24 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
|
||||
/* ODF */
|
||||
COMPOSITE(PLL1_P, "pll1_p", PARENT("pll1"), 0,
|
||||
|
|
@ -961,7 +984,7 @@ index a907555..50d739a 100644
|
|||
|
||||
COMPOSITE(PLL3_P, "pll3_p", PARENT("pll3"), 0,
|
||||
_GATE(RCC_PLL3CR, 4, 0),
|
||||
@@ -1738,20 +2298,20 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
@@ -1738,20 +2301,20 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
MUX(CK_PER, "ck_per", per_src, CLK_OPS_PARENT_ENABLE,
|
||||
RCC_CPERCKSELR, 0, 2, 0),
|
||||
|
||||
|
|
@ -987,7 +1010,15 @@ index a907555..50d739a 100644
|
|||
|
||||
DIV_TABLE(NO_ID, "pclk1", "ck_mcu", CLK_IGNORE_UNUSED, RCC_APB1DIVR, 0,
|
||||
3, CLK_DIVIDER_READ_ONLY, apb_div_table),
|
||||
@@ -1906,7 +2466,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
@@ -1896,6 +2459,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
PCLK(CRC1, "crc1", "ck_axi", 0, G_CRC1),
|
||||
PCLK(USBH, "usbh", "ck_axi", 0, G_USBH),
|
||||
PCLK(ETHSTP, "ethstp", "ck_axi", 0, G_ETHSTP),
|
||||
+ PCLK(DDRPERFM, "ddrperfm", "pclk4", 0, G_DDRPERFM),
|
||||
|
||||
/* Kernel clocks */
|
||||
KCLK(SDMMC1_K, "sdmmc1_k", sdmmc12_src, 0, G_SDMMC1, M_SDMMC12),
|
||||
@@ -1906,7 +2470,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
KCLK(RNG1_K, "rng1_k", rng_src, 0, G_RNG1, M_RNG1),
|
||||
KCLK(RNG2_K, "rng2_k", rng_src, 0, G_RNG2, M_RNG2),
|
||||
KCLK(USBPHY_K, "usbphy_k", usbphy_src, 0, G_USBPHY, M_USBPHY),
|
||||
|
|
@ -996,7 +1027,7 @@ index a907555..50d739a 100644
|
|||
KCLK(SPDIF_K, "spdif_k", spdif_src, 0, G_SPDIF, M_SPDIF),
|
||||
KCLK(SPI1_K, "spi1_k", spi123_src, 0, G_SPI1, M_SPI1),
|
||||
KCLK(SPI2_K, "spi2_k", spi123_src, 0, G_SPI2, M_SPI23),
|
||||
@@ -1952,19 +2512,20 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
@@ -1952,19 +2516,19 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
MGATE_MP1(GPU_K, "gpu_k", "pll2_q", 0, G_GPU),
|
||||
MGATE_MP1(DAC12_K, "dac12_k", "ck_lsi", 0, G_DAC12),
|
||||
|
||||
|
|
@ -1005,13 +1036,13 @@ index a907555..50d739a 100644
|
|||
+ CLK_SET_RATE_NO_REPARENT,
|
||||
_NO_GATE,
|
||||
_MMUX(M_ETHCK),
|
||||
_DIV(RCC_ETHCKSELR, 4, 4, CLK_DIVIDER_ALLOW_ZERO, NULL)),
|
||||
- _DIV(RCC_ETHCKSELR, 4, 4, CLK_DIVIDER_ALLOW_ZERO, NULL)),
|
||||
+ _DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)),
|
||||
|
||||
/* RTC clock */
|
||||
- DIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 7,
|
||||
- CLK_DIVIDER_ALLOW_ZERO),
|
||||
+ SDIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 7,
|
||||
+ CLK_DIVIDER_ALLOW_ZERO),
|
||||
+ SDIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 6, 0),
|
||||
|
||||
COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE |
|
||||
CLK_SET_RATE_PARENT,
|
||||
|
|
@ -1022,7 +1053,7 @@ index a907555..50d739a 100644
|
|||
_NO_DIV),
|
||||
|
||||
/* MCO clocks */
|
||||
@@ -2082,21 +2643,334 @@ static int stm32_rcc_init(struct device_node *np,
|
||||
@@ -2082,21 +2646,364 @@ static int stm32_rcc_init(struct device_node *np,
|
||||
return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
|
||||
}
|
||||
|
||||
|
|
@ -1061,8 +1092,6 @@ index a907555..50d739a 100644
|
|||
+ *
|
||||
+ */
|
||||
+
|
||||
+static struct regmap *pwr_syscon;
|
||||
+
|
||||
+struct reg {
|
||||
+ u32 address;
|
||||
+ u32 val;
|
||||
|
|
@ -1086,82 +1115,91 @@ index a907555..50d739a 100644
|
|||
+ u32 address;
|
||||
+ u32 secured;
|
||||
+ u32 val;
|
||||
+ u8 setclr;
|
||||
+};
|
||||
+
|
||||
+#define SREG(_addr, _setclr, _sec) { \
|
||||
+ .address = _addr,\
|
||||
+ .setclr = _setclr,\
|
||||
+ .secured = _sec,\
|
||||
+ .val = 0,\
|
||||
+}
|
||||
+
|
||||
+static struct sreg clock_gating[] = {
|
||||
+ { 0xA00, 0 }, /* APB1 */
|
||||
+ { 0xA08, 0 }, /* APB2 */
|
||||
+ { 0xA10, 0 }, /* APB3 */
|
||||
+ { 0x200, 0 }, /* APB4 */
|
||||
+ { 0x208, 1 }, /* APB5 */
|
||||
+ { 0x210, 1 }, /* AHB5 */
|
||||
+ { 0x218, 0 }, /* AHB6 */
|
||||
+ { 0xA18, 0 }, /* AHB2 */
|
||||
+ { 0xA20, 0 }, /* AHB3 */
|
||||
+ { 0xA28, 0 }, /* AHB4 */
|
||||
+ { 0xA38, 0 }, /* MLAHB */
|
||||
+ { 0x800, 0 }, /* MCO1 */
|
||||
+ { 0x804, 0 }, /* MCO2 */
|
||||
+ { 0x894, 0 }, /* PLL4 */
|
||||
+ { 0x89C, 0 }, /* PLL4CFGR2 */
|
||||
+ SREG(RCC_APB1ENSETR, 1, 0),
|
||||
+ SREG(RCC_APB2ENSETR, 1, 0),
|
||||
+ SREG(RCC_APB3ENSETR, 1, 0),
|
||||
+ SREG(RCC_APB4ENSETR, 1, 0),
|
||||
+ SREG(RCC_APB5ENSETR, 1, 1),
|
||||
+ SREG(RCC_AHB5ENSETR, 1, 1),
|
||||
+ SREG(RCC_AHB6ENSETR, 1, 0),
|
||||
+ SREG(RCC_AHB2ENSETR, 1, 0),
|
||||
+ SREG(RCC_AHB3ENSETR, 1, 0),
|
||||
+ SREG(RCC_AHB4ENSETR, 1, 0),
|
||||
+ SREG(RCC_MLAHBENSETR, 1, 0),
|
||||
+ SREG(RCC_MCO1CFGR, 0, 0),
|
||||
+ SREG(RCC_MCO2CFGR, 0, 0),
|
||||
+ SREG(RCC_PLL4CFGR2, 0, 0),
|
||||
+};
|
||||
+
|
||||
+struct smux {
|
||||
+ const char *name;
|
||||
+ struct clk *clk;
|
||||
+ struct clk *clkp;
|
||||
+ u32 clk_id;
|
||||
+ u32 mux_id;
|
||||
+ struct clk_hw *hw;
|
||||
+};
|
||||
+
|
||||
+#define KER_SRC(_clk_name)\
|
||||
+#define KER_SRC(_clk_id, _mux_id)\
|
||||
+{\
|
||||
+ .name = _clk_name,\
|
||||
+ .clk_id = _clk_id,\
|
||||
+ .mux_id = _mux_id,\
|
||||
+}
|
||||
+
|
||||
+struct smux _mux_kernel[] = {
|
||||
+ KER_SRC("sdmmc1_k"),
|
||||
+ KER_SRC("spi2_k"),
|
||||
+ KER_SRC("spi4_k"),
|
||||
+ KER_SRC("i2c1_k"),
|
||||
+ KER_SRC("i2c3_k"),
|
||||
+ KER_SRC("lptim2_k"),
|
||||
+ KER_SRC("lptim3_k"),
|
||||
+ KER_SRC("usart2_k"),
|
||||
+ KER_SRC("usart3_k"),
|
||||
+ KER_SRC("uart7_k"),
|
||||
+ KER_SRC("sai1_k"),
|
||||
+ KER_SRC("ethck_k"),
|
||||
+ KER_SRC("i2c4_k"),
|
||||
+ KER_SRC("rng2_k"),
|
||||
+ KER_SRC("sdmmc3_k"),
|
||||
+ KER_SRC("fmc_k"),
|
||||
+ KER_SRC("qspi_k"),
|
||||
+ KER_SRC("usbphy_k"),
|
||||
+ KER_SRC("usbo_k"),
|
||||
+ KER_SRC("spdif_k"),
|
||||
+ KER_SRC("spi1_k"),
|
||||
+ KER_SRC("cec_k"),
|
||||
+ KER_SRC("lptim1_k"),
|
||||
+ KER_SRC("uart6_k"),
|
||||
+ KER_SRC("fdcan_k"),
|
||||
+ KER_SRC("sai2_k"),
|
||||
+ KER_SRC("sai3_k"),
|
||||
+ KER_SRC("sai4_k"),
|
||||
+ KER_SRC("adc12_k"),
|
||||
+ KER_SRC("dsi_k"),
|
||||
+ KER_SRC("ck_per"),
|
||||
+ KER_SRC("rng1_k"),
|
||||
+ KER_SRC("stgen_k"),
|
||||
+ KER_SRC("usart1_k"),
|
||||
+ KER_SRC("spi6_k"),
|
||||
+struct smux _mux_kernel[M_LAST] = {
|
||||
+ KER_SRC(SDMMC1_K, M_SDMMC12),
|
||||
+ KER_SRC(SDMMC3_K, M_SDMMC3),
|
||||
+ KER_SRC(FMC_K, M_FMC),
|
||||
+ KER_SRC(QSPI_K, M_QSPI),
|
||||
+ KER_SRC(RNG1_K, M_RNG1),
|
||||
+ KER_SRC(RNG2_K, M_RNG2),
|
||||
+ KER_SRC(USBPHY_K, M_USBPHY),
|
||||
+ KER_SRC(USBO_K, M_USBO),
|
||||
+ KER_SRC(STGEN_K, M_STGEN),
|
||||
+ KER_SRC(SPDIF_K, M_SPDIF),
|
||||
+ KER_SRC(SPI1_K, M_SPI1),
|
||||
+ KER_SRC(SPI2_K, M_SPI23),
|
||||
+ KER_SRC(SPI4_K, M_SPI45),
|
||||
+ KER_SRC(SPI6_K, M_SPI6),
|
||||
+ KER_SRC(CEC_K, M_CEC),
|
||||
+ KER_SRC(I2C1_K, M_I2C12),
|
||||
+ KER_SRC(I2C3_K, M_I2C35),
|
||||
+ KER_SRC(I2C4_K, M_I2C46),
|
||||
+ KER_SRC(LPTIM1_K, M_LPTIM1),
|
||||
+ KER_SRC(LPTIM2_K, M_LPTIM23),
|
||||
+ KER_SRC(LPTIM4_K, M_LPTIM45),
|
||||
+ KER_SRC(USART1_K, M_USART1),
|
||||
+ KER_SRC(USART2_K, M_UART24),
|
||||
+ KER_SRC(USART3_K, M_UART35),
|
||||
+ KER_SRC(USART6_K, M_USART6),
|
||||
+ KER_SRC(UART7_K, M_UART78),
|
||||
+ KER_SRC(SAI1_K, M_SAI1),
|
||||
+ KER_SRC(SAI2_K, M_SAI2),
|
||||
+ KER_SRC(SAI3_K, M_SAI3),
|
||||
+ KER_SRC(SAI4_K, M_SAI4),
|
||||
+ KER_SRC(DSI_K, M_DSI),
|
||||
+ KER_SRC(FDCAN_K, M_FDCAN),
|
||||
+ KER_SRC(ADC12_K, M_ADC12),
|
||||
+ KER_SRC(ETHCK_K, M_ETHCK),
|
||||
+ KER_SRC(CK_PER, M_CKPER),
|
||||
+};
|
||||
+
|
||||
+static struct sreg pll_clock[] = {
|
||||
+ { 0x880, 0 }, /* PLL3 */
|
||||
+ { 0x894, 0 }, /* PLL4 */
|
||||
+ SREG(RCC_PLL3CR, 0, 0),
|
||||
+ SREG(RCC_PLL4CR, 0, 0),
|
||||
+};
|
||||
+
|
||||
+static struct sreg mcu_source[] = {
|
||||
+ { 0x048, 0 }, /* MSSCKSELR */
|
||||
+ SREG(RCC_MCUDIVR, 0, 0),
|
||||
+ SREG(RCC_MSSCKSELR, 0, 0),
|
||||
+};
|
||||
+
|
||||
+#define RCC_IRQ_FLAGS_MASK 0x110F1F
|
||||
|
|
@ -1173,9 +1211,6 @@ index a907555..50d739a 100644
|
|||
+#define SBF (BIT(11))
|
||||
+#define SBF_MPU (BIT(12))
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+static irqreturn_t stm32mp1_rcc_irq_handler(int irq, void *sdata)
|
||||
+{
|
||||
+ pr_info("RCC generic interrupt received\n");
|
||||
|
|
@ -1197,7 +1232,7 @@ index a907555..50d739a 100644
|
|||
+static void stm32mp1_restore_sreg(struct sreg *sreg, int size)
|
||||
+{
|
||||
+ int i;
|
||||
+ u32 val, address;
|
||||
+ u32 val, address, reg;
|
||||
+ int soc_secured;
|
||||
+
|
||||
+ soc_secured = _is_soc_secured(rcc_base);
|
||||
|
|
@ -1206,11 +1241,21 @@ index a907555..50d739a 100644
|
|||
+ val = sreg[i].val;
|
||||
+ address = sreg[i].address;
|
||||
+
|
||||
+ if (soc_secured && sreg[i].secured)
|
||||
+ SMC(STM32_SVC_RCC, STM32_WRITE,
|
||||
+ address, val);
|
||||
+ else
|
||||
+ reg = readl_relaxed(rcc_base + address);
|
||||
+ if (reg == val)
|
||||
+ continue;
|
||||
+
|
||||
+ if (soc_secured && sreg[i].secured) {
|
||||
+ SMC(STM32_SVC_RCC, STM32_WRITE, address, val);
|
||||
+ if (sreg[i].setclr)
|
||||
+ SMC(STM32_SVC_RCC, STM32_WRITE,
|
||||
+ address + RCC_CLR, ~val);
|
||||
+ } else {
|
||||
+ writel_relaxed(val, rcc_base + address);
|
||||
+ if (sreg[i].setclr)
|
||||
+ writel_relaxed(~val,
|
||||
+ rcc_base + address + RCC_CLR);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
|
|
@ -1236,22 +1281,52 @@ index a907555..50d739a 100644
|
|||
+ }
|
||||
+}
|
||||
+
|
||||
+static void stm32mp1_backup_mux(struct smux *smux, int size)
|
||||
+static void stm32mp1_backup_mux(struct device_node *np,
|
||||
+ struct smux *smux, int size)
|
||||
+{
|
||||
+ int i;
|
||||
+ struct of_phandle_args clkspec;
|
||||
+
|
||||
+ clkspec.np = np;
|
||||
+ clkspec.args_count = 1;
|
||||
+
|
||||
+ for (i = 0; i < size; i++) {
|
||||
+ smux[i].clk = __clk_lookup(smux[i].name);
|
||||
+ smux[i].clkp = clk_get_parent(smux[i].clk);
|
||||
+ clkspec.args[0] = smux[i].clk_id;
|
||||
+ smux[i].hw = __clk_get_hw(of_clk_get_from_provider(&clkspec));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void stm32mp1_restore_mux(struct smux *smux, int size)
|
||||
+{
|
||||
+ int i;
|
||||
+ struct clk_hw *hw, *hwp1, *hwp2;
|
||||
+ struct mux_cfg *mux;
|
||||
+ u8 idx;
|
||||
+
|
||||
+ for (i = 0; i < size; i++)
|
||||
+ clk_set_parent_force(smux[i].clk, smux[i].clkp);
|
||||
+ /* These MUX are glitch free.
|
||||
+ * Then we have to restore mux thru clock framework
|
||||
+ * to be sure that CLK_OPS_PARENT_ENABLE will be exploited
|
||||
+ */
|
||||
+ for (i = 0; i < M_LAST; i++) {
|
||||
+ /* get parent strored in clock framework */
|
||||
+ hw = smux[i].hw;
|
||||
+ hwp1 = clk_hw_get_parent(hw);
|
||||
+
|
||||
+ /* Get parent corresponding to mux register */
|
||||
+ mux = ker_mux_cfg[smux[i].mux_id].mux;
|
||||
+ idx = readl_relaxed(rcc_base + mux->reg_off) >> mux->shift;
|
||||
+ idx &= (BIT(mux->width) - 1);
|
||||
+ hwp2 = clk_hw_get_parent_by_index(hw, idx);
|
||||
+
|
||||
+ /* check if parent from mux & clock framework are differents */
|
||||
+ if (hwp1 != hwp2) {
|
||||
+ /* update first clock framework with the true parent */
|
||||
+ clk_set_parent(hw->clk, hwp2->clk);
|
||||
+
|
||||
+ /* Restore now new parent */
|
||||
+ clk_set_parent(hw->clk, hwp1->clk);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#define RCC_BIT_HSI 0
|
||||
|
|
@ -1275,38 +1350,27 @@ index a907555..50d739a 100644
|
|||
+ /* Save clock gating regs */
|
||||
+ stm32mp1_backup_sreg(clock_gating, ARRAY_SIZE(clock_gating));
|
||||
+
|
||||
+ /* Save kernel clock regs */
|
||||
+ stm32mp1_backup_mux(_mux_kernel, ARRAY_SIZE(_mux_kernel));
|
||||
+
|
||||
+ /* Enable ck_xxx_ker clocks if ck_xxx was on */
|
||||
+ reg = readl_relaxed(rcc_base + RCC_OCENSETR) & RCC_CK_OSC_MASK;
|
||||
+ writel_relaxed(reg << 1, rcc_base + RCC_OCENSETR);
|
||||
+
|
||||
+ SMC(STM32_SVC_RCC, STM32_WRITE, RCC_RSTSR, 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void stm32mp1_clk_resume(void)
|
||||
+{
|
||||
+ u32 power_flags_rcc, power_flags_pwr;
|
||||
+
|
||||
+ /* Read power flags and decide what to resume */
|
||||
+ regmap_read(pwr_syscon, PWR_MPUCR, &power_flags_pwr);
|
||||
+ power_flags_rcc = readl_relaxed(rcc_base + RCC_RSTSR);
|
||||
+ /* Restore pll */
|
||||
+ stm32mp1_restore_pll(pll_clock, ARRAY_SIZE(pll_clock));
|
||||
+
|
||||
+ if ((power_flags_pwr & STOP_FLAG) == STOP_FLAG) {
|
||||
+ /* Restore pll */
|
||||
+ stm32mp1_restore_pll(pll_clock, ARRAY_SIZE(pll_clock));
|
||||
+ /* Restore mcu source */
|
||||
+ stm32mp1_restore_sreg(mcu_source, ARRAY_SIZE(mcu_source));
|
||||
+
|
||||
+ /* Restore mcu source */
|
||||
+ stm32mp1_restore_sreg(mcu_source, ARRAY_SIZE(mcu_source));
|
||||
+ } else if (((power_flags_rcc & SBF) == SBF) ||
|
||||
+ ((power_flags_rcc & SBF_MPU) == SBF_MPU)) {
|
||||
+ stm32mp1_restore_sreg(clock_gating, ARRAY_SIZE(clock_gating));
|
||||
+ stm32mp1_restore_sreg(clock_gating, ARRAY_SIZE(clock_gating));
|
||||
+
|
||||
+ stm32mp1_restore_mux(_mux_kernel, ARRAY_SIZE(_mux_kernel));
|
||||
+ }
|
||||
+
|
||||
+ SMC(STM32_SVC_RCC, STM32_WRITE, RCC_RSTSR, 0);
|
||||
+ stm32mp1_restore_mux(_mux_kernel, ARRAY_SIZE(_mux_kernel));
|
||||
+
|
||||
+ /* Disable ck_xxx_ker clocks */
|
||||
+ stm32_clk_bit_secure(STM32_SET_BITS, RCC_CK_XXX_KER_MASK,
|
||||
|
|
@ -1330,17 +1394,11 @@ index a907555..50d739a 100644
|
|||
+ int ret;
|
||||
+ int i;
|
||||
+
|
||||
+ pwr_syscon = syscon_regmap_lookup_by_phandle(np, "st,pwr");
|
||||
+ if (IS_ERR(pwr_syscon)) {
|
||||
+ pr_err("%s: pwr syscon required !\n", __func__);
|
||||
+ return PTR_ERR(pwr_syscon);
|
||||
+ }
|
||||
+
|
||||
+ /* register generic irq */
|
||||
+ irq = of_irq_get(np, 0);
|
||||
+ if (irq < 0) {
|
||||
+ if (irq <= 0) {
|
||||
+ pr_err("%s: failed to get RCC generic IRQ\n", __func__);
|
||||
+ return irq;
|
||||
+ return irq ? irq : -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ ret = setup_irq(irq, &rcc_irq);
|
||||
|
|
@ -1359,12 +1417,15 @@ index a907555..50d739a 100644
|
|||
+
|
||||
+ SMC(STM32_SVC_RCC, STM32_WRITE, RCC_SREQCLRR, RCC_STOP_MASK);
|
||||
+
|
||||
+ /* Prepare kernel clock source backup */
|
||||
+ stm32mp1_backup_mux(np, _mux_kernel, ARRAY_SIZE(_mux_kernel));
|
||||
+
|
||||
+ register_syscore_ops(&stm32mp1_clk_ops);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
|
||||
index d31055a..6d8326d 100644
|
||||
index 5413ffa..25a4af5 100644
|
||||
--- a/drivers/clk/clk.c
|
||||
+++ b/drivers/clk/clk.c
|
||||
@@ -2204,7 +2204,8 @@ bool clk_has_parent(struct clk *clk, struct clk *parent)
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
From 234beab933e3faccae9ea8ea383ac85fa718a886 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:16:55 +0100
|
||||
Subject: [PATCH 03/52] ARM: stm32mp1-r0-rc1: DMA
|
||||
From d13371d49b7675f62cdd16b4937eac738d862acd Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:00 +0200
|
||||
Subject: [PATCH 05/30] ARM stm32mp1 r2 DMA
|
||||
|
||||
---
|
||||
drivers/dma/stm32-dma.c | 1030 ++++++++++++++++++++++++++++++++++++++------
|
||||
drivers/dma/stm32-dma.c | 1142 +++++++++++++++++++++++++++++++++++++-------
|
||||
drivers/dma/stm32-dmamux.c | 110 ++++-
|
||||
drivers/dma/stm32-mdma.c | 222 +++++++++-
|
||||
3 files changed, 1195 insertions(+), 167 deletions(-)
|
||||
drivers/dma/stm32-mdma.c | 232 ++++++++-
|
||||
3 files changed, 1285 insertions(+), 199 deletions(-)
|
||||
|
||||
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
|
||||
index 379e8d5..4830f8e 100644
|
||||
index 379e8d5..87db5a7 100644
|
||||
--- a/drivers/dma/stm32-dma.c
|
||||
+++ b/drivers/dma/stm32-dma.c
|
||||
@@ -15,14 +15,18 @@
|
||||
|
|
@ -53,7 +53,7 @@ index 379e8d5..4830f8e 100644
|
|||
|
||||
enum stm32_dma_width {
|
||||
STM32_DMA_BYTE,
|
||||
@@ -176,15 +187,31 @@ struct stm32_dma_chan_reg {
|
||||
@@ -176,15 +187,32 @@ struct stm32_dma_chan_reg {
|
||||
u32 dma_sfcr;
|
||||
};
|
||||
|
||||
|
|
@ -83,10 +83,11 @@ index 379e8d5..4830f8e 100644
|
|||
u32 num_sgs;
|
||||
+ dma_addr_t dma_buf;
|
||||
+ void *dma_buf_cpu;
|
||||
+ u32 dma_buf_size;
|
||||
struct stm32_dma_sg_req sg_req[];
|
||||
};
|
||||
|
||||
@@ -201,6 +228,10 @@ struct stm32_dma_chan {
|
||||
@@ -201,6 +229,10 @@ struct stm32_dma_chan {
|
||||
u32 threshold;
|
||||
u32 mem_burst;
|
||||
u32 mem_width;
|
||||
|
|
@ -97,7 +98,7 @@ index 379e8d5..4830f8e 100644
|
|||
};
|
||||
|
||||
struct stm32_dma_device {
|
||||
@@ -210,6 +241,7 @@ struct stm32_dma_device {
|
||||
@@ -210,6 +242,7 @@ struct stm32_dma_device {
|
||||
struct reset_control *rst;
|
||||
bool mem2mem;
|
||||
struct stm32_dma_chan chan[STM32_DMA_MAX_CHANNELS];
|
||||
|
|
@ -105,7 +106,7 @@ index 379e8d5..4830f8e 100644
|
|||
};
|
||||
|
||||
static struct stm32_dma_device *stm32_dma_get_dev(struct stm32_dma_chan *chan)
|
||||
@@ -308,20 +340,12 @@ static bool stm32_dma_fifo_threshold_is_allowed(u32 burst, u32 threshold,
|
||||
@@ -308,20 +341,12 @@ static bool stm32_dma_fifo_threshold_is_allowed(u32 burst, u32 threshold,
|
||||
|
||||
static bool stm32_dma_is_burst_possible(u32 buf_len, u32 threshold)
|
||||
{
|
||||
|
|
@ -132,7 +133,39 @@ index 379e8d5..4830f8e 100644
|
|||
}
|
||||
|
||||
static u32 stm32_dma_get_best_burst(u32 buf_len, u32 max_burst, u32 threshold,
|
||||
@@ -497,11 +521,15 @@ static void stm32_dma_stop(struct stm32_dma_chan *chan)
|
||||
@@ -436,7 +461,6 @@ static void stm32_dma_irq_clear(struct stm32_dma_chan *chan, u32 flags)
|
||||
static int stm32_dma_disable_chan(struct stm32_dma_chan *chan)
|
||||
{
|
||||
struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
|
||||
- unsigned long timeout = jiffies + msecs_to_jiffies(5000);
|
||||
u32 dma_scr, id;
|
||||
|
||||
id = chan->id;
|
||||
@@ -446,19 +470,10 @@ static int stm32_dma_disable_chan(struct stm32_dma_chan *chan)
|
||||
dma_scr &= ~STM32_DMA_SCR_EN;
|
||||
stm32_dma_write(dmadev, STM32_DMA_SCR(id), dma_scr);
|
||||
|
||||
- do {
|
||||
- dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id));
|
||||
- dma_scr &= STM32_DMA_SCR_EN;
|
||||
- if (!dma_scr)
|
||||
- break;
|
||||
-
|
||||
- if (time_after_eq(jiffies, timeout)) {
|
||||
- dev_err(chan2dev(chan), "%s: timeout!\n",
|
||||
- __func__);
|
||||
- return -EBUSY;
|
||||
- }
|
||||
- cond_resched();
|
||||
- } while (1);
|
||||
+ return readl_relaxed_poll_timeout_atomic(
|
||||
+ dmadev->base + STM32_DMA_SCR(id),
|
||||
+ dma_scr, !(dma_scr & STM32_DMA_SCR_EN),
|
||||
+ 10, 1000000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -497,13 +512,23 @@ static void stm32_dma_stop(struct stm32_dma_chan *chan)
|
||||
static int stm32_dma_terminate_all(struct dma_chan *c)
|
||||
{
|
||||
struct stm32_dma_chan *chan = to_stm32_dma_chan(c);
|
||||
|
|
@ -140,15 +173,26 @@ index 379e8d5..4830f8e 100644
|
|||
unsigned long flags;
|
||||
LIST_HEAD(head);
|
||||
|
||||
spin_lock_irqsave(&chan->vchan.lock, flags);
|
||||
- spin_lock_irqsave(&chan->vchan.lock, flags);
|
||||
|
||||
+ if (chan->use_mdma)
|
||||
- if (chan->busy) {
|
||||
- stm32_dma_stop(chan);
|
||||
+ if (chan->use_mdma) {
|
||||
+ spin_lock_irqsave_nested(&chan->vchan.lock, flags,
|
||||
+ SINGLE_DEPTH_NESTING);
|
||||
+ dmaengine_terminate_async(mchan->chan);
|
||||
+ } else {
|
||||
+ spin_lock_irqsave(&chan->vchan.lock, flags);
|
||||
+ }
|
||||
+
|
||||
if (chan->busy) {
|
||||
stm32_dma_stop(chan);
|
||||
+ if (chan->desc) {
|
||||
+ vchan_terminate_vdesc(&chan->desc->vdesc);
|
||||
+ if (chan->busy)
|
||||
+ stm32_dma_stop(chan);
|
||||
chan->desc = NULL;
|
||||
@@ -514,9 +542,96 @@ static int stm32_dma_terminate_all(struct dma_chan *c)
|
||||
}
|
||||
|
||||
@@ -514,9 +539,96 @@ static int stm32_dma_terminate_all(struct dma_chan *c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +289,7 @@ index 379e8d5..4830f8e 100644
|
|||
|
||||
vchan_synchronize(&chan->vchan);
|
||||
}
|
||||
@@ -539,62 +654,206 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan)
|
||||
@@ -539,62 +651,205 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan)
|
||||
dev_dbg(chan2dev(chan), "SFCR: 0x%08x\n", sfcr);
|
||||
}
|
||||
|
||||
|
|
@ -374,7 +418,7 @@ index 379e8d5..4830f8e 100644
|
|||
+ dev_err(chan2dev(chan),
|
||||
+ "%s timeout waiting for last bytes\n",
|
||||
+ __func__);
|
||||
+ break;
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+ cpu_relax();
|
||||
+ residue = stm32_dma_get_remaining_bytes(chan);
|
||||
|
|
@ -438,7 +482,6 @@ index 379e8d5..4830f8e 100644
|
|||
- if (status)
|
||||
- stm32_dma_irq_clear(chan, status);
|
||||
+ if (chan->next_sg == chan->desc->num_sgs) {
|
||||
+ list_del(&chan->desc->vdesc.node);
|
||||
+ vchan_cookie_complete(&chan->desc->vdesc);
|
||||
+ chan->desc = NULL;
|
||||
+ }
|
||||
|
|
@ -490,7 +533,7 @@ index 379e8d5..4830f8e 100644
|
|||
}
|
||||
|
||||
static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan)
|
||||
@@ -626,35 +885,146 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan)
|
||||
@@ -626,35 +881,147 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -518,6 +561,8 @@ index 379e8d5..4830f8e 100644
|
|||
+ if (!vdesc)
|
||||
+ return;
|
||||
+
|
||||
+ list_del(&vdesc->node);
|
||||
+
|
||||
+ chan->desc = to_stm32_dma_desc(vdesc);
|
||||
+ chan->next_sg = 0;
|
||||
+ } else {
|
||||
|
|
@ -625,7 +670,6 @@ index 379e8d5..4830f8e 100644
|
|||
+ if (chan->use_mdma && chan->mchan.dir != DMA_MEM_TO_DEV)
|
||||
+ return;
|
||||
+ if (chan->next_sg == chan->desc->num_sgs) {
|
||||
+ list_del(&chan->desc->vdesc.node);
|
||||
+ vchan_cookie_complete(&chan->desc->vdesc);
|
||||
+ chan->desc = NULL;
|
||||
+ }
|
||||
|
|
@ -649,7 +693,7 @@ index 379e8d5..4830f8e 100644
|
|||
|
||||
if (status & STM32_DMA_TCI) {
|
||||
stm32_dma_irq_clear(chan, STM32_DMA_TCI);
|
||||
@@ -669,10 +1039,12 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid)
|
||||
@@ -669,10 +1036,12 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid)
|
||||
if (status & STM32_DMA_FEI) {
|
||||
stm32_dma_irq_clear(chan, STM32_DMA_FEI);
|
||||
status &= ~STM32_DMA_FEI;
|
||||
|
|
@ -666,15 +710,27 @@ index 379e8d5..4830f8e 100644
|
|||
}
|
||||
if (status) {
|
||||
stm32_dma_irq_clear(chan, status);
|
||||
@@ -695,7 +1067,6 @@ static void stm32_dma_issue_pending(struct dma_chan *c)
|
||||
@@ -691,12 +1060,17 @@ static void stm32_dma_issue_pending(struct dma_chan *c)
|
||||
struct stm32_dma_chan *chan = to_stm32_dma_chan(c);
|
||||
unsigned long flags;
|
||||
|
||||
- spin_lock_irqsave(&chan->vchan.lock, flags);
|
||||
+ if (chan->use_mdma)
|
||||
+ spin_lock_irqsave_nested(&chan->vchan.lock, flags,
|
||||
+ SINGLE_DEPTH_NESTING);
|
||||
+ else
|
||||
+ spin_lock_irqsave(&chan->vchan.lock, flags);
|
||||
+
|
||||
if (vchan_issue_pending(&chan->vchan) && !chan->desc && !chan->busy) {
|
||||
dev_dbg(chan2dev(chan), "vchan %pK: issued\n", &chan->vchan);
|
||||
stm32_dma_start_transfer(chan);
|
||||
-
|
||||
}
|
||||
+
|
||||
spin_unlock_irqrestore(&chan->vchan.lock, flags);
|
||||
}
|
||||
@@ -836,16 +1207,167 @@ static void stm32_dma_clear_reg(struct stm32_dma_chan_reg *regs)
|
||||
|
||||
@@ -836,16 +1210,169 @@ static void stm32_dma_clear_reg(struct stm32_dma_chan_reg *regs)
|
||||
memset(regs, 0, sizeof(struct stm32_dma_chan_reg));
|
||||
}
|
||||
|
||||
|
|
@ -695,6 +751,7 @@ index 379e8d5..4830f8e 100644
|
|||
+ &desc->dma_buf);
|
||||
+ if (!desc->dma_buf_cpu)
|
||||
+ return -ENOMEM;
|
||||
+ desc->dma_buf_size = chan->sram_size;
|
||||
+
|
||||
+ sram_period = chan->sram_size / 2;
|
||||
+
|
||||
|
|
@ -711,6 +768,7 @@ index 379e8d5..4830f8e 100644
|
|||
+ dev_err(chan2dev(chan),
|
||||
+ "max buf size = %d bytes\n",
|
||||
+ chan->sram_size);
|
||||
+ ret = -EINVAL;
|
||||
+ goto free_alloc;
|
||||
+ }
|
||||
+ } else {
|
||||
|
|
@ -787,7 +845,7 @@ index 379e8d5..4830f8e 100644
|
|||
+ }
|
||||
+free_alloc:
|
||||
+ gen_pool_free(dmadev->sram_pool, (unsigned long)desc->dma_buf_cpu,
|
||||
+ chan->sram_size);
|
||||
+ desc->dma_buf_size);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
|
|
@ -845,7 +903,7 @@ index 379e8d5..4830f8e 100644
|
|||
int i, ret;
|
||||
|
||||
if (!chan->config_init) {
|
||||
@@ -868,48 +1390,142 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
|
||||
@@ -868,48 +1395,141 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
|
||||
else
|
||||
chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL;
|
||||
|
||||
|
|
@ -916,7 +974,7 @@ index 379e8d5..4830f8e 100644
|
|||
+
|
||||
+ gen_pool_free(dmadev->sram_pool,
|
||||
+ (unsigned long)desc->dma_buf_cpu,
|
||||
+ chan->sram_size);
|
||||
+ desc->dma_buf_size);
|
||||
+ }
|
||||
kfree(desc);
|
||||
+
|
||||
|
|
@ -932,7 +990,6 @@ index 379e8d5..4830f8e 100644
|
|||
+ struct stm32_dma_mdma *mchan = &chan->mchan;
|
||||
+ struct stm32_dma_mdma_desc *m_desc = &desc->sg_req[0].m_desc;
|
||||
+ struct dma_slave_config config;
|
||||
+ dma_addr_t mem;
|
||||
+ int ret;
|
||||
+
|
||||
+ chan->sram_size = ALIGN(period_len, STM32_DMA_SRAM_GRANULARITY);
|
||||
|
|
@ -941,9 +998,9 @@ index 379e8d5..4830f8e 100644
|
|||
+ &desc->dma_buf);
|
||||
+ if (!desc->dma_buf_cpu)
|
||||
+ return -ENOMEM;
|
||||
+ desc->dma_buf_size = 2 * chan->sram_size;
|
||||
+
|
||||
+ memset(&config, 0, sizeof(config));
|
||||
+ mem = buf_addr;
|
||||
+
|
||||
+ /* Configure MDMA channel */
|
||||
+ if (chan->mchan.dir == DMA_MEM_TO_DEV)
|
||||
|
|
@ -990,7 +1047,7 @@ index 379e8d5..4830f8e 100644
|
|||
+err:
|
||||
+ gen_pool_free(dmadev->sram_pool,
|
||||
+ (unsigned long)desc->dma_buf_cpu,
|
||||
+ chan->sram_size);
|
||||
+ desc->dma_buf_size);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
|
|
@ -1008,7 +1065,7 @@ index 379e8d5..4830f8e 100644
|
|||
int i, ret;
|
||||
|
||||
if (!buf_len || !period_len) {
|
||||
@@ -957,28 +1573,49 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic(
|
||||
@@ -957,28 +1577,49 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic(
|
||||
/* Clear periph ctrl if client set it */
|
||||
chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL;
|
||||
|
||||
|
|
@ -1029,7 +1086,7 @@ index 379e8d5..4830f8e 100644
|
|||
+
|
||||
+ if (chan->use_mdma) {
|
||||
+ chan->mchan.dir = direction;
|
||||
+
|
||||
|
||||
+ ret = stm32_dma_mdma_prep_dma_cyclic(chan, buf_addr, buf_len,
|
||||
+ period_len, desc);
|
||||
+ if (ret < 0)
|
||||
|
|
@ -1038,7 +1095,7 @@ index 379e8d5..4830f8e 100644
|
|||
+ } else {
|
||||
+ dma_buf = buf_addr;
|
||||
+ }
|
||||
|
||||
+
|
||||
+ for (i = 0; i < num_periods; i++) {
|
||||
+ sg_dma_len(&desc->sg_req[i].stm32_sgl_req) = period_len;
|
||||
+ sg_dma_address(&desc->sg_req[i].stm32_sgl_req) = dma_buf;
|
||||
|
|
@ -1070,7 +1127,7 @@ index 379e8d5..4830f8e 100644
|
|||
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
|
||||
}
|
||||
|
||||
@@ -1019,13 +1656,13 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
|
||||
@@ -1019,13 +1660,13 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
|
||||
STM32_DMA_SCR_PINC |
|
||||
STM32_DMA_SCR_TCIE |
|
||||
STM32_DMA_SCR_TEIE;
|
||||
|
|
@ -1086,46 +1143,108 @@ index 379e8d5..4830f8e 100644
|
|||
}
|
||||
|
||||
desc->num_sgs = num_sgs;
|
||||
@@ -1034,18 +1671,6 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
|
||||
@@ -1034,16 +1675,28 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
|
||||
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
|
||||
}
|
||||
|
||||
-static u32 stm32_dma_get_remaining_bytes(struct stm32_dma_chan *chan)
|
||||
-{
|
||||
+static bool stm32_dma_is_current_sg(struct stm32_dma_chan *chan)
|
||||
{
|
||||
- u32 dma_scr, width, ndtr;
|
||||
- struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
|
||||
-
|
||||
struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
|
||||
+ struct stm32_dma_sg_req *sg_req;
|
||||
+ u32 dma_scr, dma_smar, id;
|
||||
|
||||
- dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id));
|
||||
- width = STM32_DMA_SCR_PSIZE_GET(dma_scr);
|
||||
- ndtr = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id));
|
||||
-
|
||||
+ id = chan->id;
|
||||
+ dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id));
|
||||
|
||||
- return ndtr << width;
|
||||
-}
|
||||
-
|
||||
+ if (!(dma_scr & STM32_DMA_SCR_DBM))
|
||||
+ return true;
|
||||
+
|
||||
+ sg_req = &chan->desc->sg_req[chan->next_sg];
|
||||
+
|
||||
+ if (dma_scr & STM32_DMA_SCR_CT) {
|
||||
+ dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM0AR(id));
|
||||
+ return (dma_smar == sg_req->chan_reg.dma_sm0ar);
|
||||
+ }
|
||||
+
|
||||
+ dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(id));
|
||||
+
|
||||
+ return (dma_smar == sg_req->chan_reg.dma_sm1ar);
|
||||
}
|
||||
|
||||
static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
|
||||
struct stm32_dma_desc *desc,
|
||||
@@ -1051,28 +1704,52 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
|
||||
u32 next_sg)
|
||||
@@ -1054,6 +1679,10 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
|
||||
u32 residue = 0;
|
||||
{
|
||||
u32 modulo, burst_size;
|
||||
- u32 residue = 0;
|
||||
+ u32 residue;
|
||||
+ u32 n_sg = next_sg;
|
||||
+ struct stm32_dma_sg_req *sg_req = &chan->desc->sg_req[chan->next_sg];
|
||||
int i;
|
||||
|
||||
+ /* Drain case */
|
||||
+ if (chan->residue_after_drain)
|
||||
+ return chan->residue_after_drain;
|
||||
+
|
||||
+ residue = stm32_dma_get_remaining_bytes(chan);
|
||||
+
|
||||
/*
|
||||
* In cyclic mode, for the last period, residue = remaining bytes from
|
||||
* NDTR
|
||||
@@ -1069,7 +1698,7 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
|
||||
* transferred
|
||||
- * In cyclic mode, for the last period, residue = remaining bytes from
|
||||
- * NDTR
|
||||
+ * Calculate the residue means compute the descriptors
|
||||
+ * information:
|
||||
+ * - the sg currently transferred
|
||||
+ * - the remaining position in this sg (NDTR).
|
||||
+ *
|
||||
+ * The issue is that a race condition can occur if DMA is
|
||||
+ * running. DMA can have started to transfer the next sg before
|
||||
+ * the position in sg is read. In this case the remaing position
|
||||
+ * can correspond to the new sg position.
|
||||
+ * The strategy implemented in the stm32 driver is to check the
|
||||
+ * sg transition. If detected we can not trust the SxNDTR register value
|
||||
+ * this register can not be up to date during the transition.
|
||||
+ * in this case we can assume that the dma is at the beginning of next
|
||||
+ * sg so we calculate the residue in consequence.
|
||||
*/
|
||||
for (i = next_sg; i < desc->num_sgs; i++)
|
||||
- residue += desc->sg_req[i].len;
|
||||
+ residue += sg_dma_len(&desc->sg_req[i].stm32_sgl_req);
|
||||
residue += stm32_dma_get_remaining_bytes(chan);
|
||||
- if (chan->desc->cyclic && next_sg == 0) {
|
||||
- residue = stm32_dma_get_remaining_bytes(chan);
|
||||
- goto end;
|
||||
+
|
||||
+ if (!stm32_dma_is_current_sg(chan)) {
|
||||
+ n_sg++;
|
||||
+ if (n_sg == chan->desc->num_sgs)
|
||||
+ n_sg = 0;
|
||||
+ residue = sg_dma_len(&sg_req->stm32_sgl_req);
|
||||
}
|
||||
|
||||
end:
|
||||
@@ -1089,11 +1718,23 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c,
|
||||
/*
|
||||
- * For all other periods in cyclic mode, and in sg mode,
|
||||
- * residue = remaining bytes from NDTR + remaining periods/sg to be
|
||||
- * transferred
|
||||
+ * In cyclic mode, for the last period, residue = remaining bytes
|
||||
+ * from NDTR
|
||||
+ * else for all other periods in cyclic mode, and in sg mode,
|
||||
+ * residue = remaining bytes from NDTR + remaining
|
||||
+ * periods/sg to be transferred
|
||||
*/
|
||||
- for (i = next_sg; i < desc->num_sgs; i++)
|
||||
- residue += desc->sg_req[i].len;
|
||||
- residue += stm32_dma_get_remaining_bytes(chan);
|
||||
+ if (!chan->desc->cyclic || n_sg != 0)
|
||||
+ for (i = n_sg; i < desc->num_sgs; i++)
|
||||
+ residue += sg_dma_len(&desc->sg_req[i].stm32_sgl_req);
|
||||
|
||||
-end:
|
||||
if (!chan->mem_burst)
|
||||
return residue;
|
||||
|
||||
@@ -1089,11 +1766,23 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c,
|
||||
struct dma_tx_state *state)
|
||||
{
|
||||
struct stm32_dma_chan *chan = to_stm32_dma_chan(c);
|
||||
|
|
@ -1149,7 +1268,7 @@ index 379e8d5..4830f8e 100644
|
|||
status = dma_cookie_status(c, cookie, state);
|
||||
if (status == DMA_COMPLETE || !state)
|
||||
return status;
|
||||
@@ -1120,15 +1761,14 @@ static int stm32_dma_alloc_chan_resources(struct dma_chan *c)
|
||||
@@ -1120,15 +1809,14 @@ static int stm32_dma_alloc_chan_resources(struct dma_chan *c)
|
||||
int ret;
|
||||
|
||||
chan->config_init = false;
|
||||
|
|
@ -1169,7 +1288,7 @@ index 379e8d5..4830f8e 100644
|
|||
|
||||
return ret;
|
||||
}
|
||||
@@ -1148,28 +1788,48 @@ static void stm32_dma_free_chan_resources(struct dma_chan *c)
|
||||
@@ -1148,28 +1836,48 @@ static void stm32_dma_free_chan_resources(struct dma_chan *c)
|
||||
spin_unlock_irqrestore(&chan->vchan.lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -1200,7 +1319,7 @@ index 379e8d5..4830f8e 100644
|
|||
+
|
||||
+ gen_pool_free(dmadev->sram_pool,
|
||||
+ (unsigned long)desc->dma_buf_cpu,
|
||||
+ chan->sram_size);
|
||||
+ desc->dma_buf_size);
|
||||
+ }
|
||||
+
|
||||
+ kfree(desc);
|
||||
|
|
@ -1224,7 +1343,7 @@ index 379e8d5..4830f8e 100644
|
|||
}
|
||||
|
||||
static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
@@ -1207,6 +1867,9 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
@@ -1207,6 +1915,9 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
|
||||
stm32_dma_set_config(chan, &cfg);
|
||||
|
||||
|
|
@ -1234,7 +1353,7 @@ index 379e8d5..4830f8e 100644
|
|||
return c;
|
||||
}
|
||||
|
||||
@@ -1219,10 +1882,12 @@ MODULE_DEVICE_TABLE(of, stm32_dma_of_match);
|
||||
@@ -1219,10 +1930,12 @@ MODULE_DEVICE_TABLE(of, stm32_dma_of_match);
|
||||
static int stm32_dma_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct stm32_dma_chan *chan;
|
||||
|
|
@ -1247,7 +1366,7 @@ index 379e8d5..4830f8e 100644
|
|||
int i, ret;
|
||||
|
||||
match = of_match_device(stm32_dma_of_match, &pdev->dev);
|
||||
@@ -1248,6 +1913,12 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
@@ -1248,6 +1961,12 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(dmadev->clk);
|
||||
}
|
||||
|
||||
|
|
@ -1260,7 +1379,7 @@ index 379e8d5..4830f8e 100644
|
|||
dmadev->mem2mem = of_property_read_bool(pdev->dev.of_node,
|
||||
"st,mem2mem");
|
||||
|
||||
@@ -1258,6 +1929,13 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
@@ -1258,6 +1977,15 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
reset_control_deassert(dmadev->rst);
|
||||
}
|
||||
|
||||
|
|
@ -1270,19 +1389,23 @@ index 379e8d5..4830f8e 100644
|
|||
+ else
|
||||
+ dev_dbg(&pdev->dev, "SRAM pool: %zu KiB\n",
|
||||
+ gen_pool_size(dmadev->sram_pool) / 1024);
|
||||
+
|
||||
+ dma_set_max_seg_size(&pdev->dev, STM32_DMA_ALIGNED_MAX_DATA_ITEMS);
|
||||
+
|
||||
dma_cap_set(DMA_SLAVE, dd->cap_mask);
|
||||
dma_cap_set(DMA_PRIVATE, dd->cap_mask);
|
||||
dma_cap_set(DMA_CYCLIC, dd->cap_mask);
|
||||
@@ -1279,6 +1957,7 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
@@ -1278,7 +2006,9 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
||||
dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
|
||||
dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
|
||||
+ dd->copy_align = DMAENGINE_ALIGN_32_BYTES;
|
||||
dd->max_burst = STM32_DMA_MAX_BURST;
|
||||
+ dd->descriptor_reuse = true;
|
||||
dd->dev = &pdev->dev;
|
||||
INIT_LIST_HEAD(&dd->channels);
|
||||
|
||||
@@ -1293,11 +1972,21 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
@@ -1293,21 +2023,34 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
chan->id = i;
|
||||
chan->vchan.desc_free = stm32_dma_desc_free;
|
||||
vchan_init(&chan->vchan, dd);
|
||||
|
|
@ -1305,7 +1428,25 @@ index 379e8d5..4830f8e 100644
|
|||
|
||||
for (i = 0; i < STM32_DMA_MAX_CHANNELS; i++) {
|
||||
chan = &dmadev->chan[i];
|
||||
@@ -1329,20 +2018,95 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
- res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
|
||||
- if (!res) {
|
||||
- ret = -EINVAL;
|
||||
- dev_err(&pdev->dev, "No irq resource for chan %d\n", i);
|
||||
+ chan->irq = platform_get_irq(pdev, i);
|
||||
+ ret = platform_get_irq(pdev, i);
|
||||
+ if (ret < 0) {
|
||||
+ if (ret != -EPROBE_DEFER)
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "No irq resource for chan %d\n", i);
|
||||
goto err_unregister;
|
||||
}
|
||||
- chan->irq = res->start;
|
||||
+ chan->irq = ret;
|
||||
+
|
||||
ret = devm_request_irq(&pdev->dev, chan->irq,
|
||||
stm32_dma_chan_irq, 0,
|
||||
dev_name(chan2dev(chan)), chan);
|
||||
@@ -1329,20 +2072,95 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, dmadev);
|
||||
|
||||
|
|
@ -1401,7 +1542,7 @@ index 379e8d5..4830f8e 100644
|
|||
},
|
||||
};
|
||||
|
||||
@@ -1350,4 +2114,4 @@ static int __init stm32_dma_init(void)
|
||||
@@ -1350,4 +2168,4 @@ static int __init stm32_dma_init(void)
|
||||
{
|
||||
return platform_driver_probe(&stm32_dma_driver, stm32_dma_probe);
|
||||
}
|
||||
|
|
@ -1587,7 +1728,7 @@ index b922db9..a878b7c 100644
|
|||
};
|
||||
|
||||
diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c
|
||||
index 06dd172..077ef5c 100644
|
||||
index 06dd172..fb4a7e3 100644
|
||||
--- a/drivers/dma/stm32-mdma.c
|
||||
+++ b/drivers/dma/stm32-mdma.c
|
||||
@@ -37,6 +37,7 @@
|
||||
|
|
@ -1784,7 +1925,29 @@ index 06dd172..077ef5c 100644
|
|||
|
||||
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
|
||||
|
||||
@@ -1287,14 +1352,28 @@ static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan,
|
||||
@@ -1137,6 +1202,8 @@ static void stm32_mdma_start_transfer(struct stm32_mdma_chan *chan)
|
||||
return;
|
||||
}
|
||||
|
||||
+ list_del(&vdesc->node);
|
||||
+
|
||||
chan->desc = to_stm32_mdma_desc(vdesc);
|
||||
hwdesc = chan->desc->node[0].hwdesc;
|
||||
chan->curr_hwdesc = 0;
|
||||
@@ -1252,8 +1319,10 @@ static int stm32_mdma_terminate_all(struct dma_chan *c)
|
||||
LIST_HEAD(head);
|
||||
|
||||
spin_lock_irqsave(&chan->vchan.lock, flags);
|
||||
- if (chan->busy) {
|
||||
- stm32_mdma_stop(chan);
|
||||
+ if (chan->desc) {
|
||||
+ vchan_terminate_vdesc(&chan->desc->vdesc);
|
||||
+ if (chan->busy)
|
||||
+ stm32_mdma_stop(chan);
|
||||
chan->desc = NULL;
|
||||
}
|
||||
vchan_get_all_descriptors(&chan->vchan, &head);
|
||||
@@ -1287,14 +1356,28 @@ static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan,
|
||||
{
|
||||
struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
|
||||
struct stm32_mdma_hwdesc *hwdesc = desc->node[0].hwdesc;
|
||||
|
|
@ -1816,7 +1979,7 @@ index 06dd172..077ef5c 100644
|
|||
cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id));
|
||||
residue += cbndtr & STM32_MDMA_CBNDTR_BNDT_MASK;
|
||||
|
||||
@@ -1314,24 +1393,39 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c,
|
||||
@@ -1314,24 +1397,39 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c,
|
||||
struct dma_tx_state *state)
|
||||
{
|
||||
struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
|
||||
|
|
@ -1861,7 +2024,15 @@ index 06dd172..077ef5c 100644
|
|||
dma_set_residue(state, residue);
|
||||
|
||||
spin_unlock_irqrestore(&chan->vchan.lock, flags);
|
||||
@@ -1456,15 +1550,13 @@ static int stm32_mdma_alloc_chan_resources(struct dma_chan *c)
|
||||
@@ -1341,7 +1439,6 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c,
|
||||
|
||||
static void stm32_mdma_xfer_end(struct stm32_mdma_chan *chan)
|
||||
{
|
||||
- list_del(&chan->desc->vdesc.node);
|
||||
vchan_cookie_complete(&chan->desc->vdesc);
|
||||
chan->desc = NULL;
|
||||
chan->busy = false;
|
||||
@@ -1456,15 +1553,13 @@ static int stm32_mdma_alloc_chan_resources(struct dma_chan *c)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
@ -1880,7 +2051,7 @@ index 06dd172..077ef5c 100644
|
|||
|
||||
return ret;
|
||||
}
|
||||
@@ -1484,7 +1576,7 @@ static void stm32_mdma_free_chan_resources(struct dma_chan *c)
|
||||
@@ -1484,7 +1579,7 @@ static void stm32_mdma_free_chan_resources(struct dma_chan *c)
|
||||
spin_unlock_irqrestore(&chan->vchan.lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -1889,7 +2060,7 @@ index 06dd172..077ef5c 100644
|
|||
vchan_free_chan_resources(to_virt_chan(c));
|
||||
dmam_pool_destroy(chan->desc_pool);
|
||||
chan->desc_pool = NULL;
|
||||
@@ -1498,7 +1590,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
@@ -1498,7 +1593,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
struct dma_chan *c;
|
||||
struct stm32_mdma_chan_config config;
|
||||
|
||||
|
|
@ -1898,7 +2069,7 @@ index 06dd172..077ef5c 100644
|
|||
dev_err(mdma2dev(dmadev), "Bad number of args\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1508,6 +1600,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
@@ -1508,6 +1603,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
config.transfer_config = dma_spec->args[2];
|
||||
config.mask_addr = dma_spec->args[3];
|
||||
config.mask_data = dma_spec->args[4];
|
||||
|
|
@ -1906,7 +2077,7 @@ index 06dd172..077ef5c 100644
|
|||
|
||||
if (config.request >= dmadev->nr_requests) {
|
||||
dev_err(mdma2dev(dmadev), "Bad request line\n");
|
||||
@@ -1597,6 +1690,12 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
@@ -1597,6 +1693,12 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1919,7 +2090,7 @@ index 06dd172..077ef5c 100644
|
|||
dmadev->rst = devm_reset_control_get(&pdev->dev, NULL);
|
||||
if (!IS_ERR(dmadev->rst)) {
|
||||
reset_control_assert(dmadev->rst);
|
||||
@@ -1621,6 +1720,8 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
@@ -1621,6 +1723,8 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
dd->device_resume = stm32_mdma_resume;
|
||||
dd->device_terminate_all = stm32_mdma_terminate_all;
|
||||
dd->device_synchronize = stm32_mdma_synchronize;
|
||||
|
|
@ -1928,7 +2099,7 @@ index 06dd172..077ef5c 100644
|
|||
dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
|
||||
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
|
||||
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
|
||||
@@ -1646,19 +1747,20 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
@@ -1646,19 +1750,20 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
dmadev->irq = platform_get_irq(pdev, 0);
|
||||
if (dmadev->irq < 0) {
|
||||
dev_err(&pdev->dev, "failed to get IRQ\n");
|
||||
|
|
@ -1952,7 +2123,7 @@ index 06dd172..077ef5c 100644
|
|||
|
||||
ret = of_dma_controller_register(of_node, stm32_mdma_of_xlate, dmadev);
|
||||
if (ret < 0) {
|
||||
@@ -1668,6 +1770,10 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
@@ -1668,6 +1773,10 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dmadev);
|
||||
|
|
@ -1963,7 +2134,7 @@ index 06dd172..077ef5c 100644
|
|||
|
||||
dev_info(&pdev->dev, "STM32 MDMA driver registered\n");
|
||||
|
||||
@@ -1675,15 +1781,85 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
@@ -1675,15 +1784,86 @@ static int stm32_mdma_probe(struct platform_device *pdev)
|
||||
|
||||
err_unregister:
|
||||
dma_async_device_unregister(dd);
|
||||
|
|
@ -2002,7 +2173,8 @@ index 06dd172..077ef5c 100644
|
|||
+static int stm32_mdma_pw_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_mdma_device *dmadev = dev_get_drvdata(dev);
|
||||
+ u32 ccr, id, ret;
|
||||
+ u32 ccr, id;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = pm_runtime_get_sync(dev);
|
||||
+ if (ret < 0)
|
||||
|
|
@ -1,48 +1,24 @@
|
|||
From fd965c7b7da4a0a21bd7750be8c3851be80a576f Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Tue, 27 Nov 2018 09:39:21 +0100
|
||||
Subject: [PATCH 18/52] ARM-stm32mp1-r0-rc2-DRM-KMS
|
||||
From ee6d275b13c56f9d60acd0dc2790262153d92668 Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:00 +0200
|
||||
Subject: [PATCH 06/30] ARM stm32mp1 r2 DRM
|
||||
|
||||
---
|
||||
.../devicetree/bindings/display/bridge/sii902x.txt | 9 +
|
||||
drivers/gpu/drm/bridge/Kconfig | 1 +
|
||||
drivers/gpu/drm/bridge/sii902x.c | 844 +++++++++++++++++++--
|
||||
drivers/gpu/drm/drm_modes.c | 19 +-
|
||||
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c | 12 +-
|
||||
drivers/gpu/drm/panel/panel-raydium-rm68200.c | 12 +-
|
||||
drivers/gpu/drm/stm/drv.c | 46 +-
|
||||
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 53 ++
|
||||
drivers/gpu/drm/stm/ltdc.c | 191 +++--
|
||||
drivers/gpu/drm/stm/ltdc.h | 6 +
|
||||
include/uapi/drm/drm_mode.h | 6 +
|
||||
11 files changed, 1060 insertions(+), 139 deletions(-)
|
||||
drivers/gpu/drm/bridge/Kconfig | 1 +
|
||||
drivers/gpu/drm/bridge/sii902x.c | 867 +++++++++++++++++++++--
|
||||
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 12 +
|
||||
drivers/gpu/drm/drm_gem.c | 6 -
|
||||
drivers/gpu/drm/drm_modes.c | 19 +-
|
||||
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c | 78 +-
|
||||
drivers/gpu/drm/panel/panel-raydium-rm68200.c | 20 +-
|
||||
drivers/gpu/drm/stm/drv.c | 46 +-
|
||||
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 114 ++-
|
||||
drivers/gpu/drm/stm/ltdc.c | 222 ++++--
|
||||
drivers/gpu/drm/stm/ltdc.h | 6 +
|
||||
include/drm/bridge/dw_mipi_dsi.h | 1 +
|
||||
include/uapi/drm/drm_mode.h | 6 +
|
||||
13 files changed, 1210 insertions(+), 188 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/display/bridge/sii902x.txt b/Documentation/devicetree/bindings/display/bridge/sii902x.txt
|
||||
index 72d2dc6..00e9e88 100644
|
||||
--- a/Documentation/devicetree/bindings/display/bridge/sii902x.txt
|
||||
+++ b/Documentation/devicetree/bindings/display/bridge/sii902x.txt
|
||||
@@ -13,6 +13,8 @@ Optional subnodes:
|
||||
- video input: this subnode can contain a video input port node
|
||||
to connect the bridge to a display controller output (See this
|
||||
documentation [1]).
|
||||
+ - audio input: this subnode can contain an audio input port node
|
||||
+ to connect the bridge to an audio controller output.
|
||||
|
||||
[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
@@ -31,5 +33,12 @@ Example:
|
||||
remote-endpoint = <&dc_out>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+ port@1 {
|
||||
+ reg = <1>;
|
||||
+ codec_endpoint: endpoint {
|
||||
+ remote-endpoint = <&i2s0_cpu_endpoint>;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
};
|
||||
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
|
||||
index bf6cad6..fe91c20 100644
|
||||
--- a/drivers/gpu/drm/bridge/Kconfig
|
||||
|
|
@ -56,7 +32,7 @@ index bf6cad6..fe91c20 100644
|
|||
Silicon Image sii902x bridge chip driver.
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
|
||||
index e59a135..512eb03 100644
|
||||
index e59a135..170657a 100644
|
||||
--- a/drivers/gpu/drm/bridge/sii902x.c
|
||||
+++ b/drivers/gpu/drm/bridge/sii902x.c
|
||||
@@ -1,4 +1,6 @@
|
||||
|
|
@ -339,7 +315,9 @@ index e59a135..512eb03 100644
|
|||
- SII902X_SYS_CTRL_DDC_BUS_REQ);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
+ bool hdmi_mode = false;
|
||||
+ int num = 0, ret;
|
||||
|
||||
- timeout = jiffies +
|
||||
- msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
|
||||
- do {
|
||||
|
|
@ -348,9 +326,7 @@ index e59a135..512eb03 100644
|
|||
- return ret;
|
||||
- } while (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
|
||||
- time_before(jiffies, timeout));
|
||||
+ bool hdmi_mode = false;
|
||||
+ int num = 0, ret;
|
||||
|
||||
-
|
||||
- if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
|
||||
- dev_err(dev, "failed to acquire the i2c bus\n");
|
||||
- return -ETIMEDOUT;
|
||||
|
|
@ -418,19 +394,12 @@ index e59a135..512eb03 100644
|
|||
|
||||
return num;
|
||||
}
|
||||
@@ -240,17 +397,29 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge)
|
||||
regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
|
||||
SII902X_SYS_CTRL_PWR_DWN,
|
||||
SII902X_SYS_CTRL_PWR_DWN);
|
||||
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||
}
|
||||
|
||||
@@ -245,12 +402,22 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge)
|
||||
static void sii902x_bridge_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
+ bool hdmi_mode;
|
||||
|
||||
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||
regmap_update_bits(sii902x->regmap, SII902X_PWR_STATE_CTRL,
|
||||
SII902X_AVI_POWER_STATE_MSK,
|
||||
SII902X_AVI_POWER_STATE_D(0));
|
||||
|
|
@ -448,7 +417,25 @@ index e59a135..512eb03 100644
|
|||
}
|
||||
|
||||
static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
||||
@@ -329,6 +498,267 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge)
|
||||
@@ -261,8 +428,17 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
||||
struct regmap *regmap = sii902x->regmap;
|
||||
u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
|
||||
struct hdmi_avi_infoframe frame;
|
||||
+ unsigned int status = 0;
|
||||
int ret;
|
||||
|
||||
+ DRM_DEBUG_DRIVER("\n");
|
||||
+
|
||||
+ regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||
+
|
||||
+ /* due to old tv, need to restore pinctrl as soon as possible */
|
||||
+ if (status & SII902X_PLUGGED_STATUS)
|
||||
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||
+
|
||||
buf[0] = adj->clock;
|
||||
buf[1] = adj->clock >> 8;
|
||||
buf[2] = adj->vrefresh;
|
||||
@@ -329,6 +505,267 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -716,7 +703,7 @@ index e59a135..512eb03 100644
|
|||
static const struct drm_bridge_funcs sii902x_bridge_funcs = {
|
||||
.attach = sii902x_bridge_attach,
|
||||
.mode_set = sii902x_bridge_mode_set,
|
||||
@@ -348,10 +778,39 @@ static const struct regmap_access_table sii902x_volatile_table = {
|
||||
@@ -348,10 +785,39 @@ static const struct regmap_access_table sii902x_volatile_table = {
|
||||
static const struct regmap_config sii902x_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
|
@ -756,7 +743,18 @@ index e59a135..512eb03 100644
|
|||
static irqreturn_t sii902x_interrupt(int irq, void *data)
|
||||
{
|
||||
struct sii902x *sii902x = data;
|
||||
@@ -366,15 +825,134 @@ static irqreturn_t sii902x_interrupt(int irq, void *data)
|
||||
@@ -360,21 +826,145 @@ static irqreturn_t sii902x_interrupt(int irq, void *data)
|
||||
regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||
regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
|
||||
|
||||
+ if (status & SII902X_PLUGGED_STATUS)
|
||||
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||
+ else
|
||||
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||
+
|
||||
if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev)
|
||||
drm_helper_hpd_irq_event(sii902x->bridge.dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -891,7 +889,7 @@ index e59a135..512eb03 100644
|
|||
sii902x = devm_kzalloc(dev, sizeof(*sii902x), GFP_KERNEL);
|
||||
if (!sii902x)
|
||||
return -ENOMEM;
|
||||
@@ -392,39 +970,67 @@ static int sii902x_probe(struct i2c_client *client,
|
||||
@@ -392,39 +982,67 @@ static int sii902x_probe(struct i2c_client *client,
|
||||
return PTR_ERR(sii902x->reset_gpio);
|
||||
}
|
||||
|
||||
|
|
@ -965,7 +963,7 @@ index e59a135..512eb03 100644
|
|||
}
|
||||
|
||||
sii902x->bridge.funcs = &sii902x_bridge_funcs;
|
||||
@@ -433,7 +1039,31 @@ static int sii902x_probe(struct i2c_client *client,
|
||||
@@ -433,7 +1051,33 @@ static int sii902x_probe(struct i2c_client *client,
|
||||
|
||||
i2c_set_clientdata(client, sii902x);
|
||||
|
||||
|
|
@ -975,14 +973,15 @@ index e59a135..512eb03 100644
|
|||
+ sii902x_i2c_bypass_deselect);
|
||||
+ if (!sii902x->i2cmux) {
|
||||
+ dev_err(dev, "failed to allocate I2C mux\n");
|
||||
+ return -ENOMEM;
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_disable_regulator;
|
||||
+ }
|
||||
+
|
||||
+ sii902x->i2cmux->priv = sii902x;
|
||||
+ ret = i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "Couldn't add i2c mux adapter\n");
|
||||
+ return ret;
|
||||
+ goto err_disable_regulator;
|
||||
+ }
|
||||
+
|
||||
+ sii902x_register_audio_driver(dev, sii902x);
|
||||
|
|
@ -990,6 +989,7 @@ index e59a135..512eb03 100644
|
|||
return 0;
|
||||
+
|
||||
+err_disable_regulator:
|
||||
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||
+ regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
|
||||
+ sii902x->supplies);
|
||||
+
|
||||
|
|
@ -997,7 +997,7 @@ index e59a135..512eb03 100644
|
|||
}
|
||||
|
||||
static int sii902x_remove(struct i2c_client *client)
|
||||
@@ -441,11 +1071,76 @@ static int sii902x_remove(struct i2c_client *client)
|
||||
@@ -441,11 +1085,85 @@ static int sii902x_remove(struct i2c_client *client)
|
||||
{
|
||||
struct sii902x *sii902x = i2c_get_clientdata(client);
|
||||
|
||||
|
|
@ -1024,6 +1024,8 @@ index e59a135..512eb03 100644
|
|||
+
|
||||
+ regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
|
||||
+ sii902x->supplies);
|
||||
+
|
||||
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1039,10 +1041,17 @@ index e59a135..512eb03 100644
|
|||
+ .len = 2,
|
||||
+ .buf = data,
|
||||
+ };
|
||||
+ unsigned int status = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ DRM_DEBUG_DRIVER("\n");
|
||||
+
|
||||
+ regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||
+
|
||||
+ /* due to old tv, need to restore pinctrl as soon as possible */
|
||||
+ if (status & SII902X_PLUGGED_STATUS)
|
||||
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||
+
|
||||
+ ret = regulator_bulk_enable(ARRAY_SIZE(sii902x->supplies),
|
||||
+ sii902x->supplies);
|
||||
+ if (ret) {
|
||||
|
|
@ -1074,7 +1083,7 @@ index e59a135..512eb03 100644
|
|||
static const struct of_device_id sii902x_dt_ids[] = {
|
||||
{ .compatible = "sil,sii9022", },
|
||||
{ }
|
||||
@@ -464,6 +1159,7 @@ static struct i2c_driver sii902x_driver = {
|
||||
@@ -464,6 +1182,7 @@ static struct i2c_driver sii902x_driver = {
|
||||
.driver = {
|
||||
.name = "sii902x",
|
||||
.of_match_table = sii902x_dt_ids,
|
||||
|
|
@ -1082,8 +1091,69 @@ index e59a135..512eb03 100644
|
|||
},
|
||||
.id_table = sii902x_i2c_ids,
|
||||
};
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
|
||||
index fd79996..8cd3ee9 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
|
||||
@@ -488,6 +488,9 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
|
||||
static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi,
|
||||
unsigned long mode_flags)
|
||||
{
|
||||
+ const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||||
+ void *priv_data = dsi->plat_data->priv_data;
|
||||
+
|
||||
dsi_write(dsi, DSI_PWR_UP, RESET);
|
||||
|
||||
if (mode_flags & MIPI_DSI_MODE_VIDEO) {
|
||||
@@ -498,6 +501,9 @@ static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi,
|
||||
dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
|
||||
}
|
||||
|
||||
+ if (phy_ops->post_set_mode)
|
||||
+ phy_ops->post_set_mode(priv_data, mode_flags);
|
||||
+
|
||||
dsi_write(dsi, DSI_PWR_UP, POWERUP);
|
||||
}
|
||||
|
||||
@@ -588,6 +594,9 @@ static void dw_mipi_dsi_video_packet_config(struct dw_mipi_dsi *dsi,
|
||||
|
||||
static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi)
|
||||
{
|
||||
+ const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||||
+ void *priv_data = dsi->plat_data->priv_data;
|
||||
+
|
||||
/*
|
||||
* TODO dw drv improvements
|
||||
* compute high speed transmission counter timeout according
|
||||
@@ -601,6 +610,9 @@ static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi)
|
||||
*/
|
||||
dsi_write(dsi, DSI_BTA_TO_CNT, 0xd00);
|
||||
dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
|
||||
+
|
||||
+ if (phy_ops->post_set_mode)
|
||||
+ phy_ops->post_set_mode(priv_data, 0);
|
||||
}
|
||||
|
||||
/* Get lane byte clock cycles. */
|
||||
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
|
||||
index bf90625..c7217b1 100644
|
||||
--- a/drivers/gpu/drm/drm_gem.c
|
||||
+++ b/drivers/gpu/drm/drm_gem.c
|
||||
@@ -326,12 +326,6 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
|
||||
if (!obj)
|
||||
return -ENOENT;
|
||||
|
||||
- /* Don't allow imported objects to be mapped */
|
||||
- if (obj->import_attach) {
|
||||
- ret = -EINVAL;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
ret = drm_gem_create_mmap_offset(obj);
|
||||
if (ret)
|
||||
goto out;
|
||||
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
|
||||
index 02db9ac..d9d9ad9 100644
|
||||
index a3104d7..f1600e4 100644
|
||||
--- a/drivers/gpu/drm/drm_modes.c
|
||||
+++ b/drivers/gpu/drm/drm_modes.c
|
||||
@@ -130,7 +130,7 @@ EXPORT_SYMBOL(drm_mode_probed_add);
|
||||
|
|
@ -1127,7 +1197,7 @@ index 02db9ac..d9d9ad9 100644
|
|||
EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode);
|
||||
|
||||
diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||
index 87fa316..a76d03a 100644
|
||||
index 58ccf64..afcae08 100644
|
||||
--- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||
+++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||
@@ -67,15 +67,15 @@ struct otm8009a {
|
||||
|
|
@ -1135,25 +1205,146 @@ index 87fa316..a76d03a 100644
|
|||
|
||||
static const struct drm_display_mode default_mode = {
|
||||
- .clock = 32729,
|
||||
+ .clock = 33000,
|
||||
+ .clock = 29700,
|
||||
.hdisplay = 480,
|
||||
.hsync_start = 480 + 120,
|
||||
- .hsync_start = 480 + 120,
|
||||
- .hsync_end = 480 + 120 + 63,
|
||||
- .htotal = 480 + 120 + 63 + 120,
|
||||
+ .hsync_end = 480 + 120 + 64,
|
||||
+ .htotal = 480 + 120 + 64 + 120,
|
||||
+ .hsync_start = 480 + 98,
|
||||
+ .hsync_end = 480 + 98 + 32,
|
||||
+ .htotal = 480 + 98 + 32 + 98,
|
||||
.vdisplay = 800,
|
||||
- .vsync_start = 800 + 12,
|
||||
- .vsync_end = 800 + 12 + 12,
|
||||
- .vtotal = 800 + 12 + 12 + 12,
|
||||
+ .vsync_start = 800 + 14,
|
||||
+ .vsync_end = 800 + 14 + 14,
|
||||
+ .vtotal = 800 + 14 + 14 + 14,
|
||||
+ .vsync_start = 800 + 15,
|
||||
+ .vsync_end = 800 + 15 + 10,
|
||||
+ .vtotal = 800 + 15 + 10 + 14,
|
||||
.vrefresh = 50,
|
||||
.flags = 0,
|
||||
.width_mm = 52,
|
||||
@@ -257,24 +257,12 @@ static int otm8009a_init_sequence(struct otm8009a *ctx)
|
||||
static int otm8009a_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct otm8009a *ctx = panel_to_otm8009a(panel);
|
||||
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
- int ret;
|
||||
|
||||
if (!ctx->enabled)
|
||||
return 0; /* This is not an issue so we return 0 here */
|
||||
|
||||
backlight_disable(ctx->bl_dev);
|
||||
|
||||
- ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- msleep(120);
|
||||
-
|
||||
ctx->enabled = false;
|
||||
|
||||
return 0;
|
||||
@@ -283,14 +271,23 @@ static int otm8009a_disable(struct drm_panel *panel)
|
||||
static int otm8009a_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct otm8009a *ctx = panel_to_otm8009a(panel);
|
||||
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
+ int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
- if (ctx->reset_gpio) {
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
- msleep(20);
|
||||
- }
|
||||
+ ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ mdelay(10);
|
||||
+
|
||||
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ mdelay(10);
|
||||
|
||||
regulator_disable(ctx->supply);
|
||||
|
||||
@@ -307,18 +304,24 @@ static int otm8009a_prepare(struct drm_panel *panel)
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
+ if (ctx->reset_gpio) {
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
+ }
|
||||
+
|
||||
+ mdelay(20);
|
||||
+
|
||||
ret = regulator_enable(ctx->supply);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to enable supply: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ mdelay(120);
|
||||
+
|
||||
if (ctx->reset_gpio) {
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
- msleep(20);
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
- msleep(100);
|
||||
+ mdelay(20);
|
||||
}
|
||||
|
||||
ret = otm8009a_init_sequence(ctx);
|
||||
@@ -433,10 +436,22 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
|
||||
return PTR_ERR(ctx->reset_gpio);
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Due to a common reset between panel & touchscreen, the reset pin
|
||||
+ * must be set to low level first and leave at high level at the
|
||||
+ * end of probe
|
||||
+ */
|
||||
+ if (ctx->reset_gpio) {
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
+ mdelay(1);
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
+ }
|
||||
+
|
||||
ctx->supply = devm_regulator_get(dev, "power");
|
||||
if (IS_ERR(ctx->supply)) {
|
||||
ret = PTR_ERR(ctx->supply);
|
||||
- dev_err(dev, "failed to request regulator: %d\n", ret);
|
||||
+ if (ret != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "failed to request regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -488,6 +503,13 @@ static int otm8009a_remove(struct mipi_dsi_device *dsi)
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
+ if (ctx->reset_gpio) {
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
+ mdelay(20);
|
||||
+ }
|
||||
+
|
||||
+ regulator_disable(ctx->supply);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/drivers/gpu/drm/panel/panel-raydium-rm68200.c b/drivers/gpu/drm/panel/panel-raydium-rm68200.c
|
||||
index 7759353..94436ea 100644
|
||||
index 7759353..9fe15a4 100644
|
||||
--- a/drivers/gpu/drm/panel/panel-raydium-rm68200.c
|
||||
+++ b/drivers/gpu/drm/panel/panel-raydium-rm68200.c
|
||||
@@ -81,15 +81,15 @@ struct rm68200 {
|
||||
|
|
@ -1178,6 +1369,28 @@ index 7759353..94436ea 100644
|
|||
.vrefresh = 50,
|
||||
.flags = 0,
|
||||
.width_mm = 68,
|
||||
@@ -265,11 +265,6 @@ static int rm68200_unprepare(struct drm_panel *panel)
|
||||
|
||||
msleep(120);
|
||||
|
||||
- if (ctx->reset_gpio) {
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
- msleep(20);
|
||||
- }
|
||||
-
|
||||
regulator_disable(ctx->supply);
|
||||
|
||||
ctx->prepared = false;
|
||||
@@ -383,7 +378,8 @@ static int rm68200_probe(struct mipi_dsi_device *dsi)
|
||||
ctx->supply = devm_regulator_get(dev, "power");
|
||||
if (IS_ERR(ctx->supply)) {
|
||||
ret = PTR_ERR(ctx->supply);
|
||||
- dev_err(dev, "cannot get regulator: %d\n", ret);
|
||||
+ if (ret != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "cannot get regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
|
||||
index f2021b2..cf61875 100644
|
||||
--- a/drivers/gpu/drm/stm/drv.c
|
||||
|
|
@ -1283,7 +1496,7 @@ index f2021b2..cf61875 100644
|
|||
};
|
||||
|
||||
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
|
||||
index a514b59..a6edd86 100644
|
||||
index a514b59..44e29af 100644
|
||||
--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
|
||||
+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
|
||||
@@ -9,6 +9,7 @@
|
||||
|
|
@ -1302,19 +1515,75 @@ index a514b59..a6edd86 100644
|
|||
};
|
||||
|
||||
static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val)
|
||||
@@ -318,16 +320,30 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||
@@ -208,12 +210,26 @@ static int dw_mipi_dsi_phy_init(void *priv_data)
|
||||
if (ret)
|
||||
DRM_DEBUG_DRIVER("!TIMEOUT! waiting PLL, let's continue\n");
|
||||
|
||||
- /* Enable the DSI wrapper */
|
||||
- dsi_set(dsi, DSI_WCR, WCR_DSIEN);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void dw_mipi_dsi_phy_post_set_mode(void *priv_data, unsigned long mode_flags)
|
||||
+{
|
||||
+ struct dw_mipi_dsi_stm *dsi = priv_data;
|
||||
+
|
||||
+ DRM_DEBUG_DRIVER("\n");
|
||||
+
|
||||
+ /*
|
||||
+ * DSI wrapper must be enabled in video mode & disabled in command mode.
|
||||
+ * If wrapper is enabled in command mode, the display controller
|
||||
+ * register access will hang.
|
||||
+ */
|
||||
+ if (mode_flags & MIPI_DSI_MODE_VIDEO)
|
||||
+ dsi_set(dsi, DSI_WCR, WCR_DSIEN);
|
||||
+ else
|
||||
+ dsi_clear(dsi, DSI_WCR, WCR_DSIEN);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
|
||||
unsigned long mode_flags, u32 lanes, u32 format,
|
||||
@@ -225,7 +241,6 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
|
||||
u32 val;
|
||||
|
||||
/* Update lane capabilities according to hw version */
|
||||
- dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
|
||||
dsi->lane_min_kbps = LANE_MIN_KBPS;
|
||||
dsi->lane_max_kbps = LANE_MAX_KBPS;
|
||||
if (dsi->hw_version == HWVER_131) {
|
||||
@@ -287,6 +302,7 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
|
||||
static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = {
|
||||
.init = dw_mipi_dsi_phy_init,
|
||||
.get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
|
||||
+ .post_set_mode = dw_mipi_dsi_phy_post_set_mode,
|
||||
};
|
||||
|
||||
static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data = {
|
||||
@@ -304,6 +320,7 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dw_mipi_dsi_stm *dsi;
|
||||
+ struct clk *pclk;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
@@ -318,17 +335,53 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(dsi->base);
|
||||
}
|
||||
|
||||
+ dsi->vdd_supply = devm_regulator_get(dev, "phy-dsi");
|
||||
+ dsi->vdd_supply = devm_regulator_get_optional(dev, "phy-dsi");
|
||||
+ if (IS_ERR(dsi->vdd_supply)) {
|
||||
+ DRM_ERROR("can't get power supply\n");
|
||||
+ return PTR_ERR(dsi->vdd_supply);
|
||||
+ ret = PTR_ERR(dsi->vdd_supply);
|
||||
+ if (ret != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "failed to request regulator: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = regulator_enable(dsi->vdd_supply);
|
||||
+ if (ret) {
|
||||
+ DRM_ERROR("can't enable power supply\n");
|
||||
+ dev_err(dev, "failed to enable regulator: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
|
|
@ -1322,26 +1591,65 @@ index a514b59..a6edd86 100644
|
|||
if (IS_ERR(dsi->pllref_clk)) {
|
||||
ret = PTR_ERR(dsi->pllref_clk);
|
||||
dev_err(dev, "Unable to get pll reference clock: %d\n", ret);
|
||||
+ regulator_disable(dsi->vdd_supply);
|
||||
return ret;
|
||||
- return ret;
|
||||
+ goto err_clk_get;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dsi->pllref_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
|
||||
+ regulator_disable(dsi->vdd_supply);
|
||||
return ret;
|
||||
- return ret;
|
||||
+ goto err_clk_get;
|
||||
+ }
|
||||
+
|
||||
+ pclk = devm_clk_get(dev, "pclk");
|
||||
+ if (IS_ERR(pclk)) {
|
||||
+ ret = PTR_ERR(pclk);
|
||||
+ dev_err(dev, "Unable to get peripheral clock: %d\n", ret);
|
||||
+ goto err_pclk_get;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(pclk);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "%s: Failed to enable peripheral clk\n", __func__);
|
||||
+ goto err_pclk_get;
|
||||
+ }
|
||||
+
|
||||
+ dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
|
||||
+ clk_disable_unprepare(pclk);
|
||||
+
|
||||
+ if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {
|
||||
+ ret = -ENODEV;
|
||||
+ dev_err(dev, "bad dsi hardware version\n");
|
||||
+ goto err_pclk_get;
|
||||
}
|
||||
|
||||
@@ -339,6 +355,7 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||
dw_mipi_dsi_stm_plat_data.base = dsi->base;
|
||||
@@ -338,12 +391,21 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||
|
||||
dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data);
|
||||
if (IS_ERR(dsi->dsi)) {
|
||||
+ ret = PTR_ERR(dsi->dsi);
|
||||
DRM_ERROR("Failed to initialize mipi dsi host\n");
|
||||
+ regulator_disable(dsi->vdd_supply);
|
||||
clk_disable_unprepare(dsi->pllref_clk);
|
||||
return PTR_ERR(dsi->dsi);
|
||||
- clk_disable_unprepare(dsi->pllref_clk);
|
||||
- return PTR_ERR(dsi->dsi);
|
||||
+ goto err_pclk_get;
|
||||
}
|
||||
@@ -351,17 +368,53 @@ static int dw_mipi_dsi_stm_remove(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
+
|
||||
+err_pclk_get:
|
||||
+ clk_disable_unprepare(dsi->pllref_clk);
|
||||
+
|
||||
+err_clk_get:
|
||||
+ regulator_disable(dsi->vdd_supply);
|
||||
+
|
||||
+ return ret;
|
||||
+
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi_stm_remove(struct platform_device *pdev)
|
||||
@@ -351,17 +413,53 @@ static int dw_mipi_dsi_stm_remove(struct platform_device *pdev)
|
||||
struct dw_mipi_dsi_stm *dsi = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(dsi->pllref_clk);
|
||||
|
|
@ -1396,7 +1704,7 @@ index a514b59..a6edd86 100644
|
|||
};
|
||||
|
||||
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
|
||||
index 808d9fb..599d2f8 100644
|
||||
index 808d9fb..3527e69 100644
|
||||
--- a/drivers/gpu/drm/stm/ltdc.c
|
||||
+++ b/drivers/gpu/drm/stm/ltdc.c
|
||||
@@ -148,6 +148,8 @@
|
||||
|
|
@ -1466,10 +1774,14 @@ index 808d9fb..599d2f8 100644
|
|||
}
|
||||
|
||||
#define CLK_TOLERANCE_HZ 50
|
||||
@@ -497,13 +533,10 @@ static bool ltdc_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
* TODO clk_round_rate() does not work yet. When ready, it can
|
||||
* be used instead of clk_set_rate() then clk_get_rate().
|
||||
*/
|
||||
@@ -493,20 +529,16 @@ static bool ltdc_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
struct ltdc_device *ldev = crtc_to_ltdc(crtc);
|
||||
int rate = mode->clock * 1000;
|
||||
|
||||
- /*
|
||||
- * TODO clk_round_rate() does not work yet. When ready, it can
|
||||
- * be used instead of clk_set_rate() then clk_get_rate().
|
||||
- */
|
||||
-
|
||||
- clk_disable(ldev->pixel_clk);
|
||||
if (clk_set_rate(ldev->pixel_clk, rate) < 0) {
|
||||
|
|
@ -1480,7 +1792,13 @@ index 808d9fb..599d2f8 100644
|
|||
|
||||
adjusted_mode->clock = clk_get_rate(ldev->pixel_clk) / 1000;
|
||||
|
||||
@@ -518,6 +551,11 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
+ DRM_DEBUG_DRIVER("requested clock %dkHz, adjusted clock %dkHz\n",
|
||||
+ mode->clock, adjusted_mode->clock);
|
||||
+
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -518,6 +550,11 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
u32 hsync, vsync, accum_hbp, accum_vbp, accum_act_w, accum_act_h;
|
||||
u32 total_width, total_height;
|
||||
u32 val;
|
||||
|
|
@ -1492,7 +1810,7 @@ index 808d9fb..599d2f8 100644
|
|||
|
||||
drm_display_mode_to_videomode(mode, &vm);
|
||||
|
||||
@@ -546,10 +584,10 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
@@ -546,10 +583,10 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
if (vm.flags & DISPLAY_FLAGS_VSYNC_HIGH)
|
||||
val |= GCR_VSPOL;
|
||||
|
||||
|
|
@ -1505,7 +1823,7 @@ index 808d9fb..599d2f8 100644
|
|||
val |= GCR_PCPOL;
|
||||
|
||||
reg_update_bits(ldev->regs, LTDC_GCR,
|
||||
@@ -611,8 +649,14 @@ static const struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = {
|
||||
@@ -611,8 +648,14 @@ static const struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = {
|
||||
static int ltdc_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct ltdc_device *ldev = crtc_to_ltdc(crtc);
|
||||
|
|
@ -1520,7 +1838,7 @@ index 808d9fb..599d2f8 100644
|
|||
reg_set(ldev->regs, LTDC_IER, IER_LIE);
|
||||
|
||||
return 0;
|
||||
@@ -623,9 +667,58 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
@@ -623,9 +666,58 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
struct ltdc_device *ldev = crtc_to_ltdc(crtc);
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
|
@ -1579,7 +1897,7 @@ index 808d9fb..599d2f8 100644
|
|||
static const struct drm_crtc_funcs ltdc_crtc_funcs = {
|
||||
.destroy = drm_crtc_cleanup,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
@@ -646,24 +739,44 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane,
|
||||
@@ -646,24 +738,44 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
|
|
@ -1608,10 +1926,7 @@ index 808d9fb..599d2f8 100644
|
|||
+ dst->y1 = state->crtc_y;
|
||||
+ dst->x2 = state->crtc_w + dst->x1 - 1;
|
||||
+ dst->y2 = state->crtc_h + dst->y1 - 1;
|
||||
|
||||
- /* Reject scaling */
|
||||
- if (src_w != state->crtc_w || src_h != state->crtc_h) {
|
||||
- DRM_ERROR("Scaling is not supported");
|
||||
+
|
||||
+ DRM_DEBUG_DRIVER("plane:%d fb:%d (%dx%d)@(%d,%d) -> (%dx%d)@(%d,%d)\n",
|
||||
+ plane->base.id, fb->base.id,
|
||||
+ src->x2 - src->x1 + 1, src->y2 - src->y1 + 1,
|
||||
|
|
@ -1625,7 +1940,10 @@ index 808d9fb..599d2f8 100644
|
|||
+ if (crtc_state && (crtc_state->mode.hdisplay <= dst->x2 ||
|
||||
+ crtc_state->mode.vdisplay <= dst->y2))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
|
||||
- /* Reject scaling */
|
||||
- if (src_w != state->crtc_w || src_h != state->crtc_h) {
|
||||
- DRM_ERROR("Scaling is not supported");
|
||||
+ /* source sizes do not have to exceed destination sizes */
|
||||
+ if (dst->x2 - dst->x1 < src->x2 - src->x1 ||
|
||||
+ dst->y2 - dst->y1 < src->y2 - src->y1)
|
||||
|
|
@ -1634,7 +1952,7 @@ index 808d9fb..599d2f8 100644
|
|||
|
||||
return 0;
|
||||
}
|
||||
@@ -673,44 +786,36 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
@@ -673,44 +785,36 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
{
|
||||
struct ltdc_device *ldev = plane_to_ltdc(plane);
|
||||
struct drm_plane_state *state = plane->state;
|
||||
|
|
@ -1689,7 +2007,7 @@ index 808d9fb..599d2f8 100644
|
|||
reg_update_bits(ldev->regs, LTDC_L1WVPCR + lofs,
|
||||
LXWVPCR_WVSTPOS | LXWVPCR_WVSPPOS, val);
|
||||
|
||||
@@ -730,7 +835,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
@@ -730,7 +834,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
/* Configures the color frame buffer pitch in bytes & line length */
|
||||
pitch_in_bytes = fb->pitches[0];
|
||||
line_length = drm_format_plane_cpp(fb->format->format, 0) *
|
||||
|
|
@ -1698,7 +2016,7 @@ index 808d9fb..599d2f8 100644
|
|||
val = ((pitch_in_bytes << 16) | line_length);
|
||||
reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs,
|
||||
LXCFBLR_CFBLL | LXCFBLR_CFBP, val);
|
||||
@@ -753,7 +858,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
@@ -753,7 +857,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
LXBFCR_BF2 | LXBFCR_BF1, val);
|
||||
|
||||
/* Configures the frame buffer line number */
|
||||
|
|
@ -1707,7 +2025,7 @@ index 808d9fb..599d2f8 100644
|
|||
reg_update_bits(ldev->regs, LTDC_L1CFBLNR + lofs, LXCFBLNR_CFBLN, val);
|
||||
|
||||
/* Sets the FB address */
|
||||
@@ -772,11 +877,11 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
@@ -772,11 +876,11 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
|
||||
mutex_lock(&ldev->err_lock);
|
||||
if (ldev->error_status & ISR_FUIF) {
|
||||
|
|
@ -1721,8 +2039,57 @@ index 808d9fb..599d2f8 100644
|
|||
ldev->error_status &= ~ISR_TERRIF;
|
||||
}
|
||||
mutex_unlock(&ldev->err_lock);
|
||||
@@ -1055,10 +1160,10 @@ int ltdc_load(struct drm_device *ddev)
|
||||
return -ENODEV;
|
||||
@@ -814,6 +918,13 @@ static void ltdc_plane_atomic_print_state(struct drm_printer *p,
|
||||
fpsi->counter = 0;
|
||||
}
|
||||
|
||||
+static bool ltdc_plane_format_mod_supported(struct drm_plane *plane,
|
||||
+ u32 format,
|
||||
+ u64 modifier)
|
||||
+{
|
||||
+ return modifier == DRM_FORMAT_MOD_LINEAR;
|
||||
+}
|
||||
+
|
||||
static const struct drm_plane_funcs ltdc_plane_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
@@ -822,6 +933,7 @@ static const struct drm_plane_funcs ltdc_plane_funcs = {
|
||||
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
|
||||
.atomic_print_state = ltdc_plane_atomic_print_state,
|
||||
+ .format_mod_supported = ltdc_plane_format_mod_supported,
|
||||
};
|
||||
|
||||
static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = {
|
||||
@@ -841,6 +953,10 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
|
||||
u32 formats[NB_PF * 2];
|
||||
u32 drm_fmt, drm_fmt_no_alpha;
|
||||
int ret;
|
||||
+ const u64 modifiers[] = {
|
||||
+ DRM_FORMAT_MOD_LINEAR,
|
||||
+ DRM_FORMAT_MOD_INVALID
|
||||
+ };
|
||||
|
||||
/* Get supported pixel formats */
|
||||
for (i = 0; i < NB_PF; i++) {
|
||||
@@ -868,7 +984,7 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
|
||||
|
||||
ret = drm_universal_plane_init(ddev, plane, possible_crtcs,
|
||||
<dc_plane_funcs, formats, nb_fmt,
|
||||
- NULL, type, NULL);
|
||||
+ modifiers, type, NULL);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
@@ -1051,14 +1167,15 @@ int ltdc_load(struct drm_device *ddev)
|
||||
|
||||
ldev->pixel_clk = devm_clk_get(dev, "lcd");
|
||||
if (IS_ERR(ldev->pixel_clk)) {
|
||||
- DRM_ERROR("Unable to get lcd clock\n");
|
||||
- return -ENODEV;
|
||||
+ if (PTR_ERR(ldev->pixel_clk) != -EPROBE_DEFER)
|
||||
+ DRM_ERROR("Unable to get lcd clock\n");
|
||||
+ return PTR_ERR(ldev->pixel_clk);
|
||||
}
|
||||
|
||||
- if (clk_prepare_enable(ldev->pixel_clk)) {
|
||||
|
|
@ -1736,7 +2103,26 @@ index 808d9fb..599d2f8 100644
|
|||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
ldev->regs = devm_ioremap_resource(dev, res);
|
||||
@@ -1150,7 +1255,7 @@ int ltdc_load(struct drm_device *ddev)
|
||||
@@ -1070,6 +1187,9 @@ int ltdc_load(struct drm_device *ddev)
|
||||
|
||||
for (i = 0; i < MAX_IRQ; i++) {
|
||||
irq = platform_get_irq(pdev, i);
|
||||
+ if (irq == -EPROBE_DEFER)
|
||||
+ goto err;
|
||||
+
|
||||
if (irq < 0)
|
||||
continue;
|
||||
|
||||
@@ -1129,6 +1249,8 @@ int ltdc_load(struct drm_device *ddev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ ddev->mode_config.allow_fb_modifiers = true;
|
||||
+
|
||||
ret = ltdc_crtc_init(ddev, crtc);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to init crtc\n");
|
||||
@@ -1150,7 +1272,7 @@ int ltdc_load(struct drm_device *ddev)
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++)
|
||||
drm_panel_bridge_remove(bridge[i]);
|
||||
|
||||
|
|
@ -1745,7 +2131,7 @@ index 808d9fb..599d2f8 100644
|
|||
|
||||
return ret;
|
||||
}
|
||||
@@ -1165,7 +1270,7 @@ void ltdc_unload(struct drm_device *ddev)
|
||||
@@ -1165,7 +1287,7 @@ void ltdc_unload(struct drm_device *ddev)
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++)
|
||||
drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i);
|
||||
|
||||
|
|
@ -1773,6 +2159,18 @@ index d5afb89..08bd69d 100644
|
|||
int ltdc_load(struct drm_device *ddev);
|
||||
void ltdc_unload(struct drm_device *ddev);
|
||||
|
||||
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
|
||||
index d9c6d54..0fdc550 100644
|
||||
--- a/include/drm/bridge/dw_mipi_dsi.h
|
||||
+++ b/include/drm/bridge/dw_mipi_dsi.h
|
||||
@@ -17,6 +17,7 @@ struct dw_mipi_dsi_phy_ops {
|
||||
int (*get_lane_mbps)(void *priv_data, struct drm_display_mode *mode,
|
||||
unsigned long mode_flags, u32 lanes, u32 format,
|
||||
unsigned int *lane_mbps);
|
||||
+ void (*post_set_mode)(void *priv_data, unsigned long mode_flags);
|
||||
};
|
||||
|
||||
struct dw_mipi_dsi_plat_data {
|
||||
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
|
||||
index 8d67243..c20c4c3 100644
|
||||
--- a/include/uapi/drm/drm_mode.h
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
From fc0e7f3b161868a6ab3e40938cb820ef23d223f6 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 17 Sep 2019 14:27:05 +0200
|
||||
Subject: [PATCH 07/30] ARM stm32mp1 r2 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 fd713326..af5d0e6 100644
|
||||
--- a/drivers/gpio/gpiolib.c
|
||||
+++ b/drivers/gpio/gpiolib.c
|
||||
@@ -2519,6 +2519,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
|
||||
@@ -2547,20 +2555,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;
|
||||
@@ -2634,8 +2641,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 */
|
||||
@@ -2643,16 +2650,16 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
|
||||
return gpiod_direction_input(desc);
|
||||
}
|
||||
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 */
|
||||
if (!value)
|
||||
return gpiod_direction_input(desc);
|
||||
} 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:
|
||||
@@ -2684,7 +2691,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);
|
||||
|
||||
@@ -2721,7 +2728,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);
|
||||
@@ -3858,6 +3865,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
|
||||
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
From 7f9a7065bc23ee2da17c45ff4097cdbc9b70065d Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:00 +0200
|
||||
Subject: [PATCH 08/30] ARM stm32mp1 r2 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
|
||||
|
||||
|
|
@ -1,17 +1,157 @@
|
|||
From 656c7df3520f4422b871a4e69c68e6a9daf7ba61 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:18:06 +0100
|
||||
Subject: [PATCH 04/52] ARM: stm32mp1-r0-rc1: I2C
|
||||
From 7394fe2e090d58063b852b0baeca2fc65f8cd07b Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:00 +0200
|
||||
Subject: [PATCH 09/30] ARM stm32mp1 r2 HWTRACING I2C
|
||||
|
||||
---
|
||||
drivers/i2c/busses/i2c-stm32f7.c | 369 +++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 320 insertions(+), 49 deletions(-)
|
||||
drivers/hwtracing/coresight/coresight-stm.c | 58 +++-
|
||||
drivers/i2c/busses/i2c-stm32f7.c | 470 ++++++++++++++++++++++++----
|
||||
2 files changed, 469 insertions(+), 59 deletions(-)
|
||||
|
||||
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
|
||||
index c46c70a..65687c0 100644
|
||||
--- a/drivers/hwtracing/coresight/coresight-stm.c
|
||||
+++ b/drivers/hwtracing/coresight/coresight-stm.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#define STMHETER 0xd20
|
||||
#define STMHEBSR 0xd60
|
||||
#define STMHEMCR 0xd64
|
||||
+#define STMHEEXTMUXR 0xd68
|
||||
#define STMHEMASTR 0xdf4
|
||||
#define STMHEFEAT1R 0xdf8
|
||||
#define STMHEIDR 0xdfc
|
||||
@@ -125,9 +126,11 @@ struct channel_space {
|
||||
* @stmheer: settings for register STMHEER.
|
||||
* @stmheter: settings for register STMHETER.
|
||||
* @stmhebsr: settings for register STMHEBSR.
|
||||
+ * @stmheextmuxr: settings for register STMHEEXTMUXR.
|
||||
*/
|
||||
struct stm_drvdata {
|
||||
void __iomem *base;
|
||||
+ void __iomem *base_cti;
|
||||
struct device *dev;
|
||||
struct clk *atclk;
|
||||
struct coresight_device *csdev;
|
||||
@@ -143,6 +146,7 @@ struct stm_drvdata {
|
||||
u32 stmheer;
|
||||
u32 stmheter;
|
||||
u32 stmhebsr;
|
||||
+ u32 stmheextmuxr;
|
||||
};
|
||||
|
||||
static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata)
|
||||
@@ -152,6 +156,7 @@ static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata)
|
||||
writel_relaxed(drvdata->stmhebsr, drvdata->base + STMHEBSR);
|
||||
writel_relaxed(drvdata->stmheter, drvdata->base + STMHETER);
|
||||
writel_relaxed(drvdata->stmheer, drvdata->base + STMHEER);
|
||||
+ writel_relaxed(drvdata->stmheextmuxr, drvdata->base + STMHEEXTMUXR);
|
||||
writel_relaxed(0x01 | /* Enable HW event tracing */
|
||||
0x04, /* Error detection on event tracing */
|
||||
drvdata->base + STMHEMCR);
|
||||
@@ -222,6 +227,7 @@ static void stm_hwevent_disable_hw(struct stm_drvdata *drvdata)
|
||||
writel_relaxed(0x0, drvdata->base + STMHEMCR);
|
||||
writel_relaxed(0x0, drvdata->base + STMHEER);
|
||||
writel_relaxed(0x0, drvdata->base + STMHETER);
|
||||
+ writel_relaxed(0x0, drvdata->base + STMHEEXTMUXR);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
@@ -455,6 +461,34 @@ static ssize_t notrace stm_generic_packet(struct stm_data *stm_data,
|
||||
return size;
|
||||
}
|
||||
|
||||
+static ssize_t hwevent_extmux_select_show(struct device *dev,
|
||||
+ struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
+ unsigned long val = drvdata->stmheextmuxr;
|
||||
+
|
||||
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
|
||||
+}
|
||||
+
|
||||
+static ssize_t hwevent_extmux_select_store(struct device *dev,
|
||||
+ struct device_attribute *attr,
|
||||
+ const char *buf, size_t size)
|
||||
+{
|
||||
+ struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
+ unsigned long val;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ ret = kstrtoul(buf, 16, &val);
|
||||
+ if (ret)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ drvdata->stmheextmuxr = val;
|
||||
+
|
||||
+ return size;
|
||||
+}
|
||||
+static DEVICE_ATTR_RW(hwevent_extmux_select);
|
||||
+
|
||||
static ssize_t hwevent_enable_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -644,10 +678,16 @@ coresight_stm_reg(spfeat1r, STMSPFEAT1R);
|
||||
coresight_stm_reg(spfeat2r, STMSPFEAT2R);
|
||||
coresight_stm_reg(spfeat3r, STMSPFEAT3R);
|
||||
coresight_stm_reg(devid, CORESIGHT_DEVID);
|
||||
+coresight_stm_reg(stmheer, STMHEER);
|
||||
+coresight_stm_reg(stmheter, STMHETER);
|
||||
+coresight_stm_reg(stmhebsr, STMHEBSR);
|
||||
+coresight_stm_reg(stmheextmux, STMHEEXTMUXR);
|
||||
+coresight_stm_reg(stmhemcr, STMHEMCR);
|
||||
|
||||
static struct attribute *coresight_stm_attrs[] = {
|
||||
&dev_attr_hwevent_enable.attr,
|
||||
&dev_attr_hwevent_select.attr,
|
||||
+ &dev_attr_hwevent_extmux_select.attr,
|
||||
&dev_attr_port_enable.attr,
|
||||
&dev_attr_port_select.attr,
|
||||
&dev_attr_traceid.attr,
|
||||
@@ -667,6 +707,11 @@ static struct attribute *coresight_stm_mgmt_attrs[] = {
|
||||
&dev_attr_spfeat2r.attr,
|
||||
&dev_attr_spfeat3r.attr,
|
||||
&dev_attr_devid.attr,
|
||||
+ &dev_attr_stmheer.attr,
|
||||
+ &dev_attr_stmheter.attr,
|
||||
+ &dev_attr_stmhebsr.attr,
|
||||
+ &dev_attr_stmheextmux.attr,
|
||||
+ &dev_attr_stmhemcr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -792,7 +837,7 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
struct coresight_platform_data *pdata = NULL;
|
||||
struct stm_drvdata *drvdata;
|
||||
struct resource *res = &adev->res;
|
||||
- struct resource ch_res;
|
||||
+ struct resource ch_res, cti_res;
|
||||
size_t res_size, bitmap_size;
|
||||
struct coresight_desc desc = { 0 };
|
||||
struct device_node *np = adev->dev.of_node;
|
||||
@@ -821,6 +866,17 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
return PTR_ERR(base);
|
||||
drvdata->base = base;
|
||||
|
||||
+ ret = stm_get_resource_byname(np, "cti-base", &cti_res);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ base = devm_ioremap_resource(dev, &cti_res);
|
||||
+
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ drvdata->base_cti = base;
|
||||
+
|
||||
ret = stm_get_resource_byname(np, "stm-stimulus-base", &ch_res);
|
||||
if (ret)
|
||||
return ret;
|
||||
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
|
||||
index 62d023e..c1cbf93 100644
|
||||
index a492da9..b052f3e 100644
|
||||
--- a/drivers/i2c/busses/i2c-stm32f7.c
|
||||
+++ b/drivers/i2c/busses/i2c-stm32f7.c
|
||||
@@ -21,12 +21,17 @@
|
||||
@@ -21,12 +21,16 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
|
@ -19,7 +159,7 @@ index 62d023e..c1cbf93 100644
|
|||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
-#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/pinctrl/consumer.h>
|
||||
|
|
@ -29,7 +169,7 @@ index 62d023e..c1cbf93 100644
|
|||
#include <linux/reset.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -46,6 +51,7 @@
|
||||
@@ -46,6 +50,7 @@
|
||||
|
||||
/* STM32F7 I2C control 1 */
|
||||
#define STM32F7_I2C_CR1_PECEN BIT(23)
|
||||
|
|
@ -37,7 +177,7 @@ index 62d023e..c1cbf93 100644
|
|||
#define STM32F7_I2C_CR1_SBC BIT(16)
|
||||
#define STM32F7_I2C_CR1_RXDMAEN BIT(15)
|
||||
#define STM32F7_I2C_CR1_TXDMAEN BIT(14)
|
||||
@@ -163,6 +169,26 @@
|
||||
@@ -163,6 +168,26 @@
|
||||
#define STM32F7_SCLH_MAX BIT(8)
|
||||
#define STM32F7_SCLL_MAX BIT(8)
|
||||
|
||||
|
|
@ -64,7 +204,7 @@ index 62d023e..c1cbf93 100644
|
|||
/**
|
||||
* struct stm32f7_i2c_spec - private i2c specification timing
|
||||
* @rate: I2C bus speed (Hz)
|
||||
@@ -259,6 +285,8 @@ struct stm32f7_i2c_msg {
|
||||
@@ -259,6 +284,8 @@ struct stm32f7_i2c_msg {
|
||||
* struct stm32f7_i2c_dev - private data of the controller
|
||||
* @adap: I2C adapter for this controller
|
||||
* @dev: device for this controller
|
||||
|
|
@ -73,11 +213,16 @@ index 62d023e..c1cbf93 100644
|
|||
* @base: virtual memory area
|
||||
* @complete: completion of I2C message
|
||||
* @clk: hw i2c clock
|
||||
@@ -276,11 +304,14 @@ struct stm32f7_i2c_msg {
|
||||
@@ -276,11 +303,19 @@ struct stm32f7_i2c_msg {
|
||||
* slave)
|
||||
* @dma: dma data
|
||||
* @use_dma: boolean to know if dma is used in the current transfer
|
||||
+ * @regmap: holds SYSCFG phandle for Fast Mode Plus bits
|
||||
+ * @sregmap: holds SYSCFG phandle for Fast Mode Plus bits
|
||||
+ * @cregmap: holds SYSCFG phandle for Fast Mode Plus clear bits
|
||||
+ * @regmap_sreg: register address for setting Fast Mode Plus bits
|
||||
+ * @regmap_smask: mask for Fast Mode Plus bits in set register
|
||||
+ * @regmap_creg: register address for setting Fast Mode Plus bits
|
||||
+ * @regmap_cmask: mask for Fast Mode Plus bits in set register
|
||||
*/
|
||||
struct stm32f7_i2c_dev {
|
||||
struct i2c_adapter adap;
|
||||
|
|
@ -88,7 +233,7 @@ index 62d023e..c1cbf93 100644
|
|||
struct completion complete;
|
||||
struct clk *clk;
|
||||
int speed;
|
||||
@@ -292,10 +323,12 @@ struct stm32f7_i2c_dev {
|
||||
@@ -292,10 +327,17 @@ struct stm32f7_i2c_dev {
|
||||
struct stm32f7_i2c_timings timing;
|
||||
struct i2c_client *slave[STM32F7_I2C_MAX_SLAVE];
|
||||
struct i2c_client *slave_running;
|
||||
|
|
@ -97,11 +242,59 @@ index 62d023e..c1cbf93 100644
|
|||
bool master_mode;
|
||||
struct stm32_i2c_dma *dma;
|
||||
bool use_dma;
|
||||
+ struct regmap *regmap;
|
||||
+ struct regmap *sregmap;
|
||||
+ struct regmap *cregmap;
|
||||
+ u32 regmap_sreg;
|
||||
+ u32 regmap_smask;
|
||||
+ u32 regmap_creg;
|
||||
+ u32 regmap_cmask;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1545,15 +1578,13 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
@@ -468,8 +510,12 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
|
||||
|
||||
list_add_tail(&v->node,
|
||||
&solutions);
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (p_prev == p)
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -941,6 +987,9 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
|
||||
cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
|
||||
f7_msg->read_write = I2C_SMBUS_READ;
|
||||
break;
|
||||
+ case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
+ /* Rely on emulated i2c transfer (through master_xfer) */
|
||||
+ return -EOPNOTSUPP;
|
||||
default:
|
||||
dev_err(dev, "Unsupported smbus protocol %d\n", f7_msg->size);
|
||||
return -EOPNOTSUPP;
|
||||
@@ -1178,6 +1227,8 @@ static void stm32f7_i2c_slave_start(struct stm32f7_i2c_dev *i2c_dev)
|
||||
STM32F7_I2C_CR1_TXIE;
|
||||
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
|
||||
|
||||
+ /* Write 1st data byte */
|
||||
+ writel_relaxed(value, base + STM32F7_I2C_TXDR);
|
||||
} else {
|
||||
/* Notify i2c slave that new write transfer is starting */
|
||||
i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
|
||||
@@ -1517,7 +1568,9 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
|
||||
mask = STM32F7_I2C_XFER_IRQ_MASK;
|
||||
else
|
||||
mask = STM32F7_I2C_ALL_IRQ_MASK;
|
||||
- stm32f7_i2c_disable_irq(i2c_dev, mask);
|
||||
+
|
||||
+ if (!i2c_dev->slave_running)
|
||||
+ stm32f7_i2c_disable_irq(i2c_dev, mask);
|
||||
|
||||
/* Disable dma */
|
||||
if (i2c_dev->use_dma) {
|
||||
@@ -1545,15 +1598,13 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
i2c_dev->msg_id = 0;
|
||||
f7_msg->smbus = false;
|
||||
|
||||
|
|
@ -120,7 +313,7 @@ index 62d023e..c1cbf93 100644
|
|||
|
||||
stm32f7_i2c_xfer_msg(i2c_dev, msgs);
|
||||
|
||||
@@ -1569,8 +1600,9 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
@@ -1569,8 +1620,9 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +325,7 @@ index 62d023e..c1cbf93 100644
|
|||
|
||||
return (ret < 0) ? ret : num;
|
||||
}
|
||||
@@ -1592,39 +1624,37 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||
@@ -1592,39 +1644,37 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||
f7_msg->read_write = read_write;
|
||||
f7_msg->smbus = true;
|
||||
|
||||
|
|
@ -179,7 +372,7 @@ index 62d023e..c1cbf93 100644
|
|||
}
|
||||
|
||||
if (read_write && size != I2C_SMBUS_QUICK) {
|
||||
@@ -1649,11 +1679,15 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||
@@ -1649,11 +1699,15 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +390,7 @@ index 62d023e..c1cbf93 100644
|
|||
static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
|
||||
@@ -1676,13 +1710,12 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||
@@ -1676,13 +1730,12 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -217,7 +410,7 @@ index 62d023e..c1cbf93 100644
|
|||
|
||||
if (id == 0) {
|
||||
/* Configure Own Address 1 */
|
||||
@@ -1703,7 +1736,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||
@@ -1703,7 +1756,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||
oar2 &= ~STM32F7_I2C_OAR2_MASK;
|
||||
if (slave->flags & I2C_CLIENT_TEN) {
|
||||
ret = -EOPNOTSUPP;
|
||||
|
|
@ -226,7 +419,7 @@ index 62d023e..c1cbf93 100644
|
|||
}
|
||||
|
||||
oar2 |= STM32F7_I2C_OAR2_OA2_7(slave->addr);
|
||||
@@ -1712,7 +1745,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||
@@ -1712,7 +1765,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||
writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2);
|
||||
} else {
|
||||
ret = -ENODEV;
|
||||
|
|
@ -235,7 +428,7 @@ index 62d023e..c1cbf93 100644
|
|||
}
|
||||
|
||||
/* Enable ACK */
|
||||
@@ -1723,11 +1756,13 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||
@@ -1723,11 +1776,13 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
|
||||
STM32F7_I2C_CR1_PE;
|
||||
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
|
||||
|
||||
|
|
@ -253,7 +446,7 @@ index 62d023e..c1cbf93 100644
|
|||
|
||||
return ret;
|
||||
}
|
||||
@@ -1745,6 +1780,10 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
|
||||
@@ -1745,6 +1800,10 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
|
||||
|
||||
WARN_ON(!i2c_dev->slave[id]);
|
||||
|
||||
|
|
@ -264,7 +457,7 @@ index 62d023e..c1cbf93 100644
|
|||
if (id == 0) {
|
||||
mask = STM32F7_I2C_OAR1_OA1EN;
|
||||
stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask);
|
||||
@@ -1755,14 +1794,56 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
|
||||
@@ -1755,21 +1814,106 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
|
||||
|
||||
i2c_dev->slave[id] = NULL;
|
||||
|
||||
|
|
@ -296,6 +489,32 @@ index 62d023e..c1cbf93 100644
|
|||
+ return device_set_wakeup_enable(i2c_dev->dev, false);
|
||||
+}
|
||||
+
|
||||
+static int stm32f7_i2c_write_fm_plus_bits(struct stm32f7_i2c_dev *i2c_dev,
|
||||
+ bool enable)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u32 reg, mask;
|
||||
+
|
||||
+ if (i2c_dev->speed != STM32_I2C_SPEED_FAST_PLUS ||
|
||||
+ IS_ERR_OR_NULL(i2c_dev->sregmap)) {
|
||||
+ /* Optional */
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ reg = i2c_dev->regmap_sreg;
|
||||
+ mask = i2c_dev->regmap_smask;
|
||||
+
|
||||
+ if (IS_ERR(i2c_dev->cregmap))
|
||||
+ ret = regmap_update_bits(i2c_dev->sregmap, reg, mask,
|
||||
+ enable ? mask : 0);
|
||||
+ else
|
||||
+ ret = regmap_write(enable ? i2c_dev->sregmap : i2c_dev->cregmap,
|
||||
+ enable ? reg : i2c_dev->regmap_creg,
|
||||
+ enable ? mask : i2c_dev->regmap_cmask);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev,
|
||||
+ struct stm32f7_i2c_dev *i2c_dev)
|
||||
+{
|
||||
|
|
@ -303,8 +522,8 @@ index 62d023e..c1cbf93 100644
|
|||
+ int ret;
|
||||
+ u32 reg, mask;
|
||||
+
|
||||
+ i2c_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg-fmp");
|
||||
+ if (IS_ERR(i2c_dev->regmap)) {
|
||||
+ i2c_dev->sregmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg-fmp");
|
||||
+ if (IS_ERR(i2c_dev->sregmap)) {
|
||||
+ /* Optional */
|
||||
+ return 0;
|
||||
+ }
|
||||
|
|
@ -317,39 +536,93 @@ index 62d023e..c1cbf93 100644
|
|||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return regmap_update_bits(i2c_dev->regmap, reg, mask, mask);
|
||||
+ i2c_dev->regmap_sreg = reg;
|
||||
+ i2c_dev->regmap_smask = mask;
|
||||
+ i2c_dev->cregmap = syscon_regmap_lookup_by_phandle(np,
|
||||
+ "st,syscfg-fmp-clr");
|
||||
+ if (!IS_ERR(i2c_dev->cregmap)) {
|
||||
+ ret = of_property_read_u32_index(np, "st,syscfg-fmp-clr", 1,
|
||||
+ &i2c_dev->regmap_creg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = of_property_read_u32_index(np, "st,syscfg-fmp-clr", 2,
|
||||
+ &i2c_dev->regmap_cmask);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return stm32f7_i2c_write_fm_plus_bits(i2c_dev, 1);
|
||||
+}
|
||||
+
|
||||
static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SLAVE |
|
||||
@@ -1786,7 +1867,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
|
||||
- I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC;
|
||||
+ I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC |
|
||||
+ I2C_FUNC_SMBUS_I2C_BLOCK;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm stm32f7_i2c_algo = {
|
||||
@@ -1782,15 +1926,14 @@ static struct i2c_algorithm stm32f7_i2c_algo = {
|
||||
|
||||
static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
- struct device_node *np = pdev->dev.of_node;
|
||||
struct stm32f7_i2c_dev *i2c_dev;
|
||||
const struct stm32f7_i2c_setup *setup;
|
||||
struct resource *res;
|
||||
- u32 irq_error, irq_event, clk_rate, rise_time, fall_time;
|
||||
+ u32 irq_error, clk_rate, rise_time, fall_time;
|
||||
+ u32 clk_rate, rise_time, fall_time;
|
||||
struct i2c_adapter *adap;
|
||||
struct reset_control *rst;
|
||||
dma_addr_t phy_addr;
|
||||
@@ -1802,13 +1883,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
- int ret;
|
||||
+ int irq_error, ret;
|
||||
|
||||
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
|
||||
if (!i2c_dev)
|
||||
@@ -1802,16 +1945,28 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(i2c_dev->base);
|
||||
phy_addr = (dma_addr_t)res->start;
|
||||
|
||||
- irq_event = irq_of_parse_and_map(np, 0);
|
||||
- if (!irq_event) {
|
||||
+ i2c_dev->irq_event = of_irq_get_byname(np, "event");
|
||||
+ if (!i2c_dev->irq_event) {
|
||||
dev_err(&pdev->dev, "IRQ event missing or invalid\n");
|
||||
return -EINVAL;
|
||||
- dev_err(&pdev->dev, "IRQ event missing or invalid\n");
|
||||
- return -EINVAL;
|
||||
+ i2c_dev->irq_event = platform_get_irq_byname(pdev, "event");
|
||||
+ if (i2c_dev->irq_event < 0) {
|
||||
+ if (i2c_dev->irq_event != -EPROBE_DEFER)
|
||||
+ dev_err(&pdev->dev, "Failed to get IRQ event: %d\n",
|
||||
+ i2c_dev->irq_event);
|
||||
+ return i2c_dev->irq_event;
|
||||
}
|
||||
|
||||
- irq_error = irq_of_parse_and_map(np, 1);
|
||||
+ irq_error = of_irq_get_byname(np, "error");
|
||||
if (!irq_error) {
|
||||
dev_err(&pdev->dev, "IRQ error missing or invalid\n");
|
||||
return -EINVAL;
|
||||
@@ -1819,6 +1900,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
- if (!irq_error) {
|
||||
- dev_err(&pdev->dev, "IRQ error missing or invalid\n");
|
||||
- return -EINVAL;
|
||||
+ irq_error = platform_get_irq_byname(pdev, "error");
|
||||
+ if (irq_error < 0) {
|
||||
+ if (irq_error != -EPROBE_DEFER)
|
||||
+ dev_err(&pdev->dev, "Failed to get IRQ error: %d\n",
|
||||
+ irq_error);
|
||||
+ return irq_error;
|
||||
+ }
|
||||
+
|
||||
+ i2c_dev->irq_wakeup = platform_get_irq_byname(pdev, "wakeup");
|
||||
+ if (i2c_dev->irq_wakeup < 0 && i2c_dev->irq_wakeup != -ENXIO) {
|
||||
+ if (i2c_dev->irq_wakeup != -EPROBE_DEFER)
|
||||
+ dev_err(&pdev->dev, "Failed to get IRQ wakeup: %d\n",
|
||||
+ i2c_dev->irq_wakeup);
|
||||
+ return i2c_dev->irq_wakeup;
|
||||
}
|
||||
|
||||
i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
@@ -1819,6 +1974,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "Error: Missing controller clock\n");
|
||||
return PTR_ERR(i2c_dev->clk);
|
||||
}
|
||||
|
|
@ -357,7 +630,7 @@ index 62d023e..c1cbf93 100644
|
|||
ret = clk_prepare_enable(i2c_dev->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to prepare_enable clock\n");
|
||||
@@ -1828,12 +1910,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
@@ -1828,12 +1984,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
|
||||
ret = device_property_read_u32(&pdev->dev, "clock-frequency",
|
||||
&clk_rate);
|
||||
|
|
@ -365,9 +638,6 @@ index 62d023e..c1cbf93 100644
|
|||
+ if (!ret && clk_rate >= 1000000) {
|
||||
i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS;
|
||||
- else if (!ret && clk_rate >= 400000)
|
||||
+ ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
|
||||
+ if (ret)
|
||||
+ goto clk_free;
|
||||
+ } else if (!ret && clk_rate >= 400000) {
|
||||
i2c_dev->speed = STM32_I2C_SPEED_FAST;
|
||||
- else if (!ret && clk_rate >= 100000)
|
||||
|
|
@ -377,7 +647,7 @@ index 62d023e..c1cbf93 100644
|
|||
|
||||
rst = devm_reset_control_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(rst)) {
|
||||
@@ -1847,14 +1933,14 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
@@ -1847,14 +2004,14 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
i2c_dev->dev = &pdev->dev;
|
||||
|
||||
|
|
@ -394,27 +664,30 @@ index 62d023e..c1cbf93 100644
|
|||
goto clk_free;
|
||||
}
|
||||
|
||||
@@ -1888,8 +1974,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
@@ -1888,7 +2045,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto clk_free;
|
||||
|
||||
- stm32f7_i2c_hw_config(i2c_dev);
|
||||
-
|
||||
+ if (i2c_dev->speed == STM32_I2C_SPEED_FAST_PLUS) {
|
||||
+ ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
|
||||
+ if (ret)
|
||||
+ goto clk_free;
|
||||
+ }
|
||||
|
||||
adap = &i2c_dev->adap;
|
||||
i2c_set_adapdata(adap, i2c_dev);
|
||||
snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)",
|
||||
@@ -1908,18 +1992,45 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
@@ -1908,18 +2069,47 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
STM32F7_I2C_TXDR,
|
||||
STM32F7_I2C_RXDR);
|
||||
|
||||
- ret = i2c_add_adapter(adap);
|
||||
- if (ret)
|
||||
- goto clk_free;
|
||||
+ i2c_dev->irq_wakeup = of_irq_get_byname(np, "wakeup");
|
||||
+ if (i2c_dev->irq_wakeup > 0) {
|
||||
+ ret = stm32f7_i2c_setup_wakeup(i2c_dev);
|
||||
+ if (ret)
|
||||
+ goto clk_free;
|
||||
+ goto fmp_clear;
|
||||
+ }
|
||||
|
||||
platform_set_drvdata(pdev, i2c_dev);
|
||||
|
|
@ -449,20 +722,24 @@ index 62d023e..c1cbf93 100644
|
|||
+ pm_runtime_disable(i2c_dev->dev);
|
||||
+ pm_runtime_set_suspended(i2c_dev->dev);
|
||||
+ pm_runtime_dont_use_autosuspend(i2c_dev->dev);
|
||||
+
|
||||
+fmp_clear:
|
||||
+ stm32f7_i2c_write_fm_plus_bits(i2c_dev, 0);
|
||||
+
|
||||
clk_free:
|
||||
clk_disable_unprepare(i2c_dev->clk);
|
||||
|
||||
@@ -1936,11 +2047,170 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
|
||||
@@ -1936,12 +2126,175 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
i2c_del_adapter(&i2c_dev->adap);
|
||||
+ pm_runtime_get_sync(i2c_dev->dev);
|
||||
+
|
||||
+ stm32f7_i2c_write_fm_plus_bits(i2c_dev, 0);
|
||||
+
|
||||
+ dev_pm_clear_wake_irq(i2c_dev->dev);
|
||||
+ device_init_wakeup(i2c_dev->dev, false);
|
||||
|
||||
- clk_unprepare(i2c_dev->clk);
|
||||
+
|
||||
+ clk_disable_unprepare(i2c_dev->clk);
|
||||
+
|
||||
+ pm_runtime_put_noidle(i2c_dev->dev);
|
||||
|
|
@ -496,9 +773,9 @@ index 62d023e..c1cbf93 100644
|
|||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
|
|
@ -516,6 +793,7 @@ index 62d023e..c1cbf93 100644
|
|||
+ i2c_dev->regs.oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2);
|
||||
+ i2c_dev->regs.pecr = readl_relaxed(i2c_dev->base + STM32F7_I2C_PECR);
|
||||
+ i2c_dev->regs.tmgr = readl_relaxed(i2c_dev->base + STM32F7_I2C_TIMINGR);
|
||||
+ stm32f7_i2c_write_fm_plus_bits(i2c_dev, 0);
|
||||
+
|
||||
+ pm_runtime_put_sync(i2c_dev->dev);
|
||||
+
|
||||
|
|
@ -546,6 +824,7 @@ index 62d023e..c1cbf93 100644
|
|||
+ writel_relaxed(i2c_dev->regs.oar1, i2c_dev->base + STM32F7_I2C_OAR1);
|
||||
+ writel_relaxed(i2c_dev->regs.oar2, i2c_dev->base + STM32F7_I2C_OAR2);
|
||||
+ writel_relaxed(i2c_dev->regs.pecr, i2c_dev->base + STM32F7_I2C_PECR);
|
||||
+ stm32f7_i2c_write_fm_plus_bits(i2c_dev, 1);
|
||||
+
|
||||
+ pm_runtime_put_sync(i2c_dev->dev);
|
||||
+
|
||||
|
|
@ -583,15 +862,16 @@ index 62d023e..c1cbf93 100644
|
|||
+ ret = stm32f7_i2c_regs_backup(i2c_dev);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
|
||||
- clk_unprepare(i2c_dev->clk);
|
||||
+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
|
||||
+ pinctrl_pm_select_sleep_state(dev);
|
||||
+ pm_runtime_force_suspend(dev);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int stm32f7_i2c_resume(struct device *dev)
|
||||
+{
|
||||
+ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
|
||||
|
|
@ -622,10 +902,11 @@ index 62d023e..c1cbf93 100644
|
|||
+ stm32f7_i2c_runtime_resume, NULL)
|
||||
+ SET_SYSTEM_SLEEP_PM_OPS(stm32f7_i2c_suspend, stm32f7_i2c_resume)
|
||||
+};
|
||||
|
||||
+
|
||||
static const struct of_device_id stm32f7_i2c_match[] = {
|
||||
{ .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup},
|
||||
@@ -1952,6 +2222,7 @@ static struct platform_driver stm32f7_i2c_driver = {
|
||||
{},
|
||||
@@ -1952,6 +2305,7 @@ static struct platform_driver stm32f7_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "stm32f7-i2c",
|
||||
.of_match_table = stm32f7_i2c_match,
|
||||
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
|
|
@ -1,18 +1,21 @@
|
|||
From 254a1f3c99a65578044558234a01b4fbc180b3d6 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:22:30 +0100
|
||||
Subject: [PATCH 08/52] ARM: stm32mp1-r0-rc1: MFD
|
||||
From 1e1b3d357ac9971d70631b624301524294ea5d3c Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:02 +0200
|
||||
Subject: [PATCH 13/30] ARM stm32mp1 r2 MFD
|
||||
|
||||
---
|
||||
drivers/mfd/Kconfig | 31 ++
|
||||
drivers/mfd/Makefile | 4 +-
|
||||
drivers/mfd/stm32-pwr.c | 287 ++++++++++++++++
|
||||
drivers/mfd/stm32-pwr.c | 400 ++++++++++++++++++++++
|
||||
drivers/mfd/stmfx.c | 626 +++++++++++++++++++++++++++++++++++
|
||||
drivers/mfd/stpmic1.c | 413 +++++++++++++++++++++++
|
||||
drivers/mfd/stpmic1.c | 409 +++++++++++++++++++++++
|
||||
drivers/mfd/syscon.c | 19 ++
|
||||
drivers/mfd/wm8994-core.c | 21 ++
|
||||
include/dt-bindings/mfd/st,stpmic1.h | 46 +++
|
||||
include/linux/mfd/stmfx.h | 27 ++
|
||||
include/linux/mfd/stpmic1.h | 213 ++++++++++++
|
||||
8 files changed, 1646 insertions(+), 1 deletion(-)
|
||||
include/linux/mfd/stpmic1.h | 212 ++++++++++++
|
||||
include/linux/mfd/wm8994/pdata.h | 6 +
|
||||
11 files changed, 1800 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/mfd/stm32-pwr.c
|
||||
create mode 100644 drivers/mfd/stmfx.c
|
||||
create mode 100644 drivers/mfd/stpmic1.c
|
||||
|
|
@ -84,10 +87,10 @@ index 5856a94..d794a2d 100644
|
|||
+obj-$(CONFIG_MFD_STMFX) += stmfx.o
|
||||
diff --git a/drivers/mfd/stm32-pwr.c b/drivers/mfd/stm32-pwr.c
|
||||
new file mode 100644
|
||||
index 0000000..377e2f5
|
||||
index 0000000..92744bf
|
||||
--- /dev/null
|
||||
+++ b/drivers/mfd/stm32-pwr.c
|
||||
@@ -0,0 +1,287 @@
|
||||
@@ -0,0 +1,400 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
|
||||
|
|
@ -95,7 +98,11 @@ index 0000000..377e2f5
|
|||
+ */
|
||||
+
|
||||
+#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>
|
||||
|
|
@ -127,18 +134,21 @@ index 0000000..377e2f5
|
|||
+ WKUP_PULL_RESERVED
|
||||
+};
|
||||
+
|
||||
+#define SMC(class, op, offset, val) \
|
||||
+{ \
|
||||
+#define SMC(class, op, offset, val) do { \
|
||||
+ struct arm_smccc_res res; \
|
||||
+ arm_smccc_smc(class, op, SMC_PWR_BASE + offset, val, \
|
||||
+ arm_smccc_smc(class, op, SMC_PWR_BASE + (offset), val, \
|
||||
+ 0, 0, 0, 0, &res); \
|
||||
+} \
|
||||
+} while (0) \
|
||||
+
|
||||
+struct stm32_pwr_data {
|
||||
+ struct device *dev; /* self device */
|
||||
+ 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)
|
||||
|
|
@ -149,12 +159,24 @@ index 0000000..377e2f5
|
|||
+ 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);
|
||||
+ SMC(STM32_SVC_PWR, STM32_CLEAR_BITS, MPUWKUPENR, BIT(d->hwirq));
|
||||
+ priv->masked |= BIT(d->hwirq);
|
||||
+ stm32_pwr_irq_set_enable(d);
|
||||
+}
|
||||
+
|
||||
+static void stm32_pwr_irq_unmask(struct irq_data *d)
|
||||
|
|
@ -162,18 +184,26 @@ index 0000000..377e2f5
|
|||
+ 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, MPUWKUPENR, BIT(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)
|
||||
+ enable_irq_wake(priv->irq);
|
||||
+ else
|
||||
+ disable_irq_wake(priv->irq);
|
||||
+ 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;
|
||||
+}
|
||||
|
|
@ -205,6 +235,7 @@ index 0000000..377e2f5
|
|||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr);
|
||||
+
|
||||
+ if (en)
|
||||
|
|
@ -213,22 +244,59 @@ index 0000000..377e2f5
|
|||
+ 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",
|
||||
+ .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_map(struct irq_domain *h, unsigned int virq,
|
||||
+ irq_hw_number_t hw)
|
||||
+{
|
||||
+ irq_set_chip_and_handler(virq, &stm32_pwr_irq_chip, handle_edge_irq);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int stm32_pwr_irq_set_pull_config(struct irq_domain *d, int pin_id,
|
||||
+ enum wkup_pull_setting config)
|
||||
+{
|
||||
|
|
@ -238,13 +306,14 @@ index 0000000..377e2f5
|
|||
+ dev_dbg(priv->dev, "irq:%d pull config:0x%x\n", pin_id, config);
|
||||
+
|
||||
+ if (config >= WKUP_PULL_RESERVED) {
|
||||
+ dev_err(priv->dev, "%s: bad irq pull config\n", __func__);
|
||||
+ pr_err("%s: bad irq pull config\n", __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ wkupcr = readl_relaxed(priv->base + WKUPCR);
|
||||
+ wkupcr &= ~((WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2));
|
||||
+ wkupcr |= (config & WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2);
|
||||
+
|
||||
+ SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr);
|
||||
+
|
||||
+ return 0;
|
||||
|
|
@ -254,10 +323,8 @@ index 0000000..377e2f5
|
|||
+ const u32 *intspec, unsigned int intsize,
|
||||
+ irq_hw_number_t *out_hwirq, unsigned int *out_type)
|
||||
+{
|
||||
+ struct stm32_pwr_data *priv = d->host_data;
|
||||
+
|
||||
+ if (WARN_ON(intsize < 3)) {
|
||||
+ dev_err(priv->dev, "%s: bad irq config parameters\n", __func__);
|
||||
+ pr_err("%s: bad irq config parameters\n", __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
|
|
@ -267,9 +334,23 @@ index 0000000..377e2f5
|
|||
+ return stm32_pwr_irq_set_pull_config(d, intspec[0], intspec[2]);
|
||||
+}
|
||||
+
|
||||
+static int stm32_pwr_alloc(struct irq_domain *d, unsigned int virq,
|
||||
+ unsigned int nr_irqs, void *data)
|
||||
+{
|
||||
+ struct irq_fwspec *fwspec = data;
|
||||
+ irq_hw_number_t hwirq;
|
||||
+
|
||||
+ hwirq = fwspec->param[0];
|
||||
+ irq_domain_set_info(d, virq, hwirq, &stm32_pwr_irq_chip, d->host_data,
|
||||
+ handle_edge_irq, NULL, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct irq_domain_ops stm32_pwr_irq_domain_ops = {
|
||||
+ .map = stm32_pwr_irq_map,
|
||||
+ .alloc = stm32_pwr_alloc,
|
||||
+ .xlate = stm32_pwr_xlate,
|
||||
+ .free = irq_domain_free_irqs_common,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
|
|
@ -285,36 +366,59 @@ index 0000000..377e2f5
|
|||
+
|
||||
+ 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);
|
||||
+ generic_handle_irq(irq_find_mapping(priv->domain, 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);
|
||||
+
|
||||
+ dev_dbg(priv->dev, "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 device_node *np = pdev->dev.of_node;
|
||||
+ struct stm32_pwr_data *priv;
|
||||
+
|
||||
+ struct device_node *np = dev->of_node;
|
||||
+ struct resource *res;
|
||||
+ int ret;
|
||||
+
|
||||
+ priv = devm_kzalloc(dev, sizeof(struct stm32_pwr_data), GFP_KERNEL);
|
||||
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, priv);
|
||||
+ priv->dev = dev;
|
||||
+ dev_set_drvdata(dev, priv);
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ priv->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ priv->base = devm_ioremap_resource(dev, res);
|
||||
+ if (IS_ERR(priv->base)) {
|
||||
+ dev_err(dev, "%s: Unable to map IO memory\n", __func__);
|
||||
+ dev_err(dev, "Unable to map registers\n");
|
||||
+ return PTR_ERR(priv->base);
|
||||
+ }
|
||||
+
|
||||
|
|
@ -327,46 +431,51 @@ index 0000000..377e2f5
|
|||
+ &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 = platform_get_irq(pdev, 0);
|
||||
+ ret = irq_of_parse_and_map(np, 0);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "failed to get PWR IRQ\n");
|
||||
+ goto err;
|
||||
+ ret = priv->irq;
|
||||
+ goto out_domain;
|
||||
+ }
|
||||
+
|
||||
+ priv->irq = ret;
|
||||
+ irq_set_chained_handler_and_data(priv->irq, stm32_pwr_handle_irq, priv);
|
||||
+
|
||||
+ irq_set_chained_handler_and_data(priv->irq,
|
||||
+ stm32_pwr_handle_irq, priv);
|
||||
+ of_node_clear_flag(np, OF_POPULATED);
|
||||
+
|
||||
+out:
|
||||
+ return 0;
|
||||
+err:
|
||||
+
|
||||
+out_domain:
|
||||
+ irq_domain_remove(priv->domain);
|
||||
+out:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int stm32_pwr_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct stm32_pwr_data *priv = platform_get_drvdata(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_match[] = {
|
||||
+ { .compatible = "st,stm32mp1-pwr" },
|
||||
+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",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = stm32_pwr_match,
|
||||
+ .probe = stm32_pwr_probe,
|
||||
+ .remove = stm32_pwr_remove,
|
||||
+ .driver = {
|
||||
+ .name = "stm32_pwr",
|
||||
+ .of_match_table = stm32_pwr_ids,
|
||||
+ .pm = &stm32_pwr_pm,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
|
|
@ -374,7 +483,14 @@ index 0000000..377e2f5
|
|||
+{
|
||||
+ 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/stmfx.c b/drivers/mfd/stmfx.c
|
||||
new file mode 100644
|
||||
index 0000000..cfd4fca
|
||||
|
|
@ -1009,10 +1125,10 @@ index 0000000..cfd4fca
|
|||
+MODULE_LICENSE("GPL v2");
|
||||
diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c
|
||||
new file mode 100644
|
||||
index 0000000..5bf6328
|
||||
index 0000000..648315d
|
||||
--- /dev/null
|
||||
+++ b/drivers/mfd/stpmic1.c
|
||||
@@ -0,0 +1,413 @@
|
||||
@@ -0,0 +1,409 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+// Copyright (C) STMicroelectronics 2018
|
||||
+// Author: Pascal Paillet <p.paillet@st.com>
|
||||
|
|
@ -1283,13 +1399,8 @@ index 0000000..5bf6328
|
|||
+ return ddata->irq;
|
||||
+ }
|
||||
+
|
||||
+ ddata->irq_wake = of_irq_get(np, STPMIC1_WAKEUP_IRQ);
|
||||
+ if (ddata->irq_wake > 0) {
|
||||
+ if (of_property_read_bool(np, "wakeup-source"))
|
||||
+ device_init_wakeup(dev, true);
|
||||
+ ret = dev_pm_set_dedicated_wake_irq(dev, ddata->irq_wake);
|
||||
+ if (ret)
|
||||
+ dev_warn(dev, "failed to set up wakeup irq");
|
||||
+ }
|
||||
+
|
||||
+ if (!of_property_read_u32(np, "st,main-control-register", ®)) {
|
||||
+ ret = regmap_update_bits(ddata->regmap,
|
||||
|
|
@ -1386,8 +1497,8 @@ index 0000000..5bf6328
|
|||
+ struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
|
||||
+
|
||||
+ disable_irq(pmic_dev->irq);
|
||||
+ if ((pmic_dev->irq_wake > 0) && device_may_wakeup(dev))
|
||||
+ enable_irq_wake(pmic_dev->irq_wake);
|
||||
+ if (device_may_wakeup(dev))
|
||||
+ enable_irq_wake(pmic_dev->irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
|
|
@ -1402,9 +1513,10 @@ index 0000000..5bf6328
|
|||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (device_may_wakeup(dev))
|
||||
+ disable_irq_wake(pmic_dev->irq);
|
||||
+
|
||||
+ enable_irq(pmic_dev->irq);
|
||||
+ if ((pmic_dev->irq_wake > 0) && device_may_wakeup(dev))
|
||||
+ disable_irq_wake(pmic_dev->irq_wake);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
|
|
@ -1426,6 +1538,103 @@ index 0000000..5bf6328
|
|||
+MODULE_DESCRIPTION("STPMIC1 PMIC Driver");
|
||||
+MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
|
||||
index b6d05cd..a0ba4ff 100644
|
||||
--- a/drivers/mfd/syscon.c
|
||||
+++ b/drivers/mfd/syscon.c
|
||||
@@ -12,6 +12,7 @@
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
+#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwspinlock.h>
|
||||
#include <linux/io.h>
|
||||
@@ -45,6 +46,7 @@ static const struct regmap_config syscon_regmap_config = {
|
||||
|
||||
static struct syscon *of_syscon_register(struct device_node *np)
|
||||
{
|
||||
+ struct clk *clk;
|
||||
struct syscon *syscon;
|
||||
struct regmap *regmap;
|
||||
void __iomem *base;
|
||||
@@ -119,6 +121,18 @@ static struct syscon *of_syscon_register(struct device_node *np)
|
||||
goto err_regmap;
|
||||
}
|
||||
|
||||
+ clk = of_clk_get(np, 0);
|
||||
+ if (IS_ERR(clk)) {
|
||||
+ ret = PTR_ERR(clk);
|
||||
+ /* clock is optional */
|
||||
+ if (ret != -ENOENT)
|
||||
+ goto err_clk;
|
||||
+ } else {
|
||||
+ ret = regmap_mmio_attach_clk(regmap, clk);
|
||||
+ if (ret)
|
||||
+ goto err_attach;
|
||||
+ }
|
||||
+
|
||||
syscon->regmap = regmap;
|
||||
syscon->np = np;
|
||||
|
||||
@@ -128,6 +142,11 @@ static struct syscon *of_syscon_register(struct device_node *np)
|
||||
|
||||
return syscon;
|
||||
|
||||
+err_attach:
|
||||
+ if (!IS_ERR(clk))
|
||||
+ clk_put(clk);
|
||||
+err_clk:
|
||||
+ regmap_exit(regmap);
|
||||
err_regmap:
|
||||
iounmap(base);
|
||||
err_map:
|
||||
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
|
||||
index 22bd652..ab8f1d4 100644
|
||||
--- a/drivers/mfd/wm8994-core.c
|
||||
+++ b/drivers/mfd/wm8994-core.c
|
||||
@@ -12,6 +12,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
+#include <linux/clk.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -191,6 +192,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) {
|
||||
@@ -314,6 +321,20 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
|
||||
if (pdata->ldo[1].enable < 0)
|
||||
pdata->ldo[1].enable = 0;
|
||||
|
||||
+ pdata->mclk1 = devm_clk_get(wm8994->dev, "MCLK1");
|
||||
+ if (IS_ERR(pdata->mclk1)) {
|
||||
+ if (PTR_ERR(pdata->mclk1) != -ENOENT)
|
||||
+ return PTR_ERR(pdata->mclk1);
|
||||
+ pdata->mclk1 = NULL;
|
||||
+ }
|
||||
+
|
||||
+ pdata->mclk2 = devm_clk_get(wm8994->dev, "MCLK2");
|
||||
+ if (IS_ERR(pdata->mclk2)) {
|
||||
+ if (PTR_ERR(pdata->mclk2) != -ENOENT)
|
||||
+ return PTR_ERR(pdata->mclk2);
|
||||
+ pdata->mclk2 = NULL;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
diff --git a/include/dt-bindings/mfd/st,stpmic1.h b/include/dt-bindings/mfd/st,stpmic1.h
|
||||
new file mode 100644
|
||||
index 0000000..b2d6c83
|
||||
|
|
@ -1513,10 +1722,10 @@ index 0000000..35c3d42
|
|||
+#endif
|
||||
diff --git a/include/linux/mfd/stpmic1.h b/include/linux/mfd/stpmic1.h
|
||||
new file mode 100644
|
||||
index 0000000..4abe5f1
|
||||
index 0000000..fa3f99f
|
||||
--- /dev/null
|
||||
+++ b/include/linux/mfd/stpmic1.h
|
||||
@@ -0,0 +1,213 @@
|
||||
@@ -0,0 +1,212 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+/*
|
||||
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||
|
|
@ -1725,11 +1934,27 @@ index 0000000..4abe5f1
|
|||
+ struct device *dev;
|
||||
+ struct regmap *regmap;
|
||||
+ int irq;
|
||||
+ int irq_wake;
|
||||
+ struct regmap_irq_chip_data *irq_data;
|
||||
+};
|
||||
+
|
||||
+#endif /* __LINUX_MFD_STPMIC1_H */
|
||||
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
|
||||
index b19c370..cdaf3f6 100644
|
||||
--- a/include/linux/mfd/wm8994/pdata.h
|
||||
+++ b/include/linux/mfd/wm8994/pdata.h
|
||||
@@ -239,6 +239,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.7.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,477 @@
|
|||
From edca8bc73b6a7e2057b821cc41e68fe3d7c0bb03 Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:02 +0200
|
||||
Subject: [PATCH 15/30] ARM stm32mp1 r2 NET
|
||||
|
||||
---
|
||||
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 166 +++++++++++++++++----
|
||||
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 -
|
||||
7 files changed, 189 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
index 7e2e79d..6e260e9 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,64 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
|
||||
static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||
struct device *dev)
|
||||
{
|
||||
+ struct platform_device *pdev = to_platform_device(dev);
|
||||
struct device_node *np = dev->of_node;
|
||||
+ int err = 0;
|
||||
|
||||
- dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk");
|
||||
+ /* 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;
|
||||
+ /* 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 +427,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 +448,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 50c0082..1df9027 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);
|
||||
|
||||
@@ -4485,14 +4485,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 */
|
||||
@@ -4514,6 +4513,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);
|
||||
@@ -4554,6 +4557,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;
|
||||
@@ -4585,7 +4589,28 @@ int stmmac_resume(struct device *dev)
|
||||
|
||||
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;
|
||||
+ }
|
||||
+
|
||||
+ if (ndev->phydev)
|
||||
+ phy_start(ndev->phydev);
|
||||
|
||||
stmmac_hw_setup(ndev, false);
|
||||
stmmac_init_tx_coalesce(priv);
|
||||
@@ -4597,10 +4622,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
|
||||
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
From a38a0eadf1db60bd8d1ff084c2ddc8016432b4fb Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:25:05 +0100
|
||||
Subject: [PATCH 11/52] ARM: stm32mp1-r0-rc1: NVMEM
|
||||
From 7a1e0bedb3066a32ff522e25daacd490d306ea40 Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:03 +0200
|
||||
Subject: [PATCH 16/30] ARM stm32mp1 r2 NVMEM
|
||||
|
||||
---
|
||||
drivers/nvmem/Kconfig | 10 ++
|
||||
drivers/nvmem/Makefile | 2 +
|
||||
drivers/nvmem/core.c | 37 ++++++++
|
||||
drivers/nvmem/stm32-romem.c | 205 +++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/nvmem/stm32-romem.c | 203 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/nvmem-consumer.h | 7 ++
|
||||
5 files changed, 261 insertions(+)
|
||||
5 files changed, 259 insertions(+)
|
||||
create mode 100644 drivers/nvmem/stm32-romem.c
|
||||
|
||||
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
|
||||
|
|
@ -96,10 +96,10 @@ index 7c530c8..60dacd7 100644
|
|||
* @nvmem: nvmem device to read from.
|
||||
diff --git a/drivers/nvmem/stm32-romem.c b/drivers/nvmem/stm32-romem.c
|
||||
new file mode 100644
|
||||
index 0000000..198872f
|
||||
index 0000000..34b388c
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/stm32-romem.c
|
||||
@@ -0,0 +1,205 @@
|
||||
@@ -0,0 +1,203 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * STM32 Factory-programmed memory read access driver
|
||||
|
|
@ -121,6 +121,12 @@ index 0000000..198872f
|
|||
+#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;
|
||||
+};
|
||||
|
|
@ -179,13 +185,21 @@ index 0000000..198872f
|
|||
+ return -EINVAL;
|
||||
+
|
||||
+ for (i = roffset; (i < roffset + rbytes); i += 4) {
|
||||
+ ret = stm32_bsec_smc(STM32_SMC_READ_OTP, i >> 2, 0, &val);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "Failed to read data%d (%d)\n",
|
||||
+ i >> 2, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ u32 otp = i >> 2;
|
||||
+
|
||||
+ if (otp < STM32MP15_BSEC_NUM_LOWER) {
|
||||
+ /* read lower data from shadow registers */
|
||||
+ val = readl_relaxed(
|
||||
+ priv->base + STM32MP15_BSEC_DATA0 + i);
|
||||
+ } else {
|
||||
+ ret = stm32_bsec_smc(STM32_SMC_READ_SHADOW, otp, 0,
|
||||
+ &val);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "Can't read data%d (%d)\n",
|
||||
+ otp, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ /* skip first bytes in case of unaligned read */
|
||||
+ if (skip_bytes)
|
||||
+ size = min(bytes, (size_t)(4 - skip_bytes));
|
||||
|
|
@ -229,7 +243,6 @@ index 0000000..198872f
|
|||
+ const struct stm32_romem_cfg *cfg;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct stm32_romem_priv *priv;
|
||||
+ struct nvmem_device *nvmem;
|
||||
+ struct resource *res;
|
||||
+
|
||||
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
|
@ -256,26 +269,12 @@ index 0000000..198872f
|
|||
+ priv->cfg.size = resource_size(res);
|
||||
+ priv->cfg.reg_read = stm32_romem_read;
|
||||
+ } else {
|
||||
+ priv->cfg.read_only = false;
|
||||
+ priv->cfg.size = cfg->size;
|
||||
+ priv->cfg.reg_read = stm32_bsec_read;
|
||||
+ priv->cfg.reg_write = stm32_bsec_write;
|
||||
+ }
|
||||
+
|
||||
+ nvmem = nvmem_register(&priv->cfg);
|
||||
+ if (IS_ERR(nvmem))
|
||||
+ return PTR_ERR(nvmem);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, nvmem);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int stm32_romem_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct nvmem_device *nvmem = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ return nvmem_unregister(nvmem);
|
||||
+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg));
|
||||
+}
|
||||
+
|
||||
+static const struct stm32_romem_cfg stm32mp15_bsec_cfg = {
|
||||
|
|
@ -293,7 +292,6 @@ index 0000000..198872f
|
|||
+
|
||||
+static struct platform_driver stm32_romem_driver = {
|
||||
+ .probe = stm32_romem_probe,
|
||||
+ .remove = stm32_romem_remove,
|
||||
+ .driver = {
|
||||
+ .name = "stm32-romem",
|
||||
+ .of_match_table = of_match_ptr(stm32_romem_of_match),
|
||||
|
|
@ -0,0 +1,603 @@
|
|||
From 34f2e1a678f0017522aeba5633b3729590b2f811 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 17 Sep 2019 14:27:10 +0200
|
||||
Subject: [PATCH 17/30] ARM stm32mp1 r2 PERF
|
||||
|
||||
---
|
||||
Documentation/perf/stm32-ddr-pmu.txt | 41 +++
|
||||
drivers/perf/Kconfig | 6 +
|
||||
drivers/perf/Makefile | 1 +
|
||||
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
|
||||
--- /dev/null
|
||||
+++ b/Documentation/perf/stm32-ddr-pmu.txt
|
||||
@@ -0,0 +1,41 @@
|
||||
+STM32 DDR Performance Monitor (DDRPERFM)
|
||||
+========================================
|
||||
+
|
||||
+The DDRPERFM is the DDR Performance Monitor embedded in STM32MP1 SOC.
|
||||
+See STM32MP157 reference manual RM0436 to get a description of this peripheral.
|
||||
+
|
||||
+
|
||||
+The five following counters are supported by stm32-ddr-pmu driver:
|
||||
+ cnt0: read operations counters (read_cnt)
|
||||
+ cnt1: write operations counters (write_cnt)
|
||||
+ cnt2: active state counters (activate_cnt)
|
||||
+ cnt3: idle state counters (idle_cnt)
|
||||
+ tcnt: time count, present for all sets (time_cnt)
|
||||
+
|
||||
+The stm32-ddr-pmu driver relies on the perf PMU framework to expose the
|
||||
+counters via sysfs:
|
||||
+ $ ls /sys/bus/event_source/devices/ddrperfm/events
|
||||
+ activate_cnt idle_cnt read_cnt time_cnt write_cnt
|
||||
+
|
||||
+
|
||||
+The perf PMU framework is usually invoked via the 'perf stat' tool.
|
||||
+
|
||||
+The DDRPERFM is a system monitor that cannot isolate the traffic coming from a
|
||||
+given thread or CPU, that is why stm32-ddr-pmu driver rejects any 'perf stat'
|
||||
+call that does not request a system-wide collection: the '-a, --all-cpus'
|
||||
+option is mandatory!
|
||||
+
|
||||
+Example:
|
||||
+ $ perf stat -e ddrperfm/read_cnt/,ddrperfm/time_cnt/ -a sleep 20
|
||||
+ Performance counter stats for 'system wide':
|
||||
+
|
||||
+ 342541560 ddrperfm/read_cnt/
|
||||
+ 10660011400 ddrperfm/time_cnt/
|
||||
+
|
||||
+ 20.021068551 seconds time elapsed
|
||||
+
|
||||
+
|
||||
+The driver also exposes a 'bandwidth' attribute that can be used to display
|
||||
+the read/write/total bandwidth achieved during the last 'perf stat' execution.
|
||||
+ $ 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
|
||||
--- a/drivers/perf/Kconfig
|
||||
+++ b/drivers/perf/Kconfig
|
||||
@@ -87,6 +87,12 @@ config QCOM_L3_PMU
|
||||
Adds the L3 cache PMU into the perf events subsystem for
|
||||
monitoring L3 cache events.
|
||||
|
||||
+config STM32_DDR_PMU
|
||||
+ bool "STM32 DDR PMU"
|
||||
+ depends on MACH_STM32MP157
|
||||
+ help
|
||||
+ Support for STM32 DDR performance monitor (DDRPERFM).
|
||||
+
|
||||
config XGENE_PMU
|
||||
depends on ARCH_XGENE
|
||||
bool "APM X-Gene SoC PMU"
|
||||
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
|
||||
index b3902bd..04f7f64 100644
|
||||
--- a/drivers/perf/Makefile
|
||||
+++ b/drivers/perf/Makefile
|
||||
@@ -7,5 +7,6 @@ obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.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_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
|
||||
--- /dev/null
|
||||
+++ b/drivers/perf/stm32_ddr_pmu.c
|
||||
@@ -0,0 +1,505 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * This file is the STM32 DDR performance monitor (DDRPERFM) driver
|
||||
+ *
|
||||
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
||||
+ * Author: Gerald Baeza <gerald.baeza@st.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/hrtimer.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/perf_event.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+#define POLL_MS 4000 /* The counter roll over after ~8s @533MHz */
|
||||
+#define WORD_LENGTH 4 /* Bytes */
|
||||
+#define BURST_LENGTH 8 /* Words */
|
||||
+
|
||||
+#define DDRPERFM_CTL 0x000
|
||||
+#define DDRPERFM_CFG 0x004
|
||||
+#define DDRPERFM_STATUS 0x008
|
||||
+#define DDRPERFM_CCR 0x00C
|
||||
+#define DDRPERFM_IER 0x010
|
||||
+#define DDRPERFM_ISR 0x014
|
||||
+#define DDRPERFM_ICR 0x018
|
||||
+#define DDRPERFM_TCNT 0x020
|
||||
+#define DDRPERFM_CNT(X) (0x030 + 8 * (X))
|
||||
+#define DDRPERFM_HWCFG 0x3F0
|
||||
+#define DDRPERFM_VER 0x3F4
|
||||
+#define DDRPERFM_ID 0x3F8
|
||||
+#define DDRPERFM_SID 0x3FC
|
||||
+
|
||||
+#define CTL_START 0x00000001
|
||||
+#define CTL_STOP 0x00000002
|
||||
+#define CCR_CLEAR_ALL 0x8000000F
|
||||
+#define SID_MAGIC_ID 0xA3C5DD01
|
||||
+
|
||||
+#define STRING "Read = %llu, Write = %llu, Read & Write = %llu (MB/s)\n"
|
||||
+
|
||||
+enum {
|
||||
+ READ_CNT,
|
||||
+ WRITE_CNT,
|
||||
+ ACTIVATE_CNT,
|
||||
+ IDLE_CNT,
|
||||
+ TIME_CNT,
|
||||
+ PMU_NR_COUNTERS
|
||||
+};
|
||||
+
|
||||
+struct stm32_ddr_pmu {
|
||||
+ struct pmu pmu;
|
||||
+ void __iomem *membase;
|
||||
+ struct clk *clk;
|
||||
+ struct clk *clk_ddr;
|
||||
+ unsigned long clk_ddr_rate;
|
||||
+ struct hrtimer hrtimer;
|
||||
+ ktime_t poll_period;
|
||||
+ spinlock_t lock; /* for shared registers access */
|
||||
+ struct perf_event *events[PMU_NR_COUNTERS];
|
||||
+ u64 events_cnt[PMU_NR_COUNTERS];
|
||||
+};
|
||||
+
|
||||
+static inline struct stm32_ddr_pmu *pmu_to_stm32_ddr_pmu(struct pmu *p)
|
||||
+{
|
||||
+ return container_of(p, struct stm32_ddr_pmu, pmu);
|
||||
+}
|
||||
+
|
||||
+static inline struct stm32_ddr_pmu *hrtimer_to_stm32_ddr_pmu(struct hrtimer *h)
|
||||
+{
|
||||
+ return container_of(h, struct stm32_ddr_pmu, hrtimer);
|
||||
+}
|
||||
+
|
||||
+static u64 stm32_ddr_pmu_compute_bw(struct stm32_ddr_pmu *stm32_ddr_pmu,
|
||||
+ int counter)
|
||||
+{
|
||||
+ u64 bw = stm32_ddr_pmu->events_cnt[counter], tmp;
|
||||
+ u64 div = stm32_ddr_pmu->events_cnt[TIME_CNT];
|
||||
+ u32 prediv = 1, premul = 1;
|
||||
+
|
||||
+ if (bw && div) {
|
||||
+ /* Maximize the dividend into 64 bits */
|
||||
+ while ((bw < 0x8000000000000000ULL) &&
|
||||
+ (premul < 0x40000000UL)) {
|
||||
+ bw = bw << 1;
|
||||
+ premul *= 2;
|
||||
+ }
|
||||
+ /* Minimize the dividor to fit in 32 bits */
|
||||
+ while ((div > 0xffffffffUL) && (prediv < 0x40000000UL)) {
|
||||
+ div = div >> 1;
|
||||
+ prediv *= 2;
|
||||
+ }
|
||||
+ /* Divide counter per time and multiply per DDR settings */
|
||||
+ do_div(bw, div);
|
||||
+ tmp = bw * BURST_LENGTH * WORD_LENGTH;
|
||||
+ tmp *= stm32_ddr_pmu->clk_ddr_rate;
|
||||
+ if (tmp < bw)
|
||||
+ goto error;
|
||||
+ bw = tmp;
|
||||
+ /* Cancel the prediv and premul factors */
|
||||
+ while (prediv > 1) {
|
||||
+ bw = bw >> 1;
|
||||
+ prediv /= 2;
|
||||
+ }
|
||||
+ while (premul > 1) {
|
||||
+ bw = bw >> 1;
|
||||
+ premul /= 2;
|
||||
+ }
|
||||
+ /* Convert MHz to Hz and B to MB, to finally get MB/s */
|
||||
+ tmp = bw * 1000000;
|
||||
+ if (tmp < bw)
|
||||
+ goto error;
|
||||
+ bw = tmp;
|
||||
+ premul = 1024 * 1024;
|
||||
+ while (premul > 1) {
|
||||
+ bw = bw >> 1;
|
||||
+ premul /= 2;
|
||||
+ }
|
||||
+ }
|
||||
+ return bw;
|
||||
+
|
||||
+error:
|
||||
+ pr_warn("stm32-ddr-pmu: overflow detected\n");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void stm32_ddr_pmu_event_configure(struct perf_event *event)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
|
||||
+ unsigned long lock_flags, config_base = event->hw.config_base;
|
||||
+ u32 val;
|
||||
+
|
||||
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags);
|
||||
+ writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL);
|
||||
+
|
||||
+ if (config_base < TIME_CNT) {
|
||||
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_CFG);
|
||||
+ val |= (1 << config_base);
|
||||
+ writel_relaxed(val, stm32_ddr_pmu->membase + DDRPERFM_CFG);
|
||||
+ }
|
||||
+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags);
|
||||
+}
|
||||
+
|
||||
+static void stm32_ddr_pmu_event_read(struct perf_event *event)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
|
||||
+ unsigned long flags, config_base = event->hw.config_base;
|
||||
+ struct hw_perf_event *hw = &event->hw;
|
||||
+ u64 prev_count, new_count, mask;
|
||||
+ u32 val, offset, bit;
|
||||
+
|
||||
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, flags);
|
||||
+
|
||||
+ writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL);
|
||||
+
|
||||
+ if (config_base == TIME_CNT) {
|
||||
+ offset = DDRPERFM_TCNT;
|
||||
+ bit = 1 << 31;
|
||||
+ } else {
|
||||
+ offset = DDRPERFM_CNT(config_base);
|
||||
+ bit = 1 << config_base;
|
||||
+ }
|
||||
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_STATUS);
|
||||
+ if (val & bit)
|
||||
+ pr_warn("stm32_ddr_pmu hardware overflow\n");
|
||||
+ val = readl_relaxed(stm32_ddr_pmu->membase + offset);
|
||||
+ writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR);
|
||||
+ writel_relaxed(CTL_START, stm32_ddr_pmu->membase + DDRPERFM_CTL);
|
||||
+
|
||||
+ do {
|
||||
+ prev_count = local64_read(&hw->prev_count);
|
||||
+ new_count = prev_count + val;
|
||||
+ } while (local64_xchg(&hw->prev_count, new_count) != prev_count);
|
||||
+
|
||||
+ mask = GENMASK_ULL(31, 0);
|
||||
+ local64_add(val & mask, &event->count);
|
||||
+
|
||||
+ if (new_count < prev_count)
|
||||
+ pr_warn("STM32 DDR PMU counter saturated\n");
|
||||
+
|
||||
+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, flags);
|
||||
+}
|
||||
+
|
||||
+static void stm32_ddr_pmu_event_start(struct perf_event *event, int flags)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
|
||||
+ struct hw_perf_event *hw = &event->hw;
|
||||
+ unsigned long lock_flags;
|
||||
+
|
||||
+ if (WARN_ON_ONCE(!(hw->state & PERF_HES_STOPPED)))
|
||||
+ return;
|
||||
+
|
||||
+ if (flags & PERF_EF_RELOAD)
|
||||
+ WARN_ON_ONCE(!(hw->state & PERF_HES_UPTODATE));
|
||||
+
|
||||
+ stm32_ddr_pmu_event_configure(event);
|
||||
+
|
||||
+ /* Clear all counters to synchronize them, then start */
|
||||
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags);
|
||||
+ writel_relaxed(CCR_CLEAR_ALL, stm32_ddr_pmu->membase + DDRPERFM_CCR);
|
||||
+ writel_relaxed(CTL_START, stm32_ddr_pmu->membase + DDRPERFM_CTL);
|
||||
+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags);
|
||||
+
|
||||
+ hw->state = 0;
|
||||
+}
|
||||
+
|
||||
+static void stm32_ddr_pmu_event_stop(struct perf_event *event, int flags)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
|
||||
+ unsigned long lock_flags, config_base = event->hw.config_base;
|
||||
+ struct hw_perf_event *hw = &event->hw;
|
||||
+ u32 val, bit;
|
||||
+
|
||||
+ if (WARN_ON_ONCE(hw->state & PERF_HES_STOPPED))
|
||||
+ return;
|
||||
+
|
||||
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags);
|
||||
+ writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL);
|
||||
+ if (config_base == TIME_CNT)
|
||||
+ bit = 1 << 31;
|
||||
+ else
|
||||
+ bit = 1 << config_base;
|
||||
+ writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR);
|
||||
+ if (config_base < TIME_CNT) {
|
||||
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_CFG);
|
||||
+ val &= ~bit;
|
||||
+ writel_relaxed(val, stm32_ddr_pmu->membase + DDRPERFM_CFG);
|
||||
+ }
|
||||
+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags);
|
||||
+
|
||||
+ hw->state |= PERF_HES_STOPPED;
|
||||
+
|
||||
+ if (flags & PERF_EF_UPDATE) {
|
||||
+ stm32_ddr_pmu_event_read(event);
|
||||
+ hw->state |= PERF_HES_UPTODATE;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int stm32_ddr_pmu_event_add(struct perf_event *event, int flags)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
|
||||
+ unsigned long config_base = event->hw.config_base;
|
||||
+ struct hw_perf_event *hw = &event->hw;
|
||||
+
|
||||
+ stm32_ddr_pmu->events_cnt[config_base] = 0;
|
||||
+ stm32_ddr_pmu->events[config_base] = event;
|
||||
+
|
||||
+ clk_enable(stm32_ddr_pmu->clk);
|
||||
+ hrtimer_start(&stm32_ddr_pmu->hrtimer, stm32_ddr_pmu->poll_period,
|
||||
+ HRTIMER_MODE_REL);
|
||||
+
|
||||
+ stm32_ddr_pmu_event_configure(event);
|
||||
+
|
||||
+ hw->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
|
||||
+
|
||||
+ if (flags & PERF_EF_START)
|
||||
+ stm32_ddr_pmu_event_start(event, 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void stm32_ddr_pmu_event_del(struct perf_event *event, int flags)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
|
||||
+ unsigned long config_base = event->hw.config_base;
|
||||
+ bool stop = true;
|
||||
+ int i;
|
||||
+
|
||||
+ stm32_ddr_pmu_event_stop(event, PERF_EF_UPDATE);
|
||||
+
|
||||
+ stm32_ddr_pmu->events_cnt[config_base] += local64_read(&event->count);
|
||||
+ stm32_ddr_pmu->events[config_base] = NULL;
|
||||
+
|
||||
+ for (i = 0; i < PMU_NR_COUNTERS; i++)
|
||||
+ if (stm32_ddr_pmu->events[i])
|
||||
+ stop = false;
|
||||
+ if (stop)
|
||||
+ hrtimer_cancel(&stm32_ddr_pmu->hrtimer);
|
||||
+
|
||||
+ clk_disable(stm32_ddr_pmu->clk);
|
||||
+}
|
||||
+
|
||||
+static int stm32_ddr_pmu_event_init(struct perf_event *event)
|
||||
+{
|
||||
+ struct hw_perf_event *hw = &event->hw;
|
||||
+
|
||||
+ if (event->attr.type != event->pmu->type)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ if (is_sampling_event(event))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (event->attach_state & PERF_ATTACH_TASK)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (event->attr.exclude_user ||
|
||||
+ event->attr.exclude_kernel ||
|
||||
+ event->attr.exclude_hv ||
|
||||
+ event->attr.exclude_idle ||
|
||||
+ event->attr.exclude_host ||
|
||||
+ event->attr.exclude_guest)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (event->cpu < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ hw->config_base = event->attr.config;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static enum hrtimer_restart stm32_ddr_pmu_poll(struct hrtimer *hrtimer)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu = hrtimer_to_stm32_ddr_pmu(hrtimer);
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < PMU_NR_COUNTERS; i++)
|
||||
+ if (stm32_ddr_pmu->events[i])
|
||||
+ stm32_ddr_pmu_event_read(stm32_ddr_pmu->events[i]);
|
||||
+
|
||||
+ hrtimer_forward_now(hrtimer, stm32_ddr_pmu->poll_period);
|
||||
+
|
||||
+ return HRTIMER_RESTART;
|
||||
+}
|
||||
+
|
||||
+static ssize_t stm32_ddr_pmu_sysfs_show(struct device *dev,
|
||||
+ struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct dev_ext_attribute *eattr;
|
||||
+
|
||||
+ eattr = container_of(attr, struct dev_ext_attribute, attr);
|
||||
+
|
||||
+ return sprintf(buf, "config=0x%lx\n", (unsigned long)eattr->var);
|
||||
+}
|
||||
+
|
||||
+static ssize_t bandwidth_show(struct device *dev,
|
||||
+ struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu = dev_get_drvdata(dev);
|
||||
+ u64 r_bw, w_bw;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (stm32_ddr_pmu->events_cnt[TIME_CNT]) {
|
||||
+ r_bw = stm32_ddr_pmu_compute_bw(stm32_ddr_pmu, READ_CNT);
|
||||
+ w_bw = stm32_ddr_pmu_compute_bw(stm32_ddr_pmu, WRITE_CNT);
|
||||
+
|
||||
+ ret = snprintf(buf, PAGE_SIZE, STRING,
|
||||
+ r_bw, w_bw, (r_bw + w_bw));
|
||||
+ } else {
|
||||
+ ret = snprintf(buf, PAGE_SIZE, "No data available\n");
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+#define STM32_DDR_PMU_ATTR(_name, _func, _config) \
|
||||
+ (&((struct dev_ext_attribute[]) { \
|
||||
+ { __ATTR(_name, 0444, _func, NULL), (void *)_config } \
|
||||
+ })[0].attr.attr)
|
||||
+
|
||||
+#define STM32_DDR_PMU_EVENT_ATTR(_name, _config) \
|
||||
+ STM32_DDR_PMU_ATTR(_name, stm32_ddr_pmu_sysfs_show, \
|
||||
+ (unsigned long)_config)
|
||||
+
|
||||
+static struct attribute *stm32_ddr_pmu_event_attrs[] = {
|
||||
+ STM32_DDR_PMU_EVENT_ATTR(read_cnt, READ_CNT),
|
||||
+ STM32_DDR_PMU_EVENT_ATTR(write_cnt, WRITE_CNT),
|
||||
+ STM32_DDR_PMU_EVENT_ATTR(activate_cnt, ACTIVATE_CNT),
|
||||
+ STM32_DDR_PMU_EVENT_ATTR(idle_cnt, IDLE_CNT),
|
||||
+ STM32_DDR_PMU_EVENT_ATTR(time_cnt, TIME_CNT),
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+static DEVICE_ATTR_RO(bandwidth);
|
||||
+static struct attribute *stm32_ddr_pmu_bandwidth_attrs[] = {
|
||||
+ &dev_attr_bandwidth.attr,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static struct attribute_group stm32_ddr_pmu_event_attrs_group = {
|
||||
+ .name = "events",
|
||||
+ .attrs = stm32_ddr_pmu_event_attrs,
|
||||
+};
|
||||
+
|
||||
+static struct attribute_group stm32_ddr_pmu_bandwidth_attrs_group = {
|
||||
+ .attrs = stm32_ddr_pmu_bandwidth_attrs,
|
||||
+};
|
||||
+
|
||||
+static const struct attribute_group *stm32_ddr_pmu_attr_groups[] = {
|
||||
+ &stm32_ddr_pmu_event_attrs_group,
|
||||
+ &stm32_ddr_pmu_bandwidth_attrs_group,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static int stm32_ddr_pmu_device_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu;
|
||||
+ struct resource *res;
|
||||
+ int i, ret;
|
||||
+ u32 val;
|
||||
+
|
||||
+ stm32_ddr_pmu = devm_kzalloc(&pdev->dev, sizeof(struct stm32_ddr_pmu),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!stm32_ddr_pmu)
|
||||
+ return -ENOMEM;
|
||||
+ platform_set_drvdata(pdev, stm32_ddr_pmu);
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ stm32_ddr_pmu->membase = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(stm32_ddr_pmu->membase)) {
|
||||
+ pr_warn("Unable to get STM32 DDR PMU membase\n");
|
||||
+ return PTR_ERR(stm32_ddr_pmu->membase);
|
||||
+ }
|
||||
+
|
||||
+ stm32_ddr_pmu->clk = devm_clk_get(&pdev->dev, "bus");
|
||||
+ if (IS_ERR(stm32_ddr_pmu->clk)) {
|
||||
+ pr_warn("Unable to get STM32 DDR PMU clock\n");
|
||||
+ return PTR_ERR(stm32_ddr_pmu->clk);
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(stm32_ddr_pmu->clk);
|
||||
+ if (ret) {
|
||||
+ pr_warn("Unable to prepare STM32 DDR PMU clock\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ stm32_ddr_pmu->clk_ddr = devm_clk_get(&pdev->dev, "ddr");
|
||||
+ if (IS_ERR(stm32_ddr_pmu->clk_ddr)) {
|
||||
+ pr_warn("Unable to get STM32 DDR clock\n");
|
||||
+ return PTR_ERR(stm32_ddr_pmu->clk_ddr);
|
||||
+ }
|
||||
+ stm32_ddr_pmu->clk_ddr_rate = clk_get_rate(stm32_ddr_pmu->clk_ddr);
|
||||
+ stm32_ddr_pmu->clk_ddr_rate /= 1000000;
|
||||
+
|
||||
+ stm32_ddr_pmu->poll_period = ms_to_ktime(POLL_MS);
|
||||
+ hrtimer_init(&stm32_ddr_pmu->hrtimer, CLOCK_MONOTONIC,
|
||||
+ HRTIMER_MODE_REL);
|
||||
+ stm32_ddr_pmu->hrtimer.function = stm32_ddr_pmu_poll;
|
||||
+ spin_lock_init(&stm32_ddr_pmu->lock);
|
||||
+
|
||||
+ for (i = 0; i < PMU_NR_COUNTERS; i++) {
|
||||
+ stm32_ddr_pmu->events[i] = NULL;
|
||||
+ stm32_ddr_pmu->events_cnt[i] = 0;
|
||||
+ }
|
||||
+
|
||||
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_SID);
|
||||
+ if (val != SID_MAGIC_ID)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ stm32_ddr_pmu->pmu = (struct pmu) {
|
||||
+ .task_ctx_nr = perf_invalid_context,
|
||||
+ .start = stm32_ddr_pmu_event_start,
|
||||
+ .stop = stm32_ddr_pmu_event_stop,
|
||||
+ .add = stm32_ddr_pmu_event_add,
|
||||
+ .del = stm32_ddr_pmu_event_del,
|
||||
+ .event_init = stm32_ddr_pmu_event_init,
|
||||
+ .attr_groups = stm32_ddr_pmu_attr_groups,
|
||||
+ };
|
||||
+ ret = perf_pmu_register(&stm32_ddr_pmu->pmu, "ddrperfm", -1);
|
||||
+ if (ret) {
|
||||
+ pr_warn("Unable to register STM32 DDR PMU\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ pr_info("stm32-ddr-pmu: probed (ID=0x%08x VER=0x%08x), DDR@%luMHz\n",
|
||||
+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_ID),
|
||||
+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_VER),
|
||||
+ stm32_ddr_pmu->clk_ddr_rate);
|
||||
+
|
||||
+ clk_disable(stm32_ddr_pmu->clk);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int stm32_ddr_pmu_device_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct stm32_ddr_pmu *stm32_ddr_pmu = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ perf_pmu_unregister(&stm32_ddr_pmu->pmu);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id stm32_ddr_pmu_of_match[] = {
|
||||
+ { .compatible = "st,stm32-ddr-pmu" },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver stm32_ddr_pmu_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "stm32-ddr-pmu",
|
||||
+ .of_match_table = of_match_ptr(stm32_ddr_pmu_of_match),
|
||||
+ },
|
||||
+ .probe = stm32_ddr_pmu_device_probe,
|
||||
+ .remove = stm32_ddr_pmu_device_remove,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(stm32_ddr_pmu_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Perf driver for STM32 DDR performance monitor");
|
||||
+MODULE_AUTHOR("Gerald Baeza <gerald.baeza@st.com>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
--
|
||||
2.7.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,276 @@
|
|||
From dbec0d5fe9520a172a3cba71781d9e19e659f43a Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:04 +0200
|
||||
Subject: [PATCH 21/30] ARM stm32mp1 r2 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
|
||||
|
||||
|
|
@ -0,0 +1,658 @@
|
|||
From 5b0a5e8f93e04129a2115dd5883ad5ca561c009a Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:05 +0200
|
||||
Subject: [PATCH 22/30] ARM stm32mp1 r2 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 113e884..a16f673 100644
|
||||
--- a/drivers/soc/Makefile
|
||||
+++ b/drivers/soc/Makefile
|
||||
@@ -18,6 +18,7 @@ obj-y += qcom/
|
||||
obj-y += renesas/
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
|
||||
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
|
||||
+obj-$(CONFIG_ARCH_STM32) += st/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-$(CONFIG_SOC_TI) += ti/
|
||||
diff --git a/drivers/soc/st/Kconfig b/drivers/soc/st/Kconfig
|
||||
new file mode 100644
|
||||
index 0000000..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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,86 +1,17 @@
|
|||
From 7a16fa25c3bd9a0c078b4d9d2ae445b975afaf69 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Mon, 26 Nov 2018 14:42:41 +0100
|
||||
Subject: [PATCH 24/52] ARM-stm32mp1-r0-rc2-THERMAL
|
||||
From acf08f1eb571f76ff42e343efa928f9b3c6112c5 Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:05 +0200
|
||||
Subject: [PATCH 24/30] ARM stm32mp1 r2 THERMAL
|
||||
|
||||
---
|
||||
.../devicetree/bindings/thermal/stm32-thermal.txt | 61 ++
|
||||
drivers/thermal/Kconfig | 2 +-
|
||||
drivers/thermal/Makefile | 2 +-
|
||||
drivers/thermal/st/Kconfig | 14 +
|
||||
drivers/thermal/st/Makefile | 1 +
|
||||
drivers/thermal/st/stm_thermal.c | 760 +++++++++++++++++++++
|
||||
6 files changed, 838 insertions(+), 2 deletions(-)
|
||||
create mode 100644 Documentation/devicetree/bindings/thermal/stm32-thermal.txt
|
||||
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/Documentation/devicetree/bindings/thermal/stm32-thermal.txt b/Documentation/devicetree/bindings/thermal/stm32-thermal.txt
|
||||
new file mode 100644
|
||||
index 0000000..8c0d5a4
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/thermal/stm32-thermal.txt
|
||||
@@ -0,0 +1,61 @@
|
||||
+Binding for Thermal Sensor for STMicroelectronics STM32 series of SoCs.
|
||||
+
|
||||
+On STM32 SoCs, the Digital Temperature Sensor (DTS) is in charge of managing an
|
||||
+analog block which delivers a frequency depending on the internal SoC's
|
||||
+temperature. By using a reference frequency, DTS is able to provide a sample
|
||||
+number which can be translated into a temperature by the user.
|
||||
+
|
||||
+DTS provides interrupt notification mechanism by threshold. This mechanism
|
||||
+offers two temperature trip points: passive and critical. The first is intended
|
||||
+for passive cooling notification while the second is used for over-temperature
|
||||
+reset.
|
||||
+
|
||||
+Required parameters:
|
||||
+-------------------
|
||||
+
|
||||
+compatible: Should be "st,stm32-thermal"
|
||||
+reg: This should be the physical base address and length of the
|
||||
+ sensor's registers.
|
||||
+clocks: Phandle of the clock used by the thermal sensor.
|
||||
+ See: Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
+clock-names: Should be "pclk" for register access clock and reference clock.
|
||||
+ See: Documentation/devicetree/bindings/resource-names.txt
|
||||
+#thermal-sensor-cells: Should be 0. See ./thermal.txt for a description.
|
||||
+interrupts: Standard way to define interrupt number.
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+ thermal-zones {
|
||||
+ cpu_thermal: cpu-thermal {
|
||||
+ polling-delay-passive = <0>;
|
||||
+ polling-delay = <0>;
|
||||
+
|
||||
+ thermal-sensors = <&thermal>;
|
||||
+
|
||||
+ trips {
|
||||
+ cpu_alert1: cpu-alert1 {
|
||||
+ temperature = <85000>;
|
||||
+ hysteresis = <0>;
|
||||
+ type = "passive";
|
||||
+ };
|
||||
+
|
||||
+ cpu-crit: cpu-crit {
|
||||
+ temperature = <120000>;
|
||||
+ hysteresis = <0>;
|
||||
+ type = "critical";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ cooling-maps {
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ thermal: thermal@50028000 {
|
||||
+ compatible = "st,stm32-thermal";
|
||||
+ reg = <0x50028000 0x100>;
|
||||
+ clocks = <&rcc TMPSENS>;
|
||||
+ clock-names = "pclk";
|
||||
+ #thermal-sensor-cells = <0>;
|
||||
+ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
|
||||
index 0e69edc..5422523 100644
|
||||
--- a/drivers/thermal/Kconfig
|
||||
|
|
@ -145,10 +76,10 @@ index b388789..b2b9e9b 100644
|
|||
\ No newline at end of file
|
||||
diff --git a/drivers/thermal/st/stm_thermal.c b/drivers/thermal/st/stm_thermal.c
|
||||
new file mode 100644
|
||||
index 0000000..bbd73c5
|
||||
index 0000000..8cafc37
|
||||
--- /dev/null
|
||||
+++ b/drivers/thermal/st/stm_thermal.c
|
||||
@@ -0,0 +1,760 @@
|
||||
@@ -0,0 +1,604 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||
|
|
@ -181,7 +112,7 @@ index 0000000..bbd73c5
|
|||
+#define DTS_DR_OFFSET 0x1C
|
||||
+#define DTS_SR_OFFSET 0x20
|
||||
+#define DTS_ITENR_OFFSET 0x24
|
||||
+#define DTS_CIFR_OFFSET 0x28
|
||||
+#define DTS_ICIFR_OFFSET 0x28
|
||||
+
|
||||
+/* DTS_CFGR1 register mask definitions */
|
||||
+#define HSREF_CLK_DIV_MASK GENMASK(30, 24)
|
||||
|
|
@ -202,10 +133,15 @@ index 0000000..bbd73c5
|
|||
+/* 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_SMP_TIME_POS 16
|
||||
+#define TS1_HITTHD_POS 16
|
||||
+#define TS1_LITTHD_POS 0
|
||||
+#define HSREF_CLK_DIV_POS 24
|
||||
+
|
||||
+/* DTS_CFGR1 bit definitions */
|
||||
|
|
@ -227,59 +163,69 @@ index 0000000..bbd73c5
|
|||
+#define ONE_MHZ 1000000
|
||||
+#define POLL_TIMEOUT 5000
|
||||
+#define STARTUP_TIME 40
|
||||
+#define TS1_T0_VAL0 30
|
||||
+#define TS1_T0_VAL1 130
|
||||
+#define TS1_T0_VAL0 30000 /* 30 celsius */
|
||||
+#define TS1_T0_VAL1 110000 /* 110 celsius */
|
||||
+#define NO_HW_TRIG 0
|
||||
+
|
||||
+/* The Thermal Framework expects millidegrees */
|
||||
+#define mcelsius(temp) ((temp) * 1000)
|
||||
+
|
||||
+/* The Sensor expects oC degrees */
|
||||
+#define celsius(temp) ((temp) / 1000)
|
||||
+#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 high_temp;
|
||||
+ int low_temp;
|
||||
+ int temp_critical;
|
||||
+ int temp_passive;
|
||||
+ unsigned int low_temp_enabled;
|
||||
+ int num_trips;
|
||||
+ int irq;
|
||||
+ unsigned int irq_enabled;
|
||||
+ void __iomem *base;
|
||||
+ int t0, fmt0, ramp_coeff;
|
||||
+ int low_en, high_en;
|
||||
+};
|
||||
+
|
||||
+static irqreturn_t stm_thermal_alarm_irq(int irq, void *sdata)
|
||||
+static void stm_thermal_disable_irq(struct stm_thermal_sensor *sensor)
|
||||
+{
|
||||
+ struct stm_thermal_sensor *sensor = sdata;
|
||||
+ u32 itenr;
|
||||
+
|
||||
+ disable_irq_nosync(irq);
|
||||
+ sensor->irq_enabled = false;
|
||||
+ /* Disable IT generation */
|
||||
+ itenr = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
|
||||
+ itenr &= ~ITENR_MASK;
|
||||
+ writel_relaxed(itenr, sensor->base + DTS_ITENR_OFFSET);
|
||||
+}
|
||||
+
|
||||
+ return IRQ_WAKE_THREAD;
|
||||
+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)
|
||||
+{
|
||||
+ u32 value;
|
||||
+ struct stm_thermal_sensor *sensor = sdata;
|
||||
+
|
||||
+ /* read IT reason in SR and clear flags */
|
||||
+ value = readl_relaxed(sensor->base + DTS_SR_OFFSET);
|
||||
+ dev_dbg(sensor->dev, "sr:%d\n",
|
||||
+ readl_relaxed(sensor->base + DTS_SR_OFFSET));
|
||||
+
|
||||
+ if ((value & LOW_THRESHOLD) == LOW_THRESHOLD)
|
||||
+ writel_relaxed(LOW_THRESHOLD, sensor->base + DTS_CIFR_OFFSET);
|
||||
+
|
||||
+ if ((value & HIGH_THRESHOLD) == HIGH_THRESHOLD)
|
||||
+ writel_relaxed(HIGH_THRESHOLD, sensor->base + DTS_CIFR_OFFSET);
|
||||
+ 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;
|
||||
+}
|
||||
+
|
||||
|
|
@ -311,6 +257,8 @@ index 0000000..bbd73c5
|
|||
+ writel_relaxed(value, sensor->base +
|
||||
+ DTS_CFGR1_OFFSET);
|
||||
+
|
||||
+ sensor->mode = THERMAL_DEVICE_ENABLED;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
|
|
@ -318,6 +266,8 @@ index 0000000..bbd73c5
|
|||
+{
|
||||
+ u32 value;
|
||||
+
|
||||
+ sensor->mode = THERMAL_DEVICE_DISABLED;
|
||||
+
|
||||
+ /* Stop measuring */
|
||||
+ value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
|
||||
+ value &= ~TS1_START;
|
||||
|
|
@ -347,12 +297,8 @@ index 0000000..bbd73c5
|
|||
+ if (!clk_freq)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ prescaler = 0;
|
||||
+ clk_freq /= ONE_MHZ;
|
||||
+ if (clk_freq) {
|
||||
+ while (prescaler <= clk_freq)
|
||||
+ prescaler++;
|
||||
+ }
|
||||
+ /* calculate divider for maximum 1MHz PCLK */
|
||||
+ prescaler = clk_freq / ONE_MHZ + 1;
|
||||
+
|
||||
+ value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
|
||||
+
|
||||
|
|
@ -360,7 +306,7 @@ index 0000000..bbd73c5
|
|||
+ value &= ~HSREF_CLK_DIV_MASK;
|
||||
+
|
||||
+ /* Set prescaler. pclk_freq/prescaler < 1MHz */
|
||||
+ value |= (prescaler << HSREF_CLK_DIV_POS);
|
||||
+ value |= (prescaler << HSREF_CLK_DIV_POS) & HSREF_CLK_DIV_MASK;
|
||||
+
|
||||
+ /* Select PCLK as reference clock */
|
||||
+ value &= ~REFCLK_SEL;
|
||||
|
|
@ -414,140 +360,17 @@ index 0000000..bbd73c5
|
|||
+ int temp, u32 *th)
|
||||
+{
|
||||
+ int freqM;
|
||||
+ u32 sampling_time;
|
||||
+
|
||||
+ /* Retrieve the number of periods to sample */
|
||||
+ sampling_time = (readl_relaxed(sensor->base + DTS_CFGR1_OFFSET) &
|
||||
+ TS1_SMP_TIME_MASK) >> TS1_SMP_TIME_POS;
|
||||
+
|
||||
+ /* Figure out the CLK_PTAT frequency for a given temperature */
|
||||
+ freqM = ((temp - sensor->t0) * sensor->ramp_coeff)
|
||||
+ + sensor->fmt0;
|
||||
+
|
||||
+ dev_dbg(sensor->dev, "%s: freqM for threshold = %d Hz",
|
||||
+ __func__, freqM);
|
||||
+ freqM = ((temp - sensor->t0) * sensor->ramp_coeff) / 1000 +
|
||||
+ sensor->fmt0;
|
||||
+
|
||||
+ /* Figure out the threshold sample number */
|
||||
+ *th = clk_get_rate(sensor->clk);
|
||||
+ *th = clk_get_rate(sensor->clk) * SAMPLING_TIME / freqM;
|
||||
+ if (!*th)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ *th = *th / freqM;
|
||||
+
|
||||
+ *th *= sampling_time;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int stm_thermal_set_threshold(struct stm_thermal_sensor *sensor)
|
||||
+{
|
||||
+ u32 value, th;
|
||||
+ int ret;
|
||||
+
|
||||
+ value = readl_relaxed(sensor->base + DTS_ITR1_OFFSET);
|
||||
+
|
||||
+ /* Erase threshold content */
|
||||
+ value &= ~(TS1_LITTHD_MASK | TS1_HITTHD_MASK);
|
||||
+
|
||||
+ /* Retrieve the sample threshold number th for a given temperature */
|
||||
+ ret = stm_thermal_calculate_threshold(sensor, sensor->high_temp, &th);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ value |= th & TS1_LITTHD_MASK;
|
||||
+
|
||||
+ if (sensor->low_temp_enabled) {
|
||||
+ /* Retrieve the sample threshold */
|
||||
+ ret = stm_thermal_calculate_threshold(sensor, sensor->low_temp,
|
||||
+ &th);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ value |= (TS1_HITTHD_MASK & (th << TS1_HITTHD_POS));
|
||||
+ }
|
||||
+
|
||||
+ /* Write value on the Low interrupt threshold */
|
||||
+ writel_relaxed(value, sensor->base + DTS_ITR1_OFFSET);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Disable temperature interrupt */
|
||||
+static int stm_disable_irq(struct stm_thermal_sensor *sensor)
|
||||
+{
|
||||
+ u32 value;
|
||||
+
|
||||
+ /* Disable IT generation for low and high thresholds */
|
||||
+ value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
|
||||
+ writel_relaxed(value & ~(LOW_THRESHOLD | HIGH_THRESHOLD),
|
||||
+ sensor->base + DTS_ITENR_OFFSET);
|
||||
+
|
||||
+ dev_dbg(sensor->dev, "%s: IT disabled on sensor side", __func__);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Enable temperature interrupt */
|
||||
+static int stm_enable_irq(struct stm_thermal_sensor *sensor)
|
||||
+{
|
||||
+ u32 value;
|
||||
+
|
||||
+ /*
|
||||
+ * Code below enables High temperature threshold using a low threshold
|
||||
+ * sampling value
|
||||
+ */
|
||||
+
|
||||
+ /* Make sure LOW_THRESHOLD IT is clear before enabling */
|
||||
+ writel_relaxed(LOW_THRESHOLD, sensor->base + DTS_CIFR_OFFSET);
|
||||
+
|
||||
+ /* Enable IT generation for low threshold */
|
||||
+ value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
|
||||
+ value |= LOW_THRESHOLD;
|
||||
+
|
||||
+ /* Enable the low temperature threshold if needed */
|
||||
+ if (sensor->low_temp_enabled) {
|
||||
+ /* Make sure HIGH_THRESHOLD IT is clear before enabling */
|
||||
+ writel_relaxed(HIGH_THRESHOLD, sensor->base + DTS_CIFR_OFFSET);
|
||||
+
|
||||
+ /* Enable IT generation for high threshold */
|
||||
+ value |= HIGH_THRESHOLD;
|
||||
+ }
|
||||
+
|
||||
+ /* Enable thresholds */
|
||||
+ writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET);
|
||||
+
|
||||
+ dev_dbg(sensor->dev, "%s: IT enabled on sensor side", __func__);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int stm_thermal_update_threshold(struct stm_thermal_sensor *sensor)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ sensor->mode = THERMAL_DEVICE_DISABLED;
|
||||
+
|
||||
+ ret = stm_sensor_power_off(sensor);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = stm_disable_irq(sensor);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = stm_thermal_set_threshold(sensor);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = stm_enable_irq(sensor);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = stm_sensor_power_on(sensor);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ sensor->mode = THERMAL_DEVICE_ENABLED;
|
||||
+ dev_dbg(sensor->dev, "freqM=%d Hz, threshold=0x%x", freqM, *th);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
|
|
@ -556,77 +379,76 @@ index 0000000..bbd73c5
|
|||
+static int stm_thermal_get_temp(void *data, int *temp)
|
||||
+{
|
||||
+ struct stm_thermal_sensor *sensor = data;
|
||||
+ u32 sampling_time;
|
||||
+ u32 periods;
|
||||
+ int freqM, ret;
|
||||
+
|
||||
+ if (sensor->mode != THERMAL_DEVICE_ENABLED)
|
||||
+ return -EAGAIN;
|
||||
+
|
||||
+ /* Retrieve the number of samples */
|
||||
+ ret = readl_poll_timeout(sensor->base + DTS_DR_OFFSET, freqM,
|
||||
+ (freqM & TS1_MFREQ_MASK), STARTUP_TIME,
|
||||
+ POLL_TIMEOUT);
|
||||
+
|
||||
+ /* 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;
|
||||
+
|
||||
+ if (!freqM)
|
||||
+ return -ENODATA;
|
||||
+
|
||||
+ /* Retrieve the number of periods sampled */
|
||||
+ sampling_time = (readl_relaxed(sensor->base + DTS_CFGR1_OFFSET) &
|
||||
+ TS1_SMP_TIME_MASK) >> TS1_SMP_TIME_POS;
|
||||
+
|
||||
+ /* Figure out the number of samples per period */
|
||||
+ freqM /= sampling_time;
|
||||
+
|
||||
+ /* Figure out the CLK_PTAT frequency */
|
||||
+ freqM = clk_get_rate(sensor->clk) / freqM;
|
||||
+ freqM = (clk_get_rate(sensor->clk) * SAMPLING_TIME) / periods;
|
||||
+ if (!freqM)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ dev_dbg(sensor->dev, "%s: freqM=%d\n", __func__, freqM);
|
||||
+
|
||||
+ /* Figure out the temperature in mili celsius */
|
||||
+ *temp = mcelsius(sensor->t0 + ((freqM - sensor->fmt0) /
|
||||
+ sensor->ramp_coeff));
|
||||
+ *temp = (freqM - sensor->fmt0) * 1000 / sensor->ramp_coeff + sensor->t0;
|
||||
+
|
||||
+ dev_dbg(sensor->dev, "%s: temperature = %d millicelsius",
|
||||
+ __func__, *temp);
|
||||
+ dev_dbg(sensor->dev, "periods=0x%x t=%d mC", periods, *temp);
|
||||
+
|
||||
+ /* Update thresholds */
|
||||
+ if (sensor->num_trips > 1) {
|
||||
+ /* Update alarm threshold value to next higher trip point */
|
||||
+ if (sensor->high_temp == sensor->temp_passive &&
|
||||
+ celsius(*temp) >= sensor->temp_passive) {
|
||||
+ sensor->high_temp = sensor->temp_critical;
|
||||
+ sensor->low_temp = sensor->temp_passive;
|
||||
+ sensor->low_temp_enabled = true;
|
||||
+ ret = stm_thermal_update_threshold(sensor);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+ if (sensor->high_temp == sensor->temp_critical &&
|
||||
+ celsius(*temp) < sensor->temp_passive) {
|
||||
+ sensor->high_temp = sensor->temp_passive;
|
||||
+ sensor->low_temp_enabled = false;
|
||||
+ ret = stm_thermal_update_threshold(sensor);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+static int stm_thermal_set_trips(void *data, int low, int high)
|
||||
+{
|
||||
+ struct stm_thermal_sensor *sensor = data;
|
||||
+ u32 itr1, th;
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * Re-enable alarm IRQ if temperature below critical
|
||||
+ * temperature
|
||||
+ */
|
||||
+ if (!sensor->irq_enabled &&
|
||||
+ (celsius(*temp) < sensor->temp_critical)) {
|
||||
+ sensor->irq_enabled = true;
|
||||
+ enable_irq(sensor->irq);
|
||||
+ }
|
||||
+ 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;
|
||||
+}
|
||||
+
|
||||
|
|
@ -644,8 +466,7 @@ index 0000000..bbd73c5
|
|||
+ }
|
||||
+
|
||||
+ ret = devm_request_threaded_irq(dev, sensor->irq,
|
||||
+ stm_thermal_alarm_irq,
|
||||
+ stm_thermal_alarm_irq_thread,
|
||||
+ NULL, stm_thermal_alarm_irq_thread,
|
||||
+ IRQF_ONESHOT,
|
||||
+ dev->driver->name, sensor);
|
||||
+ if (ret) {
|
||||
|
|
@ -654,8 +475,6 @@ index 0000000..bbd73c5
|
|||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ sensor->irq_enabled = true;
|
||||
+
|
||||
+ dev_dbg(dev, "%s: thermal IRQ registered", __func__);
|
||||
+
|
||||
+ return 0;
|
||||
|
|
@ -665,6 +484,8 @@ index 0000000..bbd73c5
|
|||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ stm_thermal_disable_irq(sensor);
|
||||
+
|
||||
+ ret = stm_sensor_power_off(sensor);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
|
@ -677,7 +498,6 @@ index 0000000..bbd73c5
|
|||
+static int stm_thermal_prepare(struct stm_thermal_sensor *sensor)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct device *dev = sensor->dev;
|
||||
+
|
||||
+ ret = clk_prepare_enable(sensor->clk);
|
||||
+ if (ret)
|
||||
|
|
@ -691,26 +511,8 @@ index 0000000..bbd73c5
|
|||
+ if (ret)
|
||||
+ goto thermal_unprepare;
|
||||
+
|
||||
+ /* Set threshold(s) for IRQ */
|
||||
+ ret = stm_thermal_set_threshold(sensor);
|
||||
+ if (ret)
|
||||
+ goto thermal_unprepare;
|
||||
+
|
||||
+ ret = stm_enable_irq(sensor);
|
||||
+ if (ret)
|
||||
+ goto thermal_unprepare;
|
||||
+
|
||||
+ ret = stm_sensor_power_on(sensor);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "%s: failed to power on sensor\n", __func__);
|
||||
+ goto irq_disable;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+irq_disable:
|
||||
+ stm_disable_irq(sensor);
|
||||
+
|
||||
+thermal_unprepare:
|
||||
+ clk_disable_unprepare(sensor->clk);
|
||||
+
|
||||
|
|
@ -728,8 +530,6 @@ index 0000000..bbd73c5
|
|||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ sensor->mode = THERMAL_DEVICE_DISABLED;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
|
|
@ -743,7 +543,12 @@ index 0000000..bbd73c5
|
|||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ sensor->mode = THERMAL_DEVICE_ENABLED;
|
||||
+ 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;
|
||||
+}
|
||||
|
|
@ -753,6 +558,7 @@ index 0000000..bbd73c5
|
|||
+
|
||||
+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[] = {
|
||||
|
|
@ -765,9 +571,8 @@ index 0000000..bbd73c5
|
|||
+{
|
||||
+ struct stm_thermal_sensor *sensor;
|
||||
+ struct resource *res;
|
||||
+ const struct thermal_trip *trip;
|
||||
+ void __iomem *base;
|
||||
+ int ret, i;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!pdev->dev.of_node) {
|
||||
+ dev_err(&pdev->dev, "%s: device tree node not found\n",
|
||||
|
|
@ -798,10 +603,23 @@ index 0000000..bbd73c5
|
|||
+ return PTR_ERR(sensor->clk);
|
||||
+ }
|
||||
+
|
||||
+ /* Register IRQ into GIC */
|
||||
+ ret = stm_register_irq(sensor);
|
||||
+ if (ret)
|
||||
+ 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,
|
||||
|
|
@ -814,53 +632,12 @@ index 0000000..bbd73c5
|
|||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (!sensor->th_dev->ops->get_crit_temp) {
|
||||
+ /* Critical point must be provided */
|
||||
+ ret = -EINVAL;
|
||||
+ /* Register IRQ into GIC */
|
||||
+ ret = stm_register_irq(sensor);
|
||||
+ if (ret)
|
||||
+ goto err_tz;
|
||||
+ }
|
||||
+
|
||||
+ ret = sensor->th_dev->ops->get_crit_temp(sensor->th_dev,
|
||||
+ &sensor->temp_critical);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "Not able to read critical_temp: %d\n", ret);
|
||||
+ goto err_tz;
|
||||
+ }
|
||||
+
|
||||
+ sensor->temp_critical = celsius(sensor->temp_critical);
|
||||
+
|
||||
+ /* Set thresholds for IRQ */
|
||||
+ sensor->high_temp = sensor->temp_critical;
|
||||
+
|
||||
+ trip = of_thermal_get_trip_points(sensor->th_dev);
|
||||
+ sensor->num_trips = of_thermal_get_ntrips(sensor->th_dev);
|
||||
+
|
||||
+ /* Find out passive temperature if it exists */
|
||||
+ for (i = (sensor->num_trips - 1); i >= 0; i--) {
|
||||
+ if (trip[i].type == THERMAL_TRIP_PASSIVE) {
|
||||
+ sensor->temp_passive = celsius(trip[i].temperature);
|
||||
+ /* Update high temperature threshold */
|
||||
+ sensor->high_temp = sensor->temp_passive;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Ensure low_temp_enabled flag is disabled.
|
||||
+ * By disabling low_temp_enabled, low threshold IT will not be
|
||||
+ * configured neither enabled because it is not needed as high
|
||||
+ * threshold is set on the lowest temperature trip point after
|
||||
+ * probe.
|
||||
+ */
|
||||
+ sensor->low_temp_enabled = false;
|
||||
+
|
||||
+ /* Configure and enable HW sensor */
|
||||
+ ret = stm_thermal_prepare(sensor);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "Not able to enable sensor: %d\n", ret);
|
||||
+ goto err_tz;
|
||||
+ }
|
||||
+ stm_thermal_set_irq_state(sensor);
|
||||
+
|
||||
+ /*
|
||||
+ * Thermal_zone doesn't enable hwmon as default,
|
||||
|
|
@ -871,8 +648,6 @@ index 0000000..bbd73c5
|
|||
+ if (ret)
|
||||
+ goto err_tz;
|
||||
+
|
||||
+ sensor->mode = THERMAL_DEVICE_ENABLED;
|
||||
+
|
||||
+ dev_info(&pdev->dev, "%s: Driver initialized successfully\n",
|
||||
+ __func__);
|
||||
+
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,13 +1,14 @@
|
|||
From 0d162ed61018cda930bb77680ab88b63633d5ce0 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:29:27 +0100
|
||||
Subject: [PATCH 14/52] ARM: stm32mp1-r0-rc1: WATCHDOG
|
||||
From cbd843990c118aaf21b72565d68b852bea8cae1b Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:06 +0200
|
||||
Subject: [PATCH 26/30] ARM stm32mp1 r2 WATCHDOG
|
||||
|
||||
---
|
||||
drivers/watchdog/Kconfig | 12 ++++
|
||||
drivers/watchdog/Makefile | 1 +
|
||||
drivers/watchdog/stm32_iwdg.c | 65 +++++++++++--------
|
||||
drivers/watchdog/stpmic1_wdt.c | 139 +++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 152 insertions(+)
|
||||
4 files changed, 192 insertions(+), 25 deletions(-)
|
||||
create mode 100644 drivers/watchdog/stpmic1_wdt.c
|
||||
|
||||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
|
||||
|
|
@ -42,6 +43,148 @@ index bf92e7b..2649cf3 100644
|
|||
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..2208e8c 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);
|
||||
diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c
|
||||
new file mode 100644
|
||||
index 0000000..a6cbc27
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,253 @@
|
|||
From a3c9e0d977420d451f6e13873a4a0921d8a9b88f Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:07 +0200
|
||||
Subject: [PATCH 28/30] ARM stm32mp1 r2 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 f6fcb8a..88849c1 100644
|
||||
--- a/arch/arm/Kconfig.debug
|
||||
+++ b/arch/arm/Kconfig.debug
|
||||
@@ -1184,6 +1184,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
|
||||
@@ -1468,6 +1504,10 @@ config DEBUG_STI_UART
|
||||
bool
|
||||
depends on ARCH_STI
|
||||
|
||||
+config DEBUG_STM32_UART
|
||||
+ bool
|
||||
+ depends on ARCH_STM32
|
||||
+
|
||||
config DEBUG_SIRFSOC_UART
|
||||
bool
|
||||
depends on ARCH_SIRF
|
||||
@@ -1517,6 +1557,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
|
||||
@@ -1580,6 +1621,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
|
||||
@@ -1673,10 +1716,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
|
||||
@@ -1788,7 +1833,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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,12 +1,13 @@
|
|||
From ae7d85a994c77d68e3e6a20a24160a5010ba42cc Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:32:03 +0100
|
||||
Subject: [PATCH 17/52] ARM: stm32mp1-r0-rc1: DEFCONFIG
|
||||
From 8352ebfd1953c5dc6514c0be878f7c8a47e33fa7 Mon Sep 17 00:00:00 2001
|
||||
From: Lionel VITTE <lionel.vitte@st.com>
|
||||
Date: Thu, 11 Jul 2019 14:12:10 +0200
|
||||
Subject: [PATCH 30/30] ARM stm32mp1 r2 DEFCONFIG
|
||||
|
||||
---
|
||||
.../arm/configs/fragment-01-multiv7_cleanup.config | 69 +++
|
||||
arch/arm/configs/fragment-02-multiv7_addons.config | 462 +++++++++++++++++++++
|
||||
2 files changed, 531 insertions(+)
|
||||
arch/arm/configs/fragment-02-multiv7_addons.config | 509 +++++++++++++++++++++
|
||||
arch/arm/configs/multi_v7_defconfig | 1 +
|
||||
3 files changed, 579 insertions(+)
|
||||
create mode 100644 arch/arm/configs/fragment-01-multiv7_cleanup.config
|
||||
create mode 100644 arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
|
||||
|
|
@ -87,15 +88,16 @@ index 0000000..22f6ffb
|
|||
+
|
||||
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
new file mode 100644
|
||||
index 0000000..c91840c
|
||||
index 0000000..7ba8387
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
@@ -0,0 +1,462 @@
|
||||
@@ -0,0 +1,509 @@
|
||||
+#
|
||||
+# General setup
|
||||
+#
|
||||
+CONFIG_POSIX_MQUEUE=y
|
||||
+CONFIG_USELIB=y
|
||||
+CONFIG_FUTEX=y
|
||||
+
|
||||
+#
|
||||
+# RCU Subsystem
|
||||
|
|
@ -147,7 +149,6 @@ index 0000000..c91840c
|
|||
+CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||
+CONFIG_ZBOOT_ROM_BSS=0x0
|
||||
+# CONFIG_KEXEC is not set
|
||||
+# CONFIG_EFI is not set
|
||||
+
|
||||
+#
|
||||
+# CPU Power Management
|
||||
|
|
@ -190,7 +191,10 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# Bluetooth device drivers
|
||||
+#
|
||||
+
|
||||
+CONFIG_BT_RTL=m
|
||||
+CONFIG_BT_HCIBTUSB=m
|
||||
+CONFIG_BT_HCIBTUSB=m
|
||||
+CONFIG_BT_HCIBTUSB_RTL=y
|
||||
+#
|
||||
+# Device Drivers
|
||||
+#
|
||||
|
|
@ -212,9 +216,6 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# LPDDR & LPDDR2 PCM memory drivers
|
||||
+#
|
||||
+CONFIG_OF_RESOLVE=y
|
||||
+CONFIG_OF_OVERLAY=y
|
||||
+CONFIG_OF_CONFIGFS=y
|
||||
+
|
||||
+#
|
||||
+# Misc devices
|
||||
|
|
@ -229,8 +230,12 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# MII PHY device drivers
|
||||
+#
|
||||
+# CONFIG_REALTEK_PHY is not set
|
||||
+
|
||||
+CONFIG_RTL_CARDS=m
|
||||
+CONFIG_RTL8192CU=m
|
||||
+CONFIG_RTLWIFI=m
|
||||
+CONFIG_RTLWIFI_USB=m
|
||||
+CONFIG_RTLWIFI_DEBUG=y
|
||||
+CONFIG_RTL8192C_COMMON=m
|
||||
+#
|
||||
+# Input Device Drivers
|
||||
+#
|
||||
|
|
@ -246,6 +251,12 @@ index 0000000..c91840c
|
|||
+# 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
|
||||
|
|
@ -272,6 +283,7 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# SPI Master Controller Drivers
|
||||
+#
|
||||
+CONFIG_SPI_STM32=y
|
||||
+CONFIG_SPI_STM32_QSPI=y
|
||||
+
|
||||
+#
|
||||
|
|
@ -307,7 +319,7 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# Watchdog Device Drivers
|
||||
+#
|
||||
+
|
||||
+CONFIG_WATCHDOG_NOWAYOUT=y
|
||||
+
|
||||
+#
|
||||
+# Sonics Silicon Backplane
|
||||
|
|
@ -330,6 +342,7 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# USB HDMI CEC adapters
|
||||
+#
|
||||
+CONFIG_VIDEO_STM32_HDMI_CEC=m
|
||||
+
|
||||
+#
|
||||
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
|
||||
|
|
@ -339,6 +352,7 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# Camera sensor devices
|
||||
+#
|
||||
+CONFIG_VIDEO_OV5640=y
|
||||
+
|
||||
+#
|
||||
+# Graphics support
|
||||
|
|
@ -354,10 +368,14 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# Display Panels
|
||||
+#
|
||||
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A=y
|
||||
+CONFIG_DRM_PANEL_RAYDIUM_RM68200=y
|
||||
+
|
||||
+#
|
||||
+# Display Interface Bridges
|
||||
+#
|
||||
+CONFIG_VIDEO_ADV7511=y
|
||||
+CONFIG_DRM_SII902X=y
|
||||
+
|
||||
+#
|
||||
+# Frame buffer hardware drivers
|
||||
|
|
@ -366,15 +384,34 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# Console display driver support
|
||||
+#
|
||||
+CONFIG_DRM_STM=y
|
||||
+CONFIG_DRM_STM_DSI=y
|
||||
+
|
||||
+#
|
||||
+# Backlight support
|
||||
+#
|
||||
+CONFIG_BACKLIGHT_GPIO=y
|
||||
+
|
||||
+#
|
||||
+# HD-Audio
|
||||
+#
|
||||
+CONFIG_SOUND=y
|
||||
+CONFIG_SND=y
|
||||
+CONFIG_SND_SOC=y
|
||||
+CONFIG_SND_SOC_STM32_SAI=y
|
||||
+CONFIG_SND_SOC_STM32_I2S=y
|
||||
+CONFIG_SND_SOC_STM32_SPDIFRX=y
|
||||
+CONFIG_SND_SOC_STM32_DFSDM=y
|
||||
+CONFIG_SND_AUDIO_GRAPH_CARD=y
|
||||
+
|
||||
+#
|
||||
+# CODEC drivers
|
||||
+#
|
||||
+
|
||||
+CONFIG_MFD_WM8994=y
|
||||
+CONFIG_SND_SOC_WM8994=y
|
||||
+CONFIG_SND_SOC_DMIC=y
|
||||
+CONFIG_SND_SOC_CS42L42=y
|
||||
+CONFIG_SND_SOC_CS42L51_I2C=y
|
||||
+
|
||||
+#
|
||||
+# USB Device Class drivers
|
||||
|
|
@ -393,10 +430,13 @@ index 0000000..c91840c
|
|||
+#
|
||||
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
|
||||
+#
|
||||
+CONFIG_USB_CONFIGFS=y
|
||||
+
|
||||
+#
|
||||
+# USB Physical Layer drivers
|
||||
+#
|
||||
+CONFIG_TYPEC=y
|
||||
+CONFIG_TYPEC_STUSB=y
|
||||
+
|
||||
+#
|
||||
+# Platform Support
|
||||
|
|
@ -418,6 +458,8 @@ index 0000000..c91840c
|
|||
+# File systems
|
||||
+#
|
||||
+CONFIG_OVERLAY_FS=y
|
||||
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||
+CONFIG_JFFS2_FS=y
|
||||
+
|
||||
+#
|
||||
+# Pseudo filesystems
|
||||
|
|
@ -553,6 +595,24 @@ index 0000000..c91840c
|
|||
+# STM32 DAC
|
||||
+#
|
||||
+CONFIG_STM32_DAC=y
|
||||
+
|
||||
+#
|
||||
+# STM32 HSEM
|
||||
+#
|
||||
+CONFIG_HWSPINLOCK=y
|
||||
+CONFIG_HWSPINLOCK_STM32=y
|
||||
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
|
||||
index fc33444..ac1e50b 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
|
||||
CONFIG_TWL4030_USB=m
|
||||
+CONFIG_STM32_DDR_PMU=y
|
||||
CONFIG_NVMEM_IMX_OCOTP=y
|
||||
CONFIG_NVMEM_SUNXI_SID=y
|
||||
CONFIG_NVMEM_VF610_OCOTP=y
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
From 07a8a17983431bcc47ef52be1370f156e56119ce Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:14:29 +0100
|
||||
Subject: [PATCH 01/52] ARM: stm32mp1-r0-rc1: MACHINE
|
||||
|
||||
---
|
||||
arch/arm/mach-stm32/Kconfig | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
|
||||
index 713c068..651bdf4 100644
|
||||
--- a/arch/arm/mach-stm32/Kconfig
|
||||
+++ b/arch/arm/mach-stm32/Kconfig
|
||||
@@ -4,6 +4,7 @@ menuconfig ARCH_STM32
|
||||
select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
|
||||
select ARM_GIC if ARCH_MULTI_V7
|
||||
select ARM_PSCI if ARCH_MULTI_V7
|
||||
+ select ARM_AMBA
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
||||
select CLKSRC_STM32
|
||||
select PINCTRL
|
||||
@@ -18,22 +19,18 @@ if ARM_SINGLE_ARMV7M
|
||||
|
||||
config MACH_STM32F429
|
||||
bool "STMicroelectronics STM32F429"
|
||||
- select ARM_AMBA
|
||||
default y
|
||||
|
||||
config MACH_STM32F469
|
||||
bool "STMicroelectronics STM32F469"
|
||||
- select ARM_AMBA
|
||||
default y
|
||||
|
||||
config MACH_STM32F746
|
||||
bool "STMicroelectronics STM32F746"
|
||||
- select ARM_AMBA
|
||||
default y
|
||||
|
||||
config MACH_STM32F769
|
||||
bool "STMicroelectronics STM32F769"
|
||||
- select ARM_AMBA
|
||||
default y
|
||||
|
||||
config MACH_STM32H743
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
From 358a1325502b2362a6fb74af3027f3f165684375 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:19:47 +0100
|
||||
Subject: [PATCH 06/52] ARM: stm32mp1-r0-rc1: IRQ Mailbox
|
||||
|
||||
---
|
||||
drivers/irqchip/irq-stm32-exti.c | 23 ++++++++++++++++++-----
|
||||
drivers/mailbox/mailbox-test.c | 26 ++++++++++++++------------
|
||||
drivers/mailbox/stm32-ipcc.c | 4 ++--
|
||||
3 files changed, 34 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
|
||||
index 0a2088e..e185ed8 100644
|
||||
--- a/drivers/irqchip/irq-stm32-exti.c
|
||||
+++ b/drivers/irqchip/irq-stm32-exti.c
|
||||
@@ -650,11 +650,6 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||
*/
|
||||
writel_relaxed(0, base + stm32_bank->imr_ofst);
|
||||
writel_relaxed(0, base + stm32_bank->emr_ofst);
|
||||
- writel_relaxed(0, base + stm32_bank->rtsr_ofst);
|
||||
- writel_relaxed(0, base + stm32_bank->ftsr_ofst);
|
||||
- writel_relaxed(~0UL, base + stm32_bank->rpr_ofst);
|
||||
- if (stm32_bank->fpr_ofst != UNDEF_REG)
|
||||
- writel_relaxed(~0UL, base + stm32_bank->fpr_ofst);
|
||||
|
||||
pr_info("%s: bank%d, External IRQs available:%#x\n",
|
||||
node->full_name, bank_idx, irqs_mask);
|
||||
@@ -735,9 +730,27 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int stm32_exti_h_translate(struct irq_domain *d,
|
||||
+ struct irq_fwspec *fwspec,
|
||||
+ unsigned long *out_hwirq,
|
||||
+ unsigned int *out_type)
|
||||
+{
|
||||
+ if (is_of_node(fwspec->fwnode)) {
|
||||
+ if (fwspec->param_count != 2)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ *out_hwirq = fwspec->param[0];
|
||||
+ *out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
static const struct irq_domain_ops stm32_exti_h_domain_ops = {
|
||||
.alloc = stm32_exti_h_domain_alloc,
|
||||
.free = irq_domain_free_irqs_common,
|
||||
+ .translate = stm32_exti_h_translate,
|
||||
};
|
||||
|
||||
static int
|
||||
diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c
|
||||
index 58bfafc..4e4ac4b 100644
|
||||
--- a/drivers/mailbox/mailbox-test.c
|
||||
+++ b/drivers/mailbox/mailbox-test.c
|
||||
@@ -31,7 +31,6 @@
|
||||
(MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
|
||||
|
||||
static bool mbox_data_ready;
|
||||
-static struct dentry *root_debugfs_dir;
|
||||
|
||||
struct mbox_test_device {
|
||||
struct device *dev;
|
||||
@@ -45,6 +44,7 @@ struct mbox_test_device {
|
||||
spinlock_t lock;
|
||||
wait_queue_head_t waitq;
|
||||
struct fasync_struct *async_queue;
|
||||
+ struct dentry *root_debugfs_dir;
|
||||
};
|
||||
|
||||
static ssize_t mbox_test_signal_write(struct file *filp,
|
||||
@@ -262,16 +262,16 @@ static int mbox_test_add_debugfs(struct platform_device *pdev,
|
||||
if (!debugfs_initialized())
|
||||
return 0;
|
||||
|
||||
- root_debugfs_dir = debugfs_create_dir("mailbox", NULL);
|
||||
- if (!root_debugfs_dir) {
|
||||
+ tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL);
|
||||
+ if (!tdev->root_debugfs_dir) {
|
||||
dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- debugfs_create_file("message", 0600, root_debugfs_dir,
|
||||
+ debugfs_create_file("message", 0600, tdev->root_debugfs_dir,
|
||||
tdev, &mbox_test_message_ops);
|
||||
|
||||
- debugfs_create_file("signal", 0200, root_debugfs_dir,
|
||||
+ debugfs_create_file("signal", 0200, tdev->root_debugfs_dir,
|
||||
tdev, &mbox_test_signal_ops);
|
||||
|
||||
return 0;
|
||||
@@ -363,22 +363,24 @@ static int mbox_test_probe(struct platform_device *pdev)
|
||||
|
||||
/* It's okay for MMIO to be NULL */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- size = resource_size(res);
|
||||
tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res);
|
||||
- if (PTR_ERR(tdev->tx_mmio) == -EBUSY)
|
||||
+ if (PTR_ERR(tdev->tx_mmio) == -EBUSY) {
|
||||
/* if reserved area in SRAM, try just ioremap */
|
||||
+ size = resource_size(res);
|
||||
tdev->tx_mmio = devm_ioremap(&pdev->dev, res->start, size);
|
||||
- else if (IS_ERR(tdev->tx_mmio))
|
||||
+ } else if (IS_ERR(tdev->tx_mmio)) {
|
||||
tdev->tx_mmio = NULL;
|
||||
+ }
|
||||
|
||||
/* If specified, second reg entry is Rx MMIO */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
- size = resource_size(res);
|
||||
tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res);
|
||||
- if (PTR_ERR(tdev->rx_mmio) == -EBUSY)
|
||||
+ if (PTR_ERR(tdev->rx_mmio) == -EBUSY) {
|
||||
+ size = resource_size(res);
|
||||
tdev->rx_mmio = devm_ioremap(&pdev->dev, res->start, size);
|
||||
- else if (IS_ERR(tdev->rx_mmio))
|
||||
+ } else if (IS_ERR(tdev->rx_mmio)) {
|
||||
tdev->rx_mmio = tdev->tx_mmio;
|
||||
+ }
|
||||
|
||||
tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
|
||||
tdev->rx_channel = mbox_test_request_channel(pdev, "rx");
|
||||
@@ -416,7 +418,7 @@ static int mbox_test_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mbox_test_device *tdev = platform_get_drvdata(pdev);
|
||||
|
||||
- debugfs_remove_recursive(root_debugfs_dir);
|
||||
+ debugfs_remove_recursive(tdev->root_debugfs_dir);
|
||||
|
||||
if (tdev->tx_channel)
|
||||
mbox_free_channel(tdev->tx_channel);
|
||||
diff --git a/drivers/mailbox/stm32-ipcc.c b/drivers/mailbox/stm32-ipcc.c
|
||||
index 533b0da..cd5ceca 100644
|
||||
--- a/drivers/mailbox/stm32-ipcc.c
|
||||
+++ b/drivers/mailbox/stm32-ipcc.c
|
||||
@@ -276,8 +276,8 @@ static int stm32_ipcc_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "Failed to set wake up irq\n");
|
||||
goto err_init_wkp;
|
||||
}
|
||||
- } else {
|
||||
- device_init_wakeup(dev, false);
|
||||
+ /* disable the wakeup source, let the user enable it or not */
|
||||
+ device_set_wakeup_enable(dev, false);
|
||||
}
|
||||
|
||||
/* mailbox controller */
|
||||
--
|
||||
2.7.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,78 +0,0 @@
|
|||
From 82c6107d054adcc906e43190ef150840876c2618 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:23:50 +0100
|
||||
Subject: [PATCH 10/52] ARM: stm32mp1-r0-rc1: ETH
|
||||
|
||||
---
|
||||
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 30 ++++++++++++++++++++++-
|
||||
1 file changed, 29 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
index 7e2e79d..d1cf145 100644
|
||||
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
@@ -42,6 +42,7 @@ struct stm32_dwmac {
|
||||
struct clk *clk_ethstp;
|
||||
struct clk *syscfg_clk;
|
||||
bool int_phyclk; /* Clock from RCC to drive PHY */
|
||||
+ int irq_pwr_wakeup;
|
||||
u32 mode_reg; /* MAC glue-logic mode register */
|
||||
struct regmap *regmap;
|
||||
u32 speed;
|
||||
@@ -232,7 +233,9 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
|
||||
static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||
struct device *dev)
|
||||
{
|
||||
+ struct platform_device *pdev = to_platform_device(dev);
|
||||
struct device_node *np = dev->of_node;
|
||||
+ int err = 0;
|
||||
|
||||
dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk");
|
||||
|
||||
@@ -260,7 +263,26 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||
return PTR_ERR(dwmac->syscfg_clk);
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ /* Get IRQ information early to have an ability to ask for deferred
|
||||
+ * probe if needed before we went too far with resource allocation.
|
||||
+ */
|
||||
+ dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev,
|
||||
+ "stm32_pwr_wakeup");
|
||||
+ if (!dwmac->int_phyclk && dwmac->irq_pwr_wakeup >= 0) {
|
||||
+ err = device_init_wakeup(&pdev->dev, true);
|
||||
+ if (err) {
|
||||
+ dev_err(&pdev->dev, "Failed to init wake up irq\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ err = dev_pm_set_dedicated_wake_irq(&pdev->dev,
|
||||
+ dwmac->irq_pwr_wakeup);
|
||||
+ if (err) {
|
||||
+ dev_err(&pdev->dev, "Failed to set wake up irq\n");
|
||||
+ device_init_wakeup(&pdev->dev, false);
|
||||
+ }
|
||||
+ device_set_wakeup_enable(&pdev->dev, false);
|
||||
+ }
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static int stm32_dwmac_probe(struct platform_device *pdev)
|
||||
@@ -326,9 +348,15 @@ static int stm32_dwmac_remove(struct platform_device *pdev)
|
||||
struct net_device *ndev = platform_get_drvdata(pdev);
|
||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||
int ret = stmmac_dvr_remove(&pdev->dev);
|
||||
+ struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
|
||||
|
||||
stm32_dwmac_clk_disable(priv->plat->bsp_priv);
|
||||
|
||||
+ if (dwmac->irq_pwr_wakeup >= 0) {
|
||||
+ dev_pm_clear_wake_irq(&pdev->dev);
|
||||
+ device_init_wakeup(&pdev->dev, false);
|
||||
+ }
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,901 +0,0 @@
|
|||
From 535343fc0142b45ec82958a4cbea41945d4d93c9 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Tue, 13 Nov 2018 12:30:43 +0100
|
||||
Subject: [PATCH 15/52] ARM: stm32mp1-r0-rc1: MISC
|
||||
|
||||
---
|
||||
arch/arm/mach-integrator/integrator_cp.c | 2 -
|
||||
arch/arm/mach-versatile/versatile_dt.c | 4 -
|
||||
drivers/soc/Kconfig | 1 +
|
||||
drivers/soc/Makefile | 1 +
|
||||
drivers/soc/st/Kconfig | 9 +
|
||||
drivers/soc/st/Makefile | 1 +
|
||||
drivers/soc/st/stm32_pm_domain.c | 212 ++++++++++++
|
||||
drivers/spi/Kconfig | 9 +
|
||||
drivers/spi/Makefile | 1 +
|
||||
drivers/spi/spi-stm32-qspi.c | 541 +++++++++++++++++++++++++++++++
|
||||
10 files changed, 775 insertions(+), 6 deletions(-)
|
||||
create mode 100644 drivers/soc/st/Kconfig
|
||||
create mode 100644 drivers/soc/st/Makefile
|
||||
create mode 100644 drivers/soc/st/stm32_pm_domain.c
|
||||
create mode 100644 drivers/spi/spi-stm32-qspi.c
|
||||
|
||||
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
|
||||
index 772a7cf..976ded5 100644
|
||||
--- a/arch/arm/mach-integrator/integrator_cp.c
|
||||
+++ b/arch/arm/mach-integrator/integrator_cp.c
|
||||
@@ -80,8 +80,6 @@ static unsigned int mmc_status(struct device *dev)
|
||||
static struct mmci_platform_data mmc_data = {
|
||||
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||
.status = mmc_status,
|
||||
- .gpio_wp = -1,
|
||||
- .gpio_cd = -1,
|
||||
};
|
||||
|
||||
static u64 notrace intcp_read_sched_clock(void)
|
||||
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
|
||||
index 3c8d39c..e9d6068 100644
|
||||
--- a/arch/arm/mach-versatile/versatile_dt.c
|
||||
+++ b/arch/arm/mach-versatile/versatile_dt.c
|
||||
@@ -89,15 +89,11 @@ unsigned int mmc_status(struct device *dev)
|
||||
static struct mmci_platform_data mmc0_plat_data = {
|
||||
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||
.status = mmc_status,
|
||||
- .gpio_wp = -1,
|
||||
- .gpio_cd = -1,
|
||||
};
|
||||
|
||||
static struct mmci_platform_data mmc1_plat_data = {
|
||||
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||
.status = mmc_status,
|
||||
- .gpio_wp = -1,
|
||||
- .gpio_cd = -1,
|
||||
};
|
||||
|
||||
/*
|
||||
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
|
||||
index c07b4a8..f2bd1ce 100644
|
||||
--- a/drivers/soc/Kconfig
|
||||
+++ b/drivers/soc/Kconfig
|
||||
@@ -11,6 +11,7 @@ source "drivers/soc/qcom/Kconfig"
|
||||
source "drivers/soc/renesas/Kconfig"
|
||||
source "drivers/soc/rockchip/Kconfig"
|
||||
source "drivers/soc/samsung/Kconfig"
|
||||
+source "drivers/soc/st/Kconfig"
|
||||
source "drivers/soc/sunxi/Kconfig"
|
||||
source "drivers/soc/tegra/Kconfig"
|
||||
source "drivers/soc/ti/Kconfig"
|
||||
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
|
||||
index 113e884..a16f673 100644
|
||||
--- a/drivers/soc/Makefile
|
||||
+++ b/drivers/soc/Makefile
|
||||
@@ -18,6 +18,7 @@ obj-y += qcom/
|
||||
obj-y += renesas/
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
|
||||
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
|
||||
+obj-$(CONFIG_ARCH_STM32) += st/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-$(CONFIG_SOC_TI) += ti/
|
||||
diff --git a/drivers/soc/st/Kconfig b/drivers/soc/st/Kconfig
|
||||
new file mode 100644
|
||||
index 0000000..82ee423
|
||||
--- /dev/null
|
||||
+++ b/drivers/soc/st/Kconfig
|
||||
@@ -0,0 +1,9 @@
|
||||
+if ARCH_STM32
|
||||
+
|
||||
+config STM32_PM_DOMAINS
|
||||
+ bool "STM32 PM domains"
|
||||
+ depends on MACH_STM32MP157
|
||||
+ select PM_GENERIC_DOMAINS
|
||||
+ default y if MACH_STM32MP157
|
||||
+
|
||||
+endif # ARCH_STM32
|
||||
diff --git a/drivers/soc/st/Makefile b/drivers/soc/st/Makefile
|
||||
new file mode 100644
|
||||
index 0000000..8d7f291
|
||||
--- /dev/null
|
||||
+++ b/drivers/soc/st/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+obj-$(CONFIG_STM32_PM_DOMAINS) += stm32_pm_domain.o
|
||||
diff --git a/drivers/soc/st/stm32_pm_domain.c b/drivers/soc/st/stm32_pm_domain.c
|
||||
new file mode 100644
|
||||
index 0000000..0386624
|
||||
--- /dev/null
|
||||
+++ b/drivers/soc/st/stm32_pm_domain.c
|
||||
@@ -0,0 +1,212 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
|
||||
+ * Author: Olivier Bideau <olivier.bideau@st.com> for STMicroelectronics.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/arm-smccc.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/pm_domain.h>
|
||||
+#include <linux/printk.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#define SMC(domain, state) \
|
||||
+{ \
|
||||
+ struct arm_smccc_res res; \
|
||||
+ arm_smccc_smc(0x82001008, domain, state, 0, \
|
||||
+ 0, 0, 0, 0, &res); \
|
||||
+}
|
||||
+
|
||||
+#define STM32_SMC_PD_DOMAIN_ON 0
|
||||
+#define STM32_SMC_PD_DOMAIN_OFF 1
|
||||
+
|
||||
+struct stm32_pm_domain {
|
||||
+ struct device *dev;
|
||||
+ struct generic_pm_domain genpd;
|
||||
+ int id;
|
||||
+};
|
||||
+
|
||||
+static int stm32_pd_power_off(struct generic_pm_domain *domain)
|
||||
+{
|
||||
+ struct stm32_pm_domain *priv = container_of(domain,
|
||||
+ struct stm32_pm_domain,
|
||||
+ genpd);
|
||||
+
|
||||
+ SMC(priv->id, STM32_SMC_PD_DOMAIN_OFF);
|
||||
+
|
||||
+ dev_dbg(priv->dev, "%s OFF\n", domain->name);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int stm32_pd_power_on(struct generic_pm_domain *domain)
|
||||
+{
|
||||
+ struct stm32_pm_domain *priv = container_of(domain,
|
||||
+ struct stm32_pm_domain,
|
||||
+ genpd);
|
||||
+
|
||||
+ SMC(priv->id, STM32_SMC_PD_DOMAIN_ON);
|
||||
+
|
||||
+ dev_dbg(priv->dev, "%s ON\n", domain->name);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void stm32_pm_domain_remove(struct stm32_pm_domain *domain)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = pm_genpd_remove(&domain->genpd);
|
||||
+ if (ret)
|
||||
+ dev_err(domain->dev, "failed to remove PM domain %s: %d\n",
|
||||
+ domain->genpd.name, ret);
|
||||
+}
|
||||
+
|
||||
+static int stm32_pm_domain_add(struct stm32_pm_domain *domain,
|
||||
+ struct device *dev,
|
||||
+ struct device_node *np)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ domain->dev = dev;
|
||||
+ domain->genpd.name = np->name;
|
||||
+ domain->genpd.power_off = stm32_pd_power_off;
|
||||
+ domain->genpd.power_on = stm32_pd_power_on;
|
||||
+ domain->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
||||
+
|
||||
+ ret = of_property_read_u32(np, "reg", &domain->id);
|
||||
+ if (ret) {
|
||||
+ dev_err(domain->dev, "no domain ID\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = pm_genpd_init(&domain->genpd, NULL, 0);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(domain->dev, "failed to initialise PM domain %s: %d\n",
|
||||
+ np->name, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = of_genpd_add_provider_simple(np, &domain->genpd);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(domain->dev, "failed to register PM domain %s: %d\n",
|
||||
+ np->name, ret);
|
||||
+ stm32_pm_domain_remove(domain);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(domain->dev, "domain %s registered\n", np->name);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void stm32_pm_subdomain_add(struct stm32_pm_domain *domain,
|
||||
+ struct device *dev,
|
||||
+ struct device_node *np)
|
||||
+{
|
||||
+ struct device_node *np_child;
|
||||
+ int ret;
|
||||
+
|
||||
+ for_each_child_of_node(np, np_child) {
|
||||
+ struct stm32_pm_domain *sub_domain;
|
||||
+
|
||||
+ sub_domain = devm_kzalloc(dev, sizeof(*sub_domain), GFP_KERNEL);
|
||||
+ if (!sub_domain)
|
||||
+ continue;
|
||||
+
|
||||
+ sub_domain->dev = dev;
|
||||
+ sub_domain->genpd.name = np_child->name;
|
||||
+ sub_domain->genpd.power_off = stm32_pd_power_off;
|
||||
+ sub_domain->genpd.power_on = stm32_pd_power_on;
|
||||
+ sub_domain->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
||||
+
|
||||
+ ret = of_property_read_u32(np_child, "reg", &sub_domain->id);
|
||||
+ if (ret) {
|
||||
+ dev_err(sub_domain->dev, "no domain ID\n");
|
||||
+ devm_kfree(dev, sub_domain);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ret = pm_genpd_init(&sub_domain->genpd, NULL, 0);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(sub_domain->dev, "failed to initialise PM domain %s: %d\n"
|
||||
+ , np_child->name, ret);
|
||||
+ devm_kfree(dev, sub_domain);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ret = of_genpd_add_provider_simple(np_child,
|
||||
+ &sub_domain->genpd);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(sub_domain->dev, "failed to register PM domain %s: %d\n"
|
||||
+ , np_child->name, ret);
|
||||
+ stm32_pm_domain_remove(sub_domain);
|
||||
+ devm_kfree(dev, sub_domain);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ret = pm_genpd_add_subdomain(&domain->genpd,
|
||||
+ &sub_domain->genpd);
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(sub_domain->dev, "failed to add Sub PM domain %s: %d\n"
|
||||
+ , np_child->name, ret);
|
||||
+ stm32_pm_domain_remove(sub_domain);
|
||||
+ devm_kfree(dev, sub_domain);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(sub_domain->dev, "subdomain %s registered\n",
|
||||
+ np_child->name);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int stm32_pm_domain_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct device_node *np = dev->of_node, *child_np;
|
||||
+ int ret;
|
||||
+
|
||||
+ for_each_child_of_node(np, child_np) {
|
||||
+ struct stm32_pm_domain *domain;
|
||||
+
|
||||
+ domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL);
|
||||
+ if (!domain)
|
||||
+ continue;
|
||||
+
|
||||
+ ret = stm32_pm_domain_add(domain, dev, child_np);
|
||||
+ if (ret) {
|
||||
+ devm_kfree(dev, domain);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ stm32_pm_subdomain_add(domain, dev, child_np);
|
||||
+ }
|
||||
+
|
||||
+ dev_info(dev, "domains probed\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id stm32_pm_domain_matches[] = {
|
||||
+ { .compatible = "st,stm32mp157c-pd", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver stm32_pm_domains_driver = {
|
||||
+ .probe = stm32_pm_domain_probe,
|
||||
+ .driver = {
|
||||
+ .name = "stm32-pm-domain",
|
||||
+ .of_match_table = stm32_pm_domain_matches,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init stm32_pm_domains_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&stm32_pm_domains_driver);
|
||||
+}
|
||||
+core_initcall(stm32_pm_domains_init);
|
||||
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
|
||||
index 671d078..448d441 100644
|
||||
--- a/drivers/spi/Kconfig
|
||||
+++ b/drivers/spi/Kconfig
|
||||
@@ -613,6 +613,15 @@ config SPI_STM32
|
||||
is not available, the driver automatically falls back to
|
||||
PIO mode.
|
||||
|
||||
+config SPI_STM32_QSPI
|
||||
+ tristate "STMicroelectronics STM32 QUAD SPI controller"
|
||||
+ depends on ARCH_STM32 || COMPILE_TEST
|
||||
+ depends on OF
|
||||
+ help
|
||||
+ This enables support for the Quad SPI controller in master mode.
|
||||
+ This driver does not support generic SPI. The implementation only
|
||||
+ supports spi-mem interface.
|
||||
+
|
||||
config SPI_ST_SSC4
|
||||
tristate "STMicroelectronics SPI SSC-based driver"
|
||||
depends on ARCH_STI || COMPILE_TEST
|
||||
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
|
||||
index a90d559..68a3c4e 100644
|
||||
--- a/drivers/spi/Makefile
|
||||
+++ b/drivers/spi/Makefile
|
||||
@@ -90,6 +90,7 @@ obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
|
||||
obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
|
||||
obj-$(CONFIG_SPI_SPRD_ADI) += spi-sprd-adi.o
|
||||
obj-$(CONFIG_SPI_STM32) += spi-stm32.o
|
||||
+obj-$(CONFIG_SPI_STM32_QSPI) += spi-stm32-qspi.o
|
||||
obj-$(CONFIG_SPI_ST_SSC4) += spi-st-ssc4.o
|
||||
obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o
|
||||
obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o
|
||||
diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c
|
||||
new file mode 100644
|
||||
index 0000000..3e8ca10
|
||||
--- /dev/null
|
||||
+++ b/drivers/spi/spi-stm32-qspi.c
|
||||
@@ -0,0 +1,541 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||
+ * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
|
||||
+ */
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/pinctrl/consumer.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/reset.h>
|
||||
+#include <linux/sizes.h>
|
||||
+#include <linux/spi/spi-mem.h>
|
||||
+
|
||||
+#define QSPI_CR 0x00
|
||||
+#define CR_EN BIT(0)
|
||||
+#define CR_ABORT BIT(1)
|
||||
+#define CR_DMAEN BIT(2)
|
||||
+#define CR_TCEN BIT(3)
|
||||
+#define CR_SSHIFT BIT(4)
|
||||
+#define CR_DFM BIT(6)
|
||||
+#define CR_FSEL BIT(7)
|
||||
+#define CR_FTHRES_MASK GENMASK(12, 8)
|
||||
+#define CR_TEIE BIT(16)
|
||||
+#define CR_TCIE BIT(17)
|
||||
+#define CR_FTIE BIT(18)
|
||||
+#define CR_SMIE BIT(19)
|
||||
+#define CR_TOIE BIT(20)
|
||||
+#define CR_PRESC_MASK GENMASK(31, 24)
|
||||
+
|
||||
+#define QSPI_DCR 0x04
|
||||
+#define DCR_FSIZE_MASK GENMASK(20, 16)
|
||||
+
|
||||
+#define QSPI_SR 0x08
|
||||
+#define SR_TEF BIT(0)
|
||||
+#define SR_TCF BIT(1)
|
||||
+#define SR_FTF BIT(2)
|
||||
+#define SR_SMF BIT(3)
|
||||
+#define SR_TOF BIT(4)
|
||||
+#define SR_BUSY BIT(5)
|
||||
+#define SR_FLEVEL_MASK GENMASK(13, 8)
|
||||
+
|
||||
+#define QSPI_FCR 0x0c
|
||||
+#define FCR_CTEF BIT(0)
|
||||
+#define FCR_CTCF BIT(1)
|
||||
+
|
||||
+#define QSPI_DLR 0x10
|
||||
+
|
||||
+#define QSPI_CCR 0x14
|
||||
+#define CCR_INST_MASK GENMASK(7, 0)
|
||||
+#define CCR_IMODE_MASK GENMASK(9, 8)
|
||||
+#define CCR_ADMODE_MASK GENMASK(11, 10)
|
||||
+#define CCR_ADSIZE_MASK GENMASK(13, 12)
|
||||
+#define CCR_DCYC_MASK GENMASK(22, 18)
|
||||
+#define CCR_DMODE_MASK GENMASK(25, 24)
|
||||
+#define CCR_FMODE_MASK GENMASK(27, 26)
|
||||
+#define CCR_FMODE_INDW (0U << 26)
|
||||
+#define CCR_FMODE_INDR (1U << 26)
|
||||
+#define CCR_FMODE_APM (2U << 26)
|
||||
+#define CCR_FMODE_MM (3U << 26)
|
||||
+#define CCR_BUSWIDTH_0 0x0
|
||||
+#define CCR_BUSWIDTH_1 0x1
|
||||
+#define CCR_BUSWIDTH_2 0x2
|
||||
+#define CCR_BUSWIDTH_4 0x3
|
||||
+
|
||||
+#define QSPI_AR 0x18
|
||||
+#define QSPI_ABR 0x1c
|
||||
+#define QSPI_DR 0x20
|
||||
+#define QSPI_PSMKR 0x24
|
||||
+#define QSPI_PSMAR 0x28
|
||||
+#define QSPI_PIR 0x2c
|
||||
+#define QSPI_LPTR 0x30
|
||||
+
|
||||
+#define STM32_QSPI_MAX_MMAP_SZ SZ_256M
|
||||
+#define STM32_QSPI_MAX_NORCHIP 2
|
||||
+
|
||||
+#define STM32_FIFO_TIMEOUT_US 30000
|
||||
+#define STM32_BUSY_TIMEOUT_US 100000
|
||||
+#define STM32_ABT_TIMEOUT_US 100000
|
||||
+
|
||||
+struct stm32_qspi_flash {
|
||||
+ struct stm32_qspi *qspi;
|
||||
+ u32 cs;
|
||||
+ u32 presc;
|
||||
+};
|
||||
+
|
||||
+struct stm32_qspi {
|
||||
+ struct device *dev;
|
||||
+ void __iomem *io_base;
|
||||
+ void __iomem *mm_base;
|
||||
+ resource_size_t mm_size;
|
||||
+ struct clk *clk;
|
||||
+ u32 clk_rate;
|
||||
+ struct stm32_qspi_flash flash[STM32_QSPI_MAX_NORCHIP];
|
||||
+ struct completion data_completion;
|
||||
+ u32 fmode;
|
||||
+
|
||||
+ u32 cr_reg;
|
||||
+ u32 dcr_reg;
|
||||
+
|
||||
+ /*
|
||||
+ * to protect device configuration, could be different between
|
||||
+ * 2 flash access (bk1, bk2)
|
||||
+ */
|
||||
+ struct mutex lock;
|
||||
+};
|
||||
+
|
||||
+static irqreturn_t stm32_qspi_irq(int irq, void *dev_id)
|
||||
+{
|
||||
+ struct stm32_qspi *qspi = (struct stm32_qspi *)dev_id;
|
||||
+ u32 cr, sr;
|
||||
+
|
||||
+ sr = readl_relaxed(qspi->io_base + QSPI_SR);
|
||||
+
|
||||
+ if (sr & (SR_TEF | SR_TCF)) {
|
||||
+ /* disable irq */
|
||||
+ cr = readl_relaxed(qspi->io_base + QSPI_CR);
|
||||
+ cr &= ~CR_TCIE & ~CR_TEIE;
|
||||
+ writel_relaxed(cr, qspi->io_base + QSPI_CR);
|
||||
+ complete(&qspi->data_completion);
|
||||
+ }
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static void stm32_qspi_read_fifo(u8 *val, void __iomem *addr)
|
||||
+{
|
||||
+ *val = readb_relaxed(addr);
|
||||
+}
|
||||
+
|
||||
+static void stm32_qspi_write_fifo(u8 *val, void __iomem *addr)
|
||||
+{
|
||||
+ writeb_relaxed(*val, addr);
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_tx_poll(struct stm32_qspi *qspi,
|
||||
+ const struct spi_mem_op *op)
|
||||
+{
|
||||
+ void (*tx_fifo)(u8 *val, void __iomem *addr);
|
||||
+ u32 len = op->data.nbytes, sr;
|
||||
+ u8 *buf;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (op->data.dir == SPI_MEM_DATA_IN) {
|
||||
+ tx_fifo = stm32_qspi_read_fifo;
|
||||
+ buf = op->data.buf.in;
|
||||
+
|
||||
+ } else {
|
||||
+ tx_fifo = stm32_qspi_write_fifo;
|
||||
+ buf = (u8 *)op->data.buf.out;
|
||||
+ }
|
||||
+
|
||||
+ while (len--) {
|
||||
+ ret = readl_relaxed_poll_timeout_atomic(qspi->io_base + QSPI_SR,
|
||||
+ sr, (sr & SR_FTF), 1,
|
||||
+ STM32_FIFO_TIMEOUT_US);
|
||||
+ if (ret) {
|
||||
+ dev_err(qspi->dev, "fifo timeout (len:%d stat:%#x)\n",
|
||||
+ len, sr);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ tx_fifo(buf++, qspi->io_base + QSPI_DR);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_tx_mm(struct stm32_qspi *qspi,
|
||||
+ const struct spi_mem_op *op)
|
||||
+{
|
||||
+ memcpy_fromio(op->data.buf.in, qspi->mm_base + op->addr.val,
|
||||
+ op->data.nbytes);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_tx(struct stm32_qspi *qspi, const struct spi_mem_op *op)
|
||||
+{
|
||||
+ if (!op->data.nbytes)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (qspi->fmode == CCR_FMODE_MM)
|
||||
+ return stm32_qspi_tx_mm(qspi, op);
|
||||
+
|
||||
+ return stm32_qspi_tx_poll(qspi, op);
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_wait_nobusy(struct stm32_qspi *qspi)
|
||||
+{
|
||||
+ u32 sr;
|
||||
+
|
||||
+ return readl_relaxed_poll_timeout_atomic(qspi->io_base + QSPI_SR, sr,
|
||||
+ !(sr & SR_BUSY), 1,
|
||||
+ STM32_BUSY_TIMEOUT_US);
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi,
|
||||
+ const struct spi_mem_op *op)
|
||||
+{
|
||||
+ u32 cr, sr;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (!op->data.nbytes)
|
||||
+ return stm32_qspi_wait_nobusy(qspi);
|
||||
+
|
||||
+ if (readl_relaxed(qspi->io_base + QSPI_SR) & SR_TCF)
|
||||
+ goto out;
|
||||
+
|
||||
+ reinit_completion(&qspi->data_completion);
|
||||
+ cr = readl_relaxed(qspi->io_base + QSPI_CR);
|
||||
+ writel_relaxed(cr | CR_TCIE | CR_TEIE, qspi->io_base + QSPI_CR);
|
||||
+
|
||||
+ if (!wait_for_completion_interruptible_timeout(&qspi->data_completion,
|
||||
+ msecs_to_jiffies(1000))) {
|
||||
+ err = -ETIMEDOUT;
|
||||
+ } else {
|
||||
+ sr = readl_relaxed(qspi->io_base + QSPI_SR);
|
||||
+ if (sr & SR_TEF)
|
||||
+ err = -EIO;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ /* clear flags */
|
||||
+ writel_relaxed(FCR_CTCF | FCR_CTEF, qspi->io_base + QSPI_FCR);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_get_mode(struct stm32_qspi *qspi, u8 buswidth)
|
||||
+{
|
||||
+ if (buswidth == 4)
|
||||
+ return CCR_BUSWIDTH_4;
|
||||
+
|
||||
+ return buswidth;
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
+{
|
||||
+ struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master);
|
||||
+ struct stm32_qspi_flash *flash = &qspi->flash[mem->spi->chip_select];
|
||||
+ u32 ccr, cr, addr_max;
|
||||
+ int timeout, err = 0;
|
||||
+
|
||||
+ dev_dbg(qspi->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n",
|
||||
+ op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
|
||||
+ op->dummy.buswidth, op->data.buswidth,
|
||||
+ op->addr.val, op->data.nbytes);
|
||||
+
|
||||
+ err = stm32_qspi_wait_nobusy(qspi);
|
||||
+ if (err)
|
||||
+ goto abort;
|
||||
+
|
||||
+ addr_max = op->addr.val + op->data.nbytes + 1;
|
||||
+
|
||||
+ if (op->data.dir == SPI_MEM_DATA_IN) {
|
||||
+ if (addr_max < qspi->mm_size &&
|
||||
+ op->addr.buswidth)
|
||||
+ qspi->fmode = CCR_FMODE_MM;
|
||||
+ else
|
||||
+ qspi->fmode = CCR_FMODE_INDR;
|
||||
+ } else {
|
||||
+ qspi->fmode = CCR_FMODE_INDW;
|
||||
+ }
|
||||
+
|
||||
+ cr = readl_relaxed(qspi->io_base + QSPI_CR);
|
||||
+ cr &= ~CR_PRESC_MASK & ~CR_FSEL;
|
||||
+ cr |= FIELD_PREP(CR_PRESC_MASK, flash->presc);
|
||||
+ cr |= FIELD_PREP(CR_FSEL, flash->cs);
|
||||
+ writel_relaxed(cr, qspi->io_base + QSPI_CR);
|
||||
+
|
||||
+ if (op->data.nbytes)
|
||||
+ writel_relaxed(op->data.nbytes - 1,
|
||||
+ qspi->io_base + QSPI_DLR);
|
||||
+ else
|
||||
+ qspi->fmode = CCR_FMODE_INDW;
|
||||
+
|
||||
+ ccr = qspi->fmode;
|
||||
+ ccr |= FIELD_PREP(CCR_INST_MASK, op->cmd.opcode);
|
||||
+ ccr |= FIELD_PREP(CCR_IMODE_MASK,
|
||||
+ stm32_qspi_get_mode(qspi, op->cmd.buswidth));
|
||||
+
|
||||
+ if (op->addr.nbytes) {
|
||||
+ ccr |= FIELD_PREP(CCR_ADMODE_MASK,
|
||||
+ stm32_qspi_get_mode(qspi, op->addr.buswidth));
|
||||
+ ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1);
|
||||
+ }
|
||||
+
|
||||
+ if (op->dummy.buswidth && op->dummy.nbytes)
|
||||
+ ccr |= FIELD_PREP(CCR_DCYC_MASK,
|
||||
+ op->dummy.nbytes * 8 / op->dummy.buswidth);
|
||||
+
|
||||
+ if (op->data.nbytes) {
|
||||
+ ccr |= FIELD_PREP(CCR_DMODE_MASK,
|
||||
+ stm32_qspi_get_mode(qspi, op->data.buswidth));
|
||||
+ }
|
||||
+
|
||||
+ writel_relaxed(ccr, qspi->io_base + QSPI_CCR);
|
||||
+
|
||||
+ if (op->addr.nbytes && qspi->fmode != CCR_FMODE_MM)
|
||||
+ writel_relaxed(op->addr.val, qspi->io_base + QSPI_AR);
|
||||
+
|
||||
+ err = stm32_qspi_tx(qspi, op);
|
||||
+
|
||||
+ /*
|
||||
+ * Abort in:
|
||||
+ * -error case
|
||||
+ * -read memory map: prefetching must be stopped if we read the last
|
||||
+ * byte of device (device size - fifo size). like device size is not
|
||||
+ * knows, the prefetching is always stop.
|
||||
+ */
|
||||
+ if (err || qspi->fmode == CCR_FMODE_MM)
|
||||
+ goto abort;
|
||||
+
|
||||
+ /* wait end of tx in indirect mode */
|
||||
+ err = stm32_qspi_wait_cmd(qspi, op);
|
||||
+ if (err)
|
||||
+ goto abort;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+abort:
|
||||
+ cr = readl_relaxed(qspi->io_base + QSPI_CR) | CR_ABORT;
|
||||
+ writel_relaxed(cr, qspi->io_base + QSPI_CR);
|
||||
+
|
||||
+ /* wait clear of abort bit by hw */
|
||||
+ timeout = readl_relaxed_poll_timeout_atomic(qspi->io_base + QSPI_CR,
|
||||
+ cr, !(cr & CR_ABORT), 1,
|
||||
+ STM32_ABT_TIMEOUT_US);
|
||||
+
|
||||
+ writel_relaxed(FCR_CTCF, qspi->io_base + QSPI_FCR);
|
||||
+
|
||||
+ if (err || timeout)
|
||||
+ dev_err(qspi->dev, "%s err:%d abort timeout:%d\n",
|
||||
+ __func__, err, timeout);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
+{
|
||||
+ struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master);
|
||||
+ int ret;
|
||||
+
|
||||
+ mutex_lock(&qspi->lock);
|
||||
+ ret = stm32_qspi_send(mem, op);
|
||||
+ mutex_unlock(&qspi->lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_setup(struct spi_device *spi)
|
||||
+{
|
||||
+ struct spi_controller *ctrl = spi->master;
|
||||
+ struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl);
|
||||
+ struct stm32_qspi_flash *flash;
|
||||
+ u32 presc;
|
||||
+
|
||||
+ if (ctrl->busy)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ if (!spi->max_speed_hz)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ presc = DIV_ROUND_UP(qspi->clk_rate, spi->max_speed_hz) - 1;
|
||||
+
|
||||
+ flash = &qspi->flash[spi->chip_select];
|
||||
+ flash->qspi = qspi;
|
||||
+ flash->cs = spi->chip_select;
|
||||
+ flash->presc = presc;
|
||||
+
|
||||
+ mutex_lock(&qspi->lock);
|
||||
+ qspi->cr_reg = FIELD_PREP(CR_FTHRES_MASK, 3) | CR_SSHIFT | CR_EN;
|
||||
+ writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
|
||||
+
|
||||
+ /* set dcr fsize to max address */
|
||||
+ qspi->dcr_reg = DCR_FSIZE_MASK;
|
||||
+ writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
|
||||
+ mutex_unlock(&qspi->lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * no special host constraint, so use default spi_mem_default_supports_op
|
||||
+ * to check supported mode.
|
||||
+ */
|
||||
+static const struct spi_controller_mem_ops stm32_qspi_mem_ops = {
|
||||
+ .exec_op = stm32_qspi_exec_op,
|
||||
+};
|
||||
+
|
||||
+static void stm32_qspi_release(struct stm32_qspi *qspi)
|
||||
+{
|
||||
+ /* disable qspi */
|
||||
+ writel_relaxed(0, qspi->io_base + QSPI_CR);
|
||||
+ mutex_destroy(&qspi->lock);
|
||||
+ clk_disable_unprepare(qspi->clk);
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct spi_controller *ctrl;
|
||||
+ struct reset_control *rstc;
|
||||
+ struct stm32_qspi *qspi;
|
||||
+ struct resource *res;
|
||||
+ int ret, irq;
|
||||
+
|
||||
+ ctrl = spi_alloc_master(dev, sizeof(*qspi));
|
||||
+ if (!ctrl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ qspi = spi_controller_get_devdata(ctrl);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi");
|
||||
+ qspi->io_base = devm_ioremap_resource(dev, res);
|
||||
+ if (IS_ERR(qspi->io_base))
|
||||
+ return PTR_ERR(qspi->io_base);
|
||||
+
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm");
|
||||
+ qspi->mm_base = devm_ioremap_resource(dev, res);
|
||||
+ if (IS_ERR(qspi->mm_base))
|
||||
+ return PTR_ERR(qspi->mm_base);
|
||||
+
|
||||
+ qspi->mm_size = resource_size(res);
|
||||
+ if (qspi->mm_size > STM32_QSPI_MAX_MMAP_SZ)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0,
|
||||
+ dev_name(dev), qspi);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to request irq\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ init_completion(&qspi->data_completion);
|
||||
+
|
||||
+ qspi->clk = devm_clk_get(dev, NULL);
|
||||
+ if (IS_ERR(qspi->clk))
|
||||
+ return PTR_ERR(qspi->clk);
|
||||
+
|
||||
+ qspi->clk_rate = clk_get_rate(qspi->clk);
|
||||
+ if (!qspi->clk_rate)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ret = clk_prepare_enable(qspi->clk);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "can not enable the clock\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ rstc = devm_reset_control_get_exclusive(dev, NULL);
|
||||
+ if (!IS_ERR(rstc)) {
|
||||
+ reset_control_assert(rstc);
|
||||
+ udelay(2);
|
||||
+ reset_control_deassert(rstc);
|
||||
+ }
|
||||
+
|
||||
+ qspi->dev = dev;
|
||||
+ platform_set_drvdata(pdev, qspi);
|
||||
+ mutex_init(&qspi->lock);
|
||||
+
|
||||
+ ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD
|
||||
+ | SPI_TX_DUAL | SPI_TX_QUAD;
|
||||
+ ctrl->setup = stm32_qspi_setup;
|
||||
+ ctrl->bus_num = -1;
|
||||
+ ctrl->mem_ops = &stm32_qspi_mem_ops;
|
||||
+ ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP;
|
||||
+ ctrl->dev.of_node = dev->of_node;
|
||||
+
|
||||
+ ret = devm_spi_register_master(dev, ctrl);
|
||||
+ if (ret)
|
||||
+ goto err_spi_register;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_spi_register:
|
||||
+ stm32_qspi_release(qspi);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int stm32_qspi_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct stm32_qspi *qspi = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ stm32_qspi_release(qspi);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __maybe_unused stm32_qspi_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_qspi *qspi = dev_get_drvdata(dev);
|
||||
+
|
||||
+ clk_disable_unprepare(qspi->clk);
|
||||
+ pinctrl_pm_select_sleep_state(dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __maybe_unused stm32_qspi_resume(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_qspi *qspi = dev_get_drvdata(dev);
|
||||
+
|
||||
+ pinctrl_pm_select_default_state(dev);
|
||||
+ clk_prepare_enable(qspi->clk);
|
||||
+
|
||||
+ writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
|
||||
+ writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+SIMPLE_DEV_PM_OPS(stm32_qspi_pm_ops, stm32_qspi_suspend, stm32_qspi_resume);
|
||||
+
|
||||
+static const struct of_device_id stm32_qspi_match[] = {
|
||||
+ {.compatible = "st,stm32f469-qspi"},
|
||||
+ {}
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, stm32_qspi_match);
|
||||
+
|
||||
+static struct platform_driver stm32_qspi_driver = {
|
||||
+ .probe = stm32_qspi_probe,
|
||||
+ .remove = stm32_qspi_remove,
|
||||
+ .driver = {
|
||||
+ .name = "stm32-qspi",
|
||||
+ .of_match_table = stm32_qspi_match,
|
||||
+ .pm = &stm32_qspi_pm_ops,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(stm32_qspi_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
|
||||
+MODULE_DESCRIPTION("STMicroelectronics STM32 quad spi driver");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,984 +0,0 @@
|
|||
From 8f36e7dd830ff5d93e240a62da54ea2afc580cca Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Mon, 26 Nov 2018 14:39:57 +0100
|
||||
Subject: [PATCH 20/52] ARM-stm32mp1-r0-rc2-MEDIA
|
||||
|
||||
---
|
||||
.../devicetree/bindings/media/video-interfaces.txt | 2 +
|
||||
drivers/media/i2c/ov5640.c | 663 ++++++++++++---------
|
||||
drivers/media/platform/stm32/stm32-dcmi.c | 41 +-
|
||||
drivers/media/v4l2-core/v4l2-fwnode.c | 3 +
|
||||
include/media/v4l2-fwnode.h | 2 +
|
||||
5 files changed, 413 insertions(+), 298 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/media/video-interfaces.txt b/Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
index baf9d97..fa4c112 100644
|
||||
--- a/Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
+++ b/Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
@@ -147,6 +147,8 @@ Optional endpoint properties
|
||||
as 0 (normal). This property is valid for serial busses only.
|
||||
- strobe: Whether the clock signal is used as clock (0) or strobe (1). Used
|
||||
with CCP2, for instance.
|
||||
+- pclk-max-frequency: maximum pixel clock frequency admissible by video
|
||||
+ host interface.
|
||||
|
||||
Example
|
||||
-------
|
||||
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
|
||||
index 30b15e9..27b75e7 100644
|
||||
--- a/drivers/media/i2c/ov5640.c
|
||||
+++ b/drivers/media/i2c/ov5640.c
|
||||
@@ -66,6 +66,7 @@
|
||||
#define OV5640_REG_TIMING_VTS 0x380e
|
||||
#define OV5640_REG_TIMING_TC_REG20 0x3820
|
||||
#define OV5640_REG_TIMING_TC_REG21 0x3821
|
||||
+#define OV5640_REG_DVP_PCLK_DIVIDER 0x3824
|
||||
#define OV5640_REG_AEC_CTRL00 0x3a00
|
||||
#define OV5640_REG_AEC_B50_STEP 0x3a08
|
||||
#define OV5640_REG_AEC_B60_STEP 0x3a0a
|
||||
@@ -261,8 +262,8 @@ static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
|
||||
static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
|
||||
{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
|
||||
{0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
|
||||
- {0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
|
||||
- {0x3037, 0x13, 0, 0}, {0x3630, 0x36, 0, 0},
|
||||
+ {0x3034, 0x18, 0, 0},
|
||||
+ {0x3630, 0x36, 0, 0},
|
||||
{0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
|
||||
{0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
|
||||
{0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
|
||||
@@ -344,85 +345,8 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
|
||||
{0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
|
||||
};
|
||||
|
||||
-static const struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
|
||||
- {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
- {0x3814, 0x31, 0, 0},
|
||||
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
- {0x3810, 0x00, 0, 0},
|
||||
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
|
||||
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
|
||||
-};
|
||||
-
|
||||
-static const struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
|
||||
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
- {0x3814, 0x31, 0, 0},
|
||||
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
- {0x3810, 0x00, 0, 0},
|
||||
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
-};
|
||||
-
|
||||
-static const struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
|
||||
- {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
- {0x3814, 0x31, 0, 0},
|
||||
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
- {0x3810, 0x00, 0, 0},
|
||||
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
|
||||
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
|
||||
- {0x3035, 0x12, 0, 0},
|
||||
-};
|
||||
-
|
||||
-static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
|
||||
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
- {0x3814, 0x31, 0, 0},
|
||||
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
- {0x3810, 0x00, 0, 0},
|
||||
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
-};
|
||||
-
|
||||
-static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
|
||||
- {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
+static const struct reg_value ov5640_setting_VGA_640_480[] = {
|
||||
+ {0x3c07, 0x08, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3814, 0x31, 0, 0},
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
@@ -436,12 +360,12 @@ static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
|
||||
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
+ {0x4407, 0x04, 0, 0},
|
||||
+ {0x5001, 0xa3, 0, 0},
|
||||
};
|
||||
|
||||
-static const struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
|
||||
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
+static const struct reg_value ov5640_setting_XGA_1024_768[] = {
|
||||
+ {0x3c07, 0x08, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3814, 0x31, 0, 0},
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
@@ -455,12 +379,11 @@ static const struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
|
||||
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
};
|
||||
|
||||
-static const struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
|
||||
- {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
+static const struct reg_value ov5640_setting_QVGA_320_240[] = {
|
||||
+ {0x3c07, 0x08, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3814, 0x31, 0, 0},
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
@@ -474,12 +397,11 @@ static const struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
|
||||
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
};
|
||||
|
||||
-static const struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
|
||||
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
+static const struct reg_value ov5640_setting_QCIF_176_144[] = {
|
||||
+ {0x3c07, 0x08, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3814, 0x31, 0, 0},
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
@@ -493,12 +415,11 @@ static const struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
|
||||
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
};
|
||||
|
||||
-static const struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
|
||||
- {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
+static const struct reg_value ov5640_setting_NTSC_720_480[] = {
|
||||
+ {0x3c07, 0x08, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3814, 0x31, 0, 0},
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
@@ -512,31 +433,11 @@ static const struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
|
||||
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
};
|
||||
|
||||
-static const struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
|
||||
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
- {0x3814, 0x31, 0, 0},
|
||||
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
- {0x3810, 0x00, 0, 0},
|
||||
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
|
||||
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
-};
|
||||
-
|
||||
-static const struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
|
||||
- {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
+static const struct reg_value ov5640_setting_PAL_720_576[] = {
|
||||
+ {0x3c07, 0x08, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3814, 0x31, 0, 0},
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
@@ -550,52 +451,11 @@ static const struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
|
||||
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
};
|
||||
|
||||
-static const struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
|
||||
- {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
- {0x3814, 0x31, 0, 0},
|
||||
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
- {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
- {0x3810, 0x00, 0, 0},
|
||||
- {0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
-};
|
||||
-
|
||||
-static const struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
|
||||
- {0x3008, 0x42, 0, 0},
|
||||
- {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
|
||||
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
- {0x3814, 0x31, 0, 0},
|
||||
- {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
- {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
|
||||
- {0x3810, 0x00, 0, 0},
|
||||
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
|
||||
- {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
- {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
|
||||
- {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
|
||||
- {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
|
||||
- {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
|
||||
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
|
||||
- {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, {0x4005, 0x1a, 0, 0},
|
||||
- {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
|
||||
-};
|
||||
-
|
||||
-static const struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
|
||||
- {0x3035, 0x41, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
|
||||
+static const struct reg_value ov5640_setting_720P_1280_720[] = {
|
||||
+ {0x3c07, 0x07, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3814, 0x31, 0, 0},
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
@@ -608,47 +468,13 @@ static const struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
|
||||
{0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
|
||||
{0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
|
||||
{0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
|
||||
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
|
||||
- {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
|
||||
-};
|
||||
-
|
||||
-static const struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
|
||||
- {0x3008, 0x42, 0, 0},
|
||||
- {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
- {0x3814, 0x11, 0, 0},
|
||||
- {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
- {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
- {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
|
||||
- {0x3810, 0x00, 0, 0},
|
||||
- {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
|
||||
- {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
|
||||
- {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
- {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
|
||||
- {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
- {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
- {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x11, 0, 0},
|
||||
- {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
|
||||
- {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
- {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
|
||||
- {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
|
||||
- {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0},
|
||||
- {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
- {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
|
||||
- {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
|
||||
- {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
|
||||
- {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
|
||||
- {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
|
||||
- {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0},
|
||||
- {0x3503, 0, 0, 0},
|
||||
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
+ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
};
|
||||
|
||||
-static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
||||
+static const struct reg_value ov5640_setting_1080P_1920_1080[] = {
|
||||
{0x3008, 0x42, 0, 0},
|
||||
- {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
+ {0x3c07, 0x08, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3814, 0x11, 0, 0},
|
||||
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
@@ -662,9 +488,9 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
||||
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x21, 0, 0},
|
||||
- {0x3036, 0x54, 0, 1}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
|
||||
+ {0x4407, 0x04, 0, 0},
|
||||
+ {0x5001, 0x83, 0, 0},
|
||||
+ {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
|
||||
{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
|
||||
@@ -674,12 +500,11 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
||||
{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
|
||||
{0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
|
||||
{0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
|
||||
- {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
|
||||
{0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
|
||||
};
|
||||
|
||||
-static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
|
||||
- {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
|
||||
+static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
|
||||
+ {0x3c07, 0x08, 0, 0},
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3814, 0x11, 0, 0},
|
||||
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
@@ -693,8 +518,8 @@ static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
|
||||
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
|
||||
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
- {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
- {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70},
|
||||
+ {0x4407, 0x04, 0, 0},
|
||||
+ {0x5001, 0x83, 0, 70},
|
||||
};
|
||||
|
||||
/* power-on sensor init reg table */
|
||||
@@ -705,79 +530,43 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
|
||||
};
|
||||
|
||||
static const struct ov5640_mode_info
|
||||
-ov5640_mode_data[OV5640_NUM_FRAMERATES][OV5640_NUM_MODES] = {
|
||||
- {
|
||||
- {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
|
||||
- 176, 1896, 144, 984,
|
||||
- ov5640_setting_15fps_QCIF_176_144,
|
||||
- ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
|
||||
- {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
|
||||
- 320, 1896, 240, 984,
|
||||
- ov5640_setting_15fps_QVGA_320_240,
|
||||
- ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
|
||||
- {OV5640_MODE_VGA_640_480, SUBSAMPLING,
|
||||
- 640, 1896, 480, 1080,
|
||||
- ov5640_setting_15fps_VGA_640_480,
|
||||
- ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
|
||||
- {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
|
||||
- 720, 1896, 480, 984,
|
||||
- ov5640_setting_15fps_NTSC_720_480,
|
||||
- ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
|
||||
- {OV5640_MODE_PAL_720_576, SUBSAMPLING,
|
||||
- 720, 1896, 576, 984,
|
||||
- ov5640_setting_15fps_PAL_720_576,
|
||||
- ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
|
||||
- {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
|
||||
- 1024, 1896, 768, 1080,
|
||||
- ov5640_setting_15fps_XGA_1024_768,
|
||||
- ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
|
||||
- {OV5640_MODE_720P_1280_720, SUBSAMPLING,
|
||||
- 1280, 1892, 720, 740,
|
||||
- ov5640_setting_15fps_720P_1280_720,
|
||||
- ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
|
||||
- {OV5640_MODE_1080P_1920_1080, SCALING,
|
||||
- 1920, 2500, 1080, 1120,
|
||||
- ov5640_setting_15fps_1080P_1920_1080,
|
||||
- ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
|
||||
- {OV5640_MODE_QSXGA_2592_1944, SCALING,
|
||||
- 2592, 2844, 1944, 1968,
|
||||
- ov5640_setting_15fps_QSXGA_2592_1944,
|
||||
- ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
|
||||
- }, {
|
||||
- {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
|
||||
- 176, 1896, 144, 984,
|
||||
- ov5640_setting_30fps_QCIF_176_144,
|
||||
- ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
|
||||
- {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
|
||||
- 320, 1896, 240, 984,
|
||||
- ov5640_setting_30fps_QVGA_320_240,
|
||||
- ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
|
||||
- {OV5640_MODE_VGA_640_480, SUBSAMPLING,
|
||||
- 640, 1896, 480, 1080,
|
||||
- ov5640_setting_30fps_VGA_640_480,
|
||||
- ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
|
||||
- {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
|
||||
- 720, 1896, 480, 984,
|
||||
- ov5640_setting_30fps_NTSC_720_480,
|
||||
- ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
|
||||
- {OV5640_MODE_PAL_720_576, SUBSAMPLING,
|
||||
- 720, 1896, 576, 984,
|
||||
- ov5640_setting_30fps_PAL_720_576,
|
||||
- ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
|
||||
- {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
|
||||
- 1024, 1896, 768, 1080,
|
||||
- ov5640_setting_30fps_XGA_1024_768,
|
||||
- ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
|
||||
- {OV5640_MODE_720P_1280_720, SUBSAMPLING,
|
||||
- 1280, 1892, 720, 740,
|
||||
- ov5640_setting_30fps_720P_1280_720,
|
||||
- ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
|
||||
- {OV5640_MODE_1080P_1920_1080, SCALING,
|
||||
- 1920, 2500, 1080, 1120,
|
||||
- ov5640_setting_30fps_1080P_1920_1080,
|
||||
- ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
|
||||
- {OV5640_MODE_QSXGA_2592_1944, -1, 0, 0, 0, 0, NULL, 0},
|
||||
- },
|
||||
+ov5640_mode_data[OV5640_NUM_MODES] = {
|
||||
+ {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
|
||||
+ 176, 1896, 144, 984,
|
||||
+ ov5640_setting_QCIF_176_144,
|
||||
+ ARRAY_SIZE(ov5640_setting_QCIF_176_144)},
|
||||
+ {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
|
||||
+ 320, 1896, 240, 984,
|
||||
+ ov5640_setting_QVGA_320_240,
|
||||
+ ARRAY_SIZE(ov5640_setting_QVGA_320_240)},
|
||||
+ {OV5640_MODE_VGA_640_480, SUBSAMPLING,
|
||||
+ 640, 1896, 480, 1080,
|
||||
+ ov5640_setting_VGA_640_480,
|
||||
+ ARRAY_SIZE(ov5640_setting_VGA_640_480)},
|
||||
+ {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
|
||||
+ 720, 1896, 480, 984,
|
||||
+ ov5640_setting_NTSC_720_480,
|
||||
+ ARRAY_SIZE(ov5640_setting_NTSC_720_480)},
|
||||
+ {OV5640_MODE_PAL_720_576, SUBSAMPLING,
|
||||
+ 720, 1896, 576, 984,
|
||||
+ ov5640_setting_PAL_720_576,
|
||||
+ ARRAY_SIZE(ov5640_setting_PAL_720_576)},
|
||||
+ {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
|
||||
+ 1024, 1896, 768, 1080,
|
||||
+ ov5640_setting_XGA_1024_768,
|
||||
+ ARRAY_SIZE(ov5640_setting_XGA_1024_768)},
|
||||
+ {OV5640_MODE_720P_1280_720, SUBSAMPLING,
|
||||
+ 1280, 1892, 720, 740,
|
||||
+ ov5640_setting_720P_1280_720,
|
||||
+ ARRAY_SIZE(ov5640_setting_720P_1280_720)},
|
||||
+ {OV5640_MODE_1080P_1920_1080, SCALING,
|
||||
+ 1920, 2500, 1080, 1120,
|
||||
+ ov5640_setting_1080P_1920_1080,
|
||||
+ ARRAY_SIZE(ov5640_setting_1080P_1920_1080)},
|
||||
+ {OV5640_MODE_QSXGA_2592_1944, SCALING,
|
||||
+ 2592, 2844, 1944, 1968,
|
||||
+ ov5640_setting_QSXGA_2592_1944,
|
||||
+ ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944)},
|
||||
};
|
||||
|
||||
static int ov5640_init_slave_id(struct ov5640_dev *sensor)
|
||||
@@ -909,6 +698,272 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
|
||||
return ov5640_write_reg(sensor, reg, val);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * After spending way too much time trying the various combinations, I
|
||||
+ * believe the clock tree is as follows:
|
||||
+ *
|
||||
+ * +--------------+
|
||||
+ * | Oscillator |
|
||||
+ * +------+-------+
|
||||
+ * |
|
||||
+ * +------+-------+
|
||||
+ * | System clock | - reg 0x3035, bits 4-7
|
||||
+ * +------+-------+
|
||||
+ * |
|
||||
+ * +------+-------+ - reg 0x3036, for the multiplier
|
||||
+ * | PLL | - reg 0x3037, bits 4 for the root divider
|
||||
+ * +------+-------+ - reg 0x3037, bits 0-3 for the pre-divider
|
||||
+ * |
|
||||
+ * +------+-------+
|
||||
+ * | SCLK | - reg 0x3108, bits 0-1 for the root divider
|
||||
+ * +------+-------+
|
||||
+ * |
|
||||
+ * +------+-------+
|
||||
+ * | PCLK | - reg 0x3108, bits 4-5 for the root divider
|
||||
+ * +--------------+
|
||||
+ *
|
||||
+ * This is deviating from the datasheet at least for the register
|
||||
+ * 0x3108, since it's said here that the PCLK would be clocked from
|
||||
+ * the PLL. However, changing the SCLK divider value has a direct
|
||||
+ * effect on the PCLK rate, which wouldn't be the case if both PCLK
|
||||
+ * and SCLK were to be sourced from the PLL.
|
||||
+ *
|
||||
+ * These parameters also match perfectly the rate that is output by
|
||||
+ * the sensor, so we shouldn't have too much factors missing (or they
|
||||
+ * would be set to 1).
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * FIXME: This is supposed to be ranging from 1 to 16, but the value
|
||||
+ * is always set to either 1 or 2 in the vendor kernels.
|
||||
+ *
|
||||
+ * Moreover issues are seen with SYSDIV set to 1:
|
||||
+ * Strange behaviour is observed when requesting 75MHz pixel clock output
|
||||
+ * for 1280x720 (1892x740) resolution, pixel clock is about 100MHz with
|
||||
+ * blanking (register values: 0x3035=0x11 and 0x3036=0x13).
|
||||
+ * When forcing system clock divider to 2, pixel clock is 75Mhz continuous
|
||||
+ * as expected (register values: 0x3035=0x21 and 0x3036=0x26).
|
||||
+ */
|
||||
+#define OV5640_SYSDIV_MIN 2
|
||||
+#define OV5640_SYSDIV_MAX 2
|
||||
+
|
||||
+static unsigned long ov5640_calc_sysclk(struct ov5640_dev *sensor,
|
||||
+ unsigned long rate,
|
||||
+ u8 *sysdiv)
|
||||
+{
|
||||
+ unsigned long best = ~0;
|
||||
+ u8 best_sysdiv = 1;
|
||||
+ u8 _sysdiv;
|
||||
+
|
||||
+ for (_sysdiv = OV5640_SYSDIV_MIN;
|
||||
+ _sysdiv <= OV5640_SYSDIV_MAX;
|
||||
+ _sysdiv++) {
|
||||
+ unsigned long tmp;
|
||||
+
|
||||
+ tmp = sensor->xclk_freq / _sysdiv;
|
||||
+ if (abs(rate - tmp) < abs(rate - best)) {
|
||||
+ best = tmp;
|
||||
+ best_sysdiv = _sysdiv;
|
||||
+ }
|
||||
+
|
||||
+ if (tmp == rate)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ *sysdiv = best_sysdiv;
|
||||
+ return best;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * FIXME: This is supposed to be ranging from 1 to 8, but the value is
|
||||
+ * always set to 3 in the vendor kernels.
|
||||
+ */
|
||||
+#define OV5640_PLL_PREDIV_MIN 3
|
||||
+#define OV5640_PLL_PREDIV_MAX 3
|
||||
+
|
||||
+/*
|
||||
+ * FIXME: This is supposed to be ranging from 1 to 2, but the value is
|
||||
+ * always set to 1 in the vendor kernels.
|
||||
+ */
|
||||
+#define OV5640_PLL_ROOT_DIV_MIN 1
|
||||
+#define OV5640_PLL_ROOT_DIV_MAX 1
|
||||
+
|
||||
+#define OV5640_PLL_MULT_MIN 4
|
||||
+#define OV5640_PLL_MULT_MAX 252
|
||||
+
|
||||
+static unsigned long ov5640_calc_pll(struct ov5640_dev *sensor,
|
||||
+ unsigned long rate,
|
||||
+ u8 *sysdiv, u8 *prediv, u8 *rdiv, u8 *mult)
|
||||
+{
|
||||
+ unsigned long best = ~0;
|
||||
+ u8 best_sysdiv = 1, best_prediv = 1, best_mult = 1, best_rdiv = 1;
|
||||
+ u8 _prediv, _mult, _rdiv;
|
||||
+
|
||||
+ for (_prediv = OV5640_PLL_PREDIV_MIN;
|
||||
+ _prediv <= OV5640_PLL_PREDIV_MAX;
|
||||
+ _prediv++) {
|
||||
+ for (_mult = OV5640_PLL_MULT_MIN;
|
||||
+ _mult <= OV5640_PLL_MULT_MAX;
|
||||
+ _mult++) {
|
||||
+ for (_rdiv = OV5640_PLL_ROOT_DIV_MIN;
|
||||
+ _rdiv <= OV5640_PLL_ROOT_DIV_MAX;
|
||||
+ _rdiv++) {
|
||||
+ unsigned long pll;
|
||||
+ unsigned long sysclk;
|
||||
+ u8 _sysdiv;
|
||||
+
|
||||
+ /*
|
||||
+ * The PLL multiplier cannot be odd if
|
||||
+ * above 127.
|
||||
+ */
|
||||
+ if (_mult > 127 && !(_mult % 2))
|
||||
+ continue;
|
||||
+
|
||||
+ sysclk = rate * _prediv * _rdiv / _mult;
|
||||
+ sysclk = ov5640_calc_sysclk(sensor, sysclk,
|
||||
+ &_sysdiv);
|
||||
+
|
||||
+ pll = sysclk / _rdiv / _prediv * _mult;
|
||||
+ if (abs(rate - pll) < abs(rate - best)) {
|
||||
+ best = pll;
|
||||
+ best_sysdiv = _sysdiv;
|
||||
+ best_prediv = _prediv;
|
||||
+ best_mult = _mult;
|
||||
+ best_rdiv = _rdiv;
|
||||
+ }
|
||||
+
|
||||
+ if (pll == rate)
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ *sysdiv = best_sysdiv;
|
||||
+ *prediv = best_prediv;
|
||||
+ *mult = best_mult;
|
||||
+ *rdiv = best_rdiv;
|
||||
+
|
||||
+ return best;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * FIXME: This is supposed to be ranging from 1 to 8, but the value is
|
||||
+ * always set to 1 in the vendor kernels.
|
||||
+ */
|
||||
+#define OV5640_PCLK_ROOT_DIV_MIN 1
|
||||
+#define OV5640_PCLK_ROOT_DIV_MAX 1
|
||||
+
|
||||
+static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
|
||||
+ unsigned long rate,
|
||||
+ u8 *sysdiv, u8 *prediv, u8 *pll_rdiv,
|
||||
+ u8 *mult, u8 *pclk_rdiv)
|
||||
+{
|
||||
+ unsigned long best = ~0;
|
||||
+ u8 best_sysdiv = 1, best_prediv = 1, best_mult = 1, best_pll_rdiv = 1;
|
||||
+ u8 best_pclk_rdiv = 1;
|
||||
+ u8 _pclk_rdiv;
|
||||
+
|
||||
+ for (_pclk_rdiv = OV5640_PCLK_ROOT_DIV_MIN;
|
||||
+ _pclk_rdiv <= OV5640_PCLK_ROOT_DIV_MAX;
|
||||
+ _pclk_rdiv <<= 1) {
|
||||
+ unsigned long pll, pclk;
|
||||
+ u8 sysdiv, prediv, mult, pll_rdiv;
|
||||
+
|
||||
+ pll = rate * OV5640_SCLK_ROOT_DIVIDER_DEFAULT * _pclk_rdiv;
|
||||
+ pll = ov5640_calc_pll(sensor, pll, &sysdiv, &prediv, &pll_rdiv,
|
||||
+ &mult);
|
||||
+
|
||||
+ pclk = pll / OV5640_SCLK_ROOT_DIVIDER_DEFAULT / _pclk_rdiv;
|
||||
+ if (abs(rate - pclk) < abs(rate - best)) {
|
||||
+ best = pclk;
|
||||
+ best_sysdiv = sysdiv;
|
||||
+ best_prediv = prediv;
|
||||
+ best_pll_rdiv = pll_rdiv;
|
||||
+ best_pclk_rdiv = _pclk_rdiv;
|
||||
+ best_mult = mult;
|
||||
+ }
|
||||
+
|
||||
+ if (pclk == rate)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ *sysdiv = best_sysdiv;
|
||||
+ *prediv = best_prediv;
|
||||
+ *pll_rdiv = best_pll_rdiv;
|
||||
+ *mult = best_mult;
|
||||
+ *pclk_rdiv = best_pclk_rdiv;
|
||||
+ return best;
|
||||
+}
|
||||
+
|
||||
+static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor,
|
||||
+ const struct ov5640_mode_info *mode,
|
||||
+ unsigned long rate)
|
||||
+{
|
||||
+ u8 sysdiv, prediv, mult, pll_rdiv, pclk_rdiv;
|
||||
+ int ret;
|
||||
+ struct i2c_client *client = sensor->i2c_client;
|
||||
+ u8 dvp_pclk_divider = mode->hact < 1024 ? 2 : 1;//FIXME
|
||||
+ unsigned int pclk_freq, max_pclk_freq;
|
||||
+
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_DVP_PCLK_DIVIDER,
|
||||
+ dvp_pclk_divider);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ pclk_freq = rate / dvp_pclk_divider;
|
||||
+ max_pclk_freq = sensor->ep.bus.parallel.pclk_max_frequency;
|
||||
+
|
||||
+ /* clip rate according to optional maximum pixel clock limit */
|
||||
+ if (max_pclk_freq && (pclk_freq > max_pclk_freq)) {
|
||||
+ rate = max_pclk_freq * dvp_pclk_divider;
|
||||
+ dev_dbg(&client->dev, "DVP pixel clock too high (%d > %d Hz), reducing rate...\n",
|
||||
+ pclk_freq, max_pclk_freq);
|
||||
+ }
|
||||
+
|
||||
+ ov5640_calc_pclk(sensor, rate, &sysdiv, &prediv, &pll_rdiv, &mult,
|
||||
+ &pclk_rdiv);
|
||||
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
|
||||
+ 0xf0, sysdiv << 4);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL2,
|
||||
+ 0xff, mult);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
|
||||
+ 0xff, prediv | ((pll_rdiv - 1) << 4));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER,
|
||||
+ 0x30, ilog2(pclk_rdiv) << 4);
|
||||
+}
|
||||
+
|
||||
+static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor, unsigned long rate)
|
||||
+{
|
||||
+ u8 sysdiv, prediv, mult, pll_rdiv, pclk_rdiv;
|
||||
+ int ret;
|
||||
+
|
||||
+ ov5640_calc_pclk(sensor, rate, &sysdiv, &prediv, &pll_rdiv, &mult,
|
||||
+ &pclk_rdiv);
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
|
||||
+ (sysdiv << 4) | pclk_rdiv);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL2,
|
||||
+ 0xff, mult);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
|
||||
+ 0xff, prediv | ((pll_rdiv - 1) << 4));
|
||||
+}
|
||||
+
|
||||
/* download ov5640 settings to sensor through i2c */
|
||||
static int ov5640_set_timings(struct ov5640_dev *sensor,
|
||||
const struct ov5640_mode_info *mode)
|
||||
@@ -1444,8 +1499,8 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
|
||||
{
|
||||
const struct ov5640_mode_info *mode;
|
||||
|
||||
- mode = v4l2_find_nearest_size(ov5640_mode_data[fr],
|
||||
- ARRAY_SIZE(ov5640_mode_data[fr]),
|
||||
+ mode = v4l2_find_nearest_size(ov5640_mode_data,
|
||||
+ ARRAY_SIZE(ov5640_mode_data),
|
||||
hact, vact,
|
||||
width, height);
|
||||
|
||||
@@ -1637,8 +1692,12 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
|
||||
enum ov5640_downsize_mode dn_mode, orig_dn_mode;
|
||||
bool auto_gain = sensor->ctrls.auto_gain->val == 1;
|
||||
bool auto_exp = sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
|
||||
+ unsigned long rate;
|
||||
int ret;
|
||||
|
||||
+ if (!orig_mode)
|
||||
+ orig_mode = mode;
|
||||
+
|
||||
dn_mode = mode->dn_mode;
|
||||
orig_dn_mode = orig_mode->dn_mode;
|
||||
|
||||
@@ -1655,6 +1714,24 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
|
||||
goto restore_auto_gain;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * All the formats we support have 2 bytes per pixel, except for JPEG
|
||||
+ * which is 1 byte per pixel, but JPEG requires the same rate
|
||||
+ * than YUV (horizontal lines blanking).
|
||||
+ */
|
||||
+ rate = mode->vtot * mode->htot * 2;
|
||||
+ rate *= ov5640_framerates[sensor->current_fr];
|
||||
+
|
||||
+ if (sensor->ep.bus_type == V4L2_MBUS_CSI2) {
|
||||
+ rate = rate / sensor->ep.bus.mipi_csi2.num_data_lanes;
|
||||
+ ret = ov5640_set_mipi_pclk(sensor, rate);
|
||||
+ } else {
|
||||
+ ret = ov5640_set_dvp_pclk(sensor, mode, rate);
|
||||
+ }
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ return 0;
|
||||
+
|
||||
if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
|
||||
(dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
|
||||
/*
|
||||
@@ -2502,10 +2579,10 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
|
||||
return -EINVAL;
|
||||
|
||||
fse->min_width =
|
||||
- ov5640_mode_data[0][fse->index].hact;
|
||||
+ ov5640_mode_data[fse->index].hact;
|
||||
fse->max_width = fse->min_width;
|
||||
fse->min_height =
|
||||
- ov5640_mode_data[0][fse->index].vact;
|
||||
+ ov5640_mode_data[fse->index].vact;
|
||||
fse->max_height = fse->min_height;
|
||||
|
||||
return 0;
|
||||
@@ -2573,8 +2650,6 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
|
||||
if (frame_rate < 0)
|
||||
frame_rate = OV5640_15_FPS;
|
||||
|
||||
- sensor->current_fr = frame_rate;
|
||||
- sensor->frame_interval = fi->interval;
|
||||
mode = ov5640_find_mode(sensor, frame_rate, mode->hact,
|
||||
mode->vact, true);
|
||||
if (!mode) {
|
||||
@@ -2582,7 +2657,10 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (mode != sensor->current_mode) {
|
||||
+ if (mode != sensor->current_mode ||
|
||||
+ (frame_rate != sensor->current_fr)) {
|
||||
+ sensor->current_fr = frame_rate;
|
||||
+ sensor->frame_interval = fi->interval;
|
||||
sensor->current_mode = mode;
|
||||
sensor->pending_mode_change = true;
|
||||
}
|
||||
@@ -2613,7 +2691,8 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
|
||||
if (sensor->streaming == !enable) {
|
||||
if (enable && sensor->pending_mode_change) {
|
||||
- ret = ov5640_set_mode(sensor);
|
||||
+ ret = ov5640_set_mode(sensor, sensor->last_mode);
|
||||
+
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
@@ -2735,7 +2814,7 @@ static int ov5640_probe(struct i2c_client *client,
|
||||
sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS];
|
||||
sensor->current_fr = OV5640_30_FPS;
|
||||
sensor->current_mode =
|
||||
- &ov5640_mode_data[OV5640_30_FPS][OV5640_MODE_VGA_640_480];
|
||||
+ &ov5640_mode_data[OV5640_MODE_VGA_640_480];
|
||||
sensor->last_mode = sensor->current_mode;
|
||||
|
||||
sensor->ae_target = 52;
|
||||
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
|
||||
index 7215641..49849e6 100644
|
||||
--- a/drivers/media/platform/stm32/stm32-dcmi.c
|
||||
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
|
||||
@@ -95,6 +95,9 @@ enum state {
|
||||
#define MIN_HEIGHT 16U
|
||||
#define MAX_HEIGHT 2592U
|
||||
|
||||
+/* DMA can sustain YUV 720p@15fps max */
|
||||
+#define MAX_DMA_BANDWIDTH (1280 * 720 * 2 * 15)
|
||||
+
|
||||
#define TIMEOUT_MS 1000
|
||||
|
||||
struct dcmi_graph_entity {
|
||||
@@ -570,9 +573,9 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_get_sync(dcmi->dev);
|
||||
- if (ret) {
|
||||
- dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync\n",
|
||||
- __func__);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync (%d)\n",
|
||||
+ __func__, ret);
|
||||
goto err_release_buffers;
|
||||
}
|
||||
|
||||
@@ -621,8 +624,31 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
dcmi_set_crop(dcmi);
|
||||
|
||||
/* Enable jpeg capture */
|
||||
- if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG)
|
||||
- reg_set(dcmi->regs, DCMI_CR, CR_CM);/* Snapshot mode */
|
||||
+ if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG) {
|
||||
+ unsigned int rate;
|
||||
+ struct v4l2_streamparm p = {
|
||||
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
|
||||
+ };
|
||||
+ struct v4l2_fract frame_interval = {1, 30};
|
||||
+
|
||||
+ ret = v4l2_g_parm_cap(dcmi->vdev, dcmi->entity.subdev, &p);
|
||||
+ if (!ret)
|
||||
+ frame_interval = p.parm.capture.timeperframe;
|
||||
+
|
||||
+ rate = dcmi->fmt.fmt.pix.sizeimage *
|
||||
+ frame_interval.denominator / frame_interval.numerator;
|
||||
+
|
||||
+ /*
|
||||
+ * If rate exceed DMA capabilities, switch to snapshot mode
|
||||
+ * to ensure that current DMA transfer is elapsed before
|
||||
+ * capturing a new JPEG.
|
||||
+ */
|
||||
+ if (rate > MAX_DMA_BANDWIDTH) {
|
||||
+ reg_set(dcmi->regs, DCMI_CR, CR_CM);/* Snapshot mode */
|
||||
+ dev_dbg(dcmi->dev, "Capture rate is too high for continuous mode (%d > %d bytes/s), switch to snapshot mode\n",
|
||||
+ rate, MAX_DMA_BANDWIDTH);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/* Enable dcmi */
|
||||
reg_set(dcmi->regs, DCMI_CR, CR_ENABLE);
|
||||
@@ -659,7 +685,10 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
}
|
||||
|
||||
/* Enable interruptions */
|
||||
- reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
|
||||
+ if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG)
|
||||
+ reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
|
||||
+ else
|
||||
+ reg_set(dcmi->regs, DCMI_IER, IT_OVR | IT_ERR);
|
||||
|
||||
return 0;
|
||||
|
||||
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
|
||||
index 169bdbb..505338e 100644
|
||||
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
|
||||
@@ -158,6 +158,9 @@ static void v4l2_fwnode_endpoint_parse_parallel_bus(
|
||||
flags |= v ? V4L2_MBUS_DATA_ENABLE_HIGH :
|
||||
V4L2_MBUS_DATA_ENABLE_LOW;
|
||||
|
||||
+ if (!fwnode_property_read_u32(fwnode, "pclk-max-frequency", &v))
|
||||
+ bus->pclk_max_frequency = v;
|
||||
+
|
||||
bus->flags = flags;
|
||||
|
||||
}
|
||||
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
|
||||
index 9cccab6..946b48d 100644
|
||||
--- a/include/media/v4l2-fwnode.h
|
||||
+++ b/include/media/v4l2-fwnode.h
|
||||
@@ -52,11 +52,13 @@ struct v4l2_fwnode_bus_mipi_csi2 {
|
||||
* @flags: media bus (V4L2_MBUS_*) flags
|
||||
* @bus_width: bus width in bits
|
||||
* @data_shift: data shift in bits
|
||||
+ * @max_pclk_frequency: maximum pixel clock in hertz
|
||||
*/
|
||||
struct v4l2_fwnode_bus_parallel {
|
||||
unsigned int flags;
|
||||
unsigned char bus_width;
|
||||
unsigned char data_shift;
|
||||
+ unsigned int pclk_max_frequency;
|
||||
};
|
||||
|
||||
/**
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,288 +0,0 @@
|
|||
From 85d48072cfb2e491d10a235c4ade2460e3bbc93a Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Mon, 26 Nov 2018 14:40:42 +0100
|
||||
Subject: [PATCH 21/52] ARM-stm32mp1-r0-rc2-PINCTRL
|
||||
|
||||
---
|
||||
.../bindings/pinctrl/st,stm32-pinctrl.txt | 1 +
|
||||
drivers/pinctrl/core.c | 15 +----
|
||||
drivers/pinctrl/pinctrl-stmfx.c | 8 +++
|
||||
drivers/pinctrl/stm32/pinctrl-stm32.c | 71 +++++++++++++++++++++-
|
||||
include/linux/pinctrl/pinctrl.h | 2 +
|
||||
5 files changed, 83 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
|
||||
index 286c981..1a5d1e2 100644
|
||||
--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
|
||||
+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
|
||||
@@ -58,6 +58,7 @@ Optional properties:
|
||||
used to select GPIOs as interrupts).
|
||||
- st,package: Indicates the SOC package used.
|
||||
More details in include/dt-bindings/pinctrl/stm32-pinfunc.h
|
||||
+ - hwlocks: reference to a phandle of a hardware spinlock provider node.
|
||||
|
||||
Example 1:
|
||||
#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
|
||||
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
|
||||
index a3dd777..0220d43 100644
|
||||
--- a/drivers/pinctrl/core.c
|
||||
+++ b/drivers/pinctrl/core.c
|
||||
@@ -1992,7 +1992,7 @@ pinctrl_init_controller(struct pinctrl_desc *pctldesc, struct device *dev,
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
-static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
|
||||
+int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
pctldev->p = create_pinctrl(pctldev->dev, pctldev);
|
||||
if (PTR_ERR(pctldev->p) == -ENODEV) {
|
||||
@@ -2030,21 +2030,10 @@ static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(pinctrl_claim_hogs);
|
||||
|
||||
int pinctrl_enable(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
- int error;
|
||||
-
|
||||
- error = pinctrl_claim_hogs(pctldev);
|
||||
- if (error) {
|
||||
- dev_err(pctldev->dev, "could not claim hogs: %i\n",
|
||||
- error);
|
||||
- mutex_destroy(&pctldev->mutex);
|
||||
- kfree(pctldev);
|
||||
-
|
||||
- return error;
|
||||
- }
|
||||
-
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
list_add_tail(&pctldev->node, &pinctrldev_list);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
|
||||
index e253ed1..15d5757 100644
|
||||
--- a/drivers/pinctrl/pinctrl-stmfx.c
|
||||
+++ b/drivers/pinctrl/pinctrl-stmfx.c
|
||||
@@ -663,6 +663,14 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ /*
|
||||
+ * Claim hogs after enabling gpio function, otherwise pin
|
||||
+ * configuration will not apply
|
||||
+ */
|
||||
+ ret = pinctrl_claim_hogs(pctl->pctl_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
pctl->irq_chip.name = dev_name(pctl->dev);
|
||||
pctl->irq_chip.irq_mask = stmfx_pinctrl_irq_mask;
|
||||
pctl->irq_chip.irq_unmask = stmfx_pinctrl_irq_unmask;
|
||||
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||
index e25917f..914bee4 100644
|
||||
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
+#include <linux/hwspinlock.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
@@ -64,6 +65,8 @@
|
||||
#define gpio_range_to_bank(chip) \
|
||||
container_of(chip, struct stm32_gpio_bank, range)
|
||||
|
||||
+#define HWSPINLOCK_TIMEOUT 5 /* msec */
|
||||
+
|
||||
static const char * const stm32_gpio_functions[] = {
|
||||
"gpio", "af0", "af1",
|
||||
"af2", "af3", "af4",
|
||||
@@ -111,6 +114,7 @@ struct stm32_pinctrl {
|
||||
u32 npins;
|
||||
u32 pkg;
|
||||
u32 pin_base_shift;
|
||||
+ struct hwspinlock *hwlock;
|
||||
};
|
||||
|
||||
static inline int stm32_gpio_pin(int gpio)
|
||||
@@ -598,14 +602,24 @@ static int stm32_pmx_get_func_groups(struct pinctrl_dev *pctldev,
|
||||
static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||
int pin, u32 mode, u32 alt)
|
||||
{
|
||||
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
u32 val;
|
||||
int alt_shift = (pin % 8) * 4;
|
||||
int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4;
|
||||
unsigned long flags;
|
||||
+ int err = 0;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
+ if (pctl->hwlock)
|
||||
+ err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||
+
|
||||
+ if (err) {
|
||||
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
val = readl_relaxed(bank->base + alt_offset);
|
||||
val &= ~GENMASK(alt_shift + 3, alt_shift);
|
||||
val |= (alt << alt_shift);
|
||||
@@ -618,6 +632,10 @@ static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||
|
||||
stm32_gpio_backup_mode(bank, pin, mode, alt);
|
||||
|
||||
+ if (pctl->hwlock)
|
||||
+ hwspin_unlock(pctl->hwlock);
|
||||
+
|
||||
+unlock:
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
clk_disable(bank->clk);
|
||||
}
|
||||
@@ -707,12 +725,22 @@ static const struct pinmux_ops stm32_pmx_ops = {
|
||||
static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||
unsigned offset, u32 drive)
|
||||
{
|
||||
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
+ int err = 0;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
+ if (pctl->hwlock)
|
||||
+ err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||
+
|
||||
+ if (err) {
|
||||
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
val = readl_relaxed(bank->base + STM32_GPIO_TYPER);
|
||||
val &= ~BIT(offset);
|
||||
val |= drive << offset;
|
||||
@@ -720,6 +748,10 @@ static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||
|
||||
stm32_gpio_backup_driving(bank, offset, drive);
|
||||
|
||||
+ if (pctl->hwlock)
|
||||
+ hwspin_unlock(pctl->hwlock);
|
||||
+
|
||||
+unlock:
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
clk_disable(bank->clk);
|
||||
}
|
||||
@@ -745,12 +777,22 @@ static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank,
|
||||
static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||
unsigned offset, u32 speed)
|
||||
{
|
||||
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
+ int err = 0;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
+ if (pctl->hwlock)
|
||||
+ err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||
+
|
||||
+ if (err) {
|
||||
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR);
|
||||
val &= ~GENMASK(offset * 2 + 1, offset * 2);
|
||||
val |= speed << (offset * 2);
|
||||
@@ -758,6 +800,10 @@ static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||
|
||||
stm32_gpio_backup_speed(bank, offset, speed);
|
||||
|
||||
+ if (pctl->hwlock)
|
||||
+ hwspin_unlock(pctl->hwlock);
|
||||
+
|
||||
+unlock:
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
clk_disable(bank->clk);
|
||||
}
|
||||
@@ -783,12 +829,22 @@ static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank,
|
||||
static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||
unsigned offset, u32 bias)
|
||||
{
|
||||
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
+ int err = 0;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
+ if (pctl->hwlock)
|
||||
+ err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||
+
|
||||
+ if (err) {
|
||||
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
val = readl_relaxed(bank->base + STM32_GPIO_PUPDR);
|
||||
val &= ~GENMASK(offset * 2 + 1, offset * 2);
|
||||
val |= bias << (offset * 2);
|
||||
@@ -796,6 +852,10 @@ static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||
|
||||
stm32_gpio_backup_bias(bank, offset, bias);
|
||||
|
||||
+ if (pctl->hwlock)
|
||||
+ hwspin_unlock(pctl->hwlock);
|
||||
+
|
||||
+unlock:
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
clk_disable(bank->clk);
|
||||
}
|
||||
@@ -1206,7 +1266,7 @@ int stm32_pctl_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct stm32_pinctrl *pctl;
|
||||
struct pinctrl_pin_desc *pins;
|
||||
- int i, ret, banks = 0;
|
||||
+ int i, ret, hwlock_id, banks = 0;
|
||||
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
@@ -1226,6 +1286,15 @@ int stm32_pctl_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, pctl);
|
||||
|
||||
+ /* hwspinlock is optional */
|
||||
+ hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
|
||||
+ if (hwlock_id < 0) {
|
||||
+ if (hwlock_id == -EPROBE_DEFER)
|
||||
+ return hwlock_id;
|
||||
+ } else {
|
||||
+ pctl->hwlock = hwspin_lock_request_specific(hwlock_id);
|
||||
+ }
|
||||
+
|
||||
pctl->dev = dev;
|
||||
pctl->match_data = match->data;
|
||||
|
||||
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
|
||||
index 8f5dbb8..bbeaa29 100644
|
||||
--- a/include/linux/pinctrl/pinctrl.h
|
||||
+++ b/include/linux/pinctrl/pinctrl.h
|
||||
@@ -148,6 +148,8 @@ extern int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
|
||||
struct pinctrl_dev **pctldev);
|
||||
extern int pinctrl_enable(struct pinctrl_dev *pctldev);
|
||||
|
||||
+extern int pinctrl_claim_hogs(struct pinctrl_dev *pctldev);
|
||||
+
|
||||
/* Please use pinctrl_register_and_init() and pinctrl_enable() instead */
|
||||
extern struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||
struct device *dev, void *driver_data);
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,781 +0,0 @@
|
|||
From aed35270f0be1c5c61a028d7c183e60269f3abe3 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Mon, 26 Nov 2018 14:41:37 +0100
|
||||
Subject: [PATCH 22/52] ARM-stm32mp1-r0-rc2-MFD-IRQ
|
||||
|
||||
---
|
||||
.../interrupt-controller/st,stm32-exti.txt | 34 +++++-
|
||||
.../devicetree/bindings/mfd/st,stpmic1.txt | 2 +-
|
||||
Documentation/devicetree/bindings/mfd/syscon.txt | 1 +
|
||||
drivers/irqchip/irq-stm32-exti.c | 133 ++++++++++++++++++---
|
||||
drivers/mfd/stm32-pwr.c | 131 +++++++++-----------
|
||||
drivers/mfd/stpmic1.c | 16 +--
|
||||
drivers/mfd/syscon.c | 19 +++
|
||||
drivers/mfd/wm8994-core.c | 15 +++
|
||||
include/linux/mfd/stpmic1.h | 1 -
|
||||
9 files changed, 247 insertions(+), 105 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
|
||||
index 6a36bf6..abcf816 100644
|
||||
--- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
|
||||
+++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
|
||||
@@ -14,7 +14,23 @@ Required properties:
|
||||
(only needed for exti controller with multiple exti under
|
||||
same parent interrupt: st,stm32-exti and st,stm32h7-exti)
|
||||
|
||||
-Example:
|
||||
+Optional properties:
|
||||
+
|
||||
+- hwlocks: reference to a phandle of a hardware spinlock provider node.
|
||||
+
|
||||
+Exti could have several parent interrupt controllers. In this case child nodes
|
||||
+are used to describe those "extra" parent controllers. Properties to use are:
|
||||
+
|
||||
+- interrupt-controller: Indentifies the node as an interrupt controller
|
||||
+- #interrupt-cells: Specifies the number of cells to encode an interrupt
|
||||
+ specifier, shall be 2
|
||||
+- interrupt-parent: Phandle to the interrupt parent node.
|
||||
+- st,irq-number: Interrupt number mapped on the parent.
|
||||
+
|
||||
+See example 2.
|
||||
+
|
||||
+
|
||||
+Example 1:
|
||||
|
||||
exti: interrupt-controller@40013c00 {
|
||||
compatible = "st,stm32-exti";
|
||||
@@ -23,3 +39,19 @@ exti: interrupt-controller@40013c00 {
|
||||
reg = <0x40013C00 0x400>;
|
||||
interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>;
|
||||
};
|
||||
+
|
||||
+Example 2:
|
||||
+
|
||||
+exti: interrupt-controller@5000d000 {
|
||||
+ compatible = "st,stm32mp1-exti", "syscon";
|
||||
+ interrupt-controller;
|
||||
+ #interrupt-cells = <2>;
|
||||
+ reg = <0x5000d000 0x400>;
|
||||
+
|
||||
+ exti_pwr: exti-pwr {
|
||||
+ interrupt-controller;
|
||||
+ #interrupt-cells = <2>;
|
||||
+ interrupt-parent = <&pwr>;
|
||||
+ st,irq-number = <6>;
|
||||
+ };
|
||||
+};
|
||||
diff --git a/Documentation/devicetree/bindings/mfd/st,stpmic1.txt b/Documentation/devicetree/bindings/mfd/st,stpmic1.txt
|
||||
index 54b64e2..0fab08a 100644
|
||||
--- a/Documentation/devicetree/bindings/mfd/st,stpmic1.txt
|
||||
+++ b/Documentation/devicetree/bindings/mfd/st,stpmic1.txt
|
||||
@@ -4,7 +4,6 @@ Required parent device properties:
|
||||
- compatible: "st,stpmic1"
|
||||
- reg: The I2C slave address for the STPMIC1 chip.
|
||||
- interrupts: The interrupt lines the device is connected to.
|
||||
- The second interrupt is used for wake-up.
|
||||
- #interrupt-cells: Should be 2.
|
||||
- interrupt-controller: Describes the STPMIC1 as an interrupt
|
||||
controller (has its own domain). Interrupt number are the following:
|
||||
@@ -81,6 +80,7 @@ Optional parent device properties:
|
||||
-bit 5: SW_OUT discharge is enabled
|
||||
-bit 6: VBUS_OTG detection is enabled
|
||||
-bit 7: BOOST_OVP is disabled
|
||||
+- wakeup-source: bool flag to indicate this device has wakeup capabilities
|
||||
|
||||
STPMIC1 consists in a varied group of sub-devices.
|
||||
Each sub-device binding is be described in own documentation file.
|
||||
diff --git a/Documentation/devicetree/bindings/mfd/syscon.txt b/Documentation/devicetree/bindings/mfd/syscon.txt
|
||||
index 25d9e9c..a9aaa51 100644
|
||||
--- a/Documentation/devicetree/bindings/mfd/syscon.txt
|
||||
+++ b/Documentation/devicetree/bindings/mfd/syscon.txt
|
||||
@@ -17,6 +17,7 @@ Optional property:
|
||||
- reg-io-width: the size (in bytes) of the IO accesses that should be
|
||||
performed on the device.
|
||||
- hwlocks: reference to a phandle of a hardware spinlock provider node.
|
||||
+- clocks: phandle to the syscon clock
|
||||
|
||||
Examples:
|
||||
gpr: iomuxc-gpr@20e0000 {
|
||||
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
|
||||
index e185ed8..9cc15f1 100644
|
||||
--- a/drivers/irqchip/irq-stm32-exti.c
|
||||
+++ b/drivers/irqchip/irq-stm32-exti.c
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
+#include <linux/hwspinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
@@ -20,6 +21,8 @@
|
||||
|
||||
#define IRQS_PER_BANK 32
|
||||
|
||||
+#define HWSPINLOCK_TIMEOUT 5 /* msec */
|
||||
+
|
||||
struct stm32_exti_bank {
|
||||
u32 imr_ofst;
|
||||
u32 emr_ofst;
|
||||
@@ -47,6 +50,7 @@ struct stm32_exti_drv_data {
|
||||
struct stm32_exti_chip_data {
|
||||
struct stm32_exti_host_data *host_data;
|
||||
const struct stm32_exti_bank *reg_bank;
|
||||
+ struct hwspinlock *hwlock;
|
||||
struct raw_spinlock rlock;
|
||||
u32 wake_active;
|
||||
u32 mask_cache;
|
||||
@@ -275,25 +279,34 @@ static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
struct stm32_exti_chip_data *chip_data = gc->private;
|
||||
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
|
||||
u32 rtsr, ftsr;
|
||||
- int err;
|
||||
+ int err = 0;
|
||||
|
||||
irq_gc_lock(gc);
|
||||
|
||||
+ if (chip_data->hwlock)
|
||||
+ err = hwspin_lock_timeout(chip_data->hwlock,
|
||||
+ HWSPINLOCK_TIMEOUT);
|
||||
+
|
||||
+ if (err)
|
||||
+ goto unlock;
|
||||
+
|
||||
rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
|
||||
ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
|
||||
|
||||
err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
|
||||
- if (err) {
|
||||
- irq_gc_unlock(gc);
|
||||
- return err;
|
||||
- }
|
||||
+ if (err)
|
||||
+ goto unspinlock;
|
||||
|
||||
irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
|
||||
irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
|
||||
|
||||
+unspinlock:
|
||||
+ if (chip_data->hwlock)
|
||||
+ hwspin_unlock(chip_data->hwlock);
|
||||
+unlock:
|
||||
irq_gc_unlock(gc);
|
||||
|
||||
- return 0;
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static void stm32_chip_suspend(struct stm32_exti_chip_data *chip_data,
|
||||
@@ -457,22 +470,36 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type)
|
||||
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
|
||||
void __iomem *base = chip_data->host_data->base;
|
||||
u32 rtsr, ftsr;
|
||||
- int err;
|
||||
+ int err = 0;
|
||||
|
||||
raw_spin_lock(&chip_data->rlock);
|
||||
+
|
||||
+ if (chip_data->hwlock)
|
||||
+ err = hwspin_lock_timeout(chip_data->hwlock,
|
||||
+ HWSPINLOCK_TIMEOUT);
|
||||
+
|
||||
+ if (err)
|
||||
+ goto unlock;
|
||||
+
|
||||
rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst);
|
||||
ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst);
|
||||
|
||||
err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
|
||||
- if (err) {
|
||||
- raw_spin_unlock(&chip_data->rlock);
|
||||
- return err;
|
||||
- }
|
||||
+ if (err)
|
||||
+ goto unspinlock;
|
||||
|
||||
writel_relaxed(rtsr, base + stm32_bank->rtsr_ofst);
|
||||
writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst);
|
||||
+
|
||||
+unspinlock:
|
||||
+ if (chip_data->hwlock)
|
||||
+ hwspin_unlock(chip_data->hwlock);
|
||||
+unlock:
|
||||
raw_spin_unlock(&chip_data->rlock);
|
||||
|
||||
+ if (d->parent_data->chip)
|
||||
+ irq_chip_set_type_parent(d, type);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -490,6 +517,9 @@ static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on)
|
||||
|
||||
raw_spin_unlock(&chip_data->rlock);
|
||||
|
||||
+ if (d->parent_data->chip)
|
||||
+ irq_chip_set_wake_parent(d, on);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -502,6 +532,12 @@ static int stm32_exti_h_set_affinity(struct irq_data *d,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+static void stm32_exti_h_ack(struct irq_data *d)
|
||||
+{
|
||||
+ if (d->parent_data->chip)
|
||||
+ irq_chip_ack_parent(d);
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_PM
|
||||
static int stm32_exti_h_suspend(void)
|
||||
{
|
||||
@@ -547,6 +583,7 @@ static inline void stm32_exti_h_syscore_init(void) {}
|
||||
static struct irq_chip stm32_exti_h_chip = {
|
||||
.name = "stm32-exti-h",
|
||||
.irq_eoi = stm32_exti_h_eoi,
|
||||
+ .irq_ack = stm32_exti_h_ack,
|
||||
.irq_mask = stm32_exti_h_mask,
|
||||
.irq_unmask = stm32_exti_h_unmask,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
@@ -574,15 +611,29 @@ static int stm32_exti_h_domain_alloc(struct irq_domain *dm,
|
||||
irq_domain_set_hwirq_and_chip(dm, virq, hwirq,
|
||||
&stm32_exti_h_chip, chip_data);
|
||||
|
||||
- p_irq = stm32_exti_to_irq(host_data->drv_data, hwirq);
|
||||
- if (p_irq >= 0) {
|
||||
+ /*
|
||||
+ * EXTI 55 to 60 are mapped to PWR interrupt controller.
|
||||
+ * The hwirq translation is done diferently than for GIC.
|
||||
+ */
|
||||
+ if (hwirq >= 55 && hwirq <= 60) {
|
||||
p_fwspec.fwnode = dm->parent->fwnode;
|
||||
- p_fwspec.param_count = 3;
|
||||
- p_fwspec.param[0] = GIC_SPI;
|
||||
- p_fwspec.param[1] = p_irq;
|
||||
- p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
|
||||
+ p_fwspec.param_count = 2;
|
||||
+ p_fwspec.param[0] = hwirq - 55;
|
||||
+ p_fwspec.param[1] = fwspec->param[1];
|
||||
|
||||
return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec);
|
||||
+ } else {
|
||||
+ p_irq = stm32_exti_to_irq(host_data->drv_data, hwirq);
|
||||
+ if (p_irq >= 0) {
|
||||
+ p_fwspec.fwnode = dm->parent->fwnode;
|
||||
+ p_fwspec.param_count = 3;
|
||||
+ p_fwspec.param[0] = GIC_SPI;
|
||||
+ p_fwspec.param[1] = p_irq;
|
||||
+ p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
|
||||
+
|
||||
+ return irq_domain_alloc_irqs_parent(dm, virq, 1,
|
||||
+ &p_fwspec);
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -665,6 +716,7 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||
int nr_irqs, ret, i;
|
||||
struct irq_chip_generic *gc;
|
||||
struct irq_domain *domain;
|
||||
+ struct hwspinlock *hwlock = NULL;
|
||||
|
||||
host_data = stm32_exti_host_init(drv_data, node);
|
||||
if (!host_data)
|
||||
@@ -687,12 +739,22 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||
goto out_free_domain;
|
||||
}
|
||||
|
||||
+ /* hwspinlock is optional */
|
||||
+ ret = of_hwspin_lock_get_id(node, 0);
|
||||
+ if (ret < 0) {
|
||||
+ if (ret == -EPROBE_DEFER)
|
||||
+ goto out_free_domain;
|
||||
+ } else {
|
||||
+ hwlock = hwspin_lock_request_specific(ret);
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < drv_data->bank_nr; i++) {
|
||||
const struct stm32_exti_bank *stm32_bank;
|
||||
struct stm32_exti_chip_data *chip_data;
|
||||
|
||||
stm32_bank = drv_data->exti_banks[i];
|
||||
chip_data = stm32_exti_chip_init(host_data, i, node);
|
||||
+ chip_data->hwlock = hwlock;
|
||||
|
||||
gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
|
||||
|
||||
@@ -760,11 +822,12 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||
{
|
||||
struct irq_domain *parent_domain, *domain;
|
||||
struct stm32_exti_host_data *host_data;
|
||||
+ struct device_node *child;
|
||||
int ret, i;
|
||||
|
||||
parent_domain = irq_find_host(parent);
|
||||
if (!parent_domain) {
|
||||
- pr_err("interrupt-parent not found\n");
|
||||
+ pr_err("GIC interrupt-parent not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -786,6 +849,40 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
+ for_each_child_of_node(node, child) {
|
||||
+ struct device_node *parent_node;
|
||||
+ u32 nirqs;
|
||||
+
|
||||
+ parent_node = of_irq_find_parent(child);
|
||||
+ parent_domain = irq_find_host(parent_node);
|
||||
+
|
||||
+ if (!parent_domain) {
|
||||
+ pr_err("%s: child interrupt-parent not found\n",
|
||||
+ child->name);
|
||||
+ ret = -EINVAL;
|
||||
+ goto out_unmap;
|
||||
+ }
|
||||
+
|
||||
+ ret = of_property_read_u32(child, "st,irq-number", &nirqs);
|
||||
+ if (ret != 0 || nirqs == 0) {
|
||||
+ pr_err("%s: Missing or bad irq-number property\n"
|
||||
+ , __func__);
|
||||
+ ret = -EINVAL;
|
||||
+ goto out_unmap;
|
||||
+ }
|
||||
+
|
||||
+ domain = irq_domain_add_hierarchy(parent_domain, 0, nirqs,
|
||||
+ child,
|
||||
+ &stm32_exti_h_domain_ops,
|
||||
+ host_data);
|
||||
+ if (!domain) {
|
||||
+ pr_err("%s: Could not register exti domain.\n",
|
||||
+ node->name);
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out_unmap;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
stm32_exti_h_syscore_init();
|
||||
|
||||
return 0;
|
||||
diff --git a/drivers/mfd/stm32-pwr.c b/drivers/mfd/stm32-pwr.c
|
||||
index 377e2f5..206a933 100644
|
||||
--- a/drivers/mfd/stm32-pwr.c
|
||||
+++ b/drivers/mfd/stm32-pwr.c
|
||||
@@ -5,7 +5,9 @@
|
||||
*/
|
||||
|
||||
#include <linux/arm-smccc.h>
|
||||
+#include <linux/irqchip.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
+#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/exception.h>
|
||||
@@ -45,7 +47,6 @@ enum wkup_pull_setting {
|
||||
} \
|
||||
|
||||
struct stm32_pwr_data {
|
||||
- struct device *dev; /* self device */
|
||||
void __iomem *base; /* IO Memory base address */
|
||||
struct irq_domain *domain; /* Domain for this controller */
|
||||
int irq; /* Parent interrupt */
|
||||
@@ -53,25 +54,19 @@ struct stm32_pwr_data {
|
||||
|
||||
static void stm32_pwr_irq_ack(struct irq_data *d)
|
||||
{
|
||||
- struct stm32_pwr_data *priv = d->domain->host_data;
|
||||
-
|
||||
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
|
||||
+ pr_debug("irq:%lu\n", d->hwirq);
|
||||
SMC(STM32_SVC_PWR, STM32_SET_BITS, WKUPCR, BIT(d->hwirq));
|
||||
}
|
||||
|
||||
static void stm32_pwr_irq_mask(struct irq_data *d)
|
||||
{
|
||||
- struct stm32_pwr_data *priv = d->domain->host_data;
|
||||
-
|
||||
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
|
||||
+ pr_debug("irq:%lu\n", d->hwirq);
|
||||
SMC(STM32_SVC_PWR, STM32_CLEAR_BITS, MPUWKUPENR, BIT(d->hwirq));
|
||||
}
|
||||
|
||||
static void stm32_pwr_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
- struct stm32_pwr_data *priv = d->domain->host_data;
|
||||
-
|
||||
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
|
||||
+ pr_debug("irq:%lu\n", d->hwirq);
|
||||
SMC(STM32_SVC_PWR, STM32_SET_BITS, MPUWKUPENR, BIT(d->hwirq));
|
||||
}
|
||||
|
||||
@@ -79,7 +74,7 @@ static int stm32_pwr_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
struct stm32_pwr_data *priv = d->domain->host_data;
|
||||
|
||||
- dev_dbg(priv->dev, "irq:%lu on:%d\n", d->hwirq, on);
|
||||
+ pr_debug("irq:%lu on:%d\n", d->hwirq, on);
|
||||
if (on)
|
||||
enable_irq_wake(priv->irq);
|
||||
else
|
||||
@@ -95,7 +90,7 @@ static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
u32 wkupcr;
|
||||
int en;
|
||||
|
||||
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
|
||||
+ pr_debug("irq:%lu\n", d->hwirq);
|
||||
|
||||
en = readl_relaxed(priv->base + MPUWKUPENR) & BIT(pin_id);
|
||||
/* reference manual request to disable the wakeup pin while
|
||||
@@ -115,6 +110,7 @@ static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
+
|
||||
SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr);
|
||||
|
||||
if (en)
|
||||
@@ -124,7 +120,7 @@ static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
}
|
||||
|
||||
static struct irq_chip stm32_pwr_irq_chip = {
|
||||
- .name = "stm32_pwr-irq",
|
||||
+ .name = "stm32-pwr-irq",
|
||||
.irq_ack = stm32_pwr_irq_ack,
|
||||
.irq_mask = stm32_pwr_irq_mask,
|
||||
.irq_unmask = stm32_pwr_irq_unmask,
|
||||
@@ -132,29 +128,23 @@ static struct irq_chip stm32_pwr_irq_chip = {
|
||||
.irq_set_wake = stm32_pwr_irq_set_wake,
|
||||
};
|
||||
|
||||
-static int stm32_pwr_irq_map(struct irq_domain *h, unsigned int virq,
|
||||
- irq_hw_number_t hw)
|
||||
-{
|
||||
- irq_set_chip_and_handler(virq, &stm32_pwr_irq_chip, handle_edge_irq);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int stm32_pwr_irq_set_pull_config(struct irq_domain *d, int pin_id,
|
||||
enum wkup_pull_setting config)
|
||||
{
|
||||
struct stm32_pwr_data *priv = d->host_data;
|
||||
u32 wkupcr;
|
||||
|
||||
- dev_dbg(priv->dev, "irq:%d pull config:0x%x\n", pin_id, config);
|
||||
+ pr_debug("irq:%d pull config:0x%x\n", pin_id, config);
|
||||
|
||||
if (config >= WKUP_PULL_RESERVED) {
|
||||
- dev_err(priv->dev, "%s: bad irq pull config\n", __func__);
|
||||
+ pr_err("%s: bad irq pull config\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wkupcr = readl_relaxed(priv->base + WKUPCR);
|
||||
wkupcr &= ~((WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2));
|
||||
wkupcr |= (config & WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2);
|
||||
+
|
||||
SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr);
|
||||
|
||||
return 0;
|
||||
@@ -164,10 +154,8 @@ static int stm32_pwr_xlate(struct irq_domain *d, struct device_node *ctrlr,
|
||||
const u32 *intspec, unsigned int intsize,
|
||||
irq_hw_number_t *out_hwirq, unsigned int *out_type)
|
||||
{
|
||||
- struct stm32_pwr_data *priv = d->host_data;
|
||||
-
|
||||
if (WARN_ON(intsize < 3)) {
|
||||
- dev_err(priv->dev, "%s: bad irq config parameters\n", __func__);
|
||||
+ pr_err("%s: bad irq config parameters\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -177,9 +165,23 @@ static int stm32_pwr_xlate(struct irq_domain *d, struct device_node *ctrlr,
|
||||
return stm32_pwr_irq_set_pull_config(d, intspec[0], intspec[2]);
|
||||
}
|
||||
|
||||
+static int stm32_pwr_alloc(struct irq_domain *d, unsigned int virq,
|
||||
+ unsigned int nr_irqs, void *data)
|
||||
+{
|
||||
+ struct irq_fwspec *fwspec = data;
|
||||
+ irq_hw_number_t hwirq;
|
||||
+
|
||||
+ hwirq = fwspec->param[0];
|
||||
+ irq_domain_set_info(d, virq, hwirq, &stm32_pwr_irq_chip, d->host_data,
|
||||
+ handle_edge_irq, NULL, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct irq_domain_ops stm32_pwr_irq_domain_ops = {
|
||||
- .map = stm32_pwr_irq_map,
|
||||
+ .alloc = stm32_pwr_alloc,
|
||||
.xlate = stm32_pwr_xlate,
|
||||
+ .free = irq_domain_free_irqs_common,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -195,9 +197,10 @@ static void stm32_pwr_handle_irq(struct irq_desc *desc)
|
||||
|
||||
wkupfr = readl_relaxed(priv->base + WKUPFR);
|
||||
wkupenr = readl_relaxed(priv->base + MPUWKUPENR);
|
||||
+
|
||||
for (i = 0; i < NB_WAKEUPPINS; i++) {
|
||||
if ((wkupfr & BIT(i)) && (wkupenr & BIT(i))) {
|
||||
- dev_dbg(priv->dev, "handle wkup irq:%d\n", i);
|
||||
+ pr_debug("handle wkup irq:%d\n", i);
|
||||
generic_handle_irq(irq_find_mapping(priv->domain, i));
|
||||
}
|
||||
}
|
||||
@@ -205,27 +208,21 @@ static void stm32_pwr_handle_irq(struct irq_desc *desc)
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
-static int stm32_pwr_probe(struct platform_device *pdev)
|
||||
+static int __init stm32_pwr_init(struct device_node *np,
|
||||
+ struct device_node *parent)
|
||||
{
|
||||
- struct device *dev = &pdev->dev;
|
||||
- struct device_node *np = pdev->dev.of_node;
|
||||
struct stm32_pwr_data *priv;
|
||||
-
|
||||
- struct resource *res;
|
||||
int ret;
|
||||
|
||||
- priv = devm_kzalloc(dev, sizeof(struct stm32_pwr_data), GFP_KERNEL);
|
||||
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
- platform_set_drvdata(pdev, priv);
|
||||
- priv->dev = dev;
|
||||
-
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- priv->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ priv->base = of_iomap(np, 0);
|
||||
if (IS_ERR(priv->base)) {
|
||||
- dev_err(dev, "%s: Unable to map IO memory\n", __func__);
|
||||
- return PTR_ERR(priv->base);
|
||||
+ pr_err("%s: Unable to map IO memory\n", __func__);
|
||||
+ ret = PTR_ERR(priv->base);
|
||||
+ goto out_free;
|
||||
}
|
||||
|
||||
/* Disable all wake-up pins */
|
||||
@@ -236,52 +233,38 @@ static int stm32_pwr_probe(struct platform_device *pdev)
|
||||
priv->domain = irq_domain_add_linear(np, NB_WAKEUPPINS,
|
||||
&stm32_pwr_irq_domain_ops, priv);
|
||||
if (!priv->domain) {
|
||||
- dev_err(dev, "%s: Unable to add irq domain!\n", __func__);
|
||||
- goto out;
|
||||
+ pr_err("%s: Unable to add irq domain!\n", __func__);
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out_unmap;
|
||||
}
|
||||
|
||||
- ret = platform_get_irq(pdev, 0);
|
||||
- if (ret < 0) {
|
||||
- dev_err(dev, "failed to get PWR IRQ\n");
|
||||
- goto err;
|
||||
+ priv->irq = irq_of_parse_and_map(np, 0);
|
||||
+ if (priv->irq < 0) {
|
||||
+ pr_err("failed to get PWR IRQ\n");
|
||||
+ ret = priv->irq;
|
||||
+ goto out_domain;
|
||||
}
|
||||
- priv->irq = ret;
|
||||
|
||||
irq_set_chained_handler_and_data(priv->irq,
|
||||
stm32_pwr_handle_irq, priv);
|
||||
|
||||
-out:
|
||||
+ of_node_clear_flag(np, OF_POPULATED);
|
||||
+
|
||||
return 0;
|
||||
-err:
|
||||
+
|
||||
+out_domain:
|
||||
irq_domain_remove(priv->domain);
|
||||
+out_unmap:
|
||||
+ iounmap(priv->base);
|
||||
+out_free:
|
||||
+ kfree(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int stm32_pwr_remove(struct platform_device *pdev)
|
||||
+static int __init stm32_pwr_of_init(struct device_node *np,
|
||||
+ struct device_node *parent)
|
||||
{
|
||||
- struct stm32_pwr_data *priv = platform_get_drvdata(pdev);
|
||||
-
|
||||
- irq_domain_remove(priv->domain);
|
||||
- return 0;
|
||||
+ return stm32_pwr_init(np, parent);
|
||||
}
|
||||
|
||||
-static const struct of_device_id stm32_pwr_match[] = {
|
||||
- { .compatible = "st,stm32mp1-pwr" },
|
||||
- {},
|
||||
-};
|
||||
-
|
||||
-static struct platform_driver stm32_pwr_driver = {
|
||||
- .probe = stm32_pwr_probe,
|
||||
- .remove = stm32_pwr_remove,
|
||||
- .driver = {
|
||||
- .name = "stm32-pwr",
|
||||
- .owner = THIS_MODULE,
|
||||
- .of_match_table = stm32_pwr_match,
|
||||
- },
|
||||
-};
|
||||
-
|
||||
-static int __init stm32_pwr_init(void)
|
||||
-{
|
||||
- return platform_driver_register(&stm32_pwr_driver);
|
||||
-}
|
||||
-arch_initcall(stm32_pwr_init);
|
||||
+IRQCHIP_DECLARE(stm32mp1_pwr_irq, "st,stm32mp1-pwr", stm32_pwr_of_init);
|
||||
diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c
|
||||
index 5bf6328..648315d 100644
|
||||
--- a/drivers/mfd/stpmic1.c
|
||||
+++ b/drivers/mfd/stpmic1.c
|
||||
@@ -268,13 +268,8 @@ static int stpmic1_probe(struct i2c_client *i2c,
|
||||
return ddata->irq;
|
||||
}
|
||||
|
||||
- ddata->irq_wake = of_irq_get(np, STPMIC1_WAKEUP_IRQ);
|
||||
- if (ddata->irq_wake > 0) {
|
||||
+ if (of_property_read_bool(np, "wakeup-source"))
|
||||
device_init_wakeup(dev, true);
|
||||
- ret = dev_pm_set_dedicated_wake_irq(dev, ddata->irq_wake);
|
||||
- if (ret)
|
||||
- dev_warn(dev, "failed to set up wakeup irq");
|
||||
- }
|
||||
|
||||
if (!of_property_read_u32(np, "st,main-control-register", ®)) {
|
||||
ret = regmap_update_bits(ddata->regmap,
|
||||
@@ -371,8 +366,8 @@ static int stpmic1_suspend(struct device *dev)
|
||||
struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
|
||||
|
||||
disable_irq(pmic_dev->irq);
|
||||
- if ((pmic_dev->irq_wake > 0) && device_may_wakeup(dev))
|
||||
- enable_irq_wake(pmic_dev->irq_wake);
|
||||
+ if (device_may_wakeup(dev))
|
||||
+ enable_irq_wake(pmic_dev->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -387,9 +382,10 @@ static int stpmic1_resume(struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ if (device_may_wakeup(dev))
|
||||
+ disable_irq_wake(pmic_dev->irq);
|
||||
+
|
||||
enable_irq(pmic_dev->irq);
|
||||
- if ((pmic_dev->irq_wake > 0) && device_may_wakeup(dev))
|
||||
- disable_irq_wake(pmic_dev->irq_wake);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
|
||||
index b6d05cd..a0ba4ff 100644
|
||||
--- a/drivers/mfd/syscon.c
|
||||
+++ b/drivers/mfd/syscon.c
|
||||
@@ -12,6 +12,7 @@
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
+#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwspinlock.h>
|
||||
#include <linux/io.h>
|
||||
@@ -45,6 +46,7 @@ static const struct regmap_config syscon_regmap_config = {
|
||||
|
||||
static struct syscon *of_syscon_register(struct device_node *np)
|
||||
{
|
||||
+ struct clk *clk;
|
||||
struct syscon *syscon;
|
||||
struct regmap *regmap;
|
||||
void __iomem *base;
|
||||
@@ -119,6 +121,18 @@ static struct syscon *of_syscon_register(struct device_node *np)
|
||||
goto err_regmap;
|
||||
}
|
||||
|
||||
+ clk = of_clk_get(np, 0);
|
||||
+ if (IS_ERR(clk)) {
|
||||
+ ret = PTR_ERR(clk);
|
||||
+ /* clock is optional */
|
||||
+ if (ret != -ENOENT)
|
||||
+ goto err_clk;
|
||||
+ } else {
|
||||
+ ret = regmap_mmio_attach_clk(regmap, clk);
|
||||
+ if (ret)
|
||||
+ goto err_attach;
|
||||
+ }
|
||||
+
|
||||
syscon->regmap = regmap;
|
||||
syscon->np = np;
|
||||
|
||||
@@ -128,6 +142,11 @@ static struct syscon *of_syscon_register(struct device_node *np)
|
||||
|
||||
return syscon;
|
||||
|
||||
+err_attach:
|
||||
+ if (!IS_ERR(clk))
|
||||
+ clk_put(clk);
|
||||
+err_clk:
|
||||
+ regmap_exit(regmap);
|
||||
err_regmap:
|
||||
iounmap(base);
|
||||
err_map:
|
||||
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
|
||||
index 22bd652..755863a 100644
|
||||
--- a/drivers/mfd/wm8994-core.c
|
||||
+++ b/drivers/mfd/wm8994-core.c
|
||||
@@ -12,6 +12,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
+#include <linux/clk.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -314,6 +315,20 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
|
||||
if (pdata->ldo[1].enable < 0)
|
||||
pdata->ldo[1].enable = 0;
|
||||
|
||||
+ pdata->mclk1 = devm_clk_get(wm8994->dev, "MCLK1");
|
||||
+ if (IS_ERR(pdata->mclk1)) {
|
||||
+ if (PTR_ERR(pdata->mclk1) != -ENOENT)
|
||||
+ return PTR_ERR(pdata->mclk1);
|
||||
+ pdata->mclk1 = NULL;
|
||||
+ }
|
||||
+
|
||||
+ pdata->mclk2 = devm_clk_get(wm8994->dev, "MCLK2");
|
||||
+ if (IS_ERR(pdata->mclk2)) {
|
||||
+ if (PTR_ERR(pdata->mclk2) != -ENOENT)
|
||||
+ return PTR_ERR(pdata->mclk2);
|
||||
+ pdata->mclk2 = NULL;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
diff --git a/include/linux/mfd/stpmic1.h b/include/linux/mfd/stpmic1.h
|
||||
index 4abe5f1..fa3f99f 100644
|
||||
--- a/include/linux/mfd/stpmic1.h
|
||||
+++ b/include/linux/mfd/stpmic1.h
|
||||
@@ -206,7 +206,6 @@ struct stpmic1 {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
int irq;
|
||||
- int irq_wake;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
};
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,372 +0,0 @@
|
|||
From 222782ff647dfeb33bb442031792a893372fad82 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Mon, 26 Nov 2018 14:43:58 +0100
|
||||
Subject: [PATCH 25/52] ARM-stm32mp1-r0-rc2-REMOTEPROC
|
||||
|
||||
---
|
||||
.../devicetree/bindings/remoteproc/rproc-srm.txt | 14 ++-
|
||||
.../devicetree/bindings/remoteproc/stm32-rproc.txt | 15 ++-
|
||||
drivers/nvmem/stm32-romem.c | 44 +++++----
|
||||
drivers/remoteproc/rproc_srm_core.h | 14 +--
|
||||
drivers/remoteproc/rproc_srm_dev.c | 103 +--------------------
|
||||
drivers/remoteproc/stm32_rproc.c | 2 +-
|
||||
6 files changed, 42 insertions(+), 150 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt
|
||||
index dce10c0..19a5255 100644
|
||||
--- a/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt
|
||||
+++ b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt
|
||||
@@ -23,12 +23,16 @@ Optional properties:
|
||||
- clocks: clocks required by the coprocessor
|
||||
- clock-names: see clock-bindings.txt
|
||||
- pinctrl-x: pins configurations required by the coprocessor
|
||||
-- pinctrl-names: see pinctrl-bindings.txt.
|
||||
- "rproc_default" is a special pin configuration which is applied except
|
||||
- if the 'early-booted' property is set.
|
||||
- In a general way, it is recommended to use names prefixed with "rproc_".
|
||||
+ The SRM reserves the pins for the coprocessor, which prevents the local
|
||||
+ processor to use them.
|
||||
+- pinctrl-names: all names must be prefixed with "rproc_" (ex: "rproc_default").
|
||||
+ This rule must be strictly followed in order to prevent the SRM to
|
||||
+ (over)write a pin configuration which is done by the coprocessor.
|
||||
- x-supply: power supplies required by the coprocessor
|
||||
-- interrupts: see interrupts.txt
|
||||
+- interrupts: external interrupts configurations required by the coprocessor.
|
||||
+ This is optional since the configuration is done by the coprocessor.
|
||||
+ When defined, the SRM (over)writes the configuration which allows the
|
||||
+ interrupt controller to check for configuration conflicts.
|
||||
- interrupt-parent: see interrupts.txt
|
||||
- interrupt-names: see interrupts.txt
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt b/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt
|
||||
index ee00f1c..7df6a26 100644
|
||||
--- a/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt
|
||||
+++ b/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt
|
||||
@@ -33,18 +33,15 @@ Optional properties:
|
||||
- from local to remote = send message
|
||||
- from remote to local = send message ack
|
||||
- a channel (b) working the opposite direction of channel (a)
|
||||
- - a channel (c) used for two different purposes:
|
||||
- - used by the remote proc to signal when it has completed
|
||||
- its critical initalisation.
|
||||
- Mono-directional channel: from remote to local
|
||||
- - used by the local proc to notify the remote proc that it
|
||||
- is about to be shut down.
|
||||
- Mono-directional channel: from local to remote, where ACK
|
||||
- from the remote means that it is ready for shutdown
|
||||
+ - a channel (c) used by the local proc to notify the remote proc
|
||||
+ that it is about to be shut down.
|
||||
+ Mono-directional channel:
|
||||
+ - from local to remote, where ACK from the remote means
|
||||
+ that it is ready for shutdown
|
||||
- mbox-names: This property is required if the mboxes property is used.
|
||||
- must be "vq0" for channel (a)
|
||||
- must be "vq1" for channel (b)
|
||||
- - must be "init_shdn" for channel (c)
|
||||
+ - must be "shutdown" for channel (c)
|
||||
- memory-region: phandle to the reserved memory node to be associated with the
|
||||
remoteproc device.
|
||||
- st,syscfg-pdds: Reference to the system configuration controlling the remote
|
||||
diff --git a/drivers/nvmem/stm32-romem.c b/drivers/nvmem/stm32-romem.c
|
||||
index 198872f..34b388c 100644
|
||||
--- a/drivers/nvmem/stm32-romem.c
|
||||
+++ b/drivers/nvmem/stm32-romem.c
|
||||
@@ -19,6 +19,12 @@
|
||||
#define STM32_SMC_WRITE_SHADOW 0x03
|
||||
#define STM32_SMC_READ_OTP 0x04
|
||||
|
||||
+/* shadow registers offest */
|
||||
+#define STM32MP15_BSEC_DATA0 0x200
|
||||
+
|
||||
+/* 32 (x 32-bits) lower shadow registers */
|
||||
+#define STM32MP15_BSEC_NUM_LOWER 32
|
||||
+
|
||||
struct stm32_romem_cfg {
|
||||
int size;
|
||||
};
|
||||
@@ -77,13 +83,21 @@ static int stm32_bsec_read(void *context, unsigned int offset, void *buf,
|
||||
return -EINVAL;
|
||||
|
||||
for (i = roffset; (i < roffset + rbytes); i += 4) {
|
||||
- ret = stm32_bsec_smc(STM32_SMC_READ_OTP, i >> 2, 0, &val);
|
||||
- if (ret) {
|
||||
- dev_err(priv->dev, "Failed to read data%d (%d)\n",
|
||||
- i >> 2, ret);
|
||||
- return ret;
|
||||
+ u32 otp = i >> 2;
|
||||
+
|
||||
+ if (otp < STM32MP15_BSEC_NUM_LOWER) {
|
||||
+ /* read lower data from shadow registers */
|
||||
+ val = readl_relaxed(
|
||||
+ priv->base + STM32MP15_BSEC_DATA0 + i);
|
||||
+ } else {
|
||||
+ ret = stm32_bsec_smc(STM32_SMC_READ_SHADOW, otp, 0,
|
||||
+ &val);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "Can't read data%d (%d)\n",
|
||||
+ otp, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
}
|
||||
-
|
||||
/* skip first bytes in case of unaligned read */
|
||||
if (skip_bytes)
|
||||
size = min(bytes, (size_t)(4 - skip_bytes));
|
||||
@@ -127,7 +141,6 @@ static int stm32_romem_probe(struct platform_device *pdev)
|
||||
const struct stm32_romem_cfg *cfg;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct stm32_romem_priv *priv;
|
||||
- struct nvmem_device *nvmem;
|
||||
struct resource *res;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
@@ -154,26 +167,12 @@ static int stm32_romem_probe(struct platform_device *pdev)
|
||||
priv->cfg.size = resource_size(res);
|
||||
priv->cfg.reg_read = stm32_romem_read;
|
||||
} else {
|
||||
- priv->cfg.read_only = false;
|
||||
priv->cfg.size = cfg->size;
|
||||
priv->cfg.reg_read = stm32_bsec_read;
|
||||
priv->cfg.reg_write = stm32_bsec_write;
|
||||
}
|
||||
|
||||
- nvmem = nvmem_register(&priv->cfg);
|
||||
- if (IS_ERR(nvmem))
|
||||
- return PTR_ERR(nvmem);
|
||||
-
|
||||
- platform_set_drvdata(pdev, nvmem);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int stm32_romem_remove(struct platform_device *pdev)
|
||||
-{
|
||||
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
|
||||
-
|
||||
- return nvmem_unregister(nvmem);
|
||||
+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg));
|
||||
}
|
||||
|
||||
static const struct stm32_romem_cfg stm32mp15_bsec_cfg = {
|
||||
@@ -191,7 +190,6 @@ MODULE_DEVICE_TABLE(of, stm32_romem_of_match);
|
||||
|
||||
static struct platform_driver stm32_romem_driver = {
|
||||
.probe = stm32_romem_probe,
|
||||
- .remove = stm32_romem_remove,
|
||||
.driver = {
|
||||
.name = "stm32-romem",
|
||||
.of_match_table = of_match_ptr(stm32_romem_of_match),
|
||||
diff --git a/drivers/remoteproc/rproc_srm_core.h b/drivers/remoteproc/rproc_srm_core.h
|
||||
index 7915f35..7dffdb38 100644
|
||||
--- a/drivers/remoteproc/rproc_srm_core.h
|
||||
+++ b/drivers/remoteproc/rproc_srm_core.h
|
||||
@@ -20,12 +20,10 @@
|
||||
/**
|
||||
* Resource type used in resource manager rpmsg:
|
||||
* RPROC_SRM_RSC_CLOCK: clock resource
|
||||
- * RPROC_SRM_RSC_PIN: pin resource
|
||||
* RPROC_SRM_RSC_REGU: regulator resource
|
||||
*/
|
||||
#define RPROC_SRM_RSC_CLOCK 0x00
|
||||
-#define RPROC_SRM_RSC_PIN 0x01
|
||||
-#define RPROC_SRM_RSC_REGU 0x02
|
||||
+#define RPROC_SRM_RSC_REGU 0x01
|
||||
|
||||
/**
|
||||
* struct clock_cfg - clock configuration used in resource manager rpmsg
|
||||
@@ -63,14 +61,6 @@ struct regu_cfg {
|
||||
};
|
||||
|
||||
/**
|
||||
- * struct pin_cfg - pin configuration used in resource manager rpmsg
|
||||
- * @name: current pin configuration name (meaningful in GetConfig message)
|
||||
- */
|
||||
-struct pin_cfg {
|
||||
- u8 name[16];
|
||||
-};
|
||||
-
|
||||
-/**
|
||||
* struct rpmsg_srm_msg - message structure used between processors to
|
||||
* dynamically update resources configuration
|
||||
* @message_type: type of the message: see RPROC_SRM_MSG*
|
||||
@@ -81,7 +71,6 @@ struct pin_cfg {
|
||||
* see RPROC_SRM_RSC*
|
||||
* @clock_cfg: clock config - relevant if &rsc_type is RPROC_SRM_RSC_CLOCK
|
||||
* @regu_cfg: regulator config - relevant if &rsc_type is RPROC_SRM_RSC_REGU
|
||||
- * @pin_cfg: pin config - relevant if &rsc_type is RPROC_SRM_RSC_PIN
|
||||
*/
|
||||
struct rpmsg_srm_msg {
|
||||
u32 message_type;
|
||||
@@ -90,7 +79,6 @@ struct rpmsg_srm_msg {
|
||||
union {
|
||||
struct clock_cfg clock_cfg;
|
||||
struct regu_cfg regu_cfg;
|
||||
- struct pin_cfg pin_cfg;
|
||||
};
|
||||
};
|
||||
|
||||
diff --git a/drivers/remoteproc/rproc_srm_dev.c b/drivers/remoteproc/rproc_srm_dev.c
|
||||
index b026f961..7dc99c5 100644
|
||||
--- a/drivers/remoteproc/rproc_srm_dev.c
|
||||
+++ b/drivers/remoteproc/rproc_srm_dev.c
|
||||
@@ -31,7 +31,6 @@ struct rproc_srm_pin_info {
|
||||
struct list_head list;
|
||||
unsigned int index;
|
||||
char *name;
|
||||
- bool selected;
|
||||
};
|
||||
|
||||
struct rproc_srm_regu_info {
|
||||
@@ -544,83 +543,6 @@ static int rproc_srm_dev_regus_get(struct rproc_srm_dev *rproc_srm_dev)
|
||||
}
|
||||
|
||||
/* Pins */
|
||||
-static int rproc_srm_dev_pin_set_cfg(struct rproc_srm_dev *rproc_srm_dev,
|
||||
- struct pin_cfg *cfg)
|
||||
-{
|
||||
- struct rproc_srm_pin_info *pi, *p = NULL;
|
||||
- struct device *dev = rproc_srm_dev->dev;
|
||||
- struct pinctrl_state *state;
|
||||
- int ret;
|
||||
-
|
||||
- list_for_each_entry(pi, &rproc_srm_dev->pin_list_head, list) {
|
||||
- if (!strcmp(pi->name, cfg->name)) {
|
||||
- p = pi;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (!p) {
|
||||
- dev_err(dev, "unknown pin config (%s)\n", cfg->name);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- state = pinctrl_lookup_state(rproc_srm_dev->pctrl, cfg->name);
|
||||
- if (IS_ERR(state)) {
|
||||
- dev_err(dev, "cannot get pin config (%s)\n", cfg->name);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- ret = pinctrl_select_state(rproc_srm_dev->pctrl, state);
|
||||
- if (ret < 0) {
|
||||
- dev_err(dev, "cannot set pin config (%s)\n", cfg->name);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- list_for_each_entry(pi, &rproc_srm_dev->pin_list_head, list) {
|
||||
- pi->selected = (pi == p);
|
||||
- }
|
||||
-
|
||||
- dev_dbg(dev, "pin config (%s) selected\n", p->name);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int rproc_srm_dev_pin_get_cfg(struct rproc_srm_dev *rproc_srm_dev,
|
||||
- struct pin_cfg *cfg)
|
||||
-{
|
||||
- struct rproc_srm_pin_info *p;
|
||||
-
|
||||
- list_for_each_entry(p, &rproc_srm_dev->pin_list_head, list) {
|
||||
- if (p->selected) {
|
||||
- strlcpy(cfg->name, p->name, sizeof(cfg->name));
|
||||
- return 0;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- dev_warn(rproc_srm_dev->dev, "cannot find selected pin state\n");
|
||||
- strcpy(cfg->name, "");
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int rproc_srm_dev_pins_setup(struct rproc_srm_dev *rproc_srm_dev)
|
||||
-{
|
||||
- struct rproc_srm_pin_info *p;
|
||||
- struct pin_cfg cfg = { .name = "rproc_default" };
|
||||
-
|
||||
- if (rproc_srm_dev->early_boot)
|
||||
- /* in early_boot mode do not update pin config */
|
||||
- return 0;
|
||||
-
|
||||
- /* set the "rproc_default" pin config if defined */
|
||||
- list_for_each_entry(p, &rproc_srm_dev->pin_list_head, list) {
|
||||
- if (!strcmp(p->name, cfg.name))
|
||||
- return rproc_srm_dev_pin_set_cfg(rproc_srm_dev, &cfg);
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static void rproc_srm_dev_pins_put(struct rproc_srm_dev *rproc_srm_dev)
|
||||
{
|
||||
struct device *dev = rproc_srm_dev->dev;
|
||||
@@ -677,11 +599,9 @@ static int rproc_srm_dev_pins_get(struct rproc_srm_dev *rproc_srm_dev)
|
||||
}
|
||||
p->name = devm_kstrdup(dev, name, GFP_KERNEL);
|
||||
|
||||
- if (!strcmp(p->name, PINCTRL_STATE_DEFAULT)) {
|
||||
- if (rproc_srm_dev->early_boot)
|
||||
- dev_warn(dev, "pin config potentially overwritten!\n");
|
||||
- p->selected = true;
|
||||
- }
|
||||
+ /* pinctrl-names shall not be "default" (but "rproc_default") */
|
||||
+ if (!strcmp(p->name, PINCTRL_STATE_DEFAULT))
|
||||
+ dev_warn(dev, "pin config potentially overwritten!\n");
|
||||
|
||||
p->index = i;
|
||||
|
||||
@@ -726,13 +646,6 @@ static int rproc_srm_dev_notify_cb(struct notifier_block *nb, unsigned long evt,
|
||||
ret = rproc_srm_dev_clock_get_cfg(rproc_srm_dev,
|
||||
&o.clock_cfg);
|
||||
break;
|
||||
- case RPROC_SRM_RSC_PIN:
|
||||
- ret = rproc_srm_dev_pin_set_cfg(rproc_srm_dev,
|
||||
- &i->pin_cfg);
|
||||
- if (!ret)
|
||||
- ret = rproc_srm_dev_pin_get_cfg(rproc_srm_dev,
|
||||
- &o.pin_cfg);
|
||||
- break;
|
||||
case RPROC_SRM_RSC_REGU:
|
||||
ret = rproc_srm_dev_regu_set_cfg(rproc_srm_dev,
|
||||
&i->regu_cfg);
|
||||
@@ -752,10 +665,6 @@ static int rproc_srm_dev_notify_cb(struct notifier_block *nb, unsigned long evt,
|
||||
ret = rproc_srm_dev_clock_get_cfg(rproc_srm_dev,
|
||||
&o.clock_cfg);
|
||||
break;
|
||||
- case RPROC_SRM_RSC_PIN:
|
||||
- ret = rproc_srm_dev_pin_get_cfg(rproc_srm_dev,
|
||||
- &o.pin_cfg);
|
||||
- break;
|
||||
case RPROC_SRM_RSC_REGU:
|
||||
ret = rproc_srm_dev_regu_get_cfg(rproc_srm_dev,
|
||||
&o.regu_cfg);
|
||||
@@ -810,11 +719,7 @@ rproc_srm_dev_bind(struct device *dev, struct device *master, void *data)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- ret = rproc_srm_dev_pins_setup(rproc_srm_dev);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- /* For IRQs: nothing to setup */
|
||||
+ /* For pins and IRQs: nothing to setup */
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
|
||||
index 998de67..548afdd 100644
|
||||
--- a/drivers/remoteproc/stm32_rproc.c
|
||||
+++ b/drivers/remoteproc/stm32_rproc.c
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#define STM32_MBX_VQ0 "vq0"
|
||||
#define STM32_MBX_VQ1 "vq1"
|
||||
-#define STM32_MBX_SHUTDOWN "init_shdn"
|
||||
+#define STM32_MBX_SHUTDOWN "shutdown"
|
||||
|
||||
struct stm32_syscon {
|
||||
struct regmap *map;
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,273 +0,0 @@
|
|||
From f03da721a19075ead436b2edbe4c4080feb8dac8 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Mon, 26 Nov 2018 14:44:24 +0100
|
||||
Subject: [PATCH 26/52] ARM-stm32mp1-r0-rc2-NET
|
||||
|
||||
---
|
||||
.../devicetree/bindings/net/stm32-dwmac.txt | 6 +-
|
||||
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 102 +++++++++++++++++----
|
||||
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 6 ++
|
||||
4 files changed, 94 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.txt b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||
index 1341012..f42dc68 100644
|
||||
--- a/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||
@@ -24,9 +24,9 @@ Required properties:
|
||||
encompases the glue register, and the offset of the control register.
|
||||
|
||||
Optional properties:
|
||||
-- clock-names: For MPU family "mac-clk-ck" for PHY without quartz
|
||||
-- st,int-phyclk (boolean) : valid only where PHY do not have quartz and need to be clock
|
||||
- by RCC
|
||||
+- clock-names: For MPU family "eth-ck" for PHY without quartz
|
||||
+- st,eth_clk_sel (boolean) : set this property in RGMII PHY when you do not want use 125Mhz
|
||||
+- st,eth_ref_clk_sel (boolean) : set this property in RMII mode when you have PHY without crystal 50MHz
|
||||
|
||||
Example:
|
||||
|
||||
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
index d1cf145..545b168 100644
|
||||
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
@@ -25,9 +25,24 @@
|
||||
|
||||
#define SYSCFG_MCU_ETH_MASK BIT(23)
|
||||
#define SYSCFG_MP1_ETH_MASK GENMASK(23, 16)
|
||||
+#define SYSCFG_PMCCLRR_OFFSET 0x40
|
||||
|
||||
#define SYSCFG_PMCR_ETH_CLK_SEL BIT(16)
|
||||
#define SYSCFG_PMCR_ETH_REF_CLK_SEL BIT(17)
|
||||
+
|
||||
+/* Ethernet PHY interface selection in register SYSCFG Configuration
|
||||
+ *------------------------------------------
|
||||
+ * src |BIT(23)| BIT(22)| BIT(21)|BIT(20)|
|
||||
+ *------------------------------------------
|
||||
+ * MII | 0 | 0 | 0 | 1 |
|
||||
+ *------------------------------------------
|
||||
+ * GMII | 0 | 0 | 0 | 0 |
|
||||
+ *------------------------------------------
|
||||
+ * RGMII | 0 | 0 | 1 | n/a |
|
||||
+ *------------------------------------------
|
||||
+ * RMII | 1 | 0 | 0 | n/a |
|
||||
+ *------------------------------------------
|
||||
+ */
|
||||
#define SYSCFG_PMCR_ETH_SEL_MII BIT(20)
|
||||
#define SYSCFG_PMCR_ETH_SEL_RGMII BIT(21)
|
||||
#define SYSCFG_PMCR_ETH_SEL_RMII BIT(23)
|
||||
@@ -35,15 +50,54 @@
|
||||
#define SYSCFG_MCU_ETH_SEL_MII 0
|
||||
#define SYSCFG_MCU_ETH_SEL_RMII 1
|
||||
|
||||
+/* STM32MP1 register definitions
|
||||
+ *
|
||||
+ * Below table summarizes the clock requirement and clock sources for
|
||||
+ * supported phy interface modes.
|
||||
+ * __________________________________________________________________________
|
||||
+ *|PHY_MODE | Normal | PHY wo crystal| PHY wo crystal |No 125Mhz from PHY|
|
||||
+ *| | | 25MHz | 50MHz | |
|
||||
+ * ---------------------------------------------------------------------------
|
||||
+ *| MII | - | eth-ck | n/a | n/a |
|
||||
+ *| | | | | |
|
||||
+ * ---------------------------------------------------------------------------
|
||||
+ *| GMII | - | eth-ck | n/a | n/a |
|
||||
+ *| | | | | |
|
||||
+ * ---------------------------------------------------------------------------
|
||||
+ *| RGMII | - | eth-ck | n/a | eth-ck (no pin) |
|
||||
+ *| | | | | st,eth_clk_sel |
|
||||
+ * ---------------------------------------------------------------------------
|
||||
+ *| RMII | - | eth-ck | eth-ck | n/a |
|
||||
+ *| | | | st,eth_ref_clk_sel | |
|
||||
+ * ---------------------------------------------------------------------------
|
||||
+ *
|
||||
+ * BIT(17) : set this bit in RMII mode when you have PHY without crystal 50MHz
|
||||
+ * BIT(16) : set this bit in GMII/RGMII PHY when you do not want use 125Mhz
|
||||
+ * from PHY
|
||||
+ *-----------------------------------------------------
|
||||
+ * src | BIT(17) | BIT(16) |
|
||||
+ *-----------------------------------------------------
|
||||
+ * MII | n/a | n/a |
|
||||
+ *-----------------------------------------------------
|
||||
+ * GMII | n/a | st,eth_clk_sel |
|
||||
+ *-----------------------------------------------------
|
||||
+ * RGMII | n/a | st,eth_clk_sel |
|
||||
+ *-----------------------------------------------------
|
||||
+ * RMII | st,eth_ref_clk_sel | n/a |
|
||||
+ *-----------------------------------------------------
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
struct stm32_dwmac {
|
||||
struct clk *clk_tx;
|
||||
struct clk *clk_rx;
|
||||
struct clk *clk_eth_ck;
|
||||
struct clk *clk_ethstp;
|
||||
struct clk *syscfg_clk;
|
||||
- bool int_phyclk; /* Clock from RCC to drive PHY */
|
||||
+ int eth_clk_sel_reg;
|
||||
+ int eth_ref_clk_sel_reg;
|
||||
int irq_pwr_wakeup;
|
||||
- u32 mode_reg; /* MAC glue-logic mode register */
|
||||
+ u32 mode_reg; /* MAC glue-logic mode register */
|
||||
struct regmap *regmap;
|
||||
u32 speed;
|
||||
const struct stm32_ops *ops;
|
||||
@@ -103,7 +157,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- if (dwmac->int_phyclk) {
|
||||
+ if (dwmac->clk_eth_ck) {
|
||||
ret = clk_prepare_enable(dwmac->clk_eth_ck);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
@@ -112,7 +166,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
|
||||
}
|
||||
} else {
|
||||
clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
- if (dwmac->int_phyclk)
|
||||
+ if (dwmac->clk_eth_ck)
|
||||
clk_disable_unprepare(dwmac->clk_eth_ck);
|
||||
}
|
||||
return ret;
|
||||
@@ -122,7 +176,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||
{
|
||||
struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
|
||||
u32 reg = dwmac->mode_reg;
|
||||
- int val;
|
||||
+ int val, ret;
|
||||
|
||||
switch (plat_dat->interface) {
|
||||
case PHY_INTERFACE_MODE_MII:
|
||||
@@ -131,19 +185,19 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_GMII:
|
||||
val = SYSCFG_PMCR_ETH_SEL_GMII;
|
||||
- if (dwmac->int_phyclk)
|
||||
+ if (dwmac->eth_clk_sel_reg)
|
||||
val |= SYSCFG_PMCR_ETH_CLK_SEL;
|
||||
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n");
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
val = SYSCFG_PMCR_ETH_SEL_RMII;
|
||||
- if (dwmac->int_phyclk)
|
||||
+ if (dwmac->eth_ref_clk_sel_reg)
|
||||
val |= SYSCFG_PMCR_ETH_REF_CLK_SEL;
|
||||
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n");
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
val = SYSCFG_PMCR_ETH_SEL_RGMII;
|
||||
- if (dwmac->int_phyclk)
|
||||
+ if (dwmac->eth_clk_sel_reg)
|
||||
val |= SYSCFG_PMCR_ETH_CLK_SEL;
|
||||
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n");
|
||||
break;
|
||||
@@ -154,6 +208,11 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ /* Need to update PMCCLRR (clear register) */
|
||||
+ ret = regmap_update_bits(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
|
||||
+ dwmac->ops->syscfg_eth_mask, ~val);
|
||||
+
|
||||
+ /* Update PMCSETR (set register) */
|
||||
return regmap_update_bits(dwmac->regmap, reg,
|
||||
dwmac->ops->syscfg_eth_mask, val);
|
||||
}
|
||||
@@ -237,22 +296,25 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||
struct device_node *np = dev->of_node;
|
||||
int err = 0;
|
||||
|
||||
- dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk");
|
||||
+ /* Gigabit Ethernet 125MHz clock selection. */
|
||||
+ dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth_clk_sel");
|
||||
|
||||
- /* Check if internal clk from RCC selected */
|
||||
- if (dwmac->int_phyclk) {
|
||||
- /* Get ETH_CLK clocks */
|
||||
- dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
|
||||
- if (IS_ERR(dwmac->clk_eth_ck)) {
|
||||
- dev_err(dev, "No ETH CK clock provided...\n");
|
||||
- return PTR_ERR(dwmac->clk_eth_ck);
|
||||
- }
|
||||
+ /* Ethernet 50Mhz RMII clock selection */
|
||||
+ dwmac->eth_ref_clk_sel_reg =
|
||||
+ of_property_read_bool(np, "st,eth_ref_clk_sel");
|
||||
+
|
||||
+ /* Get ETH_CLK clocks */
|
||||
+ dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
|
||||
+ if (IS_ERR(dwmac->clk_eth_ck)) {
|
||||
+ dev_warn(dev, "No phy clock provided...\n");
|
||||
+ dwmac->clk_eth_ck = NULL;
|
||||
}
|
||||
|
||||
/* Clock used for low power mode */
|
||||
dwmac->clk_ethstp = devm_clk_get(dev, "ethstp");
|
||||
if (IS_ERR(dwmac->clk_ethstp)) {
|
||||
- dev_err(dev, "No ETH peripheral clock provided for CStop mode ...\n");
|
||||
+ dev_err(dev,
|
||||
+ "No ETH peripheral clock provided for CStop mode ...\n");
|
||||
return PTR_ERR(dwmac->clk_ethstp);
|
||||
}
|
||||
|
||||
@@ -268,7 +330,7 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||
*/
|
||||
dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev,
|
||||
"stm32_pwr_wakeup");
|
||||
- if (!dwmac->int_phyclk && dwmac->irq_pwr_wakeup >= 0) {
|
||||
+ if ((!dwmac->clk_eth_ck) && dwmac->irq_pwr_wakeup >= 0) {
|
||||
err = device_init_wakeup(&pdev->dev, true);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to init wake up irq\n");
|
||||
@@ -370,7 +432,7 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
|
||||
|
||||
clk_disable_unprepare(dwmac->clk_tx);
|
||||
clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
- if (dwmac->int_phyclk)
|
||||
+ if (dwmac->clk_eth_ck)
|
||||
clk_disable_unprepare(dwmac->clk_eth_ck);
|
||||
|
||||
return ret;
|
||||
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||||
index 2b800ce..3031f2b 100644
|
||||
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||||
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||||
@@ -408,6 +408,9 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
|
||||
/* Default to phy auto-detection */
|
||||
plat->phy_addr = -1;
|
||||
|
||||
+ /* Get clk_csr from device tree */
|
||||
+ of_property_read_u32(np, "clk_csr", &plat->clk_csr);
|
||||
+
|
||||
/* "snps,phy-addr" is not a standard property. Mark it as deprecated
|
||||
* and warn of its use. Remove this when phy node support is added.
|
||||
*/
|
||||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||
index d2f788d..c7b41ce 100644
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||
@@ -1129,7 +1129,10 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
|
||||
enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
|
||||
else
|
||||
sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
|
||||
+ } else {
|
||||
+ brcmf_sdiod_intr_unregister(sdiodev);
|
||||
}
|
||||
+
|
||||
if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
|
||||
brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
|
||||
return 0;
|
||||
@@ -1145,6 +1148,9 @@ static int brcmf_ops_sdio_resume(struct device *dev)
|
||||
if (func->num != 2)
|
||||
return 0;
|
||||
|
||||
+ if (!sdiodev->wowl_enabled)
|
||||
+ brcmf_sdiod_intr_register(sdiodev);
|
||||
+
|
||||
brcmf_sdiod_freezer_off(sdiodev);
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.7.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,241 +0,0 @@
|
|||
From bf3772b12539b3595e60b8b334051160269f9071 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Mon, 26 Nov 2018 14:45:33 +0100
|
||||
Subject: [PATCH 28/52] ARM-stm32mp1-r0-rc2-MMC
|
||||
|
||||
---
|
||||
drivers/mmc/host/mmci.c | 36 +++++++++++++++++++++++++-----------
|
||||
drivers/mmc/host/mmci.h | 13 +++++++++++--
|
||||
2 files changed, 36 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
|
||||
index db50d1e..02b631f 100644
|
||||
--- a/drivers/mmc/host/mmci.c
|
||||
+++ b/drivers/mmc/host/mmci.c
|
||||
@@ -135,7 +135,6 @@ static struct variant_data variant_u300 = {
|
||||
.datactrl_blocksz = 11,
|
||||
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||
- .st_sdio = true,
|
||||
.pwrreg_powerup = MCI_PWR_ON,
|
||||
.f_max = 100000000,
|
||||
.signal_direction = true,
|
||||
@@ -146,6 +145,7 @@ static struct variant_data variant_u300 = {
|
||||
.start_err = MCI_STARTBITERR,
|
||||
.opendrain = MCI_OD,
|
||||
.init = mmci_variant_init,
|
||||
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||
};
|
||||
|
||||
static struct variant_data variant_nomadik = {
|
||||
@@ -161,7 +161,6 @@ static struct variant_data variant_nomadik = {
|
||||
.datactrl_blocksz = 11,
|
||||
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||
- .st_sdio = true,
|
||||
.st_clkdiv = true,
|
||||
.pwrreg_powerup = MCI_PWR_ON,
|
||||
.f_max = 100000000,
|
||||
@@ -173,6 +172,7 @@ static struct variant_data variant_nomadik = {
|
||||
.start_err = MCI_STARTBITERR,
|
||||
.opendrain = MCI_OD,
|
||||
.init = mmci_variant_init,
|
||||
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||
};
|
||||
|
||||
static struct variant_data variant_ux500 = {
|
||||
@@ -190,7 +190,6 @@ static struct variant_data variant_ux500 = {
|
||||
.datactrl_blocksz = 11,
|
||||
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||
- .st_sdio = true,
|
||||
.st_clkdiv = true,
|
||||
.pwrreg_powerup = MCI_PWR_ON,
|
||||
.f_max = 100000000,
|
||||
@@ -206,6 +205,7 @@ static struct variant_data variant_ux500 = {
|
||||
.start_err = MCI_STARTBITERR,
|
||||
.opendrain = MCI_OD,
|
||||
.init = mmci_variant_init,
|
||||
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||
};
|
||||
|
||||
static struct variant_data variant_ux500v2 = {
|
||||
@@ -224,7 +224,6 @@ static struct variant_data variant_ux500v2 = {
|
||||
.datactrl_blocksz = 11,
|
||||
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||
- .st_sdio = true,
|
||||
.st_clkdiv = true,
|
||||
.blksz_datactrl16 = true,
|
||||
.pwrreg_powerup = MCI_PWR_ON,
|
||||
@@ -241,6 +240,7 @@ static struct variant_data variant_ux500v2 = {
|
||||
.start_err = MCI_STARTBITERR,
|
||||
.opendrain = MCI_OD,
|
||||
.init = mmci_variant_init,
|
||||
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||
};
|
||||
|
||||
static struct variant_data variant_stm32 = {
|
||||
@@ -259,13 +259,13 @@ static struct variant_data variant_stm32 = {
|
||||
.datactrl_blocksz = 11,
|
||||
.datactrl_dpsm_enable = MCI_DPSM_ENABLE,
|
||||
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
|
||||
- .st_sdio = true,
|
||||
.st_clkdiv = true,
|
||||
.pwrreg_powerup = MCI_PWR_ON,
|
||||
.f_max = 48000000,
|
||||
.pwrreg_clkgate = true,
|
||||
.pwrreg_nopower = true,
|
||||
.init = mmci_variant_init,
|
||||
+ .quirks = MMCI_QUIRK_ST_SDIO,
|
||||
};
|
||||
|
||||
static struct variant_data variant_stm32_sdmmc = {
|
||||
@@ -284,12 +284,14 @@ static struct variant_data variant_stm32_sdmmc = {
|
||||
.datacnt_useless = true,
|
||||
.datalength_bits = 25,
|
||||
.datactrl_blocksz = 14,
|
||||
+ .datactrl_mask_sdio = MCI_DPSM_STM32_SDIOEN,
|
||||
.stm32_idmabsize_mask = GENMASK(12, 5),
|
||||
.busy_detect = true,
|
||||
.busy_timeout = true,
|
||||
.busy_detect_flag = MCI_STM32_BUSYD0,
|
||||
.busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
|
||||
.init = sdmmc_variant_init,
|
||||
+ .quirks = MMCI_QUIRK_STM32_DTMODE,
|
||||
};
|
||||
|
||||
static struct variant_data variant_stm32_sdmmcv2 = {
|
||||
@@ -308,6 +310,7 @@ static struct variant_data variant_stm32_sdmmcv2 = {
|
||||
.datacnt_useless = true,
|
||||
.datalength_bits = 25,
|
||||
.datactrl_blocksz = 14,
|
||||
+ .datactrl_mask_sdio = MCI_DPSM_STM32_SDIOEN,
|
||||
.stm32_idmabsize_mask = GENMASK(16, 5),
|
||||
.dma_lli = true,
|
||||
.busy_detect = true,
|
||||
@@ -315,6 +318,7 @@ static struct variant_data variant_stm32_sdmmcv2 = {
|
||||
.busy_detect_flag = MCI_STM32_BUSYD0,
|
||||
.busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
|
||||
.init = sdmmc_variant_init,
|
||||
+ .quirks = MMCI_QUIRK_STM32_DTMODE,
|
||||
};
|
||||
|
||||
static struct variant_data variant_qcom = {
|
||||
@@ -505,7 +509,8 @@ static int mmci_validate_data(struct mmci_host *host,
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
- if (!is_power_of_2(data->blksz)) {
|
||||
+ if ((host->mmc->card && !mmc_card_sdio(host->mmc->card)) &&
|
||||
+ !is_power_of_2(data->blksz)) {
|
||||
dev_err(mmc_dev(host->mmc),
|
||||
"unsupported block size (%d bytes)\n", data->blksz);
|
||||
return -EINVAL;
|
||||
@@ -1068,7 +1073,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
|
||||
writel(host->size, base + MMCIDATALENGTH);
|
||||
|
||||
blksz_bits = ffs(data->blksz) - 1;
|
||||
- BUG_ON(1 << blksz_bits != data->blksz);
|
||||
|
||||
if (variant->blksz_datactrl16)
|
||||
datactrl = variant->datactrl_dpsm_enable | (data->blksz << 16);
|
||||
@@ -1077,6 +1081,16 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
|
||||
else
|
||||
datactrl = variant->datactrl_dpsm_enable | blksz_bits << 4;
|
||||
|
||||
+ if (variant->quirks & MMCI_QUIRK_STM32_DTMODE) {
|
||||
+ if (host->mmc->card && mmc_card_sdio(host->mmc->card) &&
|
||||
+ data->blocks == 1)
|
||||
+ datactrl |= MCI_DPSM_STM32_MODE_SDIO;
|
||||
+ else if (data->stop && !host->mrq->sbc)
|
||||
+ datactrl |= MCI_DPSM_STM32_MODE_BLOCK_STOP;
|
||||
+ else
|
||||
+ datactrl |= MCI_DPSM_STM32_MODE_BLOCK;
|
||||
+ }
|
||||
+
|
||||
if (data->flags & MMC_DATA_READ)
|
||||
datactrl |= MCI_DPSM_DIRECTION;
|
||||
|
||||
@@ -1091,7 +1105,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
|
||||
* otherwise the transfer will not start. The threshold
|
||||
* depends on the rate of MCLK.
|
||||
*/
|
||||
- if (variant->st_sdio && data->flags & MMC_DATA_WRITE &&
|
||||
+ if (variant->quirks & MMCI_QUIRK_ST_SDIO &&
|
||||
+ data->flags & MMC_DATA_WRITE &&
|
||||
(host->size < 8 ||
|
||||
(host->size <= 8 && host->mclk > 50000000)))
|
||||
clk = host->clk_reg & ~variant->clkreg_enable;
|
||||
@@ -1257,11 +1272,10 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
|
||||
/* The error clause is handled above, success! */
|
||||
data->bytes_xfered = data->blksz * data->blocks;
|
||||
|
||||
- if (!data->stop || host->mrq->sbc) {
|
||||
+ if (!data->stop || (host->mrq->sbc && !data->error))
|
||||
mmci_request_end(host, data->mrq);
|
||||
- } else {
|
||||
+ else
|
||||
mmci_start_command(host, data->stop, 0);
|
||||
- }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
|
||||
index 36a744a..55867fc 100644
|
||||
--- a/drivers/mmc/host/mmci.h
|
||||
+++ b/drivers/mmc/host/mmci.h
|
||||
@@ -131,6 +131,12 @@
|
||||
/* Control register extensions in the Qualcomm versions */
|
||||
#define MCI_DPSM_QCOM_DATA_PEND BIT(17)
|
||||
#define MCI_DPSM_QCOM_RX_DATA_PEND BIT(20)
|
||||
+/* Control register extensions in STM32 versions */
|
||||
+#define MCI_DPSM_STM32_MODE_BLOCK (0 << 2)
|
||||
+#define MCI_DPSM_STM32_MODE_SDIO (1 << 2)
|
||||
+#define MCI_DPSM_STM32_MODE_STREAM (2 << 2)
|
||||
+#define MCI_DPSM_STM32_MODE_BLOCK_STOP (3 << 2)
|
||||
+#define MCI_DPSM_STM32_SDIOEN BIT(11)
|
||||
|
||||
#define MMCIDATACNT 0x030
|
||||
#define MMCISTATUS 0x034
|
||||
@@ -273,7 +279,6 @@ struct mmci_host;
|
||||
* @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
|
||||
* is asserted (likewise for RX)
|
||||
* @data_cmd_enable: enable value for data commands.
|
||||
- * @st_sdio: enable ST specific SDIO logic
|
||||
* @st_clkdiv: true if using a ST-specific clock divider algorithm
|
||||
* @stm32_clkdiv: true if using a STM32-specific clock divider algorithm
|
||||
* @datactrl_mask_ddrmode: ddr mode mask in datactrl register.
|
||||
@@ -309,6 +314,7 @@ struct mmci_host;
|
||||
* @opendrain: bitmask identifying the OPENDRAIN bit inside MMCIPOWER register
|
||||
* @dma_lli: true if variant has dma link list feature.
|
||||
* @stm32_idmabsize_mask: stm32 sdmmc idma buffer size.
|
||||
+ * @quirks: A bitmap of hardware quirks that require some special action.
|
||||
*/
|
||||
struct variant_data {
|
||||
unsigned int clkreg;
|
||||
@@ -330,7 +336,6 @@ struct variant_data {
|
||||
unsigned int datactrl_dpsm_enable;
|
||||
u8 datactrl_first:1;
|
||||
u8 datacnt_useless:1;
|
||||
- u8 st_sdio:1;
|
||||
u8 st_clkdiv:1;
|
||||
u8 stm32_clkdiv:1;
|
||||
u8 blksz_datactrl16:1;
|
||||
@@ -355,9 +360,13 @@ struct variant_data {
|
||||
u32 opendrain;
|
||||
u8 dma_lli:1;
|
||||
u32 stm32_idmabsize_mask;
|
||||
+ u32 quirks;
|
||||
void (*init)(struct mmci_host *host);
|
||||
};
|
||||
|
||||
+#define MMCI_QUIRK_STM32_DTMODE BIT(0)
|
||||
+#define MMCI_QUIRK_ST_SDIO BIT(2) /* enable ST specific SDIO logic */
|
||||
+
|
||||
/* mmci variant callbacks */
|
||||
struct mmci_host_ops {
|
||||
int (*validate_data)(struct mmci_host *host, struct mmc_data *data);
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,771 +0,0 @@
|
|||
From 72179a889501ef339df094abe108846b19e7a06c Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Mon, 26 Nov 2018 14:46:26 +0100
|
||||
Subject: [PATCH 29/52] ARM-stm32mp1-r0-rc2-HWSPINLOCK-IIO-I2C
|
||||
|
||||
---
|
||||
.../devicetree/bindings/iio/adc/st,stm32-adc.txt | 34 +++
|
||||
arch/arm/Kconfig.debug | 27 ++
|
||||
drivers/hwspinlock/Kconfig | 9 +
|
||||
drivers/hwspinlock/Makefile | 1 +
|
||||
drivers/hwspinlock/stm32_hwspinlock.c | 157 +++++++++++
|
||||
drivers/i2c/busses/i2c-stm32f7.c | 6 +-
|
||||
drivers/iio/adc/stm32-adc-core.c | 296 ++++++++++++++++++++-
|
||||
drivers/iio/adc/stm32-adc.c | 4 +-
|
||||
8 files changed, 529 insertions(+), 5 deletions(-)
|
||||
create mode 100644 drivers/hwspinlock/stm32_hwspinlock.c
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
|
||||
index c46598c..a6aa796 100644
|
||||
--- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
|
||||
+++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
|
||||
@@ -49,6 +49,40 @@ Optional properties:
|
||||
- st,max-clk-rate-hz: Allow to specify desired max clock rate used by analog
|
||||
circuitry.
|
||||
|
||||
+- vdda-supply: Phandle to the vdda input voltage. It can be used to supply ADC
|
||||
+ analog inputs switches on stm32mp1 and stm32h7.
|
||||
+
|
||||
+- vdd-supply: Phandle to the vdd input voltage. It can be used to supply ADC
|
||||
+ analog inputs switches on stm32mp1.
|
||||
+
|
||||
+- st,syscfg-vbooster: Voltage booster control for analog switches supply.
|
||||
+ This is available on stm32mp1 and stm32h7 (requires vdda-supply property).
|
||||
+ It must be composed of 3 cells:
|
||||
+ 1st cell: phandle to syscfg
|
||||
+ 2nd cell: register offset within SYSCFG
|
||||
+ 3rd cell: bitmask for BOOSTE on stm32h7, EN_BOOSTER set bit on stm32mp1
|
||||
+
|
||||
+- st,syscfg-vbooster-clr: Voltage booster clear for analog switches supply.
|
||||
+ This is available on stm32mp1 (requires st,syscfg-vbooster and vdda-supply).
|
||||
+ 1st cell: phandle to syscfg
|
||||
+ 2nd cell: clear register offset within SYSCFG
|
||||
+ 3rd cell: bitmask for EN_BOOSTER clear bit on stm32mp1
|
||||
+
|
||||
+- st,syscfg-anaswvdd: VDDA / VDD selection for analog switches supply.
|
||||
+ This is available on stm32mp1 (requires vdda-supply and vdd-supply).
|
||||
+ It must be composed of 3 cells:
|
||||
+ 1st cell: phandle to syscfg
|
||||
+ 2nd cell: register offset within SYSCFG
|
||||
+ 3rd cell: bitmask for ANASWVDD set bit
|
||||
+
|
||||
+- st,syscfg-anaswvdd-clr: VDDA / VDD selection clear for analog switches supply.
|
||||
+ This is available on stm32mp1 (requires st,syscfg-anaswvdd, vdda-supply and
|
||||
+ vdd-supply).
|
||||
+ It must be composed of 3 cells:
|
||||
+ 1st cell: phandle to syscfg
|
||||
+ 2nd cell: clear register offset within SYSCFG
|
||||
+ 3rd cell: bitmask for ANASWVDD clear bit
|
||||
+
|
||||
Contents of a stm32 adc child node:
|
||||
-----------------------------------
|
||||
An ADC block node should contain at least one subnode, representing an
|
||||
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
|
||||
index f6fcb8a..d5ec6c3 100644
|
||||
--- a/arch/arm/Kconfig.debug
|
||||
+++ b/arch/arm/Kconfig.debug
|
||||
@@ -1184,6 +1184,28 @@ choice
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+ config STM32F4_DEBUG_UART
|
||||
+ bool "Use STM32F4 UART for low-level debug"
|
||||
+ depends on ARCH_STM32
|
||||
+ select DEBUG_STM32_UART
|
||||
+ help
|
||||
+ Say Y here if you want kernel low-level debugging support
|
||||
+ on STM32F4 based platforms, which default UART is wired on
|
||||
+ USART1.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
+ config STM32F7_DEBUG_UART
|
||||
+ bool "Use STM32F7 UART for low-level debug"
|
||||
+ depends on ARCH_STM32
|
||||
+ select DEBUG_STM32_UART
|
||||
+ help
|
||||
+ Say Y here if you want kernel low-level debugging support
|
||||
+ on STM32F7 based platforms, which default UART is wired on
|
||||
+ USART1.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config TEGRA_DEBUG_UART_AUTO_ODMDATA
|
||||
bool "Kernel low-level debugging messages via Tegra UART via ODMDATA"
|
||||
depends on ARCH_TEGRA
|
||||
@@ -1468,6 +1490,10 @@ config DEBUG_STI_UART
|
||||
bool
|
||||
depends on ARCH_STI
|
||||
|
||||
+config DEBUG_STM32_UART
|
||||
+ bool
|
||||
+ depends on ARCH_STM32
|
||||
+
|
||||
config DEBUG_SIRFSOC_UART
|
||||
bool
|
||||
depends on ARCH_SIRF
|
||||
@@ -1517,6 +1543,7 @@ config DEBUG_LL_INCLUDE
|
||||
default "debug/s5pv210.S" if DEBUG_S5PV210_UART
|
||||
default "debug/sirf.S" if DEBUG_SIRFSOC_UART
|
||||
default "debug/sti.S" if DEBUG_STI_UART
|
||||
+ default "debug/stm32.S" if DEBUG_STM32_UART
|
||||
default "debug/tegra.S" if DEBUG_TEGRA_UART
|
||||
default "debug/ux500.S" if DEBUG_UX500_UART
|
||||
default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
|
||||
diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
|
||||
index e895d29..7869c67 100644
|
||||
--- a/drivers/hwspinlock/Kconfig
|
||||
+++ b/drivers/hwspinlock/Kconfig
|
||||
@@ -49,6 +49,15 @@ config HWSPINLOCK_SPRD
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config HWSPINLOCK_STM32
|
||||
+ tristate "STM32 Hardware Spinlock device"
|
||||
+ depends on MACH_STM32MP157
|
||||
+ depends on HWSPINLOCK
|
||||
+ help
|
||||
+ Say y here to support the STM32 Hardware Spinlock device.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config HSEM_U8500
|
||||
tristate "STE Hardware Semaphore functionality"
|
||||
depends on HWSPINLOCK
|
||||
diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile
|
||||
index b87c01a..ed053e3 100644
|
||||
--- a/drivers/hwspinlock/Makefile
|
||||
+++ b/drivers/hwspinlock/Makefile
|
||||
@@ -8,4 +8,5 @@ obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o
|
||||
obj-$(CONFIG_HWSPINLOCK_QCOM) += qcom_hwspinlock.o
|
||||
obj-$(CONFIG_HWSPINLOCK_SIRF) += sirf_hwspinlock.o
|
||||
obj-$(CONFIG_HWSPINLOCK_SPRD) += sprd_hwspinlock.o
|
||||
+obj-$(CONFIG_HWSPINLOCK_STM32) += stm32_hwspinlock.o
|
||||
obj-$(CONFIG_HSEM_U8500) += u8500_hsem.o
|
||||
diff --git a/drivers/hwspinlock/stm32_hwspinlock.c b/drivers/hwspinlock/stm32_hwspinlock.c
|
||||
new file mode 100644
|
||||
index 0000000..3242b72
|
||||
--- /dev/null
|
||||
+++ b/drivers/hwspinlock/stm32_hwspinlock.c
|
||||
@@ -0,0 +1,157 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) STMicroelectronics SA 2018
|
||||
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/hwspinlock.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pm_runtime.h>
|
||||
+
|
||||
+#include "hwspinlock_internal.h"
|
||||
+
|
||||
+#define STM32_MUTEX_COREID BIT(8)
|
||||
+#define STM32_MUTEX_LOCK_BIT BIT(31)
|
||||
+#define STM32_MUTEX_NUM_LOCKS 32
|
||||
+
|
||||
+struct stm32_hwspinlock {
|
||||
+ struct clk *clk;
|
||||
+ struct hwspinlock_device bank;
|
||||
+};
|
||||
+
|
||||
+static int stm32_hwspinlock_trylock(struct hwspinlock *lock)
|
||||
+{
|
||||
+ void __iomem *lock_addr = lock->priv;
|
||||
+ u32 status;
|
||||
+
|
||||
+ writel(STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID, lock_addr);
|
||||
+ status = readl(lock_addr);
|
||||
+
|
||||
+ return status == (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID);
|
||||
+}
|
||||
+
|
||||
+static void stm32_hwspinlock_unlock(struct hwspinlock *lock)
|
||||
+{
|
||||
+ void __iomem *lock_addr = lock->priv;
|
||||
+
|
||||
+ writel(STM32_MUTEX_COREID, lock_addr);
|
||||
+}
|
||||
+
|
||||
+static const struct hwspinlock_ops stm32_hwspinlock_ops = {
|
||||
+ .trylock = stm32_hwspinlock_trylock,
|
||||
+ .unlock = stm32_hwspinlock_unlock,
|
||||
+};
|
||||
+
|
||||
+static int stm32_hwspinlock_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct stm32_hwspinlock *hw;
|
||||
+ void __iomem *io_base;
|
||||
+ struct resource *res;
|
||||
+ size_t array_size;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ io_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (!io_base)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ array_size = STM32_MUTEX_NUM_LOCKS * sizeof(struct hwspinlock);
|
||||
+ hw = devm_kzalloc(&pdev->dev, sizeof(*hw) + array_size, GFP_KERNEL);
|
||||
+ if (!hw)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ hw->clk = devm_clk_get(&pdev->dev, "hsem");
|
||||
+ if (IS_ERR(hw->clk))
|
||||
+ return PTR_ERR(hw->clk);
|
||||
+
|
||||
+ for (i = 0; i < STM32_MUTEX_NUM_LOCKS; i++)
|
||||
+ hw->bank.lock[i].priv = io_base + i * sizeof(u32);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, hw);
|
||||
+ pm_runtime_enable(&pdev->dev);
|
||||
+
|
||||
+ ret = hwspin_lock_register(&hw->bank, &pdev->dev, &stm32_hwspinlock_ops,
|
||||
+ 0, STM32_MUTEX_NUM_LOCKS);
|
||||
+
|
||||
+ if (ret)
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int stm32_hwspinlock_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct stm32_hwspinlock *hw = platform_get_drvdata(pdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = hwspin_lock_unregister(&hw->bank);
|
||||
+ if (ret)
|
||||
+ dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
|
||||
+
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __maybe_unused stm32_hwspinlock_runtime_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_hwspinlock *hw = dev_get_drvdata(dev);
|
||||
+
|
||||
+ clk_disable_unprepare(hw->clk);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __maybe_unused stm32_hwspinlock_runtime_resume(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_hwspinlock *hw = dev_get_drvdata(dev);
|
||||
+
|
||||
+ clk_prepare_enable(hw->clk);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct dev_pm_ops stm32_hwspinlock_pm_ops = {
|
||||
+ SET_RUNTIME_PM_OPS(stm32_hwspinlock_runtime_suspend,
|
||||
+ stm32_hwspinlock_runtime_resume,
|
||||
+ NULL)
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id stm32_hwpinlock_ids[] = {
|
||||
+ { .compatible = "st,stm32-hwspinlock", },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, stm32_hwpinlock_ids);
|
||||
+
|
||||
+static struct platform_driver stm32_hwspinlock_driver = {
|
||||
+ .probe = stm32_hwspinlock_probe,
|
||||
+ .remove = stm32_hwspinlock_remove,
|
||||
+ .driver = {
|
||||
+ .name = "stm32_hwspinlock",
|
||||
+ .of_match_table = stm32_hwpinlock_ids,
|
||||
+ .pm = &stm32_hwspinlock_pm_ops,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init stm32_hwspinlock_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&stm32_hwspinlock_driver);
|
||||
+}
|
||||
+
|
||||
+/* board init code might need to reserve hwspinlocks for predefined purposes */
|
||||
+postcore_initcall(stm32_hwspinlock_init);
|
||||
+
|
||||
+static void __exit stm32_hwspinlock_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&stm32_hwspinlock_driver);
|
||||
+}
|
||||
+module_exit(stm32_hwspinlock_exit);
|
||||
+
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_DESCRIPTION("Hardware spinlock driver for STM32 SoCs");
|
||||
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
|
||||
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
|
||||
index c1cbf93..ac30aea 100644
|
||||
--- a/drivers/i2c/busses/i2c-stm32f7.c
|
||||
+++ b/drivers/i2c/busses/i2c-stm32f7.c
|
||||
@@ -457,7 +457,7 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
|
||||
STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0);
|
||||
dnf_delay = setup->dnf * i2cclk;
|
||||
|
||||
- sdadel_min = setup->fall_time - i2c_specs[setup->speed].hddat_min -
|
||||
+ sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time -
|
||||
af_delay_min - (setup->dnf + 3) * i2cclk;
|
||||
|
||||
sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time -
|
||||
@@ -501,8 +501,12 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
|
||||
|
||||
list_add_tail(&v->node,
|
||||
&solutions);
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (p_prev == p)
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
|
||||
index a32e826..6234456 100644
|
||||
--- a/drivers/iio/adc/stm32-adc-core.c
|
||||
+++ b/drivers/iio/adc/stm32-adc-core.c
|
||||
@@ -16,10 +16,12 @@
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/irqdesc.h>
|
||||
#include <linux/irqdomain.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -88,6 +90,8 @@
|
||||
#define STM32H7_CKMODE_SHIFT 16
|
||||
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
|
||||
|
||||
+#define STM32_ADC_CORE_SLEEP_DELAY_MS 2000
|
||||
+
|
||||
/**
|
||||
* stm32_adc_common_regs - stm32 common registers, compatible dependent data
|
||||
* @csr: common status register offset
|
||||
@@ -117,16 +121,30 @@ struct stm32_adc_priv;
|
||||
* @regs: common registers for all instances
|
||||
* @clk_sel: clock selection routine
|
||||
* @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
|
||||
+ * @has_syscfg_clr: analog switch control use set and clear registers
|
||||
* @exti_trigs EXTI triggers info
|
||||
*/
|
||||
struct stm32_adc_priv_cfg {
|
||||
const struct stm32_adc_common_regs *regs;
|
||||
int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
|
||||
u32 max_clk_rate_hz;
|
||||
+ int has_syscfg_clr;
|
||||
struct stm32_adc_trig_info *exti_trigs;
|
||||
};
|
||||
|
||||
/**
|
||||
+ * stm32_adc_syscfg - stm32 ADC SYSCFG data
|
||||
+ * @regmap: reference to syscon
|
||||
+ * @reg: register offset within SYSCFG
|
||||
+ * @mask: bitmask within SYSCFG register
|
||||
+ */
|
||||
+struct stm32_adc_syscfg {
|
||||
+ struct regmap *regmap;
|
||||
+ u32 reg;
|
||||
+ u32 mask;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
* struct stm32_adc_priv - stm32 ADC core private data
|
||||
* @irq: irq(s) for ADC block
|
||||
* @domain: irq domain reference
|
||||
@@ -137,6 +155,10 @@ struct stm32_adc_priv_cfg {
|
||||
* @cfg: compatible configuration data
|
||||
* @common: common data for all ADC instances
|
||||
* @ccr_bak: backup'ed CCR in low power mode
|
||||
+ * @vbooster: BOOSTE syscfg / EN_BOOSTER syscfg set
|
||||
+ * @vbooster_clr: EN_BOOSTER syscfg clear
|
||||
+ * @anaswvdd: ANASWVDD syscfg set
|
||||
+ * @anaswvdd_clr: ANASWVDD syscfg clear
|
||||
*/
|
||||
struct stm32_adc_priv {
|
||||
int irq[STM32_ADC_MAX_ADCS];
|
||||
@@ -144,10 +166,16 @@ struct stm32_adc_priv {
|
||||
struct clk *aclk;
|
||||
struct clk *bclk;
|
||||
u32 max_clk_rate;
|
||||
+ struct regulator *vdd;
|
||||
+ struct regulator *vdda;
|
||||
struct regulator *vref;
|
||||
const struct stm32_adc_priv_cfg *cfg;
|
||||
struct stm32_adc_common common;
|
||||
u32 ccr_bak;
|
||||
+ struct stm32_adc_syscfg vbooster;
|
||||
+ struct stm32_adc_syscfg vbooster_clr;
|
||||
+ struct stm32_adc_syscfg anaswvdd;
|
||||
+ struct stm32_adc_syscfg anaswvdd_clr;
|
||||
};
|
||||
|
||||
static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)
|
||||
@@ -567,16 +595,187 @@ static int stm32_adc_triggers_probe(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int stm32_adc_switches_supply_en(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_adc_common *common = dev_get_drvdata(dev);
|
||||
+ struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
|
||||
+ int ret, vdda, vdd = 0;
|
||||
+ u32 anaswvdd, en_booster;
|
||||
+
|
||||
+ /*
|
||||
+ * On STM32H7 and STM32MP1, the ADC inputs are multiplexed with analog
|
||||
+ * switches (e.g. PCSEL) which have reduced performances when their
|
||||
+ * supply is below 2.7V (vdda by default):
|
||||
+ * - Voltage booster can be used, to get full ADC performances
|
||||
+ * (increases power consumption).
|
||||
+ * - Vdd can be used if above 2.7V (STM32MP1 only).
|
||||
+ *
|
||||
+ * Make all this optional, since this is a trade-off between analog
|
||||
+ * performance and power consumption.
|
||||
+ */
|
||||
+ if (IS_ERR(priv->vdda) || IS_ERR(priv->vbooster.regmap)) {
|
||||
+ dev_dbg(dev, "%s: nothing to do\n", __func__);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ ret = regulator_enable(priv->vdda);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "vdda enable failed %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = regulator_get_voltage(priv->vdda);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "vdda get voltage failed %d\n", ret);
|
||||
+ goto vdda_dis;
|
||||
+ }
|
||||
+ vdda = ret;
|
||||
+
|
||||
+ if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap)) {
|
||||
+ ret = regulator_enable(priv->vdd);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "vdd enable failed %d\n", ret);
|
||||
+ goto vdda_dis;
|
||||
+ }
|
||||
+
|
||||
+ ret = regulator_get_voltage(priv->vdd);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "vdd get voltage failed %d\n", ret);
|
||||
+ goto vdd_dis;
|
||||
+ }
|
||||
+ vdd = ret;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Recommended settings for ANASWVDD and EN_BOOSTER:
|
||||
+ * - vdda > 2.7V: ANASWVDD = 0, EN_BOOSTER = 0
|
||||
+ * - vdda < 2.7V and vdd < 2.7V: ANASWVDD = 0, EN_BOOSTER = 1
|
||||
+ * - vdda < 2.7V but vdd > 2.7V: ANASWVDD = 1, EN_BOOSTER = 0 (stm32mp1)
|
||||
+ */
|
||||
+ if (vdda > 2700000) {
|
||||
+ /* analog switches supplied by vdda (default) */
|
||||
+ anaswvdd = 0;
|
||||
+ en_booster = 0;
|
||||
+ } else {
|
||||
+ if (vdd < 2700000) {
|
||||
+ /* Voltage booster enabled */
|
||||
+ anaswvdd = 0;
|
||||
+ en_booster = priv->vbooster.mask;
|
||||
+ } else {
|
||||
+ /* analog switches supplied by vdd */
|
||||
+ anaswvdd = priv->anaswvdd.mask;
|
||||
+ en_booster = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ dev_dbg(dev, "vdda=%d, vdd=%d, setting: en_booster=%x, anaswvdd=%x\n",
|
||||
+ vdda, vdd, en_booster, anaswvdd);
|
||||
+
|
||||
+ /* direct write en_booster value (or use clear register) */
|
||||
+ if (en_booster || IS_ERR(priv->vbooster_clr.regmap))
|
||||
+ ret = regmap_update_bits(priv->vbooster.regmap,
|
||||
+ priv->vbooster.reg,
|
||||
+ priv->vbooster.mask, en_booster);
|
||||
+ else
|
||||
+ ret = regmap_update_bits(priv->vbooster_clr.regmap,
|
||||
+ priv->vbooster_clr.reg,
|
||||
+ priv->vbooster_clr.mask,
|
||||
+ priv->vbooster_clr.mask);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "can't access voltage booster, %d\n", ret);
|
||||
+ goto vdd_dis;
|
||||
+ }
|
||||
+
|
||||
+ /* Booster voltage can take up to 50 μs to stabilize */
|
||||
+ if (en_booster)
|
||||
+ usleep_range(50, 100);
|
||||
+
|
||||
+ if (!IS_ERR(priv->anaswvdd.regmap)) {
|
||||
+ /* direct write anaswvdd value (or use clear register) */
|
||||
+ if (anaswvdd || IS_ERR(priv->anaswvdd_clr.regmap))
|
||||
+ ret = regmap_update_bits(priv->anaswvdd.regmap,
|
||||
+ priv->anaswvdd.reg,
|
||||
+ priv->anaswvdd.mask, anaswvdd);
|
||||
+ else
|
||||
+ ret = regmap_update_bits(priv->anaswvdd_clr.regmap,
|
||||
+ priv->anaswvdd_clr.reg,
|
||||
+ priv->anaswvdd_clr.mask,
|
||||
+ priv->anaswvdd_clr.mask);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "can't access anaswvdd, %d\n", ret);
|
||||
+ goto booster_dis;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+
|
||||
+booster_dis:
|
||||
+ if (IS_ERR(priv->vbooster_clr.regmap))
|
||||
+ regmap_update_bits(priv->vbooster.regmap, priv->vbooster.reg,
|
||||
+ priv->vbooster.mask, 0);
|
||||
+ else
|
||||
+ regmap_update_bits(priv->vbooster_clr.regmap,
|
||||
+ priv->vbooster_clr.reg,
|
||||
+ priv->vbooster_clr.mask,
|
||||
+ priv->vbooster_clr.mask);
|
||||
+vdd_dis:
|
||||
+ if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap))
|
||||
+ regulator_disable(priv->vdd);
|
||||
+vdda_dis:
|
||||
+ regulator_disable(priv->vdda);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void stm32_adc_switches_supply_dis(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_adc_common *common = dev_get_drvdata(dev);
|
||||
+ struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
|
||||
+
|
||||
+ if (IS_ERR(priv->vdda) || IS_ERR(priv->vbooster.regmap))
|
||||
+ return;
|
||||
+
|
||||
+ if (!IS_ERR(priv->anaswvdd.regmap)) {
|
||||
+ if (IS_ERR(priv->anaswvdd_clr.regmap))
|
||||
+ regmap_update_bits(priv->anaswvdd.regmap,
|
||||
+ priv->anaswvdd.reg,
|
||||
+ priv->anaswvdd.mask, 0);
|
||||
+ else
|
||||
+ regmap_update_bits(priv->anaswvdd_clr.regmap,
|
||||
+ priv->anaswvdd_clr.reg,
|
||||
+ priv->anaswvdd_clr.mask,
|
||||
+ priv->anaswvdd_clr.mask);
|
||||
+ }
|
||||
+
|
||||
+ if (IS_ERR(priv->vbooster_clr.regmap))
|
||||
+ regmap_update_bits(priv->vbooster.regmap, priv->vbooster.reg,
|
||||
+ priv->vbooster.mask, 0);
|
||||
+ else
|
||||
+ regmap_update_bits(priv->vbooster_clr.regmap,
|
||||
+ priv->vbooster_clr.reg,
|
||||
+ priv->vbooster_clr.mask,
|
||||
+ priv->vbooster_clr.mask);
|
||||
+
|
||||
+ if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap))
|
||||
+ regulator_disable(priv->vdd);
|
||||
+
|
||||
+ regulator_disable(priv->vdda);
|
||||
+}
|
||||
+
|
||||
static int stm32_adc_core_hw_start(struct device *dev)
|
||||
{
|
||||
struct stm32_adc_common *common = dev_get_drvdata(dev);
|
||||
struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
|
||||
int ret;
|
||||
|
||||
+ ret = stm32_adc_switches_supply_en(dev);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
ret = regulator_enable(priv->vref);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "vref enable failed\n");
|
||||
- return ret;
|
||||
+ goto err_switches_disable;
|
||||
}
|
||||
|
||||
if (priv->bclk) {
|
||||
@@ -604,6 +803,8 @@ static int stm32_adc_core_hw_start(struct device *dev)
|
||||
clk_disable_unprepare(priv->bclk);
|
||||
err_regulator_disable:
|
||||
regulator_disable(priv->vref);
|
||||
+err_switches_disable:
|
||||
+ stm32_adc_switches_supply_dis(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -620,6 +821,68 @@ static void stm32_adc_core_hw_stop(struct device *dev)
|
||||
if (priv->bclk)
|
||||
clk_disable_unprepare(priv->bclk);
|
||||
regulator_disable(priv->vref);
|
||||
+ stm32_adc_switches_supply_dis(dev);
|
||||
+}
|
||||
+
|
||||
+static int stm32_adc_get_syscfg_cell(struct device_node *np,
|
||||
+ struct stm32_adc_syscfg *syscfg,
|
||||
+ const char * prop)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ syscfg->regmap = syscon_regmap_lookup_by_phandle(np, prop);
|
||||
+ if (IS_ERR(syscfg->regmap)) {
|
||||
+ pr_debug("FGA: %s %ld\n", prop, PTR_ERR(syscfg->regmap));
|
||||
+ /* Optional */
|
||||
+ if (PTR_ERR(syscfg->regmap) == -ENODEV)
|
||||
+ return 0;
|
||||
+ else
|
||||
+ return PTR_ERR(syscfg->regmap);
|
||||
+ }
|
||||
+
|
||||
+ ret = of_property_read_u32_index(np, prop, 1, &syscfg->reg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return of_property_read_u32_index(np, prop, 2, &syscfg->mask);
|
||||
+}
|
||||
+
|
||||
+static int stm32_adc_syscfg_probe(struct platform_device *pdev,
|
||||
+ struct stm32_adc_priv *priv)
|
||||
+{
|
||||
+ struct device_node *np = pdev->dev.of_node;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Start to lookup BOOSTE/EN_BOOSTER first, for stm32h7/stm32mp1 */
|
||||
+ ret = stm32_adc_get_syscfg_cell(np, &priv->vbooster,
|
||||
+ "st,syscfg-vbooster");
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Continue with stm32mp1 EN_BOOSTER/ANASWVDD set and clear bits*/
|
||||
+ ret = stm32_adc_get_syscfg_cell(np, &priv->vbooster_clr,
|
||||
+ "st,syscfg-vbooster-clr");
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = stm32_adc_get_syscfg_cell(np, &priv->anaswvdd,
|
||||
+ "st,syscfg-anaswvdd");
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = stm32_adc_get_syscfg_cell(np, &priv->anaswvdd_clr,
|
||||
+ "st,syscfg-anaswvdd-clr");
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Sanity, check syscfg set/clear pairs are filled in */
|
||||
+ if (priv->cfg->has_syscfg_clr && ((!IS_ERR(priv->vbooster.regmap) &&
|
||||
+ IS_ERR(priv->vbooster_clr.regmap)) ||
|
||||
+ (!IS_ERR(priv->anaswvdd.regmap) &&
|
||||
+ IS_ERR(priv->anaswvdd_clr.regmap))))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int stm32_adc_probe(struct platform_device *pdev)
|
||||
@@ -657,6 +920,24 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ priv->vdda = devm_regulator_get_optional(&pdev->dev, "vdda");
|
||||
+ if (IS_ERR(priv->vdda)) {
|
||||
+ ret = PTR_ERR(priv->vdda);
|
||||
+ if (ret != -ENODEV) {
|
||||
+ dev_err(&pdev->dev, "vdda get failed, %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ priv->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
|
||||
+ if (IS_ERR(priv->vdd)) {
|
||||
+ ret = PTR_ERR(priv->vdd);
|
||||
+ if (ret != -ENODEV) {
|
||||
+ dev_err(&pdev->dev, "vdd get failed, %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
priv->aclk = devm_clk_get(&pdev->dev, "adc");
|
||||
if (IS_ERR(priv->aclk)) {
|
||||
ret = PTR_ERR(priv->aclk);
|
||||
@@ -677,8 +958,17 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||
priv->bclk = NULL;
|
||||
}
|
||||
|
||||
+ ret = stm32_adc_syscfg_probe(pdev, priv);
|
||||
+ if (ret) {
|
||||
+ if (ret != -EPROBE_DEFER)
|
||||
+ dev_err(&pdev->dev, "Can't probe syscfg: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
+ pm_runtime_set_autosuspend_delay(dev, STM32_ADC_CORE_SLEEP_DELAY_MS);
|
||||
+ pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = stm32_adc_core_hw_start(dev);
|
||||
@@ -718,7 +1008,8 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||
goto err_irq_remove;
|
||||
}
|
||||
|
||||
- pm_runtime_put(dev);
|
||||
+ pm_runtime_mark_last_busy(dev);
|
||||
+ pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -789,6 +1080,7 @@ static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
|
||||
static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
|
||||
.regs = &stm32h7_adc_common_regs,
|
||||
.clk_sel = stm32h7_adc_clk_sel,
|
||||
+ .has_syscfg_clr = true,
|
||||
.max_clk_rate_hz = 40000000,
|
||||
.exti_trigs = stm32h7_adc_exti_trigs,
|
||||
};
|
||||
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
|
||||
index 980355e..13d2e3c 100644
|
||||
--- a/drivers/iio/adc/stm32-adc.c
|
||||
+++ b/drivers/iio/adc/stm32-adc.c
|
||||
@@ -201,7 +201,7 @@ enum stm32h7_adc_dmngt {
|
||||
#define STM32_ADC_MAX_SMP 7 /* SMPx range is [0..7] */
|
||||
#define STM32_ADC_TIMEOUT_US 100000
|
||||
#define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
|
||||
-#define STM32_ADC_AUTO_SUSPEND_DELAY_MS 2000
|
||||
+#define STM32_ADC_HW_STOP_DELAY_MS 100
|
||||
|
||||
#define STM32_DMA_BUFFER_SIZE PAGE_SIZE
|
||||
|
||||
@@ -2783,7 +2783,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||
/* Get stm32-adc-core PM online */
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
- pm_runtime_set_autosuspend_delay(dev, STM32_ADC_AUTO_SUSPEND_DELAY_MS);
|
||||
+ pm_runtime_set_autosuspend_delay(dev, STM32_ADC_HW_STOP_DELAY_MS);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,130 +0,0 @@
|
|||
From 73813749b7f0f33a59eb8f321f7d0f9d88dbfbb3 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Priouzeau <christophe.priouzeau@st.com>
|
||||
Date: Mon, 26 Nov 2018 14:46:52 +0100
|
||||
Subject: [PATCH 31/52] ARM-stm32mp1-r0-rc2-DEFCONFIG
|
||||
|
||||
---
|
||||
arch/arm/configs/fragment-02-multiv7_addons.config | 42 +++++++++++++++++++++-
|
||||
1 file changed, 41 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
index c91840c..4470d85 100644
|
||||
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_USELIB=y
|
||||
+CONFIG_FUTEX=y
|
||||
|
||||
#
|
||||
# RCU Subsystem
|
||||
@@ -153,6 +154,12 @@ CONFIG_SERIAL_NONSTANDARD=y
|
||||
# CONFIG_SERIAL_8250 is not set
|
||||
|
||||
#
|
||||
+# Touchscreen drivers
|
||||
+#
|
||||
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
|
||||
+CONFIG_TOUCHSCREEN_GOODIX=m
|
||||
+
|
||||
+#
|
||||
# Non-8250 serial port support
|
||||
#
|
||||
# CONFIG_SERIAL_BCM63XX is not set
|
||||
@@ -179,6 +186,7 @@ CONFIG_SERIAL_NONSTANDARD=y
|
||||
#
|
||||
# SPI Master Controller Drivers
|
||||
#
|
||||
+CONFIG_SPI_STM32=y
|
||||
CONFIG_SPI_STM32_QSPI=y
|
||||
|
||||
#
|
||||
@@ -237,6 +245,7 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||
#
|
||||
# USB HDMI CEC adapters
|
||||
#
|
||||
+CONFIG_VIDEO_STM32_HDMI_CEC=m
|
||||
|
||||
#
|
||||
# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
|
||||
@@ -246,6 +255,7 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||
#
|
||||
# Camera sensor devices
|
||||
#
|
||||
+CONFIG_VIDEO_OV5640=y
|
||||
|
||||
#
|
||||
# Graphics support
|
||||
@@ -261,10 +271,14 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||
#
|
||||
# Display Panels
|
||||
#
|
||||
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
|
||||
+CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
|
||||
|
||||
#
|
||||
# Display Interface Bridges
|
||||
#
|
||||
+CONFIG_VIDEO_ADV7511=m
|
||||
+CONFIG_DRM_SII902X=m
|
||||
|
||||
#
|
||||
# Frame buffer hardware drivers
|
||||
@@ -273,15 +287,34 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||
#
|
||||
# Console display driver support
|
||||
#
|
||||
+CONFIG_DRM_STM=m
|
||||
+CONFIG_DRM_STM_DSI=m
|
||||
+
|
||||
+#
|
||||
+# Backlight support
|
||||
+#
|
||||
+CONFIG_BACKLIGHT_GPIO=y
|
||||
|
||||
#
|
||||
# HD-Audio
|
||||
#
|
||||
+CONFIG_SOUND=y
|
||||
+CONFIG_SND=y
|
||||
+CONFIG_SND_SOC=y
|
||||
+CONFIG_SND_SOC_STM32_SAI=y
|
||||
+CONFIG_SND_SOC_STM32_I2S=y
|
||||
+CONFIG_SND_SOC_STM32_SPDIFRX=y
|
||||
+CONFIG_SND_SOC_STM32_DFSDM=y
|
||||
+CONFIG_SND_AUDIO_GRAPH_CARD=y
|
||||
|
||||
#
|
||||
# CODEC drivers
|
||||
#
|
||||
-
|
||||
+CONFIG_MFD_WM8994=y
|
||||
+CONFIG_SND_SOC_WM8994=y
|
||||
+CONFIG_SND_SOC_DMIC=y
|
||||
+CONFIG_SND_SOC_CS42L42=y
|
||||
+CONFIG_SND_SOC_CS42L51_I2C=y
|
||||
|
||||
#
|
||||
# USB Device Class drivers
|
||||
@@ -300,6 +333,7 @@ CONFIG_PROTECTION_CONSUMER=y
|
||||
#
|
||||
# Gadget/Dual-role mode requires USB Gadget support to be enabled
|
||||
#
|
||||
+CONFIG_USB_CONFIGFS=y
|
||||
|
||||
#
|
||||
# USB Physical Layer drivers
|
||||
@@ -460,3 +494,9 @@ CONFIG_STM32_ADC_TEMP=y
|
||||
# STM32 DAC
|
||||
#
|
||||
CONFIG_STM32_DAC=y
|
||||
+
|
||||
+#
|
||||
+# STM32 HSEM
|
||||
+#
|
||||
+CONFIG_HWSPINLOCK=y
|
||||
+CONFIG_HWSPINLOCK_STM32=y
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
From 1028166948f7116f4dcddc74094125db0a7595c8 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:34:56 +0100
|
||||
Subject: [PATCH 32/52] ARM: stm32mp1-r0-rc3: DMA
|
||||
|
||||
---
|
||||
drivers/dma/stm32-dma.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
|
||||
index 4830f8e..1f9d606 100644
|
||||
--- a/drivers/dma/stm32-dma.c
|
||||
+++ b/drivers/dma/stm32-dma.c
|
||||
@@ -212,6 +212,7 @@ struct stm32_dma_desc {
|
||||
u32 num_sgs;
|
||||
dma_addr_t dma_buf;
|
||||
void *dma_buf_cpu;
|
||||
+ u32 dma_buf_size;
|
||||
struct stm32_dma_sg_req sg_req[];
|
||||
};
|
||||
|
||||
@@ -1224,6 +1225,7 @@ static int stm32_dma_mdma_prep_slave_sg(struct stm32_dma_chan *chan,
|
||||
&desc->dma_buf);
|
||||
if (!desc->dma_buf_cpu)
|
||||
return -ENOMEM;
|
||||
+ desc->dma_buf_size = chan->sram_size;
|
||||
|
||||
sram_period = chan->sram_size / 2;
|
||||
|
||||
@@ -1316,7 +1318,7 @@ static int stm32_dma_mdma_prep_slave_sg(struct stm32_dma_chan *chan,
|
||||
}
|
||||
free_alloc:
|
||||
gen_pool_free(dmadev->sram_pool, (unsigned long)desc->dma_buf_cpu,
|
||||
- chan->sram_size);
|
||||
+ desc->dma_buf_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1437,7 +1439,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
|
||||
|
||||
gen_pool_free(dmadev->sram_pool,
|
||||
(unsigned long)desc->dma_buf_cpu,
|
||||
- chan->sram_size);
|
||||
+ desc->dma_buf_size);
|
||||
}
|
||||
kfree(desc);
|
||||
|
||||
@@ -1462,6 +1464,7 @@ static int stm32_dma_mdma_prep_dma_cyclic(struct stm32_dma_chan *chan,
|
||||
&desc->dma_buf);
|
||||
if (!desc->dma_buf_cpu)
|
||||
return -ENOMEM;
|
||||
+ desc->dma_buf_size = 2 * chan->sram_size;
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
mem = buf_addr;
|
||||
@@ -1511,7 +1514,7 @@ static int stm32_dma_mdma_prep_dma_cyclic(struct stm32_dma_chan *chan,
|
||||
err:
|
||||
gen_pool_free(dmadev->sram_pool,
|
||||
(unsigned long)desc->dma_buf_cpu,
|
||||
- chan->sram_size);
|
||||
+ desc->dma_buf_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1813,7 +1816,7 @@ static void stm32_dma_desc_free(struct virt_dma_desc *vdesc)
|
||||
|
||||
gen_pool_free(dmadev->sram_pool,
|
||||
(unsigned long)desc->dma_buf_cpu,
|
||||
- chan->sram_size);
|
||||
+ desc->dma_buf_size);
|
||||
}
|
||||
|
||||
kfree(desc);
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
From dc9ea19f397651b7671ec4268a12d3f49e2bbda0 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:48:07 +0100
|
||||
Subject: [PATCH 33/52] ARM: stm32mp1-r0-rc3: DISPLAY
|
||||
|
||||
---
|
||||
drivers/gpu/drm/bridge/sii902x.c | 31 +++++++++++++++++++++++++++----
|
||||
drivers/gpu/drm/drm_gem.c | 6 ------
|
||||
2 files changed, 27 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
|
||||
index 512eb03..170657a 100644
|
||||
--- a/drivers/gpu/drm/bridge/sii902x.c
|
||||
+++ b/drivers/gpu/drm/bridge/sii902x.c
|
||||
@@ -397,7 +397,6 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge)
|
||||
regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
|
||||
SII902X_SYS_CTRL_PWR_DWN,
|
||||
SII902X_SYS_CTRL_PWR_DWN);
|
||||
- pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||
}
|
||||
|
||||
static void sii902x_bridge_enable(struct drm_bridge *bridge)
|
||||
@@ -405,7 +404,6 @@ static void sii902x_bridge_enable(struct drm_bridge *bridge)
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
bool hdmi_mode;
|
||||
|
||||
- pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||
regmap_update_bits(sii902x->regmap, SII902X_PWR_STATE_CTRL,
|
||||
SII902X_AVI_POWER_STATE_MSK,
|
||||
SII902X_AVI_POWER_STATE_D(0));
|
||||
@@ -430,8 +428,17 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
||||
struct regmap *regmap = sii902x->regmap;
|
||||
u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
|
||||
struct hdmi_avi_infoframe frame;
|
||||
+ unsigned int status = 0;
|
||||
int ret;
|
||||
|
||||
+ DRM_DEBUG_DRIVER("\n");
|
||||
+
|
||||
+ regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||
+
|
||||
+ /* due to old tv, need to restore pinctrl as soon as possible */
|
||||
+ if (status & SII902X_PLUGGED_STATUS)
|
||||
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||
+
|
||||
buf[0] = adj->clock;
|
||||
buf[1] = adj->clock >> 8;
|
||||
buf[2] = adj->vrefresh;
|
||||
@@ -819,6 +826,11 @@ static irqreturn_t sii902x_interrupt(int irq, void *data)
|
||||
regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||
regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
|
||||
|
||||
+ if (status & SII902X_PLUGGED_STATUS)
|
||||
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||
+ else
|
||||
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||
+
|
||||
if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev)
|
||||
drm_helper_hpd_irq_event(sii902x->bridge.dev);
|
||||
|
||||
@@ -1045,14 +1057,15 @@ static int sii902x_probe(struct i2c_client *client,
|
||||
sii902x_i2c_bypass_deselect);
|
||||
if (!sii902x->i2cmux) {
|
||||
dev_err(dev, "failed to allocate I2C mux\n");
|
||||
- return -ENOMEM;
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_disable_regulator;
|
||||
}
|
||||
|
||||
sii902x->i2cmux->priv = sii902x;
|
||||
ret = i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "Couldn't add i2c mux adapter\n");
|
||||
- return ret;
|
||||
+ goto err_disable_regulator;
|
||||
}
|
||||
|
||||
sii902x_register_audio_driver(dev, sii902x);
|
||||
@@ -1060,6 +1073,7 @@ static int sii902x_probe(struct i2c_client *client,
|
||||
return 0;
|
||||
|
||||
err_disable_regulator:
|
||||
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||
regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
|
||||
sii902x->supplies);
|
||||
|
||||
@@ -1095,6 +1109,8 @@ static int sii902x_pm_suspend(struct device *dev)
|
||||
regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
|
||||
sii902x->supplies);
|
||||
|
||||
+ pinctrl_pm_select_sleep_state(&sii902x->i2c->dev);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1109,10 +1125,17 @@ static int sii902x_pm_resume(struct device *dev)
|
||||
.len = 2,
|
||||
.buf = data,
|
||||
};
|
||||
+ unsigned int status = 0;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
+ regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||
+
|
||||
+ /* due to old tv, need to restore pinctrl as soon as possible */
|
||||
+ if (status & SII902X_PLUGGED_STATUS)
|
||||
+ pinctrl_pm_select_default_state(&sii902x->i2c->dev);
|
||||
+
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(sii902x->supplies),
|
||||
sii902x->supplies);
|
||||
if (ret) {
|
||||
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
|
||||
index bf90625..c7217b1 100644
|
||||
--- a/drivers/gpu/drm/drm_gem.c
|
||||
+++ b/drivers/gpu/drm/drm_gem.c
|
||||
@@ -326,12 +326,6 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
|
||||
if (!obj)
|
||||
return -ENOENT;
|
||||
|
||||
- /* Don't allow imported objects to be mapped */
|
||||
- if (obj->import_attach) {
|
||||
- ret = -EINVAL;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
ret = drm_gem_create_mmap_offset(obj);
|
||||
if (ret)
|
||||
goto out;
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
From f7da805ac84601d1dbbaf51e8f080844e1e5ae4e Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:40:00 +0100
|
||||
Subject: [PATCH 34/52] ARM: stm32mp1-r0-rc3: ETH
|
||||
|
||||
---
|
||||
.../devicetree/bindings/net/stm32-dwmac.txt | 4 +--
|
||||
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 36 ++++++++++++++--------
|
||||
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 20 ++++++------
|
||||
3 files changed, 36 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.txt b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||
index f42dc68..5f6a6ba 100644
|
||||
--- a/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
|
||||
@@ -14,8 +14,7 @@ Required properties:
|
||||
- clock-names: Should be "stmmaceth" for the host clock.
|
||||
Should be "mac-clk-tx" for the MAC TX clock.
|
||||
Should be "mac-clk-rx" for the MAC RX clock.
|
||||
- For MPU family need to add also "ethstp" for power mode clock and,
|
||||
- "syscfg-clk" for SYSCFG clock.
|
||||
+ For MPU family need to add also "ethstp" for power mode clock.
|
||||
- interrupt-names: Should contain a list of interrupt names corresponding to
|
||||
the interrupts in the interrupts property, if available.
|
||||
Should be "macirq" for the main MAC IRQ
|
||||
@@ -25,6 +24,7 @@ Required properties:
|
||||
|
||||
Optional properties:
|
||||
- clock-names: For MPU family "eth-ck" for PHY without quartz
|
||||
+ "syscfg-clk" for SYSCFG clock.
|
||||
- st,eth_clk_sel (boolean) : set this property in RGMII PHY when you do not want use 125Mhz
|
||||
- st,eth_ref_clk_sel (boolean) : set this property in RMII mode when you have PHY without crystal 50MHz
|
||||
|
||||
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
index 545b168..8b4ca12 100644
|
||||
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
||||
@@ -153,23 +153,32 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
|
||||
int ret = 0;
|
||||
|
||||
if (prepare) {
|
||||
- ret = clk_prepare_enable(dwmac->syscfg_clk);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
+ if (dwmac->syscfg_clk) {
|
||||
+ ret = clk_prepare_enable(dwmac->syscfg_clk);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
if (dwmac->clk_eth_ck) {
|
||||
ret = clk_prepare_enable(dwmac->clk_eth_ck);
|
||||
if (ret) {
|
||||
- clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
+ if (dwmac->syscfg_clk)
|
||||
+ goto unprepare_syscfg;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
- clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
+ if (dwmac->syscfg_clk)
|
||||
+ clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
+
|
||||
if (dwmac->clk_eth_ck)
|
||||
clk_disable_unprepare(dwmac->clk_eth_ck);
|
||||
}
|
||||
return ret;
|
||||
+
|
||||
+unprepare_syscfg:
|
||||
+ clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||
@@ -209,8 +218,8 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||
}
|
||||
|
||||
/* Need to update PMCCLRR (clear register) */
|
||||
- ret = regmap_update_bits(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
|
||||
- dwmac->ops->syscfg_eth_mask, ~val);
|
||||
+ ret = regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
|
||||
+ dwmac->ops->syscfg_eth_mask);
|
||||
|
||||
/* Update PMCSETR (set register) */
|
||||
return regmap_update_bits(dwmac->regmap, reg,
|
||||
@@ -318,11 +327,13 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
|
||||
return PTR_ERR(dwmac->clk_ethstp);
|
||||
}
|
||||
|
||||
- /* Clock for sysconfig */
|
||||
+ /* Optional Clock for sysconfig */
|
||||
dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk");
|
||||
if (IS_ERR(dwmac->syscfg_clk)) {
|
||||
- dev_err(dev, "No syscfg clock provided...\n");
|
||||
- return PTR_ERR(dwmac->syscfg_clk);
|
||||
+ err = PTR_ERR(dwmac->syscfg_clk);
|
||||
+ if (err != -ENOENT)
|
||||
+ return err;
|
||||
+ dwmac->syscfg_clk = NULL;
|
||||
}
|
||||
|
||||
/* Get IRQ information early to have an ability to ask for deferred
|
||||
@@ -431,7 +442,8 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
|
||||
return ret;
|
||||
|
||||
clk_disable_unprepare(dwmac->clk_tx);
|
||||
- clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
+ if (dwmac->syscfg_clk)
|
||||
+ clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
if (dwmac->clk_eth_ck)
|
||||
clk_disable_unprepare(dwmac->clk_eth_ck);
|
||||
|
||||
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||||
index 75896d6..281d9c7 100644
|
||||
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||||
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||||
@@ -2547,12 +2547,6 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
|
||||
netdev_warn(priv->dev, "PTP init failed\n");
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_DEBUG_FS
|
||||
- ret = stmmac_init_fs(dev);
|
||||
- if (ret < 0)
|
||||
- netdev_warn(priv->dev, "%s: failed debugFS registration\n",
|
||||
- __func__);
|
||||
-#endif
|
||||
priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
|
||||
|
||||
if (priv->use_riwt) {
|
||||
@@ -2753,10 +2747,6 @@ static int stmmac_release(struct net_device *dev)
|
||||
|
||||
netif_carrier_off(dev);
|
||||
|
||||
-#ifdef CONFIG_DEBUG_FS
|
||||
- stmmac_exit_fs(dev);
|
||||
-#endif
|
||||
-
|
||||
stmmac_release_ptp(priv);
|
||||
|
||||
return 0;
|
||||
@@ -4394,6 +4384,13 @@ int stmmac_dvr_probe(struct device *device,
|
||||
goto error_netdev_register;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_DEBUG_FS
|
||||
+ ret = stmmac_init_fs(ndev);
|
||||
+ if (ret < 0)
|
||||
+ netdev_warn(priv->dev, "%s: failed debugFS registration\n",
|
||||
+ __func__);
|
||||
+#endif
|
||||
+
|
||||
return ret;
|
||||
|
||||
error_netdev_register:
|
||||
@@ -4429,6 +4426,9 @@ int stmmac_dvr_remove(struct device *dev)
|
||||
|
||||
netdev_info(priv->dev, "%s: removing driver", __func__);
|
||||
|
||||
+#ifdef CONFIG_DEBUG_FS
|
||||
+ stmmac_exit_fs(ndev);
|
||||
+#endif
|
||||
stmmac_stop_all_dma(priv);
|
||||
|
||||
stmmac_mac_set(priv, priv->ioaddr, false);
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,479 +0,0 @@
|
|||
From 461aa8f3143d009efd0365889bddf247cfeafdce Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:35:33 +0100
|
||||
Subject: [PATCH 35/52] ARM: stm32mp1-r0-rc3: IIO
|
||||
|
||||
---
|
||||
drivers/iio/adc/stm32-adc-core.c | 35 +++++-----
|
||||
drivers/iio/dac/stm32-dac-core.c | 142 ++++++++++++++++++++++++++++++---------
|
||||
drivers/iio/dac/stm32-dac.c | 96 +++++++++++++++++++++++++-
|
||||
3 files changed, 220 insertions(+), 53 deletions(-)
|
||||
|
||||
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
|
||||
index 6234456..ed64bb0 100644
|
||||
--- a/drivers/iio/adc/stm32-adc-core.c
|
||||
+++ b/drivers/iio/adc/stm32-adc-core.c
|
||||
@@ -677,10 +677,9 @@ static int stm32_adc_switches_supply_en(struct device *dev)
|
||||
priv->vbooster.reg,
|
||||
priv->vbooster.mask, en_booster);
|
||||
else
|
||||
- ret = regmap_update_bits(priv->vbooster_clr.regmap,
|
||||
- priv->vbooster_clr.reg,
|
||||
- priv->vbooster_clr.mask,
|
||||
- priv->vbooster_clr.mask);
|
||||
+ ret = regmap_write(priv->vbooster_clr.regmap,
|
||||
+ priv->vbooster_clr.reg,
|
||||
+ priv->vbooster_clr.mask);
|
||||
if (ret) {
|
||||
dev_err(dev, "can't access voltage booster, %d\n", ret);
|
||||
goto vdd_dis;
|
||||
@@ -697,10 +696,9 @@ static int stm32_adc_switches_supply_en(struct device *dev)
|
||||
priv->anaswvdd.reg,
|
||||
priv->anaswvdd.mask, anaswvdd);
|
||||
else
|
||||
- ret = regmap_update_bits(priv->anaswvdd_clr.regmap,
|
||||
- priv->anaswvdd_clr.reg,
|
||||
- priv->anaswvdd_clr.mask,
|
||||
- priv->anaswvdd_clr.mask);
|
||||
+ ret = regmap_write(priv->anaswvdd_clr.regmap,
|
||||
+ priv->anaswvdd_clr.reg,
|
||||
+ priv->anaswvdd_clr.mask);
|
||||
if (ret) {
|
||||
dev_err(dev, "can't access anaswvdd, %d\n", ret);
|
||||
goto booster_dis;
|
||||
@@ -714,10 +712,9 @@ static int stm32_adc_switches_supply_en(struct device *dev)
|
||||
regmap_update_bits(priv->vbooster.regmap, priv->vbooster.reg,
|
||||
priv->vbooster.mask, 0);
|
||||
else
|
||||
- regmap_update_bits(priv->vbooster_clr.regmap,
|
||||
- priv->vbooster_clr.reg,
|
||||
- priv->vbooster_clr.mask,
|
||||
- priv->vbooster_clr.mask);
|
||||
+ regmap_write(priv->vbooster_clr.regmap,
|
||||
+ priv->vbooster_clr.reg,
|
||||
+ priv->vbooster_clr.mask);
|
||||
vdd_dis:
|
||||
if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap))
|
||||
regulator_disable(priv->vdd);
|
||||
@@ -741,20 +738,18 @@ static void stm32_adc_switches_supply_dis(struct device *dev)
|
||||
priv->anaswvdd.reg,
|
||||
priv->anaswvdd.mask, 0);
|
||||
else
|
||||
- regmap_update_bits(priv->anaswvdd_clr.regmap,
|
||||
- priv->anaswvdd_clr.reg,
|
||||
- priv->anaswvdd_clr.mask,
|
||||
- priv->anaswvdd_clr.mask);
|
||||
+ regmap_write(priv->anaswvdd_clr.regmap,
|
||||
+ priv->anaswvdd_clr.reg,
|
||||
+ priv->anaswvdd_clr.mask);
|
||||
}
|
||||
|
||||
if (IS_ERR(priv->vbooster_clr.regmap))
|
||||
regmap_update_bits(priv->vbooster.regmap, priv->vbooster.reg,
|
||||
priv->vbooster.mask, 0);
|
||||
else
|
||||
- regmap_update_bits(priv->vbooster_clr.regmap,
|
||||
- priv->vbooster_clr.reg,
|
||||
- priv->vbooster_clr.mask,
|
||||
- priv->vbooster_clr.mask);
|
||||
+ regmap_write(priv->vbooster_clr.regmap,
|
||||
+ priv->vbooster_clr.reg,
|
||||
+ priv->vbooster_clr.mask);
|
||||
|
||||
if (!IS_ERR(priv->vdd) && !IS_ERR(priv->anaswvdd.regmap))
|
||||
regulator_disable(priv->vdd);
|
||||
diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c
|
||||
index d0fb312..280322b 100644
|
||||
--- a/drivers/iio/dac/stm32-dac-core.c
|
||||
+++ b/drivers/iio/dac/stm32-dac-core.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
+#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
@@ -50,6 +51,41 @@ static const struct regmap_config stm32_dac_regmap_cfg = {
|
||||
.max_register = 0x3fc,
|
||||
};
|
||||
|
||||
+static int stm32_dac_core_hw_start(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_dac_common *common = dev_get_drvdata(dev);
|
||||
+ struct stm32_dac_priv *priv = to_stm32_dac_priv(common);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = regulator_enable(priv->vref);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "vref enable failed: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(priv->pclk);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "pclk enable failed: %d\n", ret);
|
||||
+ goto err_regulator_disable;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_regulator_disable:
|
||||
+ regulator_disable(priv->vref);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void stm32_dac_core_hw_stop(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_dac_common *common = dev_get_drvdata(dev);
|
||||
+ struct stm32_dac_priv *priv = to_stm32_dac_priv(common);
|
||||
+
|
||||
+ clk_disable_unprepare(priv->pclk);
|
||||
+ regulator_disable(priv->vref);
|
||||
+}
|
||||
+
|
||||
static int stm32_dac_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -66,6 +102,8 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
+ platform_set_drvdata(pdev, &priv->common);
|
||||
+
|
||||
cfg = (const struct stm32_dac_cfg *)
|
||||
of_match_device(dev->driver->of_match_table, dev)->data;
|
||||
|
||||
@@ -74,11 +112,19 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(mmio))
|
||||
return PTR_ERR(mmio);
|
||||
|
||||
- regmap = devm_regmap_init_mmio(dev, mmio, &stm32_dac_regmap_cfg);
|
||||
+ regmap = devm_regmap_init_mmio_clk(dev, "pclk", mmio,
|
||||
+ &stm32_dac_regmap_cfg);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
priv->common.regmap = regmap;
|
||||
|
||||
+ priv->pclk = devm_clk_get(dev, "pclk");
|
||||
+ if (IS_ERR(priv->pclk)) {
|
||||
+ ret = PTR_ERR(priv->pclk);
|
||||
+ dev_err(dev, "pclk get failed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
priv->vref = devm_regulator_get(dev, "vref");
|
||||
if (IS_ERR(priv->vref)) {
|
||||
ret = PTR_ERR(priv->vref);
|
||||
@@ -86,33 +132,22 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ret = regulator_enable(priv->vref);
|
||||
- if (ret < 0) {
|
||||
- dev_err(dev, "vref enable failed\n");
|
||||
- return ret;
|
||||
- }
|
||||
+ pm_runtime_get_noresume(dev);
|
||||
+ pm_runtime_set_active(dev);
|
||||
+ pm_runtime_enable(dev);
|
||||
+
|
||||
+ ret = stm32_dac_core_hw_start(dev);
|
||||
+ if (ret)
|
||||
+ goto err_pm_stop;
|
||||
|
||||
ret = regulator_get_voltage(priv->vref);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "vref get voltage failed, %d\n", ret);
|
||||
- goto err_vref;
|
||||
+ goto err_hw_stop;
|
||||
}
|
||||
priv->common.vref_mv = ret / 1000;
|
||||
dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv);
|
||||
|
||||
- priv->pclk = devm_clk_get(dev, "pclk");
|
||||
- if (IS_ERR(priv->pclk)) {
|
||||
- ret = PTR_ERR(priv->pclk);
|
||||
- dev_err(dev, "pclk get failed\n");
|
||||
- goto err_vref;
|
||||
- }
|
||||
-
|
||||
- ret = clk_prepare_enable(priv->pclk);
|
||||
- if (ret < 0) {
|
||||
- dev_err(dev, "pclk enable failed\n");
|
||||
- goto err_vref;
|
||||
- }
|
||||
-
|
||||
priv->rst = devm_reset_control_get_exclusive(dev, NULL);
|
||||
if (!IS_ERR(priv->rst)) {
|
||||
reset_control_assert(priv->rst);
|
||||
@@ -128,39 +163,83 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||
priv->common.hfsel ?
|
||||
STM32H7_DAC_CR_HFSEL : 0);
|
||||
if (ret)
|
||||
- goto err_pclk;
|
||||
+ goto err_hw_stop;
|
||||
}
|
||||
|
||||
- platform_set_drvdata(pdev, &priv->common);
|
||||
|
||||
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to populate DT children\n");
|
||||
- goto err_pclk;
|
||||
+ goto err_hw_stop;
|
||||
}
|
||||
|
||||
+ pm_runtime_put(dev);
|
||||
+
|
||||
return 0;
|
||||
|
||||
-err_pclk:
|
||||
- clk_disable_unprepare(priv->pclk);
|
||||
-err_vref:
|
||||
- regulator_disable(priv->vref);
|
||||
+err_hw_stop:
|
||||
+ stm32_dac_core_hw_stop(dev);
|
||||
+err_pm_stop:
|
||||
+ pm_runtime_disable(dev);
|
||||
+ pm_runtime_set_suspended(dev);
|
||||
+ pm_runtime_put_noidle(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_dac_remove(struct platform_device *pdev)
|
||||
{
|
||||
- struct stm32_dac_common *common = platform_get_drvdata(pdev);
|
||||
+ pm_runtime_get_sync(&pdev->dev);
|
||||
+ of_platform_depopulate(&pdev->dev);
|
||||
+ stm32_dac_core_hw_stop(&pdev->dev);
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
+ pm_runtime_set_suspended(&pdev->dev);
|
||||
+ pm_runtime_put_noidle(&pdev->dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#if defined(CONFIG_PM_SLEEP)
|
||||
+static int stm32_dac_core_resume(struct device *dev)
|
||||
+{
|
||||
+ struct stm32_dac_common *common = dev_get_drvdata(dev);
|
||||
struct stm32_dac_priv *priv = to_stm32_dac_priv(common);
|
||||
+ int ret;
|
||||
|
||||
- of_platform_depopulate(&pdev->dev);
|
||||
- clk_disable_unprepare(priv->pclk);
|
||||
- regulator_disable(priv->vref);
|
||||
+ /* Unconditionally restore hfsel (maybe lost under low power state) */
|
||||
+ if (priv->common.hfsel) {
|
||||
+ ret = regmap_update_bits(priv->common.regmap, STM32_DAC_CR,
|
||||
+ STM32H7_DAC_CR_HFSEL,
|
||||
+ STM32H7_DAC_CR_HFSEL);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return pm_runtime_force_resume(dev);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#if defined(CONFIG_PM)
|
||||
+static int stm32_dac_core_runtime_suspend(struct device *dev)
|
||||
+{
|
||||
+ stm32_dac_core_hw_stop(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int stm32_dac_core_runtime_resume(struct device *dev)
|
||||
+{
|
||||
+ return stm32_dac_core_hw_start(dev);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static const struct dev_pm_ops stm32_dac_core_pm_ops = {
|
||||
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, stm32_dac_core_resume)
|
||||
+ SET_RUNTIME_PM_OPS(stm32_dac_core_runtime_suspend,
|
||||
+ stm32_dac_core_runtime_resume,
|
||||
+ NULL)
|
||||
+};
|
||||
+
|
||||
static const struct stm32_dac_cfg stm32h7_dac_cfg = {
|
||||
.has_hfsel = true,
|
||||
};
|
||||
@@ -182,6 +261,7 @@ static struct platform_driver stm32_dac_driver = {
|
||||
.driver = {
|
||||
.name = "stm32-dac-core",
|
||||
.of_match_table = stm32_dac_of_match,
|
||||
+ .pm = &stm32_dac_core_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(stm32_dac_driver);
|
||||
diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c
|
||||
index cce26a3..0a8abc5 100644
|
||||
--- a/drivers/iio/dac/stm32-dac.c
|
||||
+++ b/drivers/iio/dac/stm32-dac.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/pm_runtime.h>
|
||||
|
||||
#include "stm32-dac-core.h"
|
||||
|
||||
@@ -20,6 +21,8 @@
|
||||
#define STM32_DAC_CHANNEL_2 2
|
||||
#define STM32_DAC_IS_CHAN_1(ch) ((ch) & STM32_DAC_CHANNEL_1)
|
||||
|
||||
+#define STM32_DAC_AUTO_SUSPEND_DELAY_MS 2000
|
||||
+
|
||||
/**
|
||||
* struct stm32_dac - private data of DAC driver
|
||||
* @common: reference to DAC common data
|
||||
@@ -49,15 +52,34 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch,
|
||||
bool enable)
|
||||
{
|
||||
struct stm32_dac *dac = iio_priv(indio_dev);
|
||||
+ struct device *dev = indio_dev->dev.parent;
|
||||
u32 msk = STM32_DAC_IS_CHAN_1(ch) ? STM32_DAC_CR_EN1 : STM32_DAC_CR_EN2;
|
||||
u32 en = enable ? msk : 0;
|
||||
int ret;
|
||||
|
||||
+ /* already enabled / disabled ? */
|
||||
+ mutex_lock(&indio_dev->mlock);
|
||||
+ ret = stm32_dac_is_enabled(indio_dev, ch);
|
||||
+ if (ret < 0 || enable == !!ret) {
|
||||
+ mutex_unlock(&indio_dev->mlock);
|
||||
+ return ret < 0 ? ret : 0;
|
||||
+ }
|
||||
+
|
||||
+ if (enable) {
|
||||
+ ret = pm_runtime_get_sync(dev);
|
||||
+ if (ret < 0) {
|
||||
+ pm_runtime_put_noidle(dev);
|
||||
+ mutex_unlock(&indio_dev->mlock);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
ret = regmap_update_bits(dac->common->regmap, STM32_DAC_CR, msk, en);
|
||||
+ mutex_unlock(&indio_dev->mlock);
|
||||
if (ret < 0) {
|
||||
dev_err(&indio_dev->dev, "%s failed\n", en ?
|
||||
"Enable" : "Disable");
|
||||
- return ret;
|
||||
+ goto err_put_pm;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -68,7 +90,20 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch,
|
||||
if (en && dac->common->hfsel)
|
||||
udelay(1);
|
||||
|
||||
+ if (!enable) {
|
||||
+ pm_runtime_mark_last_busy(dev);
|
||||
+ pm_runtime_put_autosuspend(dev);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
+
|
||||
+err_put_pm:
|
||||
+ if (enable) {
|
||||
+ pm_runtime_mark_last_busy(dev);
|
||||
+ pm_runtime_put_autosuspend(dev);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int stm32_dac_get_value(struct stm32_dac *dac, int channel, int *val)
|
||||
@@ -272,6 +307,7 @@ static int stm32_dac_chan_of_init(struct iio_dev *indio_dev)
|
||||
static int stm32_dac_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
struct iio_dev *indio_dev;
|
||||
struct stm32_dac *dac;
|
||||
int ret;
|
||||
@@ -296,9 +332,63 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- return devm_iio_device_register(&pdev->dev, indio_dev);
|
||||
+ /* Get stm32-dac-core PM online */
|
||||
+ pm_runtime_get_noresume(dev);
|
||||
+ pm_runtime_set_active(dev);
|
||||
+ pm_runtime_set_autosuspend_delay(dev, STM32_DAC_AUTO_SUSPEND_DELAY_MS);
|
||||
+ pm_runtime_use_autosuspend(dev);
|
||||
+ pm_runtime_enable(dev);
|
||||
+
|
||||
+ ret = iio_device_register(indio_dev);
|
||||
+ if (ret)
|
||||
+ goto err_pm_put;
|
||||
+
|
||||
+ pm_runtime_mark_last_busy(dev);
|
||||
+ pm_runtime_put_autosuspend(dev);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_pm_put:
|
||||
+ pm_runtime_disable(dev);
|
||||
+ pm_runtime_set_suspended(dev);
|
||||
+ pm_runtime_put_noidle(dev);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
+static int stm32_dac_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ pm_runtime_get_sync(&pdev->dev);
|
||||
+ iio_device_unregister(indio_dev);
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
+ pm_runtime_set_suspended(&pdev->dev);
|
||||
+ pm_runtime_put_noidle(&pdev->dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#if defined(CONFIG_PM_SLEEP)
|
||||
+static int stm32_dac_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
+ int channel = indio_dev->channels[0].channel;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Ensure DAC is disabled before suspend */
|
||||
+ ret = stm32_dac_is_enabled(indio_dev, channel);
|
||||
+ if (ret)
|
||||
+ return ret < 0 ? ret : -EBUSY;
|
||||
+
|
||||
+ return pm_runtime_force_suspend(dev);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static const struct dev_pm_ops stm32_dac_pm_ops = {
|
||||
+ SET_SYSTEM_SLEEP_PM_OPS(stm32_dac_suspend, pm_runtime_force_resume)
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id stm32_dac_of_match[] = {
|
||||
{ .compatible = "st,stm32-dac", },
|
||||
{},
|
||||
@@ -307,9 +397,11 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
|
||||
|
||||
static struct platform_driver stm32_dac_driver = {
|
||||
.probe = stm32_dac_probe,
|
||||
+ .remove = stm32_dac_remove,
|
||||
.driver = {
|
||||
.name = "stm32-dac",
|
||||
.of_match_table = stm32_dac_of_match,
|
||||
+ .pm = &stm32_dac_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(stm32_dac_driver);
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
From adfe9751275d51343a5b7f26ea93246ae617d986 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:37:06 +0100
|
||||
Subject: [PATCH 36/52] ARM: stm32mp1-r0-rc3: INPUT TTY
|
||||
|
||||
---
|
||||
.../devicetree/bindings/serial/st,stm32-usart.txt | 1 +
|
||||
drivers/input/touchscreen/edt-ft5x06.c | 8 +++++++-
|
||||
drivers/input/touchscreen/goodix.c | 9 +++++++++
|
||||
drivers/tty/serial/stm32-usart.c | 18 ++++++++++++++++--
|
||||
4 files changed, 33 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
|
||||
index 90ba52f..08b4990 100644
|
||||
--- a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
|
||||
+++ b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
|
||||
@@ -14,6 +14,7 @@ Required properties:
|
||||
- clocks: The input clock of the USART instance
|
||||
|
||||
Optional properties:
|
||||
+- resets: Must contain the phandle to the reset controller.
|
||||
- pinctrl-names: Set to "default". An additional "sleep" state can be defined
|
||||
to set pins in sleep state when in low power. In case the device is used as
|
||||
a wakeup source, "idle" state is defined in order to keep RX pin active.
|
||||
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
|
||||
index 1e18ca0..c1c6f2a 100644
|
||||
--- a/drivers/input/touchscreen/edt-ft5x06.c
|
||||
+++ b/drivers/input/touchscreen/edt-ft5x06.c
|
||||
@@ -1033,7 +1033,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
|
||||
|
||||
error = edt_ft5x06_ts_identify(client, tsdata, fw_version);
|
||||
if (error) {
|
||||
- dev_err(&client->dev, "touchscreen probe failed\n");
|
||||
+ dev_dbg(&client->dev, "touchscreen probe failed\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1152,11 +1152,16 @@ static const struct edt_i2c_chip_data edt_ft6236_data = {
|
||||
.max_support_points = 2,
|
||||
};
|
||||
|
||||
+static const struct edt_i2c_chip_data edt_ft6336_data = {
|
||||
+ .max_support_points = 2,
|
||||
+};
|
||||
+
|
||||
static const struct i2c_device_id edt_ft5x06_ts_id[] = {
|
||||
{ .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
|
||||
{ .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data },
|
||||
/* Note no edt- prefix for compatibility with the ft6236.c driver */
|
||||
{ .name = "ft6236", .driver_data = (long)&edt_ft6236_data },
|
||||
+ { .name = "ft6336", .driver_data = (long)&edt_ft6336_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
|
||||
@@ -1169,6 +1174,7 @@ static const struct of_device_id edt_ft5x06_of_match[] = {
|
||||
{ .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data },
|
||||
/* Note focaltech vendor prefix for compatibility with ft6236.c */
|
||||
{ .compatible = "focaltech,ft6236", .data = &edt_ft6236_data },
|
||||
+ { .compatible = "focaltech,ft6336", .data = &edt_ft6336_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
|
||||
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
|
||||
index f2d9c2c..9ce8db4 100644
|
||||
--- a/drivers/input/touchscreen/goodix.c
|
||||
+++ b/drivers/input/touchscreen/goodix.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
+#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/of.h>
|
||||
@@ -357,6 +358,13 @@ static void goodix_free_irq(struct goodix_ts_data *ts)
|
||||
|
||||
static int goodix_request_irq(struct goodix_ts_data *ts)
|
||||
{
|
||||
+ int gpio;
|
||||
+
|
||||
+ gpio = desc_to_gpio(ts->gpiod_int);
|
||||
+
|
||||
+ if (gpio_is_valid(gpio))
|
||||
+ ts->client->irq = gpio_to_irq(gpio);
|
||||
+
|
||||
return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
|
||||
NULL, goodix_ts_irq_handler,
|
||||
ts->irq_flags, ts->client->name, ts);
|
||||
@@ -949,6 +957,7 @@ static const struct of_device_id goodix_of_match[] = {
|
||||
{ .compatible = "goodix,gt9271" },
|
||||
{ .compatible = "goodix,gt928" },
|
||||
{ .compatible = "goodix,gt967" },
|
||||
+ { .compatible = "goodix,gt9147",},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, goodix_of_match);
|
||||
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
|
||||
index 5c6c3c0..d606eb5 100644
|
||||
--- a/drivers/tty/serial/stm32-usart.c
|
||||
+++ b/drivers/tty/serial/stm32-usart.c
|
||||
@@ -938,6 +938,7 @@ static int stm32_init_port(struct stm32_port *stm32port,
|
||||
{
|
||||
struct uart_port *port = &stm32port->port;
|
||||
struct resource *res;
|
||||
+ struct pinctrl *uart_pinctrl;
|
||||
int ret;
|
||||
|
||||
port->iotype = UPIO_MEM;
|
||||
@@ -952,8 +953,21 @@ static int stm32_init_port(struct stm32_port *stm32port,
|
||||
|
||||
stm32port->wakeirq = platform_get_irq_byname(pdev, "wakeup");
|
||||
stm32port->fifoen = stm32port->info->cfg.has_fifo;
|
||||
- stm32port->console_pins = pinctrl_lookup_state(pdev->dev.pins->p,
|
||||
- "no_console_suspend");
|
||||
+
|
||||
+ uart_pinctrl = devm_pinctrl_get(&pdev->dev);
|
||||
+ if (IS_ERR(uart_pinctrl)) {
|
||||
+ ret = PTR_ERR(uart_pinctrl);
|
||||
+ if (ret != -ENODEV) {
|
||||
+ dev_err(&pdev->dev,"Can't get pinctrl, error %d\n",
|
||||
+ ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ stm32port->console_pins = ERR_PTR(-ENODEV);
|
||||
+ }
|
||||
+ else
|
||||
+ stm32port->console_pins = pinctrl_lookup_state
|
||||
+ (uart_pinctrl,"no_console_suspend");
|
||||
+
|
||||
if (IS_ERR(stm32port->console_pins)
|
||||
&& PTR_ERR(stm32port->console_pins) != -ENODEV)
|
||||
return PTR_ERR(stm32port->console_pins);
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
From 4cc987cced2179b54ebc0a977ff3ef4210acb38c Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:36:09 +0100
|
||||
Subject: [PATCH 37/52] ARM: stm32mp1-r0-rc3: IRQ Mailbox
|
||||
|
||||
---
|
||||
drivers/irqchip/irq-stm32-exti.c | 122 ++++++++++++++++++++++++++-------------
|
||||
1 file changed, 83 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
|
||||
index 9cc15f1..223ee2e 100644
|
||||
--- a/drivers/irqchip/irq-stm32-exti.c
|
||||
+++ b/drivers/irqchip/irq-stm32-exti.c
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
+#include <linux/delay.h>
|
||||
#include <linux/hwspinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
@@ -21,7 +22,8 @@
|
||||
|
||||
#define IRQS_PER_BANK 32
|
||||
|
||||
-#define HWSPINLOCK_TIMEOUT 5 /* msec */
|
||||
+#define HWSPNLCK_TIMEOUT 1000 /* usec */
|
||||
+#define HWSPNLCK_RETRY_DELAY 100 /* usec */
|
||||
|
||||
struct stm32_exti_bank {
|
||||
u32 imr_ofst;
|
||||
@@ -35,6 +37,12 @@ struct stm32_exti_bank {
|
||||
|
||||
#define UNDEF_REG ~0
|
||||
|
||||
+enum stm32_exti_hwspinlock {
|
||||
+ HWSPINLOCK_UNKNOWN,
|
||||
+ HWSPINLOCK_NONE,
|
||||
+ HWSPINLOCK_READY,
|
||||
+};
|
||||
+
|
||||
struct stm32_desc_irq {
|
||||
u32 exti;
|
||||
u32 irq_parent;
|
||||
@@ -50,7 +58,6 @@ struct stm32_exti_drv_data {
|
||||
struct stm32_exti_chip_data {
|
||||
struct stm32_exti_host_data *host_data;
|
||||
const struct stm32_exti_bank *reg_bank;
|
||||
- struct hwspinlock *hwlock;
|
||||
struct raw_spinlock rlock;
|
||||
u32 wake_active;
|
||||
u32 mask_cache;
|
||||
@@ -62,6 +69,9 @@ struct stm32_exti_host_data {
|
||||
void __iomem *base;
|
||||
struct stm32_exti_chip_data *chips_data;
|
||||
const struct stm32_exti_drv_data *drv_data;
|
||||
+ struct device_node *node;
|
||||
+ enum stm32_exti_hwspinlock hwlock_state;
|
||||
+ struct hwspinlock *hwlock;
|
||||
};
|
||||
|
||||
static struct stm32_exti_host_data *stm32_host_data;
|
||||
@@ -273,20 +283,75 @@ static int stm32_exti_set_type(struct irq_data *d,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data)
|
||||
+{
|
||||
+ struct stm32_exti_host_data *host_data = chip_data->host_data;
|
||||
+ struct hwspinlock *hwlock;
|
||||
+ int id, ret = 0, timeout = 0;
|
||||
+
|
||||
+ /* first time, check for hwspinlock availability */
|
||||
+ if (unlikely(host_data->hwlock_state == HWSPINLOCK_UNKNOWN)) {
|
||||
+ id = of_hwspin_lock_get_id(host_data->node, 0);
|
||||
+ if (id >= 0) {
|
||||
+ hwlock = hwspin_lock_request_specific(id);
|
||||
+ if (hwlock) {
|
||||
+ /* found valid hwspinlock */
|
||||
+ host_data->hwlock_state = HWSPINLOCK_READY;
|
||||
+ host_data->hwlock = hwlock;
|
||||
+ pr_debug("%s hwspinlock = %d\n", __func__, id);
|
||||
+ } else {
|
||||
+ host_data->hwlock_state = HWSPINLOCK_NONE;
|
||||
+ }
|
||||
+ } else if (id != -EPROBE_DEFER) {
|
||||
+ host_data->hwlock_state = HWSPINLOCK_NONE;
|
||||
+ } else {
|
||||
+ /* hwspinlock driver shall be ready at that stage */
|
||||
+ ret = -EPROBE_DEFER;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (likely(host_data->hwlock_state == HWSPINLOCK_READY)) {
|
||||
+ /*
|
||||
+ * Use the x_raw API since we are under spin_lock protection.
|
||||
+ * Do not use the x_timeout API because we are under irq_disable
|
||||
+ * mode (see __setup_irq())
|
||||
+ */
|
||||
+ do {
|
||||
+ ret = hwspin_trylock_raw(host_data->hwlock);
|
||||
+ if (!ret)
|
||||
+ return 0;
|
||||
+
|
||||
+ udelay(HWSPNLCK_RETRY_DELAY);
|
||||
+ timeout += HWSPNLCK_RETRY_DELAY;
|
||||
+ } while (timeout < HWSPNLCK_TIMEOUT);
|
||||
+
|
||||
+ if (ret == -EBUSY)
|
||||
+ ret = -ETIMEDOUT;
|
||||
+ }
|
||||
+
|
||||
+ if (ret)
|
||||
+ pr_err("%s can't get hwspinlock (%d)\n", __func__, ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data)
|
||||
+{
|
||||
+ if (likely(chip_data->host_data->hwlock_state == HWSPINLOCK_READY))
|
||||
+ hwspin_unlock_raw(chip_data->host_data->hwlock);
|
||||
+}
|
||||
+
|
||||
static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
struct stm32_exti_chip_data *chip_data = gc->private;
|
||||
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
|
||||
u32 rtsr, ftsr;
|
||||
- int err = 0;
|
||||
+ int err;
|
||||
|
||||
irq_gc_lock(gc);
|
||||
|
||||
- if (chip_data->hwlock)
|
||||
- err = hwspin_lock_timeout(chip_data->hwlock,
|
||||
- HWSPINLOCK_TIMEOUT);
|
||||
-
|
||||
+ err = stm32_exti_hwspin_lock(chip_data);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
@@ -301,8 +366,7 @@ static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
|
||||
|
||||
unspinlock:
|
||||
- if (chip_data->hwlock)
|
||||
- hwspin_unlock(chip_data->hwlock);
|
||||
+ stm32_exti_hwspin_unlock(chip_data);
|
||||
unlock:
|
||||
irq_gc_unlock(gc);
|
||||
|
||||
@@ -470,14 +534,11 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type)
|
||||
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
|
||||
void __iomem *base = chip_data->host_data->base;
|
||||
u32 rtsr, ftsr;
|
||||
- int err = 0;
|
||||
+ int err;
|
||||
|
||||
raw_spin_lock(&chip_data->rlock);
|
||||
|
||||
- if (chip_data->hwlock)
|
||||
- err = hwspin_lock_timeout(chip_data->hwlock,
|
||||
- HWSPINLOCK_TIMEOUT);
|
||||
-
|
||||
+ err = stm32_exti_hwspin_lock(chip_data);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
@@ -492,15 +553,14 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type)
|
||||
writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst);
|
||||
|
||||
unspinlock:
|
||||
- if (chip_data->hwlock)
|
||||
- hwspin_unlock(chip_data->hwlock);
|
||||
+ stm32_exti_hwspin_unlock(chip_data);
|
||||
unlock:
|
||||
raw_spin_unlock(&chip_data->rlock);
|
||||
|
||||
if (d->parent_data->chip)
|
||||
irq_chip_set_type_parent(d, type);
|
||||
|
||||
- return 0;
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on)
|
||||
@@ -650,6 +710,8 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
|
||||
return NULL;
|
||||
|
||||
host_data->drv_data = dd;
|
||||
+ host_data->node = node;
|
||||
+ host_data->hwlock_state = HWSPINLOCK_UNKNOWN;
|
||||
host_data->chips_data = kcalloc(dd->bank_nr,
|
||||
sizeof(struct stm32_exti_chip_data),
|
||||
GFP_KERNEL);
|
||||
@@ -676,13 +738,11 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
|
||||
|
||||
static struct
|
||||
stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||
- u32 bank_idx,
|
||||
- struct device_node *node)
|
||||
+ u32 bank_idx)
|
||||
{
|
||||
const struct stm32_exti_bank *stm32_bank;
|
||||
struct stm32_exti_chip_data *chip_data;
|
||||
void __iomem *base = h_data->base;
|
||||
- u32 irqs_mask;
|
||||
|
||||
stm32_bank = h_data->drv_data->exti_banks[bank_idx];
|
||||
chip_data = &h_data->chips_data[bank_idx];
|
||||
@@ -691,10 +751,6 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||
|
||||
raw_spin_lock_init(&chip_data->rlock);
|
||||
|
||||
- /* Determine number of irqs supported */
|
||||
- writel_relaxed(~0UL, base + stm32_bank->rtsr_ofst);
|
||||
- irqs_mask = readl_relaxed(base + stm32_bank->rtsr_ofst);
|
||||
-
|
||||
/*
|
||||
* This IP has no reset, so after hot reboot we should
|
||||
* clear registers to avoid residue
|
||||
@@ -702,8 +758,7 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||
writel_relaxed(0, base + stm32_bank->imr_ofst);
|
||||
writel_relaxed(0, base + stm32_bank->emr_ofst);
|
||||
|
||||
- pr_info("%s: bank%d, External IRQs available:%#x\n",
|
||||
- node->full_name, bank_idx, irqs_mask);
|
||||
+ pr_info("%pOF: bank%d\n", h_data->node, bank_idx);
|
||||
|
||||
return chip_data;
|
||||
}
|
||||
@@ -716,7 +771,6 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||
int nr_irqs, ret, i;
|
||||
struct irq_chip_generic *gc;
|
||||
struct irq_domain *domain;
|
||||
- struct hwspinlock *hwlock = NULL;
|
||||
|
||||
host_data = stm32_exti_host_init(drv_data, node);
|
||||
if (!host_data)
|
||||
@@ -739,22 +793,12 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||
goto out_free_domain;
|
||||
}
|
||||
|
||||
- /* hwspinlock is optional */
|
||||
- ret = of_hwspin_lock_get_id(node, 0);
|
||||
- if (ret < 0) {
|
||||
- if (ret == -EPROBE_DEFER)
|
||||
- goto out_free_domain;
|
||||
- } else {
|
||||
- hwlock = hwspin_lock_request_specific(ret);
|
||||
- }
|
||||
-
|
||||
for (i = 0; i < drv_data->bank_nr; i++) {
|
||||
const struct stm32_exti_bank *stm32_bank;
|
||||
struct stm32_exti_chip_data *chip_data;
|
||||
|
||||
stm32_bank = drv_data->exti_banks[i];
|
||||
- chip_data = stm32_exti_chip_init(host_data, i, node);
|
||||
- chip_data->hwlock = hwlock;
|
||||
+ chip_data = stm32_exti_chip_init(host_data, i);
|
||||
|
||||
gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
|
||||
|
||||
@@ -836,7 +880,7 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < drv_data->bank_nr; i++)
|
||||
- stm32_exti_chip_init(host_data, i, node);
|
||||
+ stm32_exti_chip_init(host_data, i);
|
||||
|
||||
domain = irq_domain_add_hierarchy(parent_domain, 0,
|
||||
drv_data->bank_nr * IRQS_PER_BANK,
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
From 6c1f5d14ed9c421276ad7beac5475e1114520369 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:48:55 +0100
|
||||
Subject: [PATCH 38/52] ARM: stm32mp1-r0-rc3: MEDIA
|
||||
|
||||
---
|
||||
drivers/media/i2c/ov5640.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
|
||||
index 27b75e7..22ddfca4 100644
|
||||
--- a/drivers/media/i2c/ov5640.c
|
||||
+++ b/drivers/media/i2c/ov5640.c
|
||||
@@ -2691,8 +2691,7 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
|
||||
if (sensor->streaming == !enable) {
|
||||
if (enable && sensor->pending_mode_change) {
|
||||
- ret = ov5640_set_mode(sensor, sensor->last_mode);
|
||||
-
|
||||
+ ret = ov5640_set_mode(sensor);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,478 +0,0 @@
|
|||
From 0affc90bd300ecd2c60aee7fd97251a8d2aad01f Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:38:59 +0100
|
||||
Subject: [PATCH 39/52] ARM: stm32mp1-r0-rc3: MMC MTD
|
||||
|
||||
---
|
||||
Documentation/devicetree/bindings/mmc/mmci.txt | 2 +
|
||||
drivers/mmc/host/mmci.c | 61 +++++++++-
|
||||
drivers/mmc/host/mmci.h | 8 +-
|
||||
drivers/mmc/host/mmci_stm32_sdmmc.c | 162 ++++++++++++++++++++++++-
|
||||
4 files changed, 219 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/mmc/mmci.txt b/Documentation/devicetree/bindings/mmc/mmci.txt
|
||||
index 6d3c626..da6d59e 100644
|
||||
--- a/Documentation/devicetree/bindings/mmc/mmci.txt
|
||||
+++ b/Documentation/devicetree/bindings/mmc/mmci.txt
|
||||
@@ -15,6 +15,8 @@ Required properties:
|
||||
Optional properties:
|
||||
- arm,primecell-periphid : contains the PrimeCell Peripheral ID, it overrides
|
||||
the ID provided by the HW
|
||||
+- reg : sdmmc variant could have a second base register for
|
||||
+ delay block.
|
||||
- resets : phandle to internal reset line.
|
||||
Should be defined for sdmmc variant.
|
||||
- vqmmc-supply : phandle to the regulator device tree node, mentioned
|
||||
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
|
||||
index 02b631f..6c2b1a0 100644
|
||||
--- a/drivers/mmc/host/mmci.c
|
||||
+++ b/drivers/mmc/host/mmci.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/iopoll.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -25,6 +26,7 @@
|
||||
#include <linux/mmc/pm.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/card.h>
|
||||
+#include <linux/mmc/sd.h>
|
||||
#include <linux/mmc/slot-gpio.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/clk.h>
|
||||
@@ -291,7 +293,8 @@ static struct variant_data variant_stm32_sdmmc = {
|
||||
.busy_detect_flag = MCI_STM32_BUSYD0,
|
||||
.busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
|
||||
.init = sdmmc_variant_init,
|
||||
- .quirks = MMCI_QUIRK_STM32_DTMODE,
|
||||
+ .quirks = MMCI_QUIRK_STM32_DTMODE |
|
||||
+ MMCI_QUIRK_STM32_VSWITCH,
|
||||
};
|
||||
|
||||
static struct variant_data variant_stm32_sdmmcv2 = {
|
||||
@@ -318,7 +321,8 @@ static struct variant_data variant_stm32_sdmmcv2 = {
|
||||
.busy_detect_flag = MCI_STM32_BUSYD0,
|
||||
.busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
|
||||
.init = sdmmc_variant_init,
|
||||
- .quirks = MMCI_QUIRK_STM32_DTMODE,
|
||||
+ .quirks = MMCI_QUIRK_STM32_DTMODE |
|
||||
+ MMCI_QUIRK_STM32_VSWITCH,
|
||||
};
|
||||
|
||||
static struct variant_data variant_qcom = {
|
||||
@@ -1191,6 +1195,10 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
|
||||
writel_relaxed(clks, host->base + MMCIDATATIMER);
|
||||
}
|
||||
|
||||
+ if (host->variant->quirks & MMCI_QUIRK_STM32_VSWITCH &&
|
||||
+ cmd->opcode == SD_SWITCH_VOLTAGE)
|
||||
+ mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCHEN);
|
||||
+
|
||||
if (/*interrupt*/0)
|
||||
c |= MCI_CPSM_INTERRUPT;
|
||||
|
||||
@@ -1284,13 +1292,13 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
|
||||
unsigned int status)
|
||||
{
|
||||
void __iomem *base = host->base;
|
||||
- bool busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
|
||||
- bool sbc;
|
||||
+ bool busy_resp, sbc;
|
||||
u32 err_msk;
|
||||
|
||||
if (!cmd)
|
||||
return;
|
||||
|
||||
+ busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
|
||||
sbc = (cmd == host->mrq->sbc);
|
||||
|
||||
/*
|
||||
@@ -1575,11 +1583,14 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
|
||||
static irqreturn_t mmci_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct mmci_host *host = dev_id;
|
||||
+ bool busy_resp;
|
||||
u32 status;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock(&host->lock);
|
||||
|
||||
+ busy_resp = host->cmd ? !!(host->cmd->flags & MMC_RSP_BUSY) : false;
|
||||
+
|
||||
do {
|
||||
status = readl(host->base + MMCISTATUS);
|
||||
|
||||
@@ -1619,9 +1630,12 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
/*
|
||||
- * Don't poll for busy completion in irq context.
|
||||
+ * Don't poll for:
|
||||
+ * -busy completion in irq context.
|
||||
+ * -cmd without busy response check like cmd11
|
||||
*/
|
||||
- if (host->variant->busy_detect && host->busy_status)
|
||||
+ if (host->variant->busy_detect &&
|
||||
+ (!busy_resp || host->busy_status))
|
||||
status &= ~host->variant->busy_detect_flag;
|
||||
|
||||
ret = 1;
|
||||
@@ -1796,6 +1810,8 @@ static int mmci_get_cd(struct mmc_host *mmc)
|
||||
|
||||
static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
{
|
||||
+ struct mmci_host *host = mmc_priv(mmc);
|
||||
+ unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (!IS_ERR(mmc->supply.vqmmc)) {
|
||||
@@ -1808,6 +1824,28 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
case MMC_SIGNAL_VOLTAGE_180:
|
||||
ret = regulator_set_voltage(mmc->supply.vqmmc,
|
||||
1700000, 1950000);
|
||||
+
|
||||
+ if (ret)
|
||||
+ break;
|
||||
+
|
||||
+ if (host->variant->quirks & MMCI_QUIRK_STM32_VSWITCH) {
|
||||
+ u32 status;
|
||||
+
|
||||
+ spin_lock_irqsave(&host->lock, flags);
|
||||
+
|
||||
+ mmci_write_pwrreg(host, host->pwr_reg |
|
||||
+ MCI_STM32_VSWITCH);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&host->lock, flags);
|
||||
+
|
||||
+ /* wait voltage switch completion while 10ms */
|
||||
+ ret = readl_relaxed_poll_timeout(
|
||||
+ host->base + MMCISTATUS,
|
||||
+ status,
|
||||
+ (status & MCI_STM32_VSWEND),
|
||||
+ 10, 10000);
|
||||
+ }
|
||||
+
|
||||
break;
|
||||
case MMC_SIGNAL_VOLTAGE_120:
|
||||
ret = regulator_set_voltage(mmc->supply.vqmmc,
|
||||
@@ -1822,6 +1860,16 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int mmci_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||
+{
|
||||
+ struct mmci_host *host = mmc_priv(mmc);
|
||||
+
|
||||
+ if (host->ops && host->ops->execute_tuning)
|
||||
+ return host->ops->execute_tuning(mmc, opcode);
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
static struct mmc_host_ops mmci_ops = {
|
||||
.request = mmci_request,
|
||||
.pre_req = mmci_pre_request,
|
||||
@@ -1830,6 +1878,7 @@ static struct mmc_host_ops mmci_ops = {
|
||||
.get_ro = mmc_gpio_get_ro,
|
||||
.get_cd = mmci_get_cd,
|
||||
.start_signal_voltage_switch = mmci_sig_volt_switch,
|
||||
+ .execute_tuning = mmci_execute_tuning,
|
||||
};
|
||||
|
||||
static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc)
|
||||
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
|
||||
index 55867fc..e10093e 100644
|
||||
--- a/drivers/mmc/host/mmci.h
|
||||
+++ b/drivers/mmc/host/mmci.h
|
||||
@@ -170,6 +170,7 @@
|
||||
#define MCI_STM32_DPSMACTIVE BIT(12)
|
||||
#define MCI_STM32_BUSYD0 BIT(20)
|
||||
#define MCI_STM32_BUSYD0END BIT(21)
|
||||
+#define MCI_STM32_VSWEND BIT(25)
|
||||
|
||||
#define MMCICLEAR 0x038
|
||||
#define MCI_CMDCRCFAILCLR (1 << 0)
|
||||
@@ -364,8 +365,9 @@ struct variant_data {
|
||||
void (*init)(struct mmci_host *host);
|
||||
};
|
||||
|
||||
-#define MMCI_QUIRK_STM32_DTMODE BIT(0)
|
||||
-#define MMCI_QUIRK_ST_SDIO BIT(2) /* enable ST specific SDIO logic */
|
||||
+#define MMCI_QUIRK_STM32_DTMODE BIT(0)
|
||||
+#define MMCI_QUIRK_ST_SDIO BIT(2) /* enable ST specific SDIO logic */
|
||||
+#define MMCI_QUIRK_STM32_VSWITCH BIT(3)
|
||||
|
||||
/* mmci variant callbacks */
|
||||
struct mmci_host_ops {
|
||||
@@ -382,6 +384,7 @@ struct mmci_host_ops {
|
||||
void (*dma_error)(struct mmci_host *host);
|
||||
void (*set_clkreg)(struct mmci_host *host, unsigned int desired);
|
||||
void (*set_pwrreg)(struct mmci_host *host, unsigned int pwr);
|
||||
+ int (*execute_tuning)(struct mmc_host *mmc, u32 opcode);
|
||||
};
|
||||
|
||||
struct mmci_host {
|
||||
@@ -414,6 +417,7 @@ struct mmci_host {
|
||||
struct mmci_platform_data *plat;
|
||||
struct mmci_host_ops *ops;
|
||||
struct variant_data *variant;
|
||||
+ void *variant_priv;
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *pins_default;
|
||||
struct pinctrl_state *pins_opendrain;
|
||||
diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c
|
||||
index cfbfc6f..e5ccc68 100644
|
||||
--- a/drivers/mmc/host/mmci_stm32_sdmmc.c
|
||||
+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c
|
||||
@@ -3,14 +3,31 @@
|
||||
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||
* Author: Ludovic.barre@st.com for STMicroelectronics.
|
||||
*/
|
||||
+#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
+#include <linux/iopoll.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/card.h>
|
||||
+#include <linux/of_address.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include "mmci.h"
|
||||
|
||||
+#define DLYB_CR 0x0
|
||||
+#define DLYB_CR_DEN BIT(0)
|
||||
+#define DLYB_CR_SEN BIT(1)
|
||||
+
|
||||
+#define DLYB_CFGR 0x4
|
||||
+#define DLYB_CFGR_SEL_MASK GENMASK(3, 0)
|
||||
+#define DLYB_CFGR_UNIT_MASK GENMASK(14, 8)
|
||||
+#define DLYB_CFGR_LNG_MASK GENMASK(27, 16)
|
||||
+#define DLYB_CFGR_LNGF BIT(31)
|
||||
+
|
||||
+#define DLYB_NB_DELAY 11
|
||||
+#define DLYB_CFGR_SEL_MAX (DLYB_NB_DELAY + 1)
|
||||
+#define DLYB_CFGR_UNIT_MAX 127
|
||||
+
|
||||
#define SDMMC_LLI_BUF_LEN PAGE_SIZE
|
||||
#define SDMMC_IDMA_BURST BIT(MMCI_STM32_IDMABNDT_SHIFT)
|
||||
|
||||
@@ -20,11 +37,17 @@ struct sdmmc_lli_desc {
|
||||
u32 idmasize;
|
||||
};
|
||||
|
||||
-struct sdmmc_priv {
|
||||
+struct sdmmc_idma {
|
||||
dma_addr_t sg_dma;
|
||||
void *sg_cpu;
|
||||
};
|
||||
|
||||
+struct sdmmc_dlyb {
|
||||
+ void __iomem *base;
|
||||
+ u32 unit;
|
||||
+ u32 max;
|
||||
+};
|
||||
+
|
||||
int sdmmc_idma_validate_data(struct mmci_host *host,
|
||||
struct mmc_data *data)
|
||||
{
|
||||
@@ -36,8 +59,8 @@ int sdmmc_idma_validate_data(struct mmci_host *host,
|
||||
* excepted the last element which has no constraint on idmasize
|
||||
*/
|
||||
for_each_sg(data->sg, sg, data->sg_len - 1, i) {
|
||||
- if (!IS_ALIGNED(sg_dma_address(data->sg), sizeof(u32)) ||
|
||||
- !IS_ALIGNED(sg_dma_len(data->sg), SDMMC_IDMA_BURST)) {
|
||||
+ if (!IS_ALIGNED(data->sg->offset, sizeof(u32)) ||
|
||||
+ !IS_ALIGNED(data->sg->length, SDMMC_IDMA_BURST)) {
|
||||
dev_err(mmc_dev(host->mmc),
|
||||
"unaligned scatterlist: ofst:%x length:%d\n",
|
||||
data->sg->offset, data->sg->length);
|
||||
@@ -45,7 +68,7 @@ int sdmmc_idma_validate_data(struct mmci_host *host,
|
||||
}
|
||||
}
|
||||
|
||||
- if (!IS_ALIGNED(sg_dma_address(data->sg), sizeof(u32))) {
|
||||
+ if (!IS_ALIGNED(data->sg->offset, sizeof(u32))) {
|
||||
dev_err(mmc_dev(host->mmc),
|
||||
"unaligned last scatterlist: ofst:%x length:%d\n",
|
||||
data->sg->offset, data->sg->length);
|
||||
@@ -92,7 +115,7 @@ static void sdmmc_idma_unprep_data(struct mmci_host *host,
|
||||
|
||||
static int sdmmc_idma_setup(struct mmci_host *host)
|
||||
{
|
||||
- struct sdmmc_priv *idma;
|
||||
+ struct sdmmc_idma *idma;
|
||||
|
||||
idma = devm_kzalloc(mmc_dev(host->mmc), sizeof(*idma), GFP_KERNEL);
|
||||
if (!idma)
|
||||
@@ -123,7 +146,7 @@ static int sdmmc_idma_setup(struct mmci_host *host)
|
||||
static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl)
|
||||
|
||||
{
|
||||
- struct sdmmc_priv *idma = host->dma_priv;
|
||||
+ struct sdmmc_idma *idma = host->dma_priv;
|
||||
struct sdmmc_lli_desc *desc = (struct sdmmc_lli_desc *)idma->sg_cpu;
|
||||
struct mmc_data *data = host->data;
|
||||
struct scatterlist *sg;
|
||||
@@ -226,12 +249,24 @@ static void mmci_sdmmc_set_clkreg(struct mmci_host *host, unsigned int desired)
|
||||
mmci_write_clkreg(host, clk);
|
||||
}
|
||||
|
||||
+static void sdmmc_dlyb_input_ck(struct sdmmc_dlyb *dlyb)
|
||||
+{
|
||||
+ if (!dlyb || !dlyb->base)
|
||||
+ return;
|
||||
+
|
||||
+ /* Output clock = Input clock */
|
||||
+ writel_relaxed(0, dlyb->base + DLYB_CR);
|
||||
+}
|
||||
+
|
||||
static void mmci_sdmmc_set_pwrreg(struct mmci_host *host, unsigned int pwr)
|
||||
{
|
||||
struct mmc_ios ios = host->mmc->ios;
|
||||
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
|
||||
|
||||
pwr = host->pwr_reg_add;
|
||||
|
||||
+ sdmmc_dlyb_input_ck(dlyb);
|
||||
+
|
||||
if (ios.power_mode == MMC_POWER_OFF) {
|
||||
/* Only a reset could power-off sdmmc */
|
||||
reset_control_assert(host->rst);
|
||||
@@ -265,6 +300,105 @@ static void mmci_sdmmc_set_pwrreg(struct mmci_host *host, unsigned int pwr)
|
||||
}
|
||||
}
|
||||
|
||||
+static void sdmmc_dlyb_set_cfgr(struct sdmmc_dlyb *dlyb,
|
||||
+ int unit, int phase, bool sampler)
|
||||
+{
|
||||
+ u32 cr, cfgr;
|
||||
+
|
||||
+ writel_relaxed(DLYB_CR_SEN, dlyb->base + DLYB_CR);
|
||||
+
|
||||
+ cfgr = FIELD_PREP(DLYB_CFGR_UNIT_MASK, unit) |
|
||||
+ FIELD_PREP(DLYB_CFGR_SEL_MASK, phase);
|
||||
+ writel_relaxed(cfgr, dlyb->base + DLYB_CFGR);
|
||||
+
|
||||
+ cr = DLYB_CR_DEN;
|
||||
+ if (sampler)
|
||||
+ cr |= DLYB_CR_SEN;
|
||||
+
|
||||
+ writel_relaxed(cr, dlyb->base + DLYB_CR);
|
||||
+}
|
||||
+
|
||||
+static int sdmmc_dlyb_lng_tuning(struct mmci_host *host)
|
||||
+{
|
||||
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
|
||||
+ u32 cfgr;
|
||||
+ int i, lng, ret;
|
||||
+
|
||||
+ for (i = 0; i <= DLYB_CFGR_UNIT_MAX; i++) {
|
||||
+ sdmmc_dlyb_set_cfgr(dlyb, i, DLYB_CFGR_SEL_MAX, true);
|
||||
+
|
||||
+ ret = readl_relaxed_poll_timeout(dlyb->base + DLYB_CFGR, cfgr,
|
||||
+ (cfgr & DLYB_CFGR_LNGF),
|
||||
+ 1, 1000);
|
||||
+ if (ret) {
|
||||
+ dev_warn(mmc_dev(host->mmc),
|
||||
+ "delay line cfg timeout unit:%d cfgr:%d\n",
|
||||
+ i, cfgr);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ lng = FIELD_GET(DLYB_CFGR_LNG_MASK, cfgr);
|
||||
+ if (lng < BIT(DLYB_NB_DELAY) && lng > 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (i > DLYB_CFGR_UNIT_MAX)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ dlyb->unit = i;
|
||||
+ dlyb->max = __fls(lng);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode)
|
||||
+{
|
||||
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
|
||||
+ int cur_len = 0, max_len = 0, end_of_len = 0;
|
||||
+ int phase;
|
||||
+
|
||||
+ for (phase = 0; phase <= dlyb->max; phase++) {
|
||||
+ sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false);
|
||||
+
|
||||
+ if (mmc_send_tuning(host->mmc, opcode, NULL)) {
|
||||
+ cur_len = 0;
|
||||
+ } else {
|
||||
+ cur_len++;
|
||||
+ if (cur_len > max_len) {
|
||||
+ max_len = cur_len;
|
||||
+ end_of_len = phase;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!max_len) {
|
||||
+ dev_err(mmc_dev(host->mmc), "no tuning point found\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ phase = end_of_len - max_len / 2;
|
||||
+ sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false);
|
||||
+
|
||||
+ dev_dbg(mmc_dev(host->mmc), "unit:%d max_dly:%d phase:%d\n",
|
||||
+ dlyb->unit, dlyb->max, phase);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||
+{
|
||||
+ struct mmci_host *host = mmc_priv(mmc);
|
||||
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
|
||||
+
|
||||
+ if (!dlyb || !dlyb->base)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (sdmmc_dlyb_lng_tuning(host))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return sdmmc_dlyb_phase_tuning(host, opcode);
|
||||
+}
|
||||
+
|
||||
static struct mmci_host_ops sdmmc_variant_ops = {
|
||||
.validate_data = sdmmc_idma_validate_data,
|
||||
.prep_data = sdmmc_idma_prep_data,
|
||||
@@ -274,9 +408,25 @@ static struct mmci_host_ops sdmmc_variant_ops = {
|
||||
.dma_finalize = sdmmc_idma_finalize,
|
||||
.set_clkreg = mmci_sdmmc_set_clkreg,
|
||||
.set_pwrreg = mmci_sdmmc_set_pwrreg,
|
||||
+ .execute_tuning = sdmmc_execute_tuning,
|
||||
};
|
||||
|
||||
void sdmmc_variant_init(struct mmci_host *host)
|
||||
{
|
||||
+ struct device_node *np = host->mmc->parent->of_node;
|
||||
+ void __iomem *base_dlyb;
|
||||
+ struct sdmmc_dlyb *dlyb;
|
||||
+
|
||||
host->ops = &sdmmc_variant_ops;
|
||||
+
|
||||
+ base_dlyb = devm_of_iomap(mmc_dev(host->mmc), np, 1, NULL);
|
||||
+ if (IS_ERR(base_dlyb))
|
||||
+ return;
|
||||
+
|
||||
+ dlyb = devm_kzalloc(mmc_dev(host->mmc), sizeof(*dlyb), GFP_KERNEL);
|
||||
+ if (!dlyb)
|
||||
+ return;
|
||||
+
|
||||
+ dlyb->base = base_dlyb;
|
||||
+ host->variant_priv = dlyb;
|
||||
}
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,604 +0,0 @@
|
|||
From d00006c83840de8fa5a6049ce31117d4e9c76184 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:40:47 +0100
|
||||
Subject: [PATCH 40/52] ARM: stm32mp1-r0-rc3: PINCTRL PWM RESET RTC
|
||||
|
||||
---
|
||||
drivers/pinctrl/stm32/pinctrl-stm32.c | 219 +++++++++++++++++++++++-----------
|
||||
drivers/regulator/stpmic1_regulator.c | 17 +--
|
||||
2 files changed, 152 insertions(+), 84 deletions(-)
|
||||
|
||||
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||
index 914bee4..7a27431 100644
|
||||
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
|
||||
@@ -7,6 +7,7 @@
|
||||
* Heavily based on Mediatek's pinctrl driver
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
+#include <linux/delay.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/hwspinlock.h>
|
||||
#include <linux/io.h>
|
||||
@@ -65,7 +66,8 @@
|
||||
#define gpio_range_to_bank(chip) \
|
||||
container_of(chip, struct stm32_gpio_bank, range)
|
||||
|
||||
-#define HWSPINLOCK_TIMEOUT 5 /* msec */
|
||||
+#define HWSPNLCK_TIMEOUT 1000 /* usec */
|
||||
+#define HWSPNLCK_RETRY_DELAY 100 /* usec */
|
||||
|
||||
static const char * const stm32_gpio_functions[] = {
|
||||
"gpio", "af0", "af1",
|
||||
@@ -110,6 +112,8 @@ struct stm32_pinctrl {
|
||||
struct irq_domain *domain;
|
||||
struct regmap *regmap;
|
||||
struct regmap_field *irqmux[STM32_GPIO_PINS_PER_BANK];
|
||||
+ u16 irqmux_map;
|
||||
+ spinlock_t irqmux_lock; /* interrupt mux lock */
|
||||
struct stm32_desc_pin *pins;
|
||||
u32 npins;
|
||||
u32 pkg;
|
||||
@@ -150,6 +154,26 @@ static inline u32 stm32_gpio_get_alt(u32 function)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int stm32_pctrl_hwspin_lock_timeout(struct hwspinlock *hwlock)
|
||||
+{
|
||||
+ int ret, timeout = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Use the x_raw API since we are under spin_lock protection and do not
|
||||
+ * use the x_timeout API because we are under irq_disable mode
|
||||
+ */
|
||||
+ do {
|
||||
+ ret = hwspin_trylock_raw(hwlock);
|
||||
+ if (!ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ udelay(HWSPNLCK_RETRY_DELAY);
|
||||
+ timeout += HWSPNLCK_RETRY_DELAY;
|
||||
+ } while (timeout < HWSPNLCK_TIMEOUT);
|
||||
+
|
||||
+ return ret == -EBUSY ? -ETIMEDOUT : ret;
|
||||
+}
|
||||
+
|
||||
/* GPIO functions */
|
||||
|
||||
static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank,
|
||||
@@ -326,9 +350,40 @@ static int stm32_gpio_domain_activate(struct irq_domain *d,
|
||||
{
|
||||
struct stm32_gpio_bank *bank = d->host_data;
|
||||
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
+ unsigned long flags;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * gpio irq mux is shared between several banks, a lock has to be done
|
||||
+ * to avoid overriding.
|
||||
+ */
|
||||
+ spin_lock_irqsave(&pctl->irqmux_lock, flags);
|
||||
+
|
||||
+ if (pctl->irqmux_map & BIT(irq_data->hwirq)) {
|
||||
+ dev_err(pctl->dev, "irq line %ld already requested.\n",
|
||||
+ irq_data->hwirq);
|
||||
+ ret = -EBUSY;
|
||||
+ goto unlock;
|
||||
+ } else {
|
||||
+ pctl->irqmux_map |= BIT(irq_data->hwirq);
|
||||
+ }
|
||||
|
||||
regmap_field_write(pctl->irqmux[irq_data->hwirq], bank->bank_ioport_nr);
|
||||
- return 0;
|
||||
+unlock:
|
||||
+ spin_unlock_irqrestore(&pctl->irqmux_lock, flags);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void stm32_gpio_domain_deactivate(struct irq_domain *d,
|
||||
+ struct irq_data *irq_data)
|
||||
+{
|
||||
+ struct stm32_gpio_bank *bank = d->host_data;
|
||||
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&pctl->irqmux_lock, flags);
|
||||
+ pctl->irqmux_map &= ~BIT(irq_data->hwirq);
|
||||
+ spin_unlock_irqrestore(&pctl->irqmux_lock, flags);
|
||||
}
|
||||
|
||||
static int stm32_gpio_domain_alloc(struct irq_domain *d,
|
||||
@@ -357,6 +412,7 @@ static const struct irq_domain_ops stm32_gpio_domain_ops = {
|
||||
.alloc = stm32_gpio_domain_alloc,
|
||||
.free = irq_domain_free_irqs_common,
|
||||
.activate = stm32_gpio_domain_activate,
|
||||
+ .deactivate = stm32_gpio_domain_deactivate,
|
||||
};
|
||||
|
||||
/* Pinctrl functions */
|
||||
@@ -436,7 +492,7 @@ static int stm32_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
unsigned int num_configs;
|
||||
bool has_config = 0;
|
||||
unsigned reserve = 0;
|
||||
- int num_pins, num_funcs, maps_per_pin, i, err;
|
||||
+ int num_pins, num_funcs, maps_per_pin, i, err = 0;
|
||||
|
||||
pctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
@@ -463,41 +519,45 @@ static int stm32_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
if (has_config && num_pins >= 1)
|
||||
maps_per_pin++;
|
||||
|
||||
- if (!num_pins || !maps_per_pin)
|
||||
- return -EINVAL;
|
||||
+ if (!num_pins || !maps_per_pin) {
|
||||
+ err = -EINVAL;
|
||||
+ goto exit;
|
||||
+ }
|
||||
|
||||
reserve = num_pins * maps_per_pin;
|
||||
|
||||
err = pinctrl_utils_reserve_map(pctldev, map,
|
||||
reserved_maps, num_maps, reserve);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto exit;
|
||||
|
||||
for (i = 0; i < num_pins; i++) {
|
||||
err = of_property_read_u32_index(node, "pinmux",
|
||||
i, &pinfunc);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto exit;
|
||||
|
||||
pin = STM32_GET_PIN_NO(pinfunc);
|
||||
func = STM32_GET_PIN_FUNC(pinfunc);
|
||||
|
||||
if (!stm32_pctrl_is_function_valid(pctl, pin, func)) {
|
||||
dev_err(pctl->dev, "invalid function.\n");
|
||||
- return -EINVAL;
|
||||
+ err = -EINVAL;
|
||||
+ goto exit;
|
||||
}
|
||||
|
||||
grp = stm32_pctrl_find_group_by_pin(pctl, pin);
|
||||
if (!grp) {
|
||||
dev_err(pctl->dev, "unable to match pin %d to group\n",
|
||||
pin);
|
||||
- return -EINVAL;
|
||||
+ err = -EINVAL;
|
||||
+ goto exit;
|
||||
}
|
||||
|
||||
err = stm32_pctrl_dt_node_to_map_func(pctl, pin, func, grp, map,
|
||||
reserved_maps, num_maps);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto exit;
|
||||
|
||||
if (has_config) {
|
||||
err = pinctrl_utils_add_map_configs(pctldev, map,
|
||||
@@ -505,11 +565,13 @@ static int stm32_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
configs, num_configs,
|
||||
PIN_MAP_TYPE_CONFIGS_GROUP);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+exit:
|
||||
+ kfree(configs);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static int stm32_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
@@ -599,8 +661,8 @@ static int stm32_pmx_get_func_groups(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||
- int pin, u32 mode, u32 alt)
|
||||
+static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||
+ int pin, u32 mode, u32 alt)
|
||||
{
|
||||
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
u32 val;
|
||||
@@ -612,12 +674,12 @@ static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
- if (pctl->hwlock)
|
||||
- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||
-
|
||||
- if (err) {
|
||||
- dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
- goto unlock;
|
||||
+ if (pctl->hwlock) {
|
||||
+ err = stm32_pctrl_hwspin_lock_timeout(pctl->hwlock);
|
||||
+ if (err) {
|
||||
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
+ goto unlock;
|
||||
+ }
|
||||
}
|
||||
|
||||
val = readl_relaxed(bank->base + alt_offset);
|
||||
@@ -633,11 +695,12 @@ static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
||||
stm32_gpio_backup_mode(bank, pin, mode, alt);
|
||||
|
||||
if (pctl->hwlock)
|
||||
- hwspin_unlock(pctl->hwlock);
|
||||
+ hwspin_unlock_raw(pctl->hwlock);
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
clk_disable(bank->clk);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode,
|
||||
@@ -694,9 +757,7 @@ static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||
mode = stm32_gpio_get_mode(function);
|
||||
alt = stm32_gpio_get_alt(function);
|
||||
|
||||
- stm32_pmx_set_mode(bank, pin, mode, alt);
|
||||
-
|
||||
- return 0;
|
||||
+ return stm32_pmx_set_mode(bank, pin, mode, alt);
|
||||
}
|
||||
|
||||
static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
@@ -706,9 +767,7 @@ static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
struct stm32_gpio_bank *bank = gpiochip_get_data(range->gc);
|
||||
int pin = stm32_gpio_pin(gpio);
|
||||
|
||||
- stm32_pmx_set_mode(bank, pin, !input, 0);
|
||||
-
|
||||
- return 0;
|
||||
+ return stm32_pmx_set_mode(bank, pin, !input, 0);
|
||||
}
|
||||
|
||||
static const struct pinmux_ops stm32_pmx_ops = {
|
||||
@@ -722,8 +781,8 @@ static const struct pinmux_ops stm32_pmx_ops = {
|
||||
|
||||
/* Pinconf functions */
|
||||
|
||||
-static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||
- unsigned offset, u32 drive)
|
||||
+static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||
+ unsigned offset, u32 drive)
|
||||
{
|
||||
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
unsigned long flags;
|
||||
@@ -733,12 +792,12 @@ static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
- if (pctl->hwlock)
|
||||
- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||
-
|
||||
- if (err) {
|
||||
- dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
- goto unlock;
|
||||
+ if (pctl->hwlock) {
|
||||
+ err = stm32_pctrl_hwspin_lock_timeout(pctl->hwlock);
|
||||
+ if (err) {
|
||||
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
+ goto unlock;
|
||||
+ }
|
||||
}
|
||||
|
||||
val = readl_relaxed(bank->base + STM32_GPIO_TYPER);
|
||||
@@ -749,11 +808,12 @@ static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
||||
stm32_gpio_backup_driving(bank, offset, drive);
|
||||
|
||||
if (pctl->hwlock)
|
||||
- hwspin_unlock(pctl->hwlock);
|
||||
+ hwspin_unlock_raw(pctl->hwlock);
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
clk_disable(bank->clk);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank,
|
||||
@@ -774,8 +834,8 @@ static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank,
|
||||
return (val >> offset);
|
||||
}
|
||||
|
||||
-static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||
- unsigned offset, u32 speed)
|
||||
+static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||
+ unsigned offset, u32 speed)
|
||||
{
|
||||
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
unsigned long flags;
|
||||
@@ -785,12 +845,12 @@ static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
- if (pctl->hwlock)
|
||||
- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||
-
|
||||
- if (err) {
|
||||
- dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
- goto unlock;
|
||||
+ if (pctl->hwlock) {
|
||||
+ err = stm32_pctrl_hwspin_lock_timeout(pctl->hwlock);
|
||||
+ if (err) {
|
||||
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
+ goto unlock;
|
||||
+ }
|
||||
}
|
||||
|
||||
val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR);
|
||||
@@ -801,11 +861,12 @@ static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
||||
stm32_gpio_backup_speed(bank, offset, speed);
|
||||
|
||||
if (pctl->hwlock)
|
||||
- hwspin_unlock(pctl->hwlock);
|
||||
+ hwspin_unlock_raw(pctl->hwlock);
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
clk_disable(bank->clk);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank,
|
||||
@@ -826,8 +887,8 @@ static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank,
|
||||
return (val >> (offset * 2));
|
||||
}
|
||||
|
||||
-static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||
- unsigned offset, u32 bias)
|
||||
+static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||
+ unsigned offset, u32 bias)
|
||||
{
|
||||
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
|
||||
unsigned long flags;
|
||||
@@ -837,12 +898,12 @@ static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
- if (pctl->hwlock)
|
||||
- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
|
||||
-
|
||||
- if (err) {
|
||||
- dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
- goto unlock;
|
||||
+ if (pctl->hwlock) {
|
||||
+ err = stm32_pctrl_hwspin_lock_timeout(pctl->hwlock);
|
||||
+ if (err) {
|
||||
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
|
||||
+ goto unlock;
|
||||
+ }
|
||||
}
|
||||
|
||||
val = readl_relaxed(bank->base + STM32_GPIO_PUPDR);
|
||||
@@ -853,11 +914,12 @@ static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
||||
stm32_gpio_backup_bias(bank, offset, bias);
|
||||
|
||||
if (pctl->hwlock)
|
||||
- hwspin_unlock(pctl->hwlock);
|
||||
+ hwspin_unlock_raw(pctl->hwlock);
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
clk_disable(bank->clk);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank,
|
||||
@@ -920,22 +982,22 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
- stm32_pconf_set_driving(bank, offset, 0);
|
||||
+ ret = stm32_pconf_set_driving(bank, offset, 0);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
- stm32_pconf_set_driving(bank, offset, 1);
|
||||
+ ret = stm32_pconf_set_driving(bank, offset, 1);
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
- stm32_pconf_set_speed(bank, offset, arg);
|
||||
+ ret = stm32_pconf_set_speed(bank, offset, arg);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
- stm32_pconf_set_bias(bank, offset, 0);
|
||||
+ ret = stm32_pconf_set_bias(bank, offset, 0);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
- stm32_pconf_set_bias(bank, offset, 1);
|
||||
+ ret = stm32_pconf_set_bias(bank, offset, 1);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
- stm32_pconf_set_bias(bank, offset, 2);
|
||||
+ ret = stm32_pconf_set_bias(bank, offset, 2);
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
__stm32_gpio_set(bank, offset, arg);
|
||||
@@ -1295,6 +1357,8 @@ int stm32_pctl_probe(struct platform_device *pdev)
|
||||
pctl->hwlock = hwspin_lock_request_specific(hwlock_id);
|
||||
}
|
||||
|
||||
+ spin_lock_init(&pctl->irqmux_lock);
|
||||
+
|
||||
pctl->dev = dev;
|
||||
pctl->match_data = match->data;
|
||||
|
||||
@@ -1414,22 +1478,23 @@ void stm32_gpio_backup_bias(struct stm32_gpio_bank *bank,
|
||||
bank->pin_backup[offset] |= bias << STM32_GPIO_BKP_PUPD_SHIFT;
|
||||
}
|
||||
|
||||
-void stm32_pinctrl_restore_gpio_regs(struct stm32_pinctrl *pctl, u32 pin)
|
||||
+int stm32_pinctrl_restore_gpio_regs(struct stm32_pinctrl *pctl, u32 pin)
|
||||
{
|
||||
const struct pin_desc *desc = pin_desc_get(pctl->pctl_dev, pin);
|
||||
struct pinctrl_gpio_range *range;
|
||||
struct stm32_gpio_bank *bank;
|
||||
u32 val, alt, mode, offset = stm32_gpio_pin(pin);
|
||||
bool pin_is_irq;
|
||||
+ int ret;
|
||||
|
||||
range = pinctrl_find_gpio_range_from_pin(pctl->pctl_dev, pin);
|
||||
if (!range)
|
||||
- return;
|
||||
+ return 0;
|
||||
|
||||
pin_is_irq = gpiochip_line_is_irq(range->gc, offset);
|
||||
|
||||
if (!desc || (!pin_is_irq && !desc->gpio_owner))
|
||||
- return;
|
||||
+ return 0;
|
||||
|
||||
bank = gpiochip_get_data(range->gc);
|
||||
|
||||
@@ -1438,7 +1503,10 @@ void stm32_pinctrl_restore_gpio_regs(struct stm32_pinctrl *pctl, u32 pin)
|
||||
mode = bank->pin_backup[offset] & STM32_GPIO_BKP_MODE_MASK;
|
||||
mode >>= STM32_GPIO_BKP_MODE_SHIFT;
|
||||
|
||||
- stm32_pmx_set_mode(bank, offset, mode, alt);
|
||||
+ ret = stm32_pmx_set_mode(bank, offset, mode, alt);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
if (mode == 1) {
|
||||
val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_VAL);
|
||||
val = val >> STM32_GPIO_BKP_VAL;
|
||||
@@ -1447,28 +1515,39 @@ void stm32_pinctrl_restore_gpio_regs(struct stm32_pinctrl *pctl, u32 pin)
|
||||
|
||||
val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_TYPE);
|
||||
val >>= STM32_GPIO_BKP_TYPE;
|
||||
- stm32_pconf_set_driving(bank, offset, val);
|
||||
+ ret = stm32_pconf_set_driving(bank, offset, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
val = bank->pin_backup[offset] & STM32_GPIO_BKP_SPEED_MASK;
|
||||
val >>= STM32_GPIO_BKP_SPEED_SHIFT;
|
||||
- stm32_pconf_set_speed(bank, offset, val);
|
||||
+ ret = stm32_pconf_set_speed(bank, offset, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
val = bank->pin_backup[offset] & STM32_GPIO_BKP_PUPD_MASK;
|
||||
val >>= STM32_GPIO_BKP_PUPD_SHIFT;
|
||||
- stm32_pconf_set_bias(bank, offset, val);
|
||||
+ ret = stm32_pconf_set_bias(bank, offset, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
if (pin_is_irq)
|
||||
regmap_field_write(pctl->irqmux[offset], bank->bank_ioport_nr);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
int stm32_pinctrl_resume(struct device *dev)
|
||||
{
|
||||
struct stm32_pinctrl *pctl = dev_get_drvdata(dev);
|
||||
struct stm32_pinctrl_group *g = pctl->groups;
|
||||
- int i;
|
||||
+ int i, ret;
|
||||
|
||||
- for (i = g->pin; i < g->pin + pctl->ngroups; i++)
|
||||
- stm32_pinctrl_restore_gpio_regs(pctl, i);
|
||||
+ for (i = g->pin; i < g->pin + pctl->ngroups; i++) {
|
||||
+ ret = stm32_pinctrl_restore_gpio_regs(pctl, i);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c
|
||||
index 96f1808..31c960c 100644
|
||||
--- a/drivers/regulator/stpmic1_regulator.c
|
||||
+++ b/drivers/regulator/stpmic1_regulator.c
|
||||
@@ -76,8 +76,9 @@ enum {
|
||||
#define STPMIC1_BUCK_MODE_LP BUCK_HPLP_ENABLE_MASK
|
||||
|
||||
struct regulator_linear_range buck1_ranges[] = {
|
||||
- REGULATOR_LINEAR_RANGE(600000, 0, 30, 25000),
|
||||
- REGULATOR_LINEAR_RANGE(1350000, 31, 63, 0),
|
||||
+ REGULATOR_LINEAR_RANGE(725000, 0, 4, 0),
|
||||
+ REGULATOR_LINEAR_RANGE(725000, 5, 36, 25000),
|
||||
+ REGULATOR_LINEAR_RANGE(1500000, 37, 63, 0),
|
||||
};
|
||||
|
||||
struct regulator_linear_range buck2_ranges[] = {
|
||||
@@ -157,7 +158,6 @@ static struct regulator_ops stpmic1_ldo_ops = {
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
- .set_pull_down = regulator_set_pull_down_regmap,
|
||||
.set_over_current_protection = stpmic1_set_icc,
|
||||
};
|
||||
|
||||
@@ -169,7 +169,6 @@ static struct regulator_ops stpmic1_ldo3_ops = {
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
- .set_pull_down = regulator_set_pull_down_regmap,
|
||||
.get_bypass = regulator_get_bypass_regmap,
|
||||
.set_bypass = regulator_set_bypass_regmap,
|
||||
.set_over_current_protection = stpmic1_set_icc,
|
||||
@@ -179,7 +178,6 @@ static struct regulator_ops stpmic1_ldo4_fixed_regul_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
- .set_pull_down = regulator_set_pull_down_regmap,
|
||||
.set_over_current_protection = stpmic1_set_icc,
|
||||
};
|
||||
|
||||
@@ -201,7 +199,6 @@ static struct regulator_ops stpmic1_vref_ddr_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
- .set_pull_down = regulator_set_pull_down_regmap,
|
||||
};
|
||||
|
||||
static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||
@@ -227,8 +224,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||
.enable_val = 1, \
|
||||
.disable_val = 0, \
|
||||
.enable_time = PMIC_ENABLE_TIME_US, \
|
||||
- .pull_down_reg = ids##_PULL_DOWN_REG, \
|
||||
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
|
||||
.supply_name = #base, \
|
||||
}
|
||||
|
||||
@@ -252,8 +247,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||
.bypass_mask = LDO_BYPASS_MASK, \
|
||||
.bypass_val_on = LDO_BYPASS_MASK, \
|
||||
.bypass_val_off = 0, \
|
||||
- .pull_down_reg = ids##_PULL_DOWN_REG, \
|
||||
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
|
||||
.supply_name = #base, \
|
||||
}
|
||||
|
||||
@@ -271,8 +264,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||
.enable_val = 1, \
|
||||
.disable_val = 0, \
|
||||
.enable_time = PMIC_ENABLE_TIME_US, \
|
||||
- .pull_down_reg = ids##_PULL_DOWN_REG, \
|
||||
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
|
||||
.supply_name = #base, \
|
||||
}
|
||||
|
||||
@@ -312,8 +303,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
|
||||
.enable_val = 1, \
|
||||
.disable_val = 0, \
|
||||
.enable_time = PMIC_ENABLE_TIME_US, \
|
||||
- .pull_down_reg = ids##_PULL_DOWN_REG, \
|
||||
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
|
||||
.supply_name = #base, \
|
||||
}
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,112 +0,0 @@
|
|||
From 6c92e60d3e402e1fcbd1bfa11185c995ce41d190 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:47:43 +0100
|
||||
Subject: [PATCH 42/52] ARM: stm32mp1-r0-rc3: SOUND
|
||||
|
||||
---
|
||||
sound/soc/stm/stm32_sai_sub.c | 58 ++++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 41 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
|
||||
index 1f23ca4..3f0540a 100644
|
||||
--- a/sound/soc/stm/stm32_sai_sub.c
|
||||
+++ b/sound/soc/stm/stm32_sai_sub.c
|
||||
@@ -313,6 +313,23 @@ static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int stm32_sai_set_parent_clock(struct stm32_sai_sub_data *sai,
|
||||
+ unsigned int rate)
|
||||
+{
|
||||
+ struct platform_device *pdev = sai->pdev;
|
||||
+ struct clk *parent_clk = sai->pdata->clk_x8k;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!(rate % 11025))
|
||||
+ parent_clk = sai->pdata->clk_x11k;
|
||||
+
|
||||
+ ret = clk_set_parent(sai->sai_ck, parent_clk);
|
||||
+ if (ret)
|
||||
+ dev_err(&pdev->dev, "Set parent clock returned: %d\n", ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
@@ -492,25 +509,26 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
int ret;
|
||||
|
||||
- if (dir == SND_SOC_CLOCK_OUT) {
|
||||
+ if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) {
|
||||
ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
|
||||
SAI_XCR1_NODIV,
|
||||
(unsigned int)~SAI_XCR1_NODIV);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
|
||||
- sai->mclk_rate = freq;
|
||||
+ /* If master clock is used, set parent clock now */
|
||||
+ ret = stm32_sai_set_parent_clock(sai, freq);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
- if (sai->sai_mclk) {
|
||||
- ret = clk_set_rate_exclusive(sai->sai_mclk,
|
||||
- sai->mclk_rate);
|
||||
- if (ret) {
|
||||
- dev_err(cpu_dai->dev,
|
||||
- "Could not set mclk rate\n");
|
||||
- return ret;
|
||||
- }
|
||||
+ ret = clk_set_rate_exclusive(sai->sai_mclk, freq);
|
||||
+ if (ret) {
|
||||
+ dev_err(cpu_dai->dev, "Could not set mclk rate\n");
|
||||
+ return ret;
|
||||
}
|
||||
+
|
||||
+ dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
|
||||
+ sai->mclk_rate = freq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -906,11 +924,13 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
|
||||
int cr1, mask, div = 0;
|
||||
int sai_clk_rate, mclk_ratio, den;
|
||||
unsigned int rate = params_rate(params);
|
||||
+ int ret;
|
||||
|
||||
- if (!(rate % 11025))
|
||||
- clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k);
|
||||
- else
|
||||
- clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k);
|
||||
+ if (!sai->sai_mclk) {
|
||||
+ ret = stm32_sai_set_parent_clock(sai, rate);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
sai_clk_rate = clk_get_rate(sai->sai_ck);
|
||||
|
||||
if (STM_SAI_IS_F4(sai->pdata)) {
|
||||
@@ -1064,9 +1084,13 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
|
||||
regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV,
|
||||
SAI_XCR1_NODIV);
|
||||
|
||||
- clk_disable_unprepare(sai->sai_ck);
|
||||
+ /* Release mclk rate only if rate was actually set */
|
||||
+ if (sai->mclk_rate) {
|
||||
+ clk_rate_exclusive_put(sai->sai_mclk);
|
||||
+ sai->mclk_rate = 0;
|
||||
+ }
|
||||
|
||||
- clk_rate_exclusive_put(sai->sai_mclk);
|
||||
+ clk_disable_unprepare(sai->sai_ck);
|
||||
|
||||
sai->substream = NULL;
|
||||
}
|
||||
--
|
||||
2.7.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,101 +0,0 @@
|
|||
From c38f0f42372e03b8b284804190fdf53ce02722db Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Mon, 10 Dec 2018 15:53:55 +0100
|
||||
Subject: [PATCH 45/52] ARM: stm32mp1-r0-rc3: DEFCONFIG
|
||||
|
||||
---
|
||||
arch/arm/configs/fragment-02-multiv7_addons.config | 39 +++++++++++++++++-----
|
||||
1 file changed, 31 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
index 4470d85..6ae0453 100644
|
||||
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
@@ -98,7 +98,10 @@ CONFIG_CAN_M_CAN=y
|
||||
#
|
||||
# Bluetooth device drivers
|
||||
#
|
||||
-
|
||||
+CONFIG_BT_RTL=m
|
||||
+CONFIG_BT_HCIBTUSB=m
|
||||
+CONFIG_BT_HCIBTUSB=m
|
||||
+CONFIG_BT_HCIBTUSB_RTL=y
|
||||
#
|
||||
# Device Drivers
|
||||
#
|
||||
@@ -138,7 +141,12 @@ CONFIG_CHR_DEV_SG=y
|
||||
# MII PHY device drivers
|
||||
#
|
||||
# CONFIG_REALTEK_PHY is not set
|
||||
-
|
||||
+CONFIG_RTL_CARDS=m
|
||||
+CONFIG_RTL8192CU=m
|
||||
+CONFIG_RTLWIFI=m
|
||||
+CONFIG_RTLWIFI_USB=m
|
||||
+CONFIG_RTLWIFI_DEBUG=y
|
||||
+CONFIG_RTL8192C_COMMON=m
|
||||
#
|
||||
# Input Device Drivers
|
||||
#
|
||||
@@ -271,14 +279,14 @@ CONFIG_VIDEO_OV5640=y
|
||||
#
|
||||
# Display Panels
|
||||
#
|
||||
-CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
|
||||
-CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
|
||||
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A=y
|
||||
+CONFIG_DRM_PANEL_RAYDIUM_RM68200=y
|
||||
|
||||
#
|
||||
# Display Interface Bridges
|
||||
#
|
||||
-CONFIG_VIDEO_ADV7511=m
|
||||
-CONFIG_DRM_SII902X=m
|
||||
+CONFIG_VIDEO_ADV7511=y
|
||||
+CONFIG_DRM_SII902X=y
|
||||
|
||||
#
|
||||
# Frame buffer hardware drivers
|
||||
@@ -287,8 +295,8 @@ CONFIG_DRM_SII902X=m
|
||||
#
|
||||
# Console display driver support
|
||||
#
|
||||
-CONFIG_DRM_STM=m
|
||||
-CONFIG_DRM_STM_DSI=m
|
||||
+CONFIG_DRM_STM=y
|
||||
+CONFIG_DRM_STM_DSI=y
|
||||
|
||||
#
|
||||
# Backlight support
|
||||
@@ -359,6 +367,8 @@ CONFIG_USB_CONFIGFS=y
|
||||
# File systems
|
||||
#
|
||||
CONFIG_OVERLAY_FS=y
|
||||
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||
+CONFIG_JFFS2_FS=y
|
||||
|
||||
#
|
||||
# Pseudo filesystems
|
||||
@@ -452,6 +462,19 @@ CONFIG_REGULATOR_STM32_VREFBUF=y
|
||||
CONFIG_NVMEM_STM32_ROMEM=y
|
||||
|
||||
#
|
||||
+# STM32 CORESIGHT
|
||||
+#
|
||||
+CONFIG_STM_SOURCE_CONSOLE=y
|
||||
+CONFIG_STM_SOURCE_FTRACE=y
|
||||
+CONFIG_FUNCTION_TRACER=y
|
||||
+CONFIG_CORESIGHT=y
|
||||
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
|
||||
+CONFIG_CORESIGHT_SINK_TPIU=y
|
||||
+CONFIG_CORESIGHT_SINK_ETBV10=y
|
||||
+CONFIG_CORESIGHT_SOURCE_ETM3X=y
|
||||
+CONFIG_CORESIGHT_STM=y
|
||||
+
|
||||
+#
|
||||
# STM32 IPCC
|
||||
#
|
||||
CONFIG_STM32_IPCC=y
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
From 1c6166a178939316cfdd437f8c999616ddf9a7bd Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Fri, 21 Dec 2018 16:57:57 +0100
|
||||
Subject: [PATCH 46/52] ARM: stm32mp1-r0-rc4: MMC MTD
|
||||
|
||||
---
|
||||
drivers/mmc/host/mmci.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
|
||||
index 6c2b1a0..0b7b607 100644
|
||||
--- a/drivers/mmc/host/mmci.c
|
||||
+++ b/drivers/mmc/host/mmci.c
|
||||
@@ -2072,6 +2072,8 @@ static int mmci_probe(struct amba_device *dev,
|
||||
else if (plat->ocr_mask)
|
||||
dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
|
||||
|
||||
+ host->pwr_reg = readl_relaxed(host->base + MMCIPOWER);
|
||||
+
|
||||
/* We support these capabilities. */
|
||||
mmc->caps |= MMC_CAP_CMD23;
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
From 41d9204c142d8245f898ca877b4e4044d5db2426 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Fri, 21 Dec 2018 16:58:12 +0100
|
||||
Subject: [PATCH 47/52] ARM: stm32mp1-r0-rc4: PINCTRL PWM RESET RTC
|
||||
|
||||
---
|
||||
drivers/pinctrl/pinctrl-stmfx.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
|
||||
index 15d5757..b68fece 100644
|
||||
--- a/drivers/pinctrl/pinctrl-stmfx.c
|
||||
+++ b/drivers/pinctrl/pinctrl-stmfx.c
|
||||
@@ -542,6 +542,7 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
|
||||
struct stmfx_pinctrl *pctl = (struct stmfx_pinctrl *)dev_id;
|
||||
struct gpio_chip *gc = &pctl->gpio_chip;
|
||||
u8 pending[NR_GPIO_REGS];
|
||||
+ u8 src[NR_GPIO_REGS] = {0, 0, 0};
|
||||
unsigned long n, status;
|
||||
int ret;
|
||||
|
||||
@@ -550,10 +551,8 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
|
||||
if (ret)
|
||||
return IRQ_NONE;
|
||||
|
||||
- ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_ACK,
|
||||
- pending, NR_GPIO_REGS);
|
||||
- if (ret)
|
||||
- return IRQ_NONE;
|
||||
+ regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
|
||||
+ src, NR_GPIO_REGS);
|
||||
|
||||
status = *(unsigned long *)pending;
|
||||
for_each_set_bit(n, &status, gc->ngpio) {
|
||||
@@ -561,6 +560,9 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
|
||||
stmfx_pinctrl_irq_toggle_trigger(pctl, n);
|
||||
}
|
||||
|
||||
+ regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
|
||||
+ pctl->irq_gpi_src, NR_GPIO_REGS);
|
||||
+
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
From 457cfdb049a39670f15df8cae1d78a2479962ef9 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Fri, 21 Dec 2018 16:57:38 +0100
|
||||
Subject: [PATCH 48/52] ARM: stm32mp1-r0-rc4: REMOTEPROC RPMSG
|
||||
|
||||
---
|
||||
drivers/remoteproc/rproc_srm_core.c | 2 +-
|
||||
drivers/remoteproc/stm32_rproc.c | 40 +++++++++++++++++++++++++++----------
|
||||
2 files changed, 30 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/remoteproc/rproc_srm_core.c b/drivers/remoteproc/rproc_srm_core.c
|
||||
index 66be92e..fc61e8b 100644
|
||||
--- a/drivers/remoteproc/rproc_srm_core.c
|
||||
+++ b/drivers/remoteproc/rproc_srm_core.c
|
||||
@@ -189,7 +189,7 @@ static int rproc_srm_core_prepare(struct rproc_subdev *subdev)
|
||||
/* Wait for every child to be bound */
|
||||
if (!wait_for_completion_timeout(&rproc_srm_core->all_bound,
|
||||
msecs_to_jiffies(BIND_TIMEOUT))) {
|
||||
- dev_err(dev, "bind timeout\n");
|
||||
+ dev_err(dev, "failed to bind one or more system resource device(s)\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto master;
|
||||
}
|
||||
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
|
||||
index 9a7e034..70b7e55c 100644
|
||||
--- a/drivers/remoteproc/stm32_rproc.c
|
||||
+++ b/drivers/remoteproc/stm32_rproc.c
|
||||
@@ -196,22 +196,12 @@ static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name)
|
||||
static int stm32_rproc_elf_load_rsc_table(struct rproc *rproc,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
- int status, i;
|
||||
+ int status;
|
||||
struct resource_table *table = NULL;
|
||||
struct stm32_rproc *ddata = rproc->priv;
|
||||
size_t tablesz = 0;
|
||||
- const struct elf32_hdr *ehdr;
|
||||
- const struct elf32_phdr *phdr;
|
||||
|
||||
if (!rproc->early_boot) {
|
||||
- /* set coredump segments */
|
||||
- ehdr = (const struct elf32_hdr *)fw->data;
|
||||
- phdr = (const struct elf32_phdr *)(fw->data + ehdr->e_phoff);
|
||||
- for (i = 0; i < ehdr->e_phnum; i++, phdr++)
|
||||
- rproc_coredump_add_segment(rproc, phdr->p_paddr,
|
||||
- phdr->p_memsz);
|
||||
-
|
||||
- /* load resource table */
|
||||
status = rproc_elf_load_rsc_table(rproc, fw);
|
||||
if (status)
|
||||
goto no_rsc_table;
|
||||
@@ -276,6 +266,10 @@ static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
|
||||
stm32_rproc_mem_alloc,
|
||||
stm32_rproc_mem_release,
|
||||
it.node->name);
|
||||
+
|
||||
+ if (mem)
|
||||
+ rproc_coredump_add_segment(rproc, da,
|
||||
+ rmem->size);
|
||||
} else {
|
||||
/* Register reserved memory for vdev buffer alloc */
|
||||
mem = rproc_of_resm_mem_entry_init(dev, index,
|
||||
@@ -436,10 +430,34 @@ static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold)
|
||||
return err;
|
||||
}
|
||||
|
||||
+static void stm32_rproc_add_coredump_trace(struct rproc *rproc)
|
||||
+{
|
||||
+ struct rproc_debug_trace *trace;
|
||||
+ struct rproc_dump_segment *segment;
|
||||
+ bool already_added;
|
||||
+
|
||||
+ list_for_each_entry(trace, &rproc->traces, node) {
|
||||
+ already_added = false;
|
||||
+
|
||||
+ list_for_each_entry(segment, &rproc->dump_segments, node) {
|
||||
+ if (segment->da == trace->trace_mem.da) {
|
||||
+ already_added = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!already_added)
|
||||
+ rproc_coredump_add_segment(rproc, trace->trace_mem.da,
|
||||
+ trace->trace_mem.len);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int stm32_rproc_start(struct rproc *rproc)
|
||||
{
|
||||
int err;
|
||||
|
||||
+ stm32_rproc_add_coredump_trace(rproc);
|
||||
+
|
||||
/*
|
||||
* If M4 previously started by bootloader, just guarantee holdboot
|
||||
* is set to catch any crash.
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
From 06f5ef8ca4c11074b595a4318dba9766092886d5 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Fri, 21 Dec 2018 16:58:47 +0100
|
||||
Subject: [PATCH 49/52] ARM: stm32mp1-r0-rc4: SOUND
|
||||
|
||||
---
|
||||
sound/soc/codecs/wm8994.c | 3 +--
|
||||
sound/soc/stm/stm32_sai_sub.c | 21 ++++++++++++++++++++-
|
||||
2 files changed, 21 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
|
||||
index eb222da..c83ae39 100644
|
||||
--- a/sound/soc/codecs/wm8994.c
|
||||
+++ b/sound/soc/codecs/wm8994.c
|
||||
@@ -868,7 +868,7 @@ static int mclk_event(struct snd_soc_dapm_widget *w,
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
dev_dbg(comp->dev, "Disable master clock %s\n",
|
||||
- mclk_id ? "MCLK1" : "MCLK2");
|
||||
+ mclk_id ? "MCLK2" : "MCLK1");
|
||||
clk_disable_unprepare(mclk);
|
||||
break;
|
||||
}
|
||||
@@ -1193,7 +1193,6 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w,
|
||||
else
|
||||
adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA;
|
||||
|
||||
-
|
||||
val = snd_soc_component_read32(component, WM8994_AIF2_CONTROL_2);
|
||||
if ((val & WM8994_AIF2DACL_SRC) &&
|
||||
(val & WM8994_AIF2DACR_SRC))
|
||||
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
|
||||
index 3f0540a..a9b37f9 100644
|
||||
--- a/sound/soc/stm/stm32_sai_sub.c
|
||||
+++ b/sound/soc/stm/stm32_sai_sub.c
|
||||
@@ -102,6 +102,7 @@
|
||||
* @spdif_frm_cnt: S/PDIF playback frame counter
|
||||
* @snd_aes_iec958: iec958 data
|
||||
* @ctrl_lock: control lock
|
||||
+ * @spinlock_t: prevent race condition with IRQ
|
||||
*/
|
||||
struct stm32_sai_sub_data {
|
||||
struct platform_device *pdev;
|
||||
@@ -133,6 +134,7 @@ struct stm32_sai_sub_data {
|
||||
unsigned int spdif_frm_cnt;
|
||||
struct snd_aes_iec958 iec958;
|
||||
struct mutex ctrl_lock; /* protect resources accessed by controls */
|
||||
+ spinlock_t irq_lock; /* used to prevent race condition with IRQ */
|
||||
};
|
||||
|
||||
enum stm32_sai_fifo_th {
|
||||
@@ -497,8 +499,10 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
|
||||
status = SNDRV_PCM_STATE_XRUN;
|
||||
}
|
||||
|
||||
- if (status != SNDRV_PCM_STATE_RUNNING)
|
||||
+ spin_lock(&sai->irq_lock);
|
||||
+ if (status != SNDRV_PCM_STATE_RUNNING && sai->substream)
|
||||
snd_pcm_stop_xrun(sai->substream);
|
||||
+ spin_unlock(&sai->irq_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@@ -703,8 +707,19 @@ static int stm32_sai_startup(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
int imr, cr2, ret;
|
||||
+ unsigned long flags;
|
||||
|
||||
+ spin_lock_irqsave(&sai->irq_lock, flags);
|
||||
sai->substream = substream;
|
||||
+ spin_unlock_irqrestore(&sai->irq_lock, flags);
|
||||
+
|
||||
+ if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
|
||||
+ snd_pcm_hw_constraint_mask64(substream->runtime,
|
||||
+ SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
+ SNDRV_PCM_FMTBIT_S32_LE);
|
||||
+ snd_pcm_hw_constraint_single(substream->runtime,
|
||||
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2);
|
||||
+ }
|
||||
|
||||
ret = clk_prepare_enable(sai->sai_ck);
|
||||
if (ret < 0) {
|
||||
@@ -1078,6 +1093,7 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
+ unsigned long flags;
|
||||
|
||||
regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0);
|
||||
|
||||
@@ -1092,7 +1108,9 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
|
||||
|
||||
clk_disable_unprepare(sai->sai_ck);
|
||||
|
||||
+ spin_lock_irqsave(&sai->irq_lock, flags);
|
||||
sai->substream = NULL;
|
||||
+ spin_unlock_irqrestore(&sai->irq_lock, flags);
|
||||
}
|
||||
|
||||
static int stm32_sai_pcm_new(struct snd_soc_pcm_runtime *rtd,
|
||||
@@ -1459,6 +1477,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
|
||||
|
||||
sai->pdev = pdev;
|
||||
mutex_init(&sai->ctrl_lock);
|
||||
+ spin_lock_init(&sai->irq_lock);
|
||||
platform_set_drvdata(pdev, sai);
|
||||
|
||||
sai->pdata = dev_get_drvdata(pdev->dev.parent);
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
From fc74bada7f6940619f8930556b7c61fe618f2a64 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Fri, 21 Dec 2018 16:56:27 +0100
|
||||
Subject: [PATCH 50/52] ARM: stm32mp1-r0-rc4: USB
|
||||
|
||||
---
|
||||
Documentation/devicetree/bindings/usb/dwc2.txt | 2 +
|
||||
drivers/usb/dwc2/core.h | 11 ++++
|
||||
drivers/usb/dwc2/core_intr.c | 4 +-
|
||||
drivers/usb/dwc2/hw.h | 2 +
|
||||
drivers/usb/dwc2/params.c | 7 ++-
|
||||
drivers/usb/dwc2/platform.c | 74 +++++++++++++++++++++++---
|
||||
6 files changed, 90 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt
|
||||
index 32b245c..03c62de 100644
|
||||
--- a/Documentation/devicetree/bindings/usb/dwc2.txt
|
||||
+++ b/Documentation/devicetree/bindings/usb/dwc2.txt
|
||||
@@ -43,6 +43,8 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties
|
||||
doesn't drive it.
|
||||
- usb33d-supply: external VBUS and ID sensing comparators supply, in order to
|
||||
perform OTG operation, used on STM32MP1 SoCs.
|
||||
+- force-b-session-valid: force B-peripheral session instead of relying on
|
||||
+ VBUS sensing (only valid when dr_mode = "peripheral").
|
||||
|
||||
Deprecated properties:
|
||||
- g-use-dma: gadget DMA mode is automatically detected
|
||||
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
|
||||
index 4c689d1..4c1736f 100644
|
||||
--- a/drivers/usb/dwc2/core.h
|
||||
+++ b/drivers/usb/dwc2/core.h
|
||||
@@ -415,6 +415,12 @@ enum dwc2_ep0_state {
|
||||
* in DWORDS with possible values from from
|
||||
* 16-32768 (default: 256, 256, 256, 256, 768,
|
||||
* 768, 768, 768, 0, 0, 0, 0, 0, 0, 0).
|
||||
+ * @force_b_session_valid: force B-peripheral session instead of relying on
|
||||
+ * VBUS sensing (only valid when dr_mode = "peripheral").
|
||||
+ * @suspend_ignore_power_down: prevent the controller to enter low power mode
|
||||
+ * upon suspend interrupt. This may help in device mode,
|
||||
+ * when suspend (3ms idle bus) gets detected before
|
||||
+ * device session end (VBUS discharge > 3ms).
|
||||
* @change_speed_quirk: Change speed configuration to DWC2_SPEED_PARAM_FULL
|
||||
* while full&low speed device connect. And change speed
|
||||
* back to DWC2_SPEED_PARAM_HIGH while device is gone.
|
||||
@@ -492,6 +498,8 @@ struct dwc2_core_params {
|
||||
u32 g_rx_fifo_size;
|
||||
u32 g_np_tx_fifo_size;
|
||||
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
|
||||
+ bool force_b_session_valid;
|
||||
+ bool suspend_ignore_power_down;
|
||||
|
||||
bool change_speed_quirk;
|
||||
};
|
||||
@@ -849,6 +857,8 @@ struct dwc2_hregs_backup {
|
||||
* removed once all SoCs support usb transceiver.
|
||||
* @supplies: Definition of USB power supplies
|
||||
* @vbus_supply: Regulator supplying vbus.
|
||||
+ * @usb33d: Optional 3.3v regulator used on some stm32 devices to
|
||||
+ * supply ID and VBUS detection hardware.
|
||||
* @phyif: PHY interface width
|
||||
* @lock: Spinlock that protects all the driver data structures
|
||||
* @priv: Stores a pointer to the struct usb_hcd
|
||||
@@ -1032,6 +1042,7 @@ struct dwc2_hsotg {
|
||||
struct dwc2_hsotg_plat *plat;
|
||||
struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES];
|
||||
struct regulator *vbus_supply;
|
||||
+ struct regulator *usb33d;
|
||||
u32 phyif;
|
||||
|
||||
spinlock_t lock;
|
||||
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
|
||||
index 19ae259..7b4162c 100644
|
||||
--- a/drivers/usb/dwc2/core_intr.c
|
||||
+++ b/drivers/usb/dwc2/core_intr.c
|
||||
@@ -492,7 +492,9 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
|
||||
hsotg->hw_params.hibernation);
|
||||
|
||||
/* Ignore suspend request before enumeration */
|
||||
- if (!dwc2_is_device_connected(hsotg)) {
|
||||
+ if (!dwc2_is_device_connected(hsotg) ||
|
||||
+ hsotg->params.force_b_session_valid ||
|
||||
+ hsotg->params.suspend_ignore_power_down) {
|
||||
dev_dbg(hsotg->dev,
|
||||
"ignore suspend request before enumeration\n");
|
||||
return;
|
||||
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
|
||||
index afde335..31f8c60 100644
|
||||
--- a/drivers/usb/dwc2/hw.h
|
||||
+++ b/drivers/usb/dwc2/hw.h
|
||||
@@ -54,6 +54,8 @@
|
||||
#define GOTGCTL_HSTSETHNPEN BIT(10)
|
||||
#define GOTGCTL_HNPREQ BIT(9)
|
||||
#define GOTGCTL_HSTNEGSCS BIT(8)
|
||||
+#define GOTGCTL_BVALOVAL BIT(7)
|
||||
+#define GOTGCTL_BVALOEN BIT(6)
|
||||
#define GOTGCTL_SESREQ BIT(1)
|
||||
#define GOTGCTL_SESREQSCS BIT(0)
|
||||
|
||||
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
|
||||
index 63ccfc9..7fef905 100644
|
||||
--- a/drivers/usb/dwc2/params.c
|
||||
+++ b/drivers/usb/dwc2/params.c
|
||||
@@ -167,7 +167,7 @@ static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_hsotg *hsotg)
|
||||
p->host_rx_fifo_size = 440;
|
||||
p->host_nperio_tx_fifo_size = 256;
|
||||
p->host_perio_tx_fifo_size = 256;
|
||||
- p->power_down = false;
|
||||
+ p->suspend_ignore_power_down = true;
|
||||
}
|
||||
|
||||
const struct of_device_id dwc2_of_match_table[] = {
|
||||
@@ -404,6 +404,11 @@ static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg)
|
||||
|
||||
if (of_find_property(hsotg->dev->of_node, "disable-over-current", NULL))
|
||||
p->oc_disable = true;
|
||||
+
|
||||
+ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
|
||||
+ p->force_b_session_valid =
|
||||
+ of_property_read_bool(hsotg->dev->of_node,
|
||||
+ "force-b-session-valid");
|
||||
}
|
||||
|
||||
static void dwc2_check_param_otg_cap(struct dwc2_hsotg *hsotg)
|
||||
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
|
||||
index 2061254..b2e5ddc 100644
|
||||
--- a/drivers/usb/dwc2/platform.c
|
||||
+++ b/drivers/usb/dwc2/platform.c
|
||||
@@ -324,6 +324,10 @@ static int dwc2_driver_remove(struct platform_device *dev)
|
||||
if (hsotg->gadget_enabled)
|
||||
dwc2_hsotg_remove(hsotg);
|
||||
|
||||
+ if (hsotg->params.activate_stm_id_vb_detection &&
|
||||
+ !hsotg->params.force_b_session_valid)
|
||||
+ regulator_disable(hsotg->usb33d);
|
||||
+
|
||||
if (hsotg->ll_hw_enabled)
|
||||
dwc2_lowlevel_hw_disable(hsotg);
|
||||
|
||||
@@ -474,18 +478,18 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
- if (hsotg->params.activate_stm_id_vb_detection) {
|
||||
- struct regulator *usb33d;
|
||||
+ if (hsotg->params.activate_stm_id_vb_detection &&
|
||||
+ !hsotg->params.force_b_session_valid) {
|
||||
u32 ggpio;
|
||||
|
||||
- usb33d = devm_regulator_get(hsotg->dev, "usb33d");
|
||||
- if (IS_ERR(usb33d)) {
|
||||
- retval = PTR_ERR(usb33d);
|
||||
+ hsotg->usb33d = devm_regulator_get(hsotg->dev, "usb33d");
|
||||
+ if (IS_ERR(hsotg->usb33d)) {
|
||||
+ retval = PTR_ERR(hsotg->usb33d);
|
||||
dev_err(hsotg->dev,
|
||||
"can't get voltage level detector supply\n");
|
||||
goto error;
|
||||
}
|
||||
- retval = regulator_enable(usb33d);
|
||||
+ retval = regulator_enable(hsotg->usb33d);
|
||||
if (retval) {
|
||||
dev_err(hsotg->dev,
|
||||
"can't enable voltage level detector supply\n");
|
||||
@@ -498,6 +502,15 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||
dwc2_writel(hsotg, ggpio, GGPIO);
|
||||
}
|
||||
|
||||
+ if (hsotg->params.force_b_session_valid) {
|
||||
+ u32 gotgctl;
|
||||
+
|
||||
+ gotgctl = dwc2_readl(hsotg, GOTGCTL);
|
||||
+ gotgctl |= GOTGCTL_BVALOVAL; /* B-peripheral session value */
|
||||
+ gotgctl |= GOTGCTL_BVALOEN; /* B-peripheral override enable */
|
||||
+ dwc2_writel(hsotg, gotgctl, GOTGCTL);
|
||||
+ }
|
||||
+
|
||||
if (hsotg->params.activate_stm_fs_transceiver) {
|
||||
u32 ggpio;
|
||||
|
||||
@@ -516,7 +529,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||
if (hsotg->dr_mode != USB_DR_MODE_HOST) {
|
||||
retval = dwc2_gadget_init(hsotg);
|
||||
if (retval)
|
||||
- goto error;
|
||||
+ goto error_init;
|
||||
hsotg->gadget_enabled = 1;
|
||||
}
|
||||
|
||||
@@ -525,7 +538,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||
if (retval) {
|
||||
if (hsotg->gadget_enabled)
|
||||
dwc2_hsotg_remove(hsotg);
|
||||
- goto error;
|
||||
+ goto error_init;
|
||||
}
|
||||
hsotg->hcd_enabled = 1;
|
||||
}
|
||||
@@ -541,6 +554,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||
|
||||
return 0;
|
||||
|
||||
+error_init:
|
||||
+ if (hsotg->params.activate_stm_id_vb_detection &&
|
||||
+ !hsotg->params.force_b_session_valid)
|
||||
+ regulator_disable(hsotg->usb33d);
|
||||
error:
|
||||
dwc2_lowlevel_hw_disable(hsotg);
|
||||
return retval;
|
||||
@@ -554,6 +571,18 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||
if (dwc2_is_device_mode(dwc2))
|
||||
dwc2_hsotg_suspend(dwc2);
|
||||
|
||||
+ if (dwc2->params.activate_stm_id_vb_detection &&
|
||||
+ !dwc2->params.force_b_session_valid) {
|
||||
+ u32 ggpio;
|
||||
+
|
||||
+ ggpio = dwc2_readl(dwc2, GGPIO);
|
||||
+ ggpio &= ~GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||
+ ggpio &= ~GGPIO_STM32_OTG_GCCFG_VBDEN;
|
||||
+ dwc2_writel(dwc2, ggpio, GGPIO);
|
||||
+
|
||||
+ regulator_disable(dwc2->usb33d);
|
||||
+ }
|
||||
+
|
||||
if (dwc2->ll_hw_enabled)
|
||||
ret = __dwc2_lowlevel_hw_disable(dwc2);
|
||||
|
||||
@@ -571,6 +600,35 @@ static int __maybe_unused dwc2_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ /* Need to restore FORCEDEVMODE/FORCEHOSTMODE */
|
||||
+ dwc2_force_dr_mode(dwc2);
|
||||
+
|
||||
+ if (dwc2->params.activate_stm_id_vb_detection &&
|
||||
+ !dwc2->params.force_b_session_valid) {
|
||||
+ u32 ggpio;
|
||||
+
|
||||
+ ret = regulator_enable(dwc2->usb33d);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ggpio = dwc2_readl(dwc2, GGPIO);
|
||||
+ ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||
+ ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN;
|
||||
+ dwc2_writel(dwc2, ggpio, GGPIO);
|
||||
+
|
||||
+ /* ID/VBUS detection startup time */
|
||||
+ usleep_range(5000, 7000);
|
||||
+ }
|
||||
+
|
||||
+ if (dwc2->params.force_b_session_valid) {
|
||||
+ u32 gotgctl;
|
||||
+
|
||||
+ gotgctl = dwc2_readl(dwc2, GOTGCTL);
|
||||
+ gotgctl |= GOTGCTL_BVALOVAL; /* B-peripheral session value */
|
||||
+ gotgctl |= GOTGCTL_BVALOEN; /* B-peripheral override enable */
|
||||
+ dwc2_writel(dwc2, gotgctl, GOTGCTL);
|
||||
+ }
|
||||
+
|
||||
if (dwc2_is_device_mode(dwc2))
|
||||
ret = dwc2_hsotg_resume(dwc2);
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,607 +0,0 @@
|
|||
From a3f6ac74fe67cfacb73bda2ba631d1e5e2680988 Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Fri, 21 Dec 2018 16:56:44 +0100
|
||||
Subject: [PATCH 51/52] ARM: stm32mp1-r0-rc4: DEVICETREE
|
||||
|
||||
---
|
||||
arch/arm/boot/dts/stm32mp157a-dk1.dts | 14 ++--
|
||||
arch/arm/boot/dts/stm32mp157c-ed1.dts | 9 ---
|
||||
arch/arm/boot/dts/stm32mp157c-ev1.dts | 2 -
|
||||
arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi | 122 +++++++++++++++---------------
|
||||
arch/arm/boot/dts/stm32mp157c.dtsi | 2 +-
|
||||
5 files changed, 67 insertions(+), 82 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
index 0a6cf35..7e911f3 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
@@ -77,11 +77,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
- iio-hwmon {
|
||||
- compatible = "iio-hwmon";
|
||||
- io-channels = <&adc_temp>;
|
||||
- };
|
||||
-
|
||||
sram: sram@10050000 {
|
||||
compatible = "mmio-sram";
|
||||
reg = <0x10050000 0x10000>;
|
||||
@@ -174,6 +169,10 @@
|
||||
sram = <&dma_pool>;
|
||||
};
|
||||
|
||||
+&dts {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
ðernet0 {
|
||||
status = "okay";
|
||||
pinctrl-0 = <ðernet0_rgmii_pins_a>;
|
||||
@@ -198,10 +197,6 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
-&hsem {
|
||||
- status = "okay";
|
||||
-};
|
||||
-
|
||||
&i2c1 {
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&i2c1_pins_a>;
|
||||
@@ -679,6 +674,7 @@
|
||||
|
||||
&usbotg_hs {
|
||||
dr_mode = "peripheral";
|
||||
+ force-b-session-valid;
|
||||
phys = <&usbphyc_port1 0>;
|
||||
phy-names = "usb2-phy";
|
||||
status = "okay";
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||
index 798580e..cf2750e 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||
@@ -74,11 +74,6 @@
|
||||
serial0 = &uart4;
|
||||
};
|
||||
|
||||
- iio-hwmon {
|
||||
- compatible = "iio-hwmon";
|
||||
- io-channels = <&adc_temp>;
|
||||
- };
|
||||
-
|
||||
sram: sram@10050000 {
|
||||
compatible = "mmio-sram";
|
||||
reg = <0x10050000 0x10000>;
|
||||
@@ -173,10 +168,6 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
-&hsem {
|
||||
- status = "okay";
|
||||
-};
|
||||
-
|
||||
&i2c4 {
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&i2c4_pins_a>;
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts
|
||||
index 49a62aa..18742e8 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c-ev1.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts
|
||||
@@ -177,7 +177,6 @@
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&cec_pins_a>;
|
||||
pinctrl-1 = <&cec_pins_sleep_a>;
|
||||
- status = "okay";
|
||||
};
|
||||
|
||||
&dcmi {
|
||||
@@ -530,7 +529,6 @@
|
||||
pinctrl-1 = <&i2c5_pins_sleep_a>;
|
||||
i2c-scl-rising-time-ns = <185>;
|
||||
i2c-scl-falling-time-ns = <20>;
|
||||
- status = "okay";
|
||||
/delete-property/dmas;
|
||||
/delete-property/dma-names;
|
||||
};
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi b/arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi
|
||||
index a1d132d0..5ebe24b 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi
|
||||
@@ -5,106 +5,106 @@
|
||||
|
||||
m4_timers2: timer@40000000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40000000 0x400>;
|
||||
+ reg = <0x40000000>;
|
||||
clocks = <&rcc TIM2_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers3: timer@40001000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40001000 0x400>;
|
||||
+ reg = <0x40001000>;
|
||||
clocks = <&rcc TIM3_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers4: timer@40002000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40002000 0x400>;
|
||||
+ reg = <0x40002000>;
|
||||
clocks = <&rcc TIM4_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers5: timer@40003000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40003000 0x400>;
|
||||
+ reg = <0x40003000>;
|
||||
clocks = <&rcc TIM5_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers6: timer@40004000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40004000 0x400>;
|
||||
+ reg = <0x40004000>;
|
||||
clocks = <&rcc TIM6_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers7: timer@40005000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40005000 0x400>;
|
||||
+ reg = <0x40005000>;
|
||||
clocks = <&rcc TIM7_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers12: timer@40006000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40006000 0x400>;
|
||||
+ reg = <0x40006000>;
|
||||
clocks = <&rcc TIM12_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers13: timer@40007000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40007000 0x400>;
|
||||
+ reg = <0x40007000>;
|
||||
clocks = <&rcc TIM13_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers14: timer@40008000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40008000 0x400>;
|
||||
+ reg = <0x40008000>;
|
||||
clocks = <&rcc TIM14_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_lptimer1: timer@40009000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40009000 0x400>;
|
||||
+ reg = <0x40009000>;
|
||||
clocks = <&rcc LPTIM1_K>;
|
||||
clock-names = "mux";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_spi2: spi@4000b000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4000b000 0x400>;
|
||||
+ reg = <0x4000b000>;
|
||||
clocks = <&rcc SPI2_K>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_i2s2: audio-controller@4000b000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4000b000 0x400>;
|
||||
+ reg = <0x4000b000>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_spi3: spi@4000c000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4000c000 0x400>;
|
||||
+ reg = <0x4000c000>;
|
||||
clocks = <&rcc SPI3_K>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_i2s3: audio-controller@4000c000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4000c000 0x400>;
|
||||
+ reg = <0x4000c000>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_spdifrx: audio-controller@4000d000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4000d000 0x400>;
|
||||
+ reg = <0x4000d000>;
|
||||
clocks = <&rcc SPDIF_K>;
|
||||
clock-names = "kclk";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_usart2: serial@4000e000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4000e000 0x400>;
|
||||
+ reg = <0x4000e000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <27 1>;
|
||||
clocks = <&rcc USART2_K>;
|
||||
@@ -112,7 +112,7 @@
|
||||
};
|
||||
m4_usart3: serial@4000f000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4000f000 0x400>;
|
||||
+ reg = <0x4000f000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <28 1>;
|
||||
clocks = <&rcc USART3_K>;
|
||||
@@ -120,7 +120,7 @@
|
||||
};
|
||||
m4_uart4: serial@40010000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40010000 0x400>;
|
||||
+ reg = <0x40010000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <30 1>;
|
||||
clocks = <&rcc UART4_K>;
|
||||
@@ -128,7 +128,7 @@
|
||||
};
|
||||
m4_uart5: serial@40011000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40011000 0x400>;
|
||||
+ reg = <0x40011000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <31 1>;
|
||||
clocks = <&rcc UART5_K>;
|
||||
@@ -136,7 +136,7 @@
|
||||
};
|
||||
m4_i2c1: i2c@40012000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40012000 0x400>;
|
||||
+ reg = <0x40012000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <21 1>;
|
||||
clocks = <&rcc I2C1_K>;
|
||||
@@ -144,7 +144,7 @@
|
||||
};
|
||||
m4_i2c2: i2c@40013000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40013000 0x400>;
|
||||
+ reg = <0x40013000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <22 1>;
|
||||
clocks = <&rcc I2C2_K>;
|
||||
@@ -152,7 +152,7 @@
|
||||
};
|
||||
m4_i2c3: i2c@40014000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40014000 0x400>;
|
||||
+ reg = <0x40014000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <23 1>;
|
||||
clocks = <&rcc I2C3_K>;
|
||||
@@ -160,7 +160,7 @@
|
||||
};
|
||||
m4_i2c5: i2c@40015000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40015000 0x400>;
|
||||
+ reg = <0x40015000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <25 1>;
|
||||
clocks = <&rcc I2C5_K>;
|
||||
@@ -168,7 +168,7 @@
|
||||
};
|
||||
m4_cec: cec@40016000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40016000 0x400>;
|
||||
+ reg = <0x40016000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <69 1>;
|
||||
clocks = <&rcc CEC_K>, <&rcc CK_LSE>;
|
||||
@@ -177,14 +177,14 @@
|
||||
};
|
||||
m4_dac: dac@40017000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40017000 0x400>;
|
||||
+ reg = <0x40017000>;
|
||||
clocks = <&rcc DAC12>;
|
||||
clock-names = "pclk";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_uart7: serial@40018000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40018000 0x400>;
|
||||
+ reg = <0x40018000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <32 1>;
|
||||
clocks = <&rcc UART7_K>;
|
||||
@@ -192,7 +192,7 @@
|
||||
};
|
||||
m4_uart8: serial@40019000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x40019000 0x400>;
|
||||
+ reg = <0x40019000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <33 1>;
|
||||
clocks = <&rcc UART8_K>;
|
||||
@@ -200,21 +200,21 @@
|
||||
};
|
||||
m4_timers1: timer@44000000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44000000 0x400>;
|
||||
+ reg = <0x44000000>;
|
||||
clocks = <&rcc TIM1_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers8: timer@44001000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44001000 0x400>;
|
||||
+ reg = <0x44001000>;
|
||||
clocks = <&rcc TIM8_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_usart6: serial@44003000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44003000 0x400>;
|
||||
+ reg = <0x44003000>;
|
||||
interrupt-parent = <&exti>;
|
||||
interrupts = <29 1>;
|
||||
clocks = <&rcc USART6_K>;
|
||||
@@ -222,203 +222,203 @@
|
||||
};
|
||||
m4_spi1: spi@44004000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44004000 0x400>;
|
||||
+ reg = <0x44004000>;
|
||||
clocks = <&rcc SPI1_K>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_i2s1: audio-controller@44004000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44004000 0x400>;
|
||||
+ reg = <0x44004000>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_spi4: spi@44005000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44005000 0x400>;
|
||||
+ reg = <0x44005000>;
|
||||
clocks = <&rcc SPI4_K>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers15: timer@44006000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44006000 0x400>;
|
||||
+ reg = <0x44006000>;
|
||||
clocks = <&rcc TIM15_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers16: timer@44007000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44007000 0x400>;
|
||||
+ reg = <0x44007000>;
|
||||
clocks = <&rcc TIM16_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_timers17: timer@44008000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44008000 0x400>;
|
||||
+ reg = <0x44008000>;
|
||||
clocks = <&rcc TIM17_K>;
|
||||
clock-names = "int";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_spi5: spi@44009000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x44009000 0x400>;
|
||||
+ reg = <0x44009000>;
|
||||
clocks = <&rcc SPI5_K>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_sai1: sai@4400a000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4400a000 0x4>;
|
||||
+ reg = <0x4400a000>;
|
||||
clocks = <&rcc SAI1_K>;
|
||||
clock-names = "sai_ck";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_sai2: sai@4400b000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4400b000 0x4>;
|
||||
+ reg = <0x4400b000>;
|
||||
clocks = <&rcc SAI2_K>;
|
||||
clock-names = "sai_ck";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_sai3: sai@4400c000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4400c000 0x4>;
|
||||
+ reg = <0x4400c000>;
|
||||
clocks = <&rcc SAI3_K>;
|
||||
clock-names = "sai_ck";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_dfsdm: dfsdm@4400d000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4400d000 0x800>;
|
||||
+ reg = <0x4400d000>;
|
||||
clocks = <&rcc DFSDM_K>;
|
||||
clock-names = "dfsdm";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_m_can1: can@4400e000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4400e000 0x400>, <0x44011000 0x2800>;
|
||||
+ reg = <0x4400e000>, <0x44011000>;
|
||||
clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
|
||||
clock-names = "hclk", "cclk";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_m_can2: can@4400f000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4400f000 0x400>, <0x44011000 0x2800>;
|
||||
+ reg = <0x4400f000>, <0x44011000>;
|
||||
clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
|
||||
clock-names = "hclk", "cclk";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_dma1: dma@48000000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x48000000 0x400>;
|
||||
+ reg = <0x48000000>;
|
||||
clocks = <&rcc DMA1>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_dma2: dma@48001000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x48001000 0x400>;
|
||||
+ reg = <0x48001000>;
|
||||
clocks = <&rcc DMA2>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_dmamux1: dma-router@48002000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x48002000 0x1c>;
|
||||
+ reg = <0x48002000>;
|
||||
clocks = <&rcc DMAMUX>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_adc: adc@48003000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x48003000 0x400>;
|
||||
+ reg = <0x48003000>;
|
||||
clocks = <&rcc ADC12>, <&rcc ADC12_K>;
|
||||
clock-names = "bus", "adc";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_sdmmc3: sdmmc@48004000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x48004000 0x400>, <0x48005000 0x400>;
|
||||
+ reg = <0x48004000>, <0x48005000>;
|
||||
clocks = <&rcc SDMMC3_K>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_usbotg_hs: usb-otg@49000000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x49000000 0x10000>;
|
||||
+ reg = <0x49000000>;
|
||||
clocks = <&rcc USBO_K>;
|
||||
clock-names = "otg";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_hash2: hash@4c002000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4c002000 0x400>;
|
||||
+ reg = <0x4c002000>;
|
||||
clocks = <&rcc HASH2>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_rng2: rng@4c003000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4c003000 0x400>;
|
||||
+ reg = <0x4c003000>;
|
||||
clocks = <&rcc RNG2_K>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_crc2: crc@4c004000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4c004000 0x400>;
|
||||
+ reg = <0x4c004000>;
|
||||
clocks = <&rcc CRC2>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_cryp2: cryp@4c005000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4c005000 0x400>;
|
||||
+ reg = <0x4c005000>;
|
||||
clocks = <&rcc CRYP2>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_dcmi: dcmi@4c006000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x4c006000 0x400>;
|
||||
+ reg = <0x4c006000>;
|
||||
clocks = <&rcc DCMI>;
|
||||
clock-names = "mclk";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_lptimer2: timer@50021000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x50021000 0x400>;
|
||||
+ reg = <0x50021000>;
|
||||
clocks = <&rcc LPTIM2_K>;
|
||||
clock-names = "mux";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_lptimer3: timer@50022000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x50022000 0x400>;
|
||||
+ reg = <0x50022000>;
|
||||
clocks = <&rcc LPTIM3_K>;
|
||||
clock-names = "mux";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_lptimer4: timer@50023000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x50023000 0x400>;
|
||||
+ reg = <0x50023000>;
|
||||
clocks = <&rcc LPTIM4_K>;
|
||||
clock-names = "mux";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_lptimer5: timer@50024000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x50024000 0x400>;
|
||||
+ reg = <0x50024000>;
|
||||
clocks = <&rcc LPTIM5_K>;
|
||||
clock-names = "mux";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_sai4: sai@50027000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x50027000 0x4>;
|
||||
+ reg = <0x50027000>;
|
||||
clocks = <&rcc SAI4_K>;
|
||||
clock-names = "sai_ck";
|
||||
status = "disabled";
|
||||
};
|
||||
m4_qspi: qspi@58003000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
|
||||
+ reg = <0x58003000>, <0x70000000>;
|
||||
clocks = <&rcc QSPI_K>;
|
||||
status = "disabled";
|
||||
};
|
||||
m4_ethernet0: ethernet@5800a000 {
|
||||
compatible = "rproc-srm-dev";
|
||||
- reg = <0x5800a000 0x2000>;
|
||||
+ reg = <0x5800a000>;
|
||||
clock-names = "stmmaceth",
|
||||
"mac-clk-tx",
|
||||
"mac-clk-rx",
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
index 7a7ef47..4de499e 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
@@ -1231,7 +1231,7 @@
|
||||
reg = <0x4c000000 0x400>;
|
||||
clocks = <&rcc HSEM>;
|
||||
clock-names = "hsem";
|
||||
- status = "disabled";
|
||||
+ status = "okay";
|
||||
};
|
||||
|
||||
ipcc: mailbox@4c001000 {
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
From 619ff8e35045cb1cb0f235bd24236ff36453186a Mon Sep 17 00:00:00 2001
|
||||
From: Romuald JEANNE <romuald.jeanne@st.com>
|
||||
Date: Fri, 21 Dec 2018 16:57:19 +0100
|
||||
Subject: [PATCH 52/52] ARM: stm32mp1-r0-rc4: DEFCONFIG
|
||||
|
||||
---
|
||||
arch/arm/configs/fragment-02-multiv7_addons.config | 13 -------------
|
||||
1 file changed, 13 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
index 6ae0453..38c5562 100644
|
||||
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
@@ -462,19 +462,6 @@ CONFIG_REGULATOR_STM32_VREFBUF=y
|
||||
CONFIG_NVMEM_STM32_ROMEM=y
|
||||
|
||||
#
|
||||
-# STM32 CORESIGHT
|
||||
-#
|
||||
-CONFIG_STM_SOURCE_CONSOLE=y
|
||||
-CONFIG_STM_SOURCE_FTRACE=y
|
||||
-CONFIG_FUNCTION_TRACER=y
|
||||
-CONFIG_CORESIGHT=y
|
||||
-CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
|
||||
-CONFIG_CORESIGHT_SINK_TPIU=y
|
||||
-CONFIG_CORESIGHT_SINK_ETBV10=y
|
||||
-CONFIG_CORESIGHT_SOURCE_ETM3X=y
|
||||
-CONFIG_CORESIGHT_STM=y
|
||||
-
|
||||
-#
|
||||
# STM32 IPCC
|
||||
#
|
||||
CONFIG_STM32_IPCC=y
|
||||
--
|
||||
2.7.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,117 +0,0 @@
|
|||
From 5648392b05ff7bb1f513ad9e9eb27b5420ce745d Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Mon, 14 Jan 2019 17:19:51 +0100
|
||||
Subject: [PATCH 54/55] ARM stm32mp1 r0 rc4 hotfix-w903.1 DEVICETREE
|
||||
|
||||
---
|
||||
arch/arm/boot/dts/stm32mp157a-dk1.dts | 13 +++++++++++++
|
||||
arch/arm/boot/dts/stm32mp157c-dk2.dts | 1 +
|
||||
arch/arm/boot/dts/stm32mp157c.dtsi | 14 ++++++++++++++
|
||||
3 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
index 7e911f3..28017e4 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
@@ -287,6 +287,19 @@
|
||||
/delete-property/dmas;
|
||||
/delete-property/dma-names;
|
||||
|
||||
+ typec: stusb1600@28 {
|
||||
+ compatible = "st,stusb1600";
|
||||
+ reg = <0x28>;
|
||||
+ status = "okay";
|
||||
+
|
||||
+ typec_con: connector {
|
||||
+ compatible = "usb-c-connector";
|
||||
+ label = "USB-C";
|
||||
+ power-role = "sink";
|
||||
+ power-opmode = "default";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
pmic: stpmic@33 {
|
||||
compatible = "st,stpmic1";
|
||||
reg = <0x33>;
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||
index c276c59..340e022 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||
@@ -106,6 +106,7 @@
|
||||
|
||||
/* Wifi */
|
||||
&sdmmc2 {
|
||||
+ arm,primecell-periphid = <0x10153180>;
|
||||
pinctrl-names = "default", "opendrain", "sleep";
|
||||
pinctrl-0 = <&sdmmc2_b4_pins_a>;
|
||||
pinctrl-1 = <&sdmmc2_b4_od_pins_a>;
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
index 4de499e..b09ef8b 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
@@ -892,6 +892,8 @@
|
||||
|
||||
compatible = "st,stm32-sai-sub-a";
|
||||
reg = <0x4 0x1c>;
|
||||
+ clocks = <&rcc SAI1_K>;
|
||||
+ clock-names = "sai_ck";
|
||||
dmas = <&dmamux1 87 0x400 0x01>;
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -900,6 +902,8 @@
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "st,stm32-sai-sub-b";
|
||||
reg = <0x24 0x1c>;
|
||||
+ clocks = <&rcc SAI1_K>;
|
||||
+ clock-names = "sai_ck";
|
||||
dmas = <&dmamux1 88 0x400 0x01>;
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -919,6 +923,8 @@
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "st,stm32-sai-sub-a";
|
||||
reg = <0x4 0x1c>;
|
||||
+ clocks = <&rcc SAI2_K>;
|
||||
+ clock-names = "sai_ck";
|
||||
dmas = <&dmamux1 89 0x400 0x01>;
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -927,6 +933,8 @@
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "st,stm32-sai-sub-b";
|
||||
reg = <0x24 0x1c>;
|
||||
+ clocks = <&rcc SAI2_K>;
|
||||
+ clock-names = "sai_ck";
|
||||
dmas = <&dmamux1 90 0x400 0x01>;
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -946,6 +954,8 @@
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "st,stm32-sai-sub-a";
|
||||
reg = <0x04 0x1c>;
|
||||
+ clocks = <&rcc SAI3_K>;
|
||||
+ clock-names = "sai_ck";
|
||||
dmas = <&dmamux1 113 0x400 0x01>;
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -954,6 +964,8 @@
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "st,stm32-sai-sub-b";
|
||||
reg = <0x24 0x1c>;
|
||||
+ clocks = <&rcc SAI3_K>;
|
||||
+ clock-names = "sai_ck";
|
||||
dmas = <&dmamux1 114 0x400 0x01>;
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -1442,6 +1454,8 @@
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "st,stm32-sai-sub-b";
|
||||
reg = <0x24 0x1c>;
|
||||
+ clocks = <&rcc SAI4_K>;
|
||||
+ clock-names = "sai_ck";
|
||||
dmas = <&dmamux1 100 0x400 0x01>;
|
||||
status = "disabled";
|
||||
};
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
From 449bea3af472f64774547738478ca3b2cfa91cae Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Mon, 14 Jan 2019 17:20:30 +0100
|
||||
Subject: [PATCH 55/55] ARM stm32mp1 r0 rc4 hotfix-w903.1 DEFCONFIG
|
||||
|
||||
---
|
||||
arch/arm/configs/fragment-02-multiv7_addons.config | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
index 38c5562..ddf15a9 100644
|
||||
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
@@ -346,6 +346,8 @@ CONFIG_USB_CONFIGFS=y
|
||||
#
|
||||
# USB Physical Layer drivers
|
||||
#
|
||||
+CONFIG_TYPEC=y
|
||||
+CONFIG_TYPEC_STUSB=y
|
||||
|
||||
#
|
||||
# Platform Support
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,554 +0,0 @@
|
|||
From b6678ec426d7dbc5248a2d98c0c2c7a5b55e4d5f Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Wed, 16 Jan 2019 17:51:05 +0100
|
||||
Subject: [PATCH 56/58] ARM stm32mp1 r0 rc4 hotfix w903.3 DRIVERS
|
||||
|
||||
---
|
||||
drivers/clk/clk-stm32mp1.c | 142 ++++++++++++++++++++--------------
|
||||
drivers/i2c/busses/i2c-stm32f7.c | 33 +++++++-
|
||||
drivers/irqchip/irq-stm32-exti.c | 160 +++++++++++++++++++++++++--------------
|
||||
kernel/power/suspend.c | 1 -
|
||||
4 files changed, 218 insertions(+), 118 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
|
||||
index 7eccaa1..56d7b86 100644
|
||||
--- a/drivers/clk/clk-stm32mp1.c
|
||||
+++ b/drivers/clk/clk-stm32mp1.c
|
||||
@@ -2215,8 +2215,8 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
|
||||
|
||||
static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
/* Oscillator divider */
|
||||
- DIV(NO_ID, "clk-hsi-div", "clk-hsi", 0, RCC_HSICFGR, 0, 2,
|
||||
- CLK_DIVIDER_READ_ONLY),
|
||||
+ DIV(NO_ID, "clk-hsi-div", "clk-hsi", CLK_DIVIDER_POWER_OF_TWO,
|
||||
+ RCC_HSICFGR, 0, 2, CLK_DIVIDER_READ_ONLY),
|
||||
|
||||
/* External / Internal Oscillators */
|
||||
SGATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0),
|
||||
@@ -2517,11 +2517,10 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
||||
CLK_SET_RATE_NO_REPARENT,
|
||||
_NO_GATE,
|
||||
_MMUX(M_ETHCK),
|
||||
- _DIV(RCC_ETHCKSELR, 4, 4, CLK_DIVIDER_ALLOW_ZERO, NULL)),
|
||||
+ _DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)),
|
||||
|
||||
/* RTC clock */
|
||||
- SDIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 7,
|
||||
- CLK_DIVIDER_ALLOW_ZERO),
|
||||
+ SDIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 6, 0),
|
||||
|
||||
COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE |
|
||||
CLK_SET_RATE_PARENT,
|
||||
@@ -2724,52 +2723,53 @@ static struct sreg clock_gating[] = {
|
||||
};
|
||||
|
||||
struct smux {
|
||||
- const char *name;
|
||||
- struct clk *clk;
|
||||
- struct clk *clkp;
|
||||
+ u32 clk_id;
|
||||
+ u32 mux_id;
|
||||
+ struct clk_hw *hw;
|
||||
};
|
||||
|
||||
-#define KER_SRC(_clk_name)\
|
||||
+#define KER_SRC(_clk_id, _mux_id)\
|
||||
{\
|
||||
- .name = _clk_name,\
|
||||
-}
|
||||
-
|
||||
-struct smux _mux_kernel[] = {
|
||||
- KER_SRC("sdmmc1_k"),
|
||||
- KER_SRC("spi2_k"),
|
||||
- KER_SRC("spi4_k"),
|
||||
- KER_SRC("i2c1_k"),
|
||||
- KER_SRC("i2c3_k"),
|
||||
- KER_SRC("lptim2_k"),
|
||||
- KER_SRC("lptim3_k"),
|
||||
- KER_SRC("usart2_k"),
|
||||
- KER_SRC("usart3_k"),
|
||||
- KER_SRC("uart7_k"),
|
||||
- KER_SRC("sai1_k"),
|
||||
- KER_SRC("ethck_k"),
|
||||
- KER_SRC("i2c4_k"),
|
||||
- KER_SRC("rng2_k"),
|
||||
- KER_SRC("sdmmc3_k"),
|
||||
- KER_SRC("fmc_k"),
|
||||
- KER_SRC("qspi_k"),
|
||||
- KER_SRC("usbphy_k"),
|
||||
- KER_SRC("usbo_k"),
|
||||
- KER_SRC("spdif_k"),
|
||||
- KER_SRC("spi1_k"),
|
||||
- KER_SRC("cec_k"),
|
||||
- KER_SRC("lptim1_k"),
|
||||
- KER_SRC("uart6_k"),
|
||||
- KER_SRC("fdcan_k"),
|
||||
- KER_SRC("sai2_k"),
|
||||
- KER_SRC("sai3_k"),
|
||||
- KER_SRC("sai4_k"),
|
||||
- KER_SRC("adc12_k"),
|
||||
- KER_SRC("dsi_k"),
|
||||
- KER_SRC("ck_per"),
|
||||
- KER_SRC("rng1_k"),
|
||||
- KER_SRC("stgen_k"),
|
||||
- KER_SRC("usart1_k"),
|
||||
- KER_SRC("spi6_k"),
|
||||
+ .clk_id = _clk_id,\
|
||||
+ .mux_id = _mux_id,\
|
||||
+}
|
||||
+
|
||||
+struct smux _mux_kernel[M_LAST] = {
|
||||
+ KER_SRC(SDMMC1_K, M_SDMMC12),
|
||||
+ KER_SRC(SDMMC3_K, M_SDMMC3),
|
||||
+ KER_SRC(FMC_K, M_FMC),
|
||||
+ KER_SRC(QSPI_K, M_QSPI),
|
||||
+ KER_SRC(RNG1_K, M_RNG1),
|
||||
+ KER_SRC(RNG2_K, M_RNG2),
|
||||
+ KER_SRC(USBPHY_K, M_USBPHY),
|
||||
+ KER_SRC(USBO_K, M_USBO),
|
||||
+ KER_SRC(STGEN_K, M_STGEN),
|
||||
+ KER_SRC(SPDIF_K, M_SPDIF),
|
||||
+ KER_SRC(SPI1_K, M_SPI1),
|
||||
+ KER_SRC(SPI2_K, M_SPI23),
|
||||
+ KER_SRC(SPI4_K, M_SPI45),
|
||||
+ KER_SRC(SPI6_K, M_SPI6),
|
||||
+ KER_SRC(CEC_K, M_CEC),
|
||||
+ KER_SRC(I2C1_K, M_I2C12),
|
||||
+ KER_SRC(I2C3_K, M_I2C35),
|
||||
+ KER_SRC(I2C4_K, M_I2C46),
|
||||
+ KER_SRC(LPTIM1_K, M_LPTIM1),
|
||||
+ KER_SRC(LPTIM2_K, M_LPTIM23),
|
||||
+ KER_SRC(LPTIM4_K, M_LPTIM45),
|
||||
+ KER_SRC(USART1_K, M_USART1),
|
||||
+ KER_SRC(USART2_K, M_UART24),
|
||||
+ KER_SRC(USART3_K, M_UART35),
|
||||
+ KER_SRC(USART6_K, M_USART6),
|
||||
+ KER_SRC(UART7_K, M_UART78),
|
||||
+ KER_SRC(SAI1_K, M_SAI1),
|
||||
+ KER_SRC(SAI2_K, M_SAI2),
|
||||
+ KER_SRC(SAI3_K, M_SAI3),
|
||||
+ KER_SRC(SAI4_K, M_SAI4),
|
||||
+ KER_SRC(DSI_K, M_DSI),
|
||||
+ KER_SRC(FDCAN_K, M_FDCAN),
|
||||
+ KER_SRC(ADC12_K, M_ADC12),
|
||||
+ KER_SRC(ETHCK_K, M_ETHCK),
|
||||
+ KER_SRC(CK_PER, M_CKPER),
|
||||
};
|
||||
|
||||
static struct sreg pll_clock[] = {
|
||||
@@ -2861,22 +2861,52 @@ static void stm32mp1_restore_pll(struct sreg *sreg, int size)
|
||||
}
|
||||
}
|
||||
|
||||
-static void stm32mp1_backup_mux(struct smux *smux, int size)
|
||||
+static void stm32mp1_backup_mux(struct device_node *np,
|
||||
+ struct smux *smux, int size)
|
||||
{
|
||||
int i;
|
||||
+ struct of_phandle_args clkspec;
|
||||
+
|
||||
+ clkspec.np = np;
|
||||
+ clkspec.args_count = 1;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
- smux[i].clk = __clk_lookup(smux[i].name);
|
||||
- smux[i].clkp = clk_get_parent(smux[i].clk);
|
||||
+ clkspec.args[0] = smux[i].clk_id;
|
||||
+ smux[i].hw = __clk_get_hw(of_clk_get_from_provider(&clkspec));
|
||||
}
|
||||
}
|
||||
|
||||
static void stm32mp1_restore_mux(struct smux *smux, int size)
|
||||
{
|
||||
int i;
|
||||
+ struct clk_hw *hw, *hwp1, *hwp2;
|
||||
+ struct mux_cfg *mux;
|
||||
+ u8 idx;
|
||||
|
||||
- for (i = 0; i < size; i++)
|
||||
- clk_set_parent_force(smux[i].clk, smux[i].clkp);
|
||||
+ /* These MUX are glitch free.
|
||||
+ * Then we have to restore mux thru clock framework
|
||||
+ * to be sure that CLK_OPS_PARENT_ENABLE will be exploited
|
||||
+ */
|
||||
+ for (i = 0; i < M_LAST; i++) {
|
||||
+ /* get parent strored in clock framework */
|
||||
+ hw = smux[i].hw;
|
||||
+ hwp1 = clk_hw_get_parent(hw);
|
||||
+
|
||||
+ /* Get parent corresponding to mux register */
|
||||
+ mux = ker_mux_cfg[smux[i].mux_id].mux;
|
||||
+ idx = readl_relaxed(rcc_base + mux->reg_off) >> mux->shift;
|
||||
+ idx &= (BIT(mux->width) - 1);
|
||||
+ hwp2 = clk_hw_get_parent_by_index(hw, idx);
|
||||
+
|
||||
+ /* check if parent from mux & clock framework are differents */
|
||||
+ if (hwp1 != hwp2) {
|
||||
+ /* update first clock framework with the true parent */
|
||||
+ clk_set_parent(hw->clk, hwp2->clk);
|
||||
+
|
||||
+ /* Restore now new parent */
|
||||
+ clk_set_parent(hw->clk, hwp1->clk);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
#define RCC_BIT_HSI 0
|
||||
@@ -2900,9 +2930,6 @@ static int stm32mp1_clk_suspend(void)
|
||||
/* Save clock gating regs */
|
||||
stm32mp1_backup_sreg(clock_gating, ARRAY_SIZE(clock_gating));
|
||||
|
||||
- /* Save kernel clock regs */
|
||||
- stm32mp1_backup_mux(_mux_kernel, ARRAY_SIZE(_mux_kernel));
|
||||
-
|
||||
/* Enable ck_xxx_ker clocks if ck_xxx was on */
|
||||
reg = readl_relaxed(rcc_base + RCC_OCENSETR) & RCC_CK_OSC_MASK;
|
||||
writel_relaxed(reg << 1, rcc_base + RCC_OCENSETR);
|
||||
@@ -2970,6 +2997,9 @@ static int stm32_rcc_init_pwr(struct device_node *np)
|
||||
|
||||
SMC(STM32_SVC_RCC, STM32_WRITE, RCC_SREQCLRR, RCC_STOP_MASK);
|
||||
|
||||
+ /* Prepare kernel clock source backup */
|
||||
+ stm32mp1_backup_mux(np, _mux_kernel, ARRAY_SIZE(_mux_kernel));
|
||||
+
|
||||
register_syscore_ops(&stm32mp1_clk_ops);
|
||||
|
||||
return 0;
|
||||
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
|
||||
index ac30aea..3af2637 100644
|
||||
--- a/drivers/i2c/busses/i2c-stm32f7.c
|
||||
+++ b/drivers/i2c/busses/i2c-stm32f7.c
|
||||
@@ -978,6 +978,26 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
|
||||
cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
|
||||
f7_msg->read_write = I2C_SMBUS_READ;
|
||||
break;
|
||||
+ case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
|
||||
+ dev_err(dev, "Invalid block %s size %d\n",
|
||||
+ f7_msg->read_write == I2C_SMBUS_READ ?
|
||||
+ "read" : "write",
|
||||
+ data->block[0]);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (f7_msg->read_write) {
|
||||
+ f7_msg->stop = false;
|
||||
+ f7_msg->count = data->block[0];
|
||||
+ cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
|
||||
+ } else {
|
||||
+ f7_msg->stop = true;
|
||||
+ f7_msg->count = data->block[0] + 1;
|
||||
+ for (i = 1; i <= data->block[0]; i++)
|
||||
+ f7_msg->smbus_buf[i] = data->block[i];
|
||||
+ }
|
||||
+ break;
|
||||
default:
|
||||
dev_err(dev, "Unsupported smbus protocol %d\n", f7_msg->size);
|
||||
return -EOPNOTSUPP;
|
||||
@@ -986,7 +1006,8 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
|
||||
f7_msg->buf = f7_msg->smbus_buf;
|
||||
|
||||
/* Configure PEC */
|
||||
- if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK) {
|
||||
+ if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK &&
|
||||
+ f7_msg->size != I2C_SMBUS_I2C_BLOCK_DATA) {
|
||||
cr1 |= STM32F7_I2C_CR1_PECEN;
|
||||
cr2 |= STM32F7_I2C_CR2_PECBYTE;
|
||||
if (!f7_msg->read_write)
|
||||
@@ -1655,7 +1676,8 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||
}
|
||||
|
||||
/* Check PEC */
|
||||
- if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && read_write) {
|
||||
+ if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK &&
|
||||
+ size != I2C_SMBUS_I2C_BLOCK_DATA && read_write) {
|
||||
ret = stm32f7_i2c_smbus_check_pec(i2c_dev);
|
||||
if (ret)
|
||||
goto pm_free;
|
||||
@@ -1672,6 +1694,10 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||
data->word = f7_msg->smbus_buf[0] |
|
||||
(f7_msg->smbus_buf[1] << 8);
|
||||
break;
|
||||
+ case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
+ for (i = 0; i < data->block[0]; i++)
|
||||
+ data->block[i + 1] = f7_msg->smbus_buf[i];
|
||||
+ break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL:
|
||||
for (i = 0; i <= f7_msg->smbus_buf[0]; i++)
|
||||
@@ -1854,7 +1880,8 @@ static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
|
||||
I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
|
||||
- I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC;
|
||||
+ I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC |
|
||||
+ I2C_FUNC_SMBUS_I2C_BLOCK;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm stm32f7_i2c_algo = {
|
||||
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
|
||||
index 223ee2e..793be075a 100644
|
||||
--- a/drivers/irqchip/irq-stm32-exti.c
|
||||
+++ b/drivers/irqchip/irq-stm32-exti.c
|
||||
@@ -14,8 +14,10 @@
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
+#include <linux/of_platform.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
@@ -37,12 +39,6 @@ struct stm32_exti_bank {
|
||||
|
||||
#define UNDEF_REG ~0
|
||||
|
||||
-enum stm32_exti_hwspinlock {
|
||||
- HWSPINLOCK_UNKNOWN,
|
||||
- HWSPINLOCK_NONE,
|
||||
- HWSPINLOCK_READY,
|
||||
-};
|
||||
-
|
||||
struct stm32_desc_irq {
|
||||
u32 exti;
|
||||
u32 irq_parent;
|
||||
@@ -69,8 +65,6 @@ struct stm32_exti_host_data {
|
||||
void __iomem *base;
|
||||
struct stm32_exti_chip_data *chips_data;
|
||||
const struct stm32_exti_drv_data *drv_data;
|
||||
- struct device_node *node;
|
||||
- enum stm32_exti_hwspinlock hwlock_state;
|
||||
struct hwspinlock *hwlock;
|
||||
};
|
||||
|
||||
@@ -285,49 +279,27 @@ static int stm32_exti_set_type(struct irq_data *d,
|
||||
|
||||
static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data)
|
||||
{
|
||||
- struct stm32_exti_host_data *host_data = chip_data->host_data;
|
||||
- struct hwspinlock *hwlock;
|
||||
- int id, ret = 0, timeout = 0;
|
||||
-
|
||||
- /* first time, check for hwspinlock availability */
|
||||
- if (unlikely(host_data->hwlock_state == HWSPINLOCK_UNKNOWN)) {
|
||||
- id = of_hwspin_lock_get_id(host_data->node, 0);
|
||||
- if (id >= 0) {
|
||||
- hwlock = hwspin_lock_request_specific(id);
|
||||
- if (hwlock) {
|
||||
- /* found valid hwspinlock */
|
||||
- host_data->hwlock_state = HWSPINLOCK_READY;
|
||||
- host_data->hwlock = hwlock;
|
||||
- pr_debug("%s hwspinlock = %d\n", __func__, id);
|
||||
- } else {
|
||||
- host_data->hwlock_state = HWSPINLOCK_NONE;
|
||||
- }
|
||||
- } else if (id != -EPROBE_DEFER) {
|
||||
- host_data->hwlock_state = HWSPINLOCK_NONE;
|
||||
- } else {
|
||||
- /* hwspinlock driver shall be ready at that stage */
|
||||
- ret = -EPROBE_DEFER;
|
||||
- }
|
||||
- }
|
||||
+ int ret, timeout = 0;
|
||||
|
||||
- if (likely(host_data->hwlock_state == HWSPINLOCK_READY)) {
|
||||
- /*
|
||||
- * Use the x_raw API since we are under spin_lock protection.
|
||||
- * Do not use the x_timeout API because we are under irq_disable
|
||||
- * mode (see __setup_irq())
|
||||
- */
|
||||
- do {
|
||||
- ret = hwspin_trylock_raw(host_data->hwlock);
|
||||
- if (!ret)
|
||||
- return 0;
|
||||
-
|
||||
- udelay(HWSPNLCK_RETRY_DELAY);
|
||||
- timeout += HWSPNLCK_RETRY_DELAY;
|
||||
- } while (timeout < HWSPNLCK_TIMEOUT);
|
||||
-
|
||||
- if (ret == -EBUSY)
|
||||
- ret = -ETIMEDOUT;
|
||||
- }
|
||||
+ if (!chip_data->host_data->hwlock)
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Use the x_raw API since we are under spin_lock protection.
|
||||
+ * Do not use the x_timeout API because we are under irq_disable
|
||||
+ * mode (see __setup_irq())
|
||||
+ */
|
||||
+ do {
|
||||
+ ret = hwspin_trylock_raw(chip_data->host_data->hwlock);
|
||||
+ if (!ret)
|
||||
+ return 0;
|
||||
+
|
||||
+ udelay(HWSPNLCK_RETRY_DELAY);
|
||||
+ timeout += HWSPNLCK_RETRY_DELAY;
|
||||
+ } while (timeout < HWSPNLCK_TIMEOUT);
|
||||
+
|
||||
+ if (ret == -EBUSY)
|
||||
+ ret = -ETIMEDOUT;
|
||||
|
||||
if (ret)
|
||||
pr_err("%s can't get hwspinlock (%d)\n", __func__, ret);
|
||||
@@ -337,7 +309,7 @@ static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data)
|
||||
|
||||
static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data)
|
||||
{
|
||||
- if (likely(chip_data->host_data->hwlock_state == HWSPINLOCK_READY))
|
||||
+ if (chip_data->host_data->hwlock)
|
||||
hwspin_unlock_raw(chip_data->host_data->hwlock);
|
||||
}
|
||||
|
||||
@@ -710,8 +682,6 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
|
||||
return NULL;
|
||||
|
||||
host_data->drv_data = dd;
|
||||
- host_data->node = node;
|
||||
- host_data->hwlock_state = HWSPINLOCK_UNKNOWN;
|
||||
host_data->chips_data = kcalloc(dd->bank_nr,
|
||||
sizeof(struct stm32_exti_chip_data),
|
||||
GFP_KERNEL);
|
||||
@@ -738,7 +708,8 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
|
||||
|
||||
static struct
|
||||
stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||
- u32 bank_idx)
|
||||
+ u32 bank_idx,
|
||||
+ struct device_node *node)
|
||||
{
|
||||
const struct stm32_exti_bank *stm32_bank;
|
||||
struct stm32_exti_chip_data *chip_data;
|
||||
@@ -758,7 +729,7 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
|
||||
writel_relaxed(0, base + stm32_bank->imr_ofst);
|
||||
writel_relaxed(0, base + stm32_bank->emr_ofst);
|
||||
|
||||
- pr_info("%pOF: bank%d\n", h_data->node, bank_idx);
|
||||
+ pr_info("%pOF: bank%d\n", node, bank_idx);
|
||||
|
||||
return chip_data;
|
||||
}
|
||||
@@ -798,7 +769,7 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
|
||||
struct stm32_exti_chip_data *chip_data;
|
||||
|
||||
stm32_bank = drv_data->exti_banks[i];
|
||||
- chip_data = stm32_exti_chip_init(host_data, i);
|
||||
+ chip_data = stm32_exti_chip_init(host_data, i, node);
|
||||
|
||||
gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
|
||||
|
||||
@@ -880,7 +851,7 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < drv_data->bank_nr; i++)
|
||||
- stm32_exti_chip_init(host_data, i);
|
||||
+ stm32_exti_chip_init(host_data, i, node);
|
||||
|
||||
domain = irq_domain_add_hierarchy(parent_domain, 0,
|
||||
drv_data->bank_nr * IRQS_PER_BANK,
|
||||
@@ -938,6 +909,71 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* Note : stm32_exti_probe() is called after stm32*_exti_of_init() */
|
||||
+static int stm32_exti_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ int id, ret = 0;
|
||||
+
|
||||
+ id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
|
||||
+
|
||||
+ if (id == -EPROBE_DEFER)
|
||||
+ /* hwspinlock framework not ready */
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
+ if (id == -ENOENT)
|
||||
+ /* no hwspinlock defined (not an error, it is optional) */
|
||||
+ return 0;
|
||||
+
|
||||
+ if (id >= 0) {
|
||||
+ stm32_host_data->hwlock = hwspin_lock_request_specific(id);
|
||||
+ if (!stm32_host_data->hwlock) {
|
||||
+ dev_err(&pdev->dev, "Failed to request hwspinlock\n");
|
||||
+ ret = -EINVAL;
|
||||
+ }
|
||||
+ } else {
|
||||
+ dev_err(&pdev->dev, "Failed to get hwspinlock\n");
|
||||
+ ret = id;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int stm32_exti_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ if (stm32_host_data->hwlock)
|
||||
+ return hwspin_lock_free(stm32_host_data->hwlock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id stm32_exti_ids[] = {
|
||||
+ { .compatible = "st,stm32mp1-exti", },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, stm32_exti_ids);
|
||||
+
|
||||
+static struct platform_driver stm32_exti_driver = {
|
||||
+ .probe = stm32_exti_probe,
|
||||
+ .remove = stm32_exti_remove,
|
||||
+ .driver = {
|
||||
+ .name = "stm32_exti",
|
||||
+ .of_match_table = stm32_exti_ids,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init stm32_exti_arch_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&stm32_exti_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit stm32_exti_arch_exit(void)
|
||||
+{
|
||||
+ return platform_driver_unregister(&stm32_exti_driver);
|
||||
+}
|
||||
+
|
||||
+arch_initcall(stm32_exti_arch_init);
|
||||
+module_exit(stm32_exti_arch_exit);
|
||||
+
|
||||
static int __init stm32f4_exti_of_init(struct device_node *np,
|
||||
struct device_node *parent)
|
||||
{
|
||||
@@ -957,7 +993,15 @@ IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);
|
||||
static int __init stm32mp1_exti_of_init(struct device_node *np,
|
||||
struct device_node *parent)
|
||||
{
|
||||
- return stm32_exti_hierarchy_init(&stm32mp1_drv_data, np, parent);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = stm32_exti_hierarchy_init(&stm32mp1_drv_data, np, parent);
|
||||
+
|
||||
+ /* Clear the OF_POPULATED flag so that stm32_exti_probe can be called */
|
||||
+ if (!ret)
|
||||
+ of_node_clear_flag(np, OF_POPULATED);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
IRQCHIP_DECLARE(stm32mp1_exti, "st,stm32mp1-exti", stm32mp1_exti_of_init);
|
||||
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
|
||||
index 0bd595a..64f6aec 100644
|
||||
--- a/kernel/power/suspend.c
|
||||
+++ b/kernel/power/suspend.c
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "power.h"
|
||||
|
||||
const char * const pm_labels[] = {
|
||||
- [PM_SUSPEND_TO_IDLE] = "freeze",
|
||||
[PM_SUSPEND_STANDBY] = "standby",
|
||||
[PM_SUSPEND_MEM] = "mem",
|
||||
};
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
From f30f869d9bb396c6981fc2800149c373d21586de Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Wed, 16 Jan 2019 17:52:31 +0100
|
||||
Subject: [PATCH 57/58] ARM stm32mp1 r0 rc4 hotfix w903.3 DEVICETREE
|
||||
|
||||
---
|
||||
arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 30 ++++++++++++++++++++++++++++++
|
||||
arch/arm/boot/dts/stm32mp157a-dk1.dts | 12 +++++++++++-
|
||||
arch/arm/boot/dts/stm32mp157c-dk2.dts | 2 +-
|
||||
arch/arm/boot/dts/stm32mp157c-ed1.dts | 2 +-
|
||||
4 files changed, 43 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||
index 183d7ba..474e7e3 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||
@@ -1413,6 +1413,36 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ uart7_pins_a: uart7-0 {
|
||||
+ pins1 {
|
||||
+ pinmux = <STM32_PINMUX('E', 8, AF7)>; /* USART7_TX */
|
||||
+ bias-disable;
|
||||
+ drive-push-pull;
|
||||
+ slew-rate = <0>;
|
||||
+ };
|
||||
+ pins2 {
|
||||
+ pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ uart7_idle_pins_a: uart7-idle-0 {
|
||||
+ pins1 {
|
||||
+ pinmux = <STM32_PINMUX('E', 8, ANALOG)>; /* USART7_TX */
|
||||
+ };
|
||||
+ pins2 {
|
||||
+ pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ uart7_sleep_pins_a: uart7-sleep-0 {
|
||||
+ pins {
|
||||
+ pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* USART7_TX */
|
||||
+ <STM32_PINMUX('E', 7, ANALOG)>; /* USART7_RX */
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
usart2_pins_a: usart2-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('D', 5, AF7)>, /* USART2_TX */
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
index 28017e4..467c226 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
@@ -20,6 +20,8 @@
|
||||
aliases {
|
||||
ethernet0 = ðernet0;
|
||||
serial0 = &uart4;
|
||||
+ serial1 = &usart3;
|
||||
+ serial2 = &uart7;
|
||||
};
|
||||
|
||||
chosen {
|
||||
@@ -310,7 +312,7 @@
|
||||
|
||||
st,main-control-register = <0x04>;
|
||||
st,vin-control-register = <0xc0>;
|
||||
- st,usb-control-register = <0x30>;
|
||||
+ st,usb-control-register = <0x20>;
|
||||
|
||||
regulators {
|
||||
compatible = "st,stpmic1-regulators";
|
||||
@@ -671,6 +673,14 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+&uart7 {
|
||||
+ pinctrl-names = "default", "sleep", "idle";
|
||||
+ pinctrl-0 = <&uart7_pins_a>;
|
||||
+ pinctrl-1 = <&uart7_sleep_pins_a>;
|
||||
+ pinctrl-2 = <&uart7_idle_pins_a>;
|
||||
+ status = "disabled";
|
||||
+};
|
||||
+
|
||||
&usart3 {
|
||||
pinctrl-names = "default", "sleep", "idle";
|
||||
pinctrl-0 = <&usart3_pins_b>;
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||
index 340e022..4da15cd 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||
@@ -14,7 +14,7 @@
|
||||
compatible = "st,stm32mp157c-dk2", "st,stm32mp157";
|
||||
|
||||
aliases {
|
||||
- serial1 = &usart2;
|
||||
+ serial3 = &usart2;
|
||||
};
|
||||
|
||||
wifi_pwrseq: wifi-pwrseq {
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||
index cf2750e..6d49f21 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||
@@ -188,7 +188,7 @@
|
||||
|
||||
st,main-control-register = <0x04>;
|
||||
st,vin-control-register = <0xc0>;
|
||||
- st,usb-control-register = <0x30>;
|
||||
+ st,usb-control-register = <0x20>;
|
||||
|
||||
regulators {
|
||||
compatible = "st,stpmic1-regulators";
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
From 2cfb67b0a4403e68016a50c1302da9a8eeb15a6b Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Wed, 16 Jan 2019 17:53:15 +0100
|
||||
Subject: [PATCH 58/58] ARM stm32mp1 r0 rc4 hotfix w903.3 DEFCONFIG
|
||||
|
||||
---
|
||||
arch/arm/configs/fragment-02-multiv7_addons.config | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
index ddf15a9..7b489e4 100644
|
||||
--- a/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
|
||||
@@ -123,9 +123,6 @@ CONFIG_CMA_SIZE_MBYTES=128
|
||||
#
|
||||
# LPDDR & LPDDR2 PCM memory drivers
|
||||
#
|
||||
-CONFIG_OF_RESOLVE=y
|
||||
-CONFIG_OF_OVERLAY=y
|
||||
-CONFIG_OF_CONFIGFS=y
|
||||
|
||||
#
|
||||
# Misc devices
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,927 +0,0 @@
|
|||
From dbfd12db19506dc6d598c11d72aa0fb81c41aa82 Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Thu, 24 Jan 2019 10:51:36 +0100
|
||||
Subject: [PATCH 59/60] ARM stm32mp1 r0 rc4 hotfix w904.3 DRIVERS
|
||||
|
||||
---
|
||||
drivers/dma/stm32-dma.c | 4 +
|
||||
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c | 64 +++++------
|
||||
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 51 ++++++---
|
||||
drivers/remoteproc/stm32_rproc.c | 21 ++--
|
||||
drivers/tty/serial/stm32-usart.c | 8 ++
|
||||
drivers/tty/serial/stm32-usart.h | 2 +-
|
||||
drivers/usb/dwc2/core.h | 29 +++++
|
||||
drivers/usb/dwc2/debugfs.c | 1 +
|
||||
drivers/usb/dwc2/gadget.c | 133 +++++++++++++++++++++--
|
||||
drivers/usb/dwc2/hcd.c | 3 -
|
||||
drivers/usb/dwc2/hcd.h | 2 +-
|
||||
drivers/usb/dwc2/hcd_queue.c | 19 ++--
|
||||
drivers/usb/dwc2/hw.h | 17 +++
|
||||
drivers/usb/dwc2/params.c | 18 ++-
|
||||
14 files changed, 294 insertions(+), 78 deletions(-)
|
||||
|
||||
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
|
||||
index 1f9d606..5abfa4f 100644
|
||||
--- a/drivers/dma/stm32-dma.c
|
||||
+++ b/drivers/dma/stm32-dma.c
|
||||
@@ -1242,6 +1242,7 @@ static int stm32_dma_mdma_prep_slave_sg(struct stm32_dma_chan *chan,
|
||||
dev_err(chan2dev(chan),
|
||||
"max buf size = %d bytes\n",
|
||||
chan->sram_size);
|
||||
+ ret = -EINVAL;
|
||||
goto free_alloc;
|
||||
}
|
||||
} else {
|
||||
@@ -1939,6 +1940,8 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
dev_dbg(&pdev->dev, "SRAM pool: %zu KiB\n",
|
||||
gen_pool_size(dmadev->sram_pool) / 1024);
|
||||
|
||||
+ dma_set_max_seg_size(&pdev->dev, STM32_DMA_ALIGNED_MAX_DATA_ITEMS);
|
||||
+
|
||||
dma_cap_set(DMA_SLAVE, dd->cap_mask);
|
||||
dma_cap_set(DMA_PRIVATE, dd->cap_mask);
|
||||
dma_cap_set(DMA_CYCLIC, dd->cap_mask);
|
||||
@@ -1959,6 +1962,7 @@ static int stm32_dma_probe(struct platform_device *pdev)
|
||||
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
||||
dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
|
||||
dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
|
||||
+ dd->copy_align = DMAENGINE_ALIGN_32_BYTES;
|
||||
dd->max_burst = STM32_DMA_MAX_BURST;
|
||||
dd->descriptor_reuse = true;
|
||||
dd->dev = &pdev->dev;
|
||||
diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||
index a76d03a..ee7486b 100644
|
||||
--- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||
+++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||
@@ -254,24 +254,12 @@ static int otm8009a_init_sequence(struct otm8009a *ctx)
|
||||
static int otm8009a_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct otm8009a *ctx = panel_to_otm8009a(panel);
|
||||
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
- int ret;
|
||||
|
||||
if (!ctx->enabled)
|
||||
return 0; /* This is not an issue so we return 0 here */
|
||||
|
||||
backlight_disable(ctx->bl_dev);
|
||||
|
||||
- ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- msleep(120);
|
||||
-
|
||||
ctx->enabled = false;
|
||||
|
||||
return 0;
|
||||
@@ -280,16 +268,23 @@ static int otm8009a_disable(struct drm_panel *panel)
|
||||
static int otm8009a_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct otm8009a *ctx = panel_to_otm8009a(panel);
|
||||
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
+ int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
- if (ctx->reset_gpio) {
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
- msleep(20);
|
||||
- }
|
||||
+ ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
- regulator_disable(ctx->supply);
|
||||
+ msleep(10);
|
||||
+
|
||||
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ msleep(120);
|
||||
|
||||
ctx->prepared = false;
|
||||
|
||||
@@ -304,20 +299,6 @@ static int otm8009a_prepare(struct drm_panel *panel)
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
- ret = regulator_enable(ctx->supply);
|
||||
- if (ret < 0) {
|
||||
- DRM_ERROR("failed to enable supply: %d\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- if (ctx->reset_gpio) {
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
- msleep(20);
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
- msleep(100);
|
||||
- }
|
||||
-
|
||||
ret = otm8009a_init_sequence(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -475,6 +456,20 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ ret = regulator_enable(ctx->supply);
|
||||
+ if (ret < 0) {
|
||||
+ DRM_ERROR("failed to enable supply: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (ctx->reset_gpio) {
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
+ msleep(20);
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
+ msleep(100);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -485,6 +480,13 @@ static int otm8009a_remove(struct mipi_dsi_device *dsi)
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
+ if (ctx->reset_gpio) {
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
+ msleep(20);
|
||||
+ }
|
||||
+
|
||||
+ regulator_disable(ctx->supply);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
|
||||
index a373651..7b37f97 100644
|
||||
--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
|
||||
+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
|
||||
@@ -305,6 +305,7 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dw_mipi_dsi_stm *dsi;
|
||||
+ struct clk *pclk;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
@@ -335,23 +336,13 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(dsi->pllref_clk)) {
|
||||
ret = PTR_ERR(dsi->pllref_clk);
|
||||
dev_err(dev, "Unable to get pll reference clock: %d\n", ret);
|
||||
- regulator_disable(dsi->vdd_supply);
|
||||
- return ret;
|
||||
+ goto err_clk_get;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dsi->pllref_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
|
||||
- regulator_disable(dsi->vdd_supply);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
|
||||
- if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {
|
||||
- dev_err(dev, "bad dsi hardware version\n");
|
||||
- clk_disable_unprepare(dsi->pllref_clk);
|
||||
- regulator_disable(dsi->vdd_supply);
|
||||
- return -ENODEV;
|
||||
+ goto err_clk_get;
|
||||
}
|
||||
|
||||
dw_mipi_dsi_stm_plat_data.base = dsi->base;
|
||||
@@ -361,13 +352,43 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||
|
||||
dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data);
|
||||
if (IS_ERR(dsi->dsi)) {
|
||||
+ ret = PTR_ERR(dsi->dsi);
|
||||
DRM_ERROR("Failed to initialize mipi dsi host\n");
|
||||
- regulator_disable(dsi->vdd_supply);
|
||||
- clk_disable_unprepare(dsi->pllref_clk);
|
||||
- return PTR_ERR(dsi->dsi);
|
||||
+ goto err_probe;
|
||||
+ }
|
||||
+
|
||||
+ pclk = devm_clk_get(dev, "pclk");
|
||||
+ if (IS_ERR(pclk)) {
|
||||
+ ret = PTR_ERR(pclk);
|
||||
+ dev_err(dev, "Unable to get peripheral clock: %d\n", ret);
|
||||
+ goto err_probe;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(pclk);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "%s: Failed to enable peripheral clk\n", __func__);
|
||||
+ goto err_probe;
|
||||
+ }
|
||||
+
|
||||
+ dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
|
||||
+ clk_disable_unprepare(pclk);
|
||||
+
|
||||
+ if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {
|
||||
+ ret = -ENODEV;
|
||||
+ dev_err(dev, "bad dsi hardware version\n");
|
||||
+ goto err_probe;
|
||||
}
|
||||
|
||||
return 0;
|
||||
+
|
||||
+err_probe:
|
||||
+ clk_disable_unprepare(dsi->pllref_clk);
|
||||
+
|
||||
+err_clk_get:
|
||||
+ regulator_disable(dsi->vdd_supply);
|
||||
+
|
||||
+ return ret;
|
||||
+
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi_stm_remove(struct platform_device *pdev)
|
||||
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
|
||||
index 1d2be11..1827c25 100644
|
||||
--- a/drivers/remoteproc/stm32_rproc.c
|
||||
+++ b/drivers/remoteproc/stm32_rproc.c
|
||||
@@ -104,10 +104,12 @@ static int stm32_rproc_da_to_pa(struct rproc *rproc, u64 da, phys_addr_t *pa)
|
||||
da >= p_mem->dev_addr + p_mem->size)
|
||||
continue;
|
||||
*pa = da - p_mem->dev_addr + p_mem->bus_addr;
|
||||
- dev_err(rproc->dev.parent, "da %llx to pa %#x\n", da, *pa);
|
||||
+ dev_dbg(rproc->dev.parent, "da %llx to pa %#x\n", da, *pa);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ dev_err(rproc->dev.parent, "can't translate da %llx\n", da);
|
||||
+
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -657,20 +659,21 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev)
|
||||
|
||||
if (of_property_read_bool(np, "early-booted")) {
|
||||
rproc->early_boot = true;
|
||||
-
|
||||
err = of_property_read_u32(np, "rsc-address", &rsc_da);
|
||||
- if (!err) {
|
||||
- err = of_property_read_u32(np, "rsc-size",
|
||||
- &ddata->rsc_len);
|
||||
+ if (err)
|
||||
+ /* no optional rsc table found */
|
||||
+ return 0;
|
||||
|
||||
- if (err) {
|
||||
- dev_err(dev, "resource table size required as address defined\n");
|
||||
- return err;
|
||||
- }
|
||||
+ err = of_property_read_u32(np, "rsc-size", &ddata->rsc_len);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "resource table size required as address defined\n");
|
||||
+ return err;
|
||||
}
|
||||
+
|
||||
err = stm32_rproc_da_to_pa(rproc, rsc_da, &rsc_pa);
|
||||
if (err)
|
||||
return err;
|
||||
+
|
||||
ddata->rsc_va = ioremap_wc(rsc_pa, ddata->rsc_len);
|
||||
if (IS_ERR_OR_NULL(ddata->rsc_va)) {
|
||||
dev_err(dev, "Unable to map memory region: %pa+%zx\n",
|
||||
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
|
||||
index d606eb5..6fc57fc 100644
|
||||
--- a/drivers/tty/serial/stm32-usart.c
|
||||
+++ b/drivers/tty/serial/stm32-usart.c
|
||||
@@ -250,8 +250,16 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded)
|
||||
ofs->icr);
|
||||
port->icount.overrun++;
|
||||
} else if (sr & USART_SR_PE) {
|
||||
+ if (ofs->icr != UNDEF_REG)
|
||||
+ writel_relaxed(USART_ICR_PECF,
|
||||
+ port->membase +
|
||||
+ ofs->icr);
|
||||
port->icount.parity++;
|
||||
} else if (sr & USART_SR_FE) {
|
||||
+ if (ofs->icr != UNDEF_REG)
|
||||
+ writel_relaxed(USART_ICR_FECF,
|
||||
+ port->membase +
|
||||
+ ofs->icr);
|
||||
port->icount.frame++;
|
||||
}
|
||||
|
||||
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
|
||||
index f1f5c1c..53d7e7b 100644
|
||||
--- a/drivers/tty/serial/stm32-usart.h
|
||||
+++ b/drivers/tty/serial/stm32-usart.h
|
||||
@@ -241,7 +241,7 @@ struct stm32_usart_info stm32h7_info = {
|
||||
|
||||
/* USART_ICR */
|
||||
#define USART_ICR_PECF BIT(0) /* F7 */
|
||||
-#define USART_ICR_FFECF BIT(1) /* F7 */
|
||||
+#define USART_ICR_FECF BIT(1) /* F7 */
|
||||
#define USART_ICR_NCF BIT(2) /* F7 */
|
||||
#define USART_ICR_ORECF BIT(3) /* F7 */
|
||||
#define USART_ICR_IDLECF BIT(4) /* F7 */
|
||||
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
|
||||
index 4c1736f..3d8fa58 100644
|
||||
--- a/drivers/usb/dwc2/core.h
|
||||
+++ b/drivers/usb/dwc2/core.h
|
||||
@@ -393,6 +393,20 @@ enum dwc2_ep0_state {
|
||||
* 0 - No
|
||||
* 1 - Yes
|
||||
* @hird_threshold: Value of BESL or HIRD Threshold.
|
||||
+ * @ref_clk_per: Indicates in terms of pico seconds the period
|
||||
+ * of ref_clk.
|
||||
+ * 62500 - 16MHz
|
||||
+ * 58823 - 17MHz
|
||||
+ * 52083 - 19.2MHz
|
||||
+ * 50000 - 20MHz
|
||||
+ * 41666 - 24MHz
|
||||
+ * 33333 - 30MHz (default)
|
||||
+ * 25000 - 40MHz
|
||||
+ * @sof_cnt_wkup_alert: Indicates in term of number of SOF's after which
|
||||
+ * the controller should generate an interrupt if the
|
||||
+ * device had been in L1 state until that period.
|
||||
+ * This is used by SW to initiate Remote WakeUp in the
|
||||
+ * controller so as to sync to the uF number from the host.
|
||||
* @activate_stm_fs_transceiver: Activate internal transceiver using GGPIO
|
||||
* register.
|
||||
* 0 - Deactivate the transceiver (default)
|
||||
@@ -426,6 +440,9 @@ enum dwc2_ep0_state {
|
||||
* back to DWC2_SPEED_PARAM_HIGH while device is gone.
|
||||
* 0 - No (default)
|
||||
* 1 - Yes
|
||||
+ * @service_interval: Enable service interval based scheduling.
|
||||
+ * 0 - No
|
||||
+ * 1 - Yes
|
||||
*
|
||||
* The following parameters may be specified when starting the module. These
|
||||
* parameters define how the DWC_otg controller should be configured. A
|
||||
@@ -471,6 +488,7 @@ struct dwc2_core_params {
|
||||
bool lpm_clock_gating;
|
||||
bool besl;
|
||||
bool hird_threshold_en;
|
||||
+ bool service_interval;
|
||||
u8 hird_threshold;
|
||||
bool activate_stm_fs_transceiver;
|
||||
bool activate_stm_id_vb_detection;
|
||||
@@ -479,6 +497,10 @@ struct dwc2_core_params {
|
||||
u32 max_transfer_size;
|
||||
u32 ahbcfg;
|
||||
|
||||
+ /* GREFCLK parameters */
|
||||
+ u32 ref_clk_per;
|
||||
+ u16 sof_cnt_wkup_alert;
|
||||
+
|
||||
/* Host parameters */
|
||||
bool host_dma;
|
||||
bool dma_desc_enable;
|
||||
@@ -618,6 +640,10 @@ struct dwc2_core_params {
|
||||
* FIFO sizing is enabled 16 to 32768
|
||||
* Actual maximum value is autodetected and also
|
||||
* the default.
|
||||
+ * @service_interval_mode: For enabling service interval based scheduling in the
|
||||
+ * controller.
|
||||
+ * 0 - Disable
|
||||
+ * 1 - Enable
|
||||
*/
|
||||
struct dwc2_hw_params {
|
||||
unsigned op_mode:3;
|
||||
@@ -648,6 +674,7 @@ struct dwc2_hw_params {
|
||||
unsigned utmi_phy_data_width:2;
|
||||
unsigned lpm_mode:1;
|
||||
unsigned ipg_isoc_en:1;
|
||||
+ unsigned service_interval_mode:1;
|
||||
u32 snpsid;
|
||||
u32 dev_ep_dirs;
|
||||
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
|
||||
@@ -1372,6 +1399,7 @@ int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg);
|
||||
int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
|
||||
int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
|
||||
void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg);
|
||||
+void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg);
|
||||
#else
|
||||
static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
|
||||
{ return 0; }
|
||||
@@ -1406,6 +1434,7 @@ static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
||||
static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
|
||||
{ return 0; }
|
||||
static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {}
|
||||
+static inline void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) {}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
|
||||
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c
|
||||
index 22d015b..7f62f4c 100644
|
||||
--- a/drivers/usb/dwc2/debugfs.c
|
||||
+++ b/drivers/usb/dwc2/debugfs.c
|
||||
@@ -701,6 +701,7 @@ static int params_show(struct seq_file *seq, void *v)
|
||||
print_param(seq, p, besl);
|
||||
print_param(seq, p, hird_threshold_en);
|
||||
print_param(seq, p, hird_threshold);
|
||||
+ print_param(seq, p, service_interval);
|
||||
print_param(seq, p, host_dma);
|
||||
print_param(seq, p, g_dma);
|
||||
print_param(seq, p, g_dma_desc);
|
||||
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
|
||||
index 220c0f9..55ef3cc 100644
|
||||
--- a/drivers/usb/dwc2/gadget.c
|
||||
+++ b/drivers/usb/dwc2/gadget.c
|
||||
@@ -123,6 +123,24 @@ static inline void dwc2_gadget_incr_frame_num(struct dwc2_hsotg_ep *hs_ep)
|
||||
}
|
||||
|
||||
/**
|
||||
+ * dwc2_gadget_dec_frame_num_by_one - Decrements the targeted frame number
|
||||
+ * by one.
|
||||
+ * @hs_ep: The endpoint.
|
||||
+ *
|
||||
+ * This function used in service interval based scheduling flow to calculate
|
||||
+ * descriptor frame number filed value. For service interval mode frame
|
||||
+ * number in descriptor should point to last (u)frame in the interval.
|
||||
+ *
|
||||
+ */
|
||||
+static inline void dwc2_gadget_dec_frame_num_by_one(struct dwc2_hsotg_ep *hs_ep)
|
||||
+{
|
||||
+ if (hs_ep->target_frame)
|
||||
+ hs_ep->target_frame -= 1;
|
||||
+ else
|
||||
+ hs_ep->target_frame = DSTS_SOFFN_LIMIT;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* dwc2_hsotg_en_gsint - enable one or more of the general interrupt
|
||||
* @hsotg: The device state
|
||||
* @ints: A bitmask of the interrupts to enable
|
||||
@@ -228,6 +246,27 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
||||
}
|
||||
|
||||
/**
|
||||
+ * dwc2_gadget_wkup_alert_handler - Handler for WKUP_ALERT interrupt
|
||||
+ *
|
||||
+ * @hsotg: Programming view of the DWC_otg controller
|
||||
+ *
|
||||
+ */
|
||||
+static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg)
|
||||
+{
|
||||
+ u32 gintsts2;
|
||||
+ u32 gintmsk2;
|
||||
+
|
||||
+ gintsts2 = dwc2_readl(hsotg, GINTSTS2);
|
||||
+ gintmsk2 = dwc2_readl(hsotg, GINTMSK2);
|
||||
+
|
||||
+ if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) {
|
||||
+ dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__);
|
||||
+ dwc2_set_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
|
||||
+ dwc2_set_bit(hsotg, DCTL, DCTL_RMTWKUPSIG);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode
|
||||
* TX FIFOs
|
||||
*
|
||||
@@ -2812,6 +2851,23 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)
|
||||
if (using_desc_dma(hsotg)) {
|
||||
hs_ep->target_frame = hsotg->frame_number;
|
||||
dwc2_gadget_incr_frame_num(hs_ep);
|
||||
+
|
||||
+ /* In service interval mode target_frame must
|
||||
+ * be set to last (u)frame of the service interval.
|
||||
+ */
|
||||
+ if (hsotg->params.service_interval) {
|
||||
+ /* Set target_frame to the first (u)frame of
|
||||
+ * the service interval
|
||||
+ */
|
||||
+ hs_ep->target_frame &= ~hs_ep->interval + 1;
|
||||
+
|
||||
+ /* Set target_frame to the last (u)frame of
|
||||
+ * the service interval
|
||||
+ */
|
||||
+ dwc2_gadget_incr_frame_num(hs_ep);
|
||||
+ dwc2_gadget_dec_frame_num_by_one(hs_ep);
|
||||
+ }
|
||||
+
|
||||
dwc2_gadget_start_isoc_ddma(hs_ep);
|
||||
return;
|
||||
}
|
||||
@@ -3127,6 +3183,7 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
|
||||
hsotg->connected = 0;
|
||||
hsotg->test_mode = 0;
|
||||
|
||||
+ /* all endpoints should be shutdown */
|
||||
for (ep = 0; ep < hsotg->num_of_eps; ep++) {
|
||||
if (hsotg->eps_in[ep])
|
||||
kill_all_requests(hsotg, hsotg->eps_in[ep],
|
||||
@@ -3177,6 +3234,7 @@ static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
|
||||
GINTSTS_PTXFEMP | \
|
||||
GINTSTS_RXFLVL)
|
||||
|
||||
+static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
|
||||
/**
|
||||
* dwc2_hsotg_core_init - issue softreset to the core
|
||||
* @hsotg: The device state
|
||||
@@ -3191,13 +3249,23 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
||||
u32 val;
|
||||
u32 usbcfg;
|
||||
u32 dcfg = 0;
|
||||
+ int ep;
|
||||
|
||||
/* Kill any ep0 requests as controller will be reinitialized */
|
||||
kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
|
||||
|
||||
- if (!is_usb_reset)
|
||||
+ if (!is_usb_reset) {
|
||||
if (dwc2_core_reset(hsotg, true))
|
||||
return;
|
||||
+ } else {
|
||||
+ /* all endpoints should be shutdown */
|
||||
+ for (ep = 1; ep < hsotg->num_of_eps; ep++) {
|
||||
+ if (hsotg->eps_in[ep])
|
||||
+ dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
|
||||
+ if (hsotg->eps_out[ep])
|
||||
+ dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/*
|
||||
* we must now enable ep0 ready for host detection and then
|
||||
@@ -3312,6 +3380,10 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
||||
dwc2_set_bit(hsotg, DIEPMSK, DIEPMSK_BNAININTRMSK);
|
||||
}
|
||||
|
||||
+ /* Enable Service Interval mode if supported */
|
||||
+ if (using_desc_dma(hsotg) && hsotg->params.service_interval)
|
||||
+ dwc2_set_bit(hsotg, DCTL, DCTL_SERVICE_INTERVAL_SUPPORTED);
|
||||
+
|
||||
dwc2_writel(hsotg, 0, DAINTMSK);
|
||||
|
||||
dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
|
||||
@@ -3368,6 +3440,10 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
||||
/* configure the core to support LPM */
|
||||
dwc2_gadget_init_lpm(hsotg);
|
||||
|
||||
+ /* program GREFCLK register if needed */
|
||||
+ if (using_desc_dma(hsotg) && hsotg->params.service_interval)
|
||||
+ dwc2_gadget_program_ref_clk(hsotg);
|
||||
+
|
||||
/* must be at-least 3ms to allow bus to see disconnect */
|
||||
mdelay(3);
|
||||
|
||||
@@ -3676,6 +3752,10 @@ static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
|
||||
if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
|
||||
goto irq_retry;
|
||||
|
||||
+ /* Check WKUP_ALERT interrupt*/
|
||||
+ if (hsotg->params.service_interval)
|
||||
+ dwc2_gadget_wkup_alert_handler(hsotg);
|
||||
+
|
||||
spin_unlock(&hsotg->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@@ -3990,7 +4070,6 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
|
||||
struct dwc2_hsotg *hsotg = hs_ep->parent;
|
||||
int dir_in = hs_ep->dir_in;
|
||||
int index = hs_ep->index;
|
||||
- unsigned long flags;
|
||||
u32 epctrl_reg;
|
||||
u32 ctrl;
|
||||
|
||||
@@ -4008,8 +4087,6 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
|
||||
|
||||
epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
|
||||
|
||||
- spin_lock_irqsave(&hsotg->lock, flags);
|
||||
-
|
||||
ctrl = dwc2_readl(hsotg, epctrl_reg);
|
||||
|
||||
if (ctrl & DXEPCTL_EPENA)
|
||||
@@ -4032,10 +4109,22 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
|
||||
hs_ep->fifo_index = 0;
|
||||
hs_ep->fifo_size = 0;
|
||||
|
||||
- spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int dwc2_hsotg_ep_disable_lock(struct usb_ep *ep)
|
||||
+{
|
||||
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
|
||||
+ struct dwc2_hsotg *hsotg = hs_ep->parent;
|
||||
+ unsigned long flags;
|
||||
+ int ret;
|
||||
+
|
||||
+ spin_lock_irqsave(&hsotg->lock, flags);
|
||||
+ ret = dwc2_hsotg_ep_disable(ep);
|
||||
+ spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* on_list - check request is on the given endpoint
|
||||
* @ep: The endpoint to check.
|
||||
@@ -4183,7 +4272,7 @@ static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
|
||||
|
||||
static const struct usb_ep_ops dwc2_hsotg_ep_ops = {
|
||||
.enable = dwc2_hsotg_ep_enable,
|
||||
- .disable = dwc2_hsotg_ep_disable,
|
||||
+ .disable = dwc2_hsotg_ep_disable_lock,
|
||||
.alloc_request = dwc2_hsotg_ep_alloc_request,
|
||||
.free_request = dwc2_hsotg_ep_free_request,
|
||||
.queue = dwc2_hsotg_ep_queue_lock,
|
||||
@@ -4323,9 +4412,9 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
|
||||
/* all endpoints should be shutdown */
|
||||
for (ep = 1; ep < hsotg->num_of_eps; ep++) {
|
||||
if (hsotg->eps_in[ep])
|
||||
- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
|
||||
+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
|
||||
if (hsotg->eps_out[ep])
|
||||
- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
|
||||
+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&hsotg->lock, flags);
|
||||
@@ -4773,9 +4862,9 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg)
|
||||
|
||||
for (ep = 0; ep < hsotg->num_of_eps; ep++) {
|
||||
if (hsotg->eps_in[ep])
|
||||
- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
|
||||
+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
|
||||
if (hsotg->eps_out[ep])
|
||||
- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
|
||||
+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4942,8 +5031,32 @@ void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg)
|
||||
val |= hsotg->params.lpm_clock_gating ? GLPMCFG_ENBLSLPM : 0;
|
||||
val |= hsotg->params.hird_threshold << GLPMCFG_HIRD_THRES_SHIFT;
|
||||
val |= hsotg->params.besl ? GLPMCFG_ENBESL : 0;
|
||||
+ val |= GLPMCFG_LPM_ACCEPT_CTRL_ISOC;
|
||||
dwc2_writel(hsotg, val, GLPMCFG);
|
||||
dev_dbg(hsotg->dev, "GLPMCFG=0x%08x\n", dwc2_readl(hsotg, GLPMCFG));
|
||||
+
|
||||
+ /* Unmask WKUP_ALERT Interrupt */
|
||||
+ if (hsotg->params.service_interval)
|
||||
+ dwc2_set_bit(hsotg, GINTMSK2, GINTMSK2_WKUP_ALERT_INT_MSK);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * dwc2_gadget_program_ref_clk - Program GREFCLK register in device mode
|
||||
+ *
|
||||
+ * @hsotg: Programming view of DWC_otg controller
|
||||
+ *
|
||||
+ */
|
||||
+void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg)
|
||||
+{
|
||||
+ u32 val = 0;
|
||||
+
|
||||
+ val |= GREFCLK_REF_CLK_MODE;
|
||||
+ val |= hsotg->params.ref_clk_per << GREFCLK_REFCLKPER_SHIFT;
|
||||
+ val |= hsotg->params.sof_cnt_wkup_alert <<
|
||||
+ GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT;
|
||||
+
|
||||
+ dwc2_writel(hsotg, val, GREFCLK);
|
||||
+ dev_dbg(hsotg->dev, "GREFCLK=0x%08x\n", dwc2_readl(hsotg, GREFCLK));
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
|
||||
index 12fa6c0..7f128b1 100644
|
||||
--- a/drivers/usb/dwc2/hcd.c
|
||||
+++ b/drivers/usb/dwc2/hcd.c
|
||||
@@ -1309,14 +1309,11 @@ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg,
|
||||
u32 remaining_count;
|
||||
u32 byte_count;
|
||||
u32 dword_count;
|
||||
- u32 __iomem *data_fifo;
|
||||
u32 *data_buf = (u32 *)chan->xfer_buf;
|
||||
|
||||
if (dbg_hc(chan))
|
||||
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||
|
||||
- data_fifo = (u32 __iomem *)(hsotg->regs + HCFIFO(chan->hc_num));
|
||||
-
|
||||
remaining_count = chan->xfer_len - chan->xfer_count;
|
||||
if (remaining_count > chan->max_packet)
|
||||
byte_count = chan->max_packet;
|
||||
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h
|
||||
index 3f9bccc..c089ffa 100644
|
||||
--- a/drivers/usb/dwc2/hcd.h
|
||||
+++ b/drivers/usb/dwc2/hcd.h
|
||||
@@ -366,7 +366,7 @@ struct dwc2_qh {
|
||||
u32 desc_list_sz;
|
||||
u32 *n_bytes;
|
||||
struct timer_list unreserve_timer;
|
||||
- struct timer_list wait_timer;
|
||||
+ struct hrtimer wait_timer;
|
||||
struct dwc2_tt *dwc_tt;
|
||||
int ttport;
|
||||
unsigned tt_buffer_dirty:1;
|
||||
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
|
||||
index 40839591..ea3aa64 100644
|
||||
--- a/drivers/usb/dwc2/hcd_queue.c
|
||||
+++ b/drivers/usb/dwc2/hcd_queue.c
|
||||
@@ -59,7 +59,7 @@
|
||||
#define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5))
|
||||
|
||||
/* If we get a NAK, wait this long before retrying */
|
||||
-#define DWC2_RETRY_WAIT_DELAY (msecs_to_jiffies(1))
|
||||
+#define DWC2_RETRY_WAIT_DELAY 1*1E6L
|
||||
|
||||
/**
|
||||
* dwc2_periodic_channel_available() - Checks that a channel is available for a
|
||||
@@ -1464,10 +1464,12 @@ static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg,
|
||||
* qh back to the "inactive" list, then queues transactions.
|
||||
*
|
||||
* @t: Pointer to wait_timer in a qh.
|
||||
+ *
|
||||
+ * Return: HRTIMER_NORESTART to not automatically restart this timer.
|
||||
*/
|
||||
-static void dwc2_wait_timer_fn(struct timer_list *t)
|
||||
+static enum hrtimer_restart dwc2_wait_timer_fn(struct hrtimer *t)
|
||||
{
|
||||
- struct dwc2_qh *qh = from_timer(qh, t, wait_timer);
|
||||
+ struct dwc2_qh *qh = container_of(t, struct dwc2_qh, wait_timer);
|
||||
struct dwc2_hsotg *hsotg = qh->hsotg;
|
||||
unsigned long flags;
|
||||
|
||||
@@ -1491,6 +1493,7 @@ static void dwc2_wait_timer_fn(struct timer_list *t)
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
+ return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1521,7 +1524,8 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
|
||||
/* Initialize QH */
|
||||
qh->hsotg = hsotg;
|
||||
timer_setup(&qh->unreserve_timer, dwc2_unreserve_timer_fn, 0);
|
||||
- timer_setup(&qh->wait_timer, dwc2_wait_timer_fn, 0);
|
||||
+ hrtimer_init(&qh->wait_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
+ qh->wait_timer.function = &dwc2_wait_timer_fn;
|
||||
qh->ep_type = ep_type;
|
||||
qh->ep_is_in = ep_is_in;
|
||||
|
||||
@@ -1690,7 +1694,7 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||
* won't do anything anyway, but we want it to finish before we free
|
||||
* memory.
|
||||
*/
|
||||
- del_timer_sync(&qh->wait_timer);
|
||||
+ hrtimer_cancel(&qh->wait_timer);
|
||||
|
||||
dwc2_host_put_tt_info(hsotg, qh->dwc_tt);
|
||||
|
||||
@@ -1716,6 +1720,7 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||
{
|
||||
int status;
|
||||
u32 intr_mask;
|
||||
+ ktime_t delay;
|
||||
|
||||
if (dbg_qh(qh))
|
||||
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||
@@ -1734,8 +1739,8 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||
list_add_tail(&qh->qh_list_entry,
|
||||
&hsotg->non_periodic_sched_waiting);
|
||||
qh->wait_timer_cancel = false;
|
||||
- mod_timer(&qh->wait_timer,
|
||||
- jiffies + DWC2_RETRY_WAIT_DELAY + 1);
|
||||
+ delay = ktime_set(0, DWC2_RETRY_WAIT_DELAY);
|
||||
+ hrtimer_start(&qh->wait_timer, delay, HRTIMER_MODE_REL);
|
||||
} else {
|
||||
list_add_tail(&qh->qh_list_entry,
|
||||
&hsotg->non_periodic_sched_inactive);
|
||||
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
|
||||
index 31f8c60..4980ecb 100644
|
||||
--- a/drivers/usb/dwc2/hw.h
|
||||
+++ b/drivers/usb/dwc2/hw.h
|
||||
@@ -316,6 +316,7 @@
|
||||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14
|
||||
#define GHWCFG4_ACG_SUPPORTED BIT(12)
|
||||
#define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11)
|
||||
+#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED BIT(10)
|
||||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0
|
||||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1
|
||||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2
|
||||
@@ -336,6 +337,8 @@
|
||||
#define GLPMCFG_SNDLPM BIT(24)
|
||||
#define GLPMCFG_RETRY_CNT_MASK (0x7 << 21)
|
||||
#define GLPMCFG_RETRY_CNT_SHIFT 21
|
||||
+#define GLPMCFG_LPM_ACCEPT_CTRL_CONTROL BIT(21)
|
||||
+#define GLPMCFG_LPM_ACCEPT_CTRL_ISOC BIT(22)
|
||||
#define GLPMCFG_LPM_CHNL_INDX_MASK (0xf << 17)
|
||||
#define GLPMCFG_LPM_CHNL_INDX_SHIFT 17
|
||||
#define GLPMCFG_L1RESUMEOK BIT(16)
|
||||
@@ -408,6 +411,19 @@
|
||||
#define ADPCTL_PRB_DSCHRG_MASK (0x3 << 0)
|
||||
#define ADPCTL_PRB_DSCHRG_SHIFT 0
|
||||
|
||||
+#define GREFCLK HSOTG_REG(0x0064)
|
||||
+#define GREFCLK_REFCLKPER_MASK (0x1ffff << 15)
|
||||
+#define GREFCLK_REFCLKPER_SHIFT 15
|
||||
+#define GREFCLK_REF_CLK_MODE BIT(14)
|
||||
+#define GREFCLK_SOF_CNT_WKUP_ALERT_MASK (0x3ff)
|
||||
+#define GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT 0
|
||||
+
|
||||
+#define GINTMSK2 HSOTG_REG(0x0068)
|
||||
+#define GINTMSK2_WKUP_ALERT_INT_MSK BIT(0)
|
||||
+
|
||||
+#define GINTSTS2 HSOTG_REG(0x006c)
|
||||
+#define GINTSTS2_WKUP_ALERT_INT BIT(0)
|
||||
+
|
||||
#define HPTXFSIZ HSOTG_REG(0x100)
|
||||
/* Use FIFOSIZE_* constants to access this register */
|
||||
|
||||
@@ -447,6 +463,7 @@
|
||||
#define DCFG_DEVSPD_FS48 3
|
||||
|
||||
#define DCTL HSOTG_REG(0x804)
|
||||
+#define DCTL_SERVICE_INTERVAL_SUPPORTED BIT(19)
|
||||
#define DCTL_PWRONPRGDONE BIT(11)
|
||||
#define DCTL_CGOUTNAK BIT(10)
|
||||
#define DCTL_SGOUTNAK BIT(9)
|
||||
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
|
||||
index 7fef905..bdcabb1 100644
|
||||
--- a/drivers/usb/dwc2/params.c
|
||||
+++ b/drivers/usb/dwc2/params.c
|
||||
@@ -71,6 +71,13 @@ static void dwc2_set_his_params(struct dwc2_hsotg *hsotg)
|
||||
p->power_down = false;
|
||||
}
|
||||
|
||||
+static void dwc2_set_s3c6400_params(struct dwc2_hsotg *hsotg)
|
||||
+{
|
||||
+ struct dwc2_core_params *p = &hsotg->params;
|
||||
+
|
||||
+ p->power_down = 0;
|
||||
+}
|
||||
+
|
||||
static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
@@ -81,6 +88,7 @@ static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg)
|
||||
p->host_perio_tx_fifo_size = 256;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
|
||||
GAHBCFG_HBSTLEN_SHIFT;
|
||||
+ p->power_down = 0;
|
||||
}
|
||||
|
||||
static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg)
|
||||
@@ -110,6 +118,7 @@ static void dwc2_set_amlogic_params(struct dwc2_hsotg *hsotg)
|
||||
p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR8 <<
|
||||
GAHBCFG_HBSTLEN_SHIFT;
|
||||
+ p->power_down = DWC2_POWER_DOWN_PARAM_NONE;
|
||||
}
|
||||
|
||||
static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg)
|
||||
@@ -177,7 +186,8 @@ const struct of_device_id dwc2_of_match_table[] = {
|
||||
{ .compatible = "lantiq,arx100-usb", .data = dwc2_set_ltq_params },
|
||||
{ .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params },
|
||||
{ .compatible = "snps,dwc2" },
|
||||
- { .compatible = "samsung,s3c6400-hsotg" },
|
||||
+ { .compatible = "samsung,s3c6400-hsotg",
|
||||
+ .data = dwc2_set_s3c6400_params },
|
||||
{ .compatible = "amlogic,meson8-usb",
|
||||
.data = dwc2_set_amlogic_params },
|
||||
{ .compatible = "amlogic,meson8b-usb",
|
||||
@@ -330,9 +340,12 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg)
|
||||
p->hird_threshold_en = true;
|
||||
p->hird_threshold = 4;
|
||||
p->ipg_isoc_en = false;
|
||||
+ p->service_interval = false;
|
||||
p->max_packet_count = hw->max_packet_count;
|
||||
p->max_transfer_size = hw->max_transfer_size;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR << GAHBCFG_HBSTLEN_SHIFT;
|
||||
+ p->ref_clk_per = 33333;
|
||||
+ p->sof_cnt_wkup_alert = 100;
|
||||
|
||||
if ((hsotg->dr_mode == USB_DR_MODE_HOST) ||
|
||||
(hsotg->dr_mode == USB_DR_MODE_OTG)) {
|
||||
@@ -628,6 +641,7 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg)
|
||||
CHECK_BOOL(besl, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a));
|
||||
CHECK_BOOL(hird_threshold_en, hsotg->params.lpm);
|
||||
CHECK_RANGE(hird_threshold, 0, hsotg->params.besl ? 12 : 7, 0);
|
||||
+ CHECK_BOOL(service_interval, hw->service_interval_mode);
|
||||
CHECK_RANGE(max_packet_count,
|
||||
15, hw->max_packet_count,
|
||||
hw->max_packet_count);
|
||||
@@ -816,6 +830,8 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
||||
GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT;
|
||||
hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED);
|
||||
hw->ipg_isoc_en = !!(hwcfg4 & GHWCFG4_IPG_ISOC_SUPPORTED);
|
||||
+ hw->service_interval_mode = !!(hwcfg4 &
|
||||
+ GHWCFG4_SERVICE_INTERVAL_SUPPORTED);
|
||||
|
||||
/* fifo sizes */
|
||||
hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >>
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
From 56b9c52ec61df693bd997e3ef1465230a6cb1834 Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Thu, 24 Jan 2019 10:52:11 +0100
|
||||
Subject: [PATCH 60/60] ARM stm32mp1 r0 rc4 hotfix w904.3 DEVICETREE
|
||||
|
||||
---
|
||||
arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 43 +++++++++++++++++++++++++++++++
|
||||
arch/arm/boot/dts/stm32mp157a-dk1.dts | 2 +-
|
||||
arch/arm/boot/dts/stm32mp157c-dk2.dts | 4 +--
|
||||
arch/arm/boot/dts/stm32mp157c-ed1.dts | 2 +-
|
||||
arch/arm/boot/dts/stm32mp157c.dtsi | 22 +++++++---------
|
||||
5 files changed, 57 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||
index 474e7e3..6e4e5c9 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
|
||||
@@ -1249,6 +1249,49 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ sdmmc2_b4_pins_b: sdmmc2-b4-1 {
|
||||
+ pins1 {
|
||||
+ pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
|
||||
+ <STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
|
||||
+ <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
|
||||
+ <STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
|
||||
+ <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
|
||||
+ slew-rate = <1>;
|
||||
+ drive-push-pull;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ pins2 {
|
||||
+ pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
|
||||
+ slew-rate = <2>;
|
||||
+ drive-push-pull;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 {
|
||||
+ pins1 {
|
||||
+ pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
|
||||
+ <STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
|
||||
+ <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
|
||||
+ <STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
|
||||
+ slew-rate = <1>;
|
||||
+ drive-push-pull;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ pins2 {
|
||||
+ pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
|
||||
+ slew-rate = <2>;
|
||||
+ drive-push-pull;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ pins3 {
|
||||
+ pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
|
||||
+ slew-rate = <1>;
|
||||
+ drive-open-drain;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
sdmmc2_d47_pins_a: sdmmc2-d47-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
index 467c226..e3a36d3 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
|
||||
@@ -325,7 +325,7 @@
|
||||
|
||||
vddcore: buck1 {
|
||||
regulator-name = "vddcore";
|
||||
- regulator-min-microvolt = <800000>;
|
||||
+ regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
regulator-initial-mode = <0>;
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||
index 4da15cd..20a86f1 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts
|
||||
@@ -108,8 +108,8 @@
|
||||
&sdmmc2 {
|
||||
arm,primecell-periphid = <0x10153180>;
|
||||
pinctrl-names = "default", "opendrain", "sleep";
|
||||
- pinctrl-0 = <&sdmmc2_b4_pins_a>;
|
||||
- pinctrl-1 = <&sdmmc2_b4_od_pins_a>;
|
||||
+ pinctrl-0 = <&sdmmc2_b4_pins_b>;
|
||||
+ pinctrl-1 = <&sdmmc2_b4_od_pins_b>;
|
||||
pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>;
|
||||
non-removable;
|
||||
st,neg-edge;
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||
index 6d49f21..780c992 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
|
||||
@@ -203,7 +203,7 @@
|
||||
|
||||
vddcore: buck1 {
|
||||
regulator-name = "vddcore";
|
||||
- regulator-min-microvolt = <800000>;
|
||||
+ regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
regulator-initial-mode = <0>;
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
index b09ef8b..694e6e0 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
@@ -430,8 +430,8 @@
|
||||
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI2_K>;
|
||||
resets = <&rcc SPI2_R>;
|
||||
- dmas = <&dmamux1 39 0x400 0x05>,
|
||||
- <&dmamux1 40 0x400 0x05>;
|
||||
+ dmas = <&dmamux1 39 0x400 0x01>,
|
||||
+ <&dmamux1 40 0x400 0x01>;
|
||||
dma-names = "rx", "tx";
|
||||
power-domains = <&pd_core>;
|
||||
status = "disabled";
|
||||
@@ -456,8 +456,8 @@
|
||||
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI3_K>;
|
||||
resets = <&rcc SPI3_R>;
|
||||
- dmas = <&dmamux1 61 0x400 0x05>,
|
||||
- <&dmamux1 62 0x400 0x05>;
|
||||
+ dmas = <&dmamux1 61 0x400 0x01>,
|
||||
+ <&dmamux1 62 0x400 0x01>;
|
||||
dma-names = "rx", "tx";
|
||||
power-domains = <&pd_core>;
|
||||
status = "disabled";
|
||||
@@ -756,8 +756,8 @@
|
||||
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI1_K>;
|
||||
resets = <&rcc SPI1_R>;
|
||||
- dmas = <&dmamux1 37 0x400 0x05>,
|
||||
- <&dmamux1 38 0x400 0x05>;
|
||||
+ dmas = <&dmamux1 37 0x400 0x01>,
|
||||
+ <&dmamux1 38 0x400 0x01>;
|
||||
dma-names = "rx", "tx";
|
||||
power-domains = <&pd_core>;
|
||||
status = "disabled";
|
||||
@@ -782,8 +782,8 @@
|
||||
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI4_K>;
|
||||
resets = <&rcc SPI4_R>;
|
||||
- dmas = <&dmamux1 83 0x400 0x05>,
|
||||
- <&dmamux1 84 0x400 0x05>;
|
||||
+ dmas = <&dmamux1 83 0x400 0x01>,
|
||||
+ <&dmamux1 84 0x400 0x01>;
|
||||
dma-names = "rx", "tx";
|
||||
power-domains = <&pd_core>;
|
||||
status = "disabled";
|
||||
@@ -870,8 +870,8 @@
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI5_K>;
|
||||
resets = <&rcc SPI5_R>;
|
||||
- dmas = <&dmamux1 85 0x400 0x05>,
|
||||
- <&dmamux1 86 0x400 0x05>;
|
||||
+ dmas = <&dmamux1 85 0x400 0x01>,
|
||||
+ <&dmamux1 86 0x400 0x01>;
|
||||
dma-names = "rx", "tx";
|
||||
power-domains = <&pd_core>;
|
||||
status = "disabled";
|
||||
@@ -1770,7 +1770,6 @@
|
||||
clocks = <&rcc USBH>;
|
||||
resets = <&rcc USBH_R>;
|
||||
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
||||
- power-domains = <&pd_core>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -1781,7 +1780,6 @@
|
||||
resets = <&rcc USBH_R>;
|
||||
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
|
||||
companion = <&usbh_ohci>;
|
||||
- power-domains = <&pd_core>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
From 5f558583046192d07b1718d6db15cef522fa0bce Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Mon, 28 Jan 2019 10:49:20 +0100
|
||||
Subject: [PATCH 61/62] ARM stm32mp1 r0 rc4 hotfix w904.5 DRIVERS
|
||||
|
||||
---
|
||||
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c | 38 ++++++++++++++----------
|
||||
drivers/usb/dwc2/platform.c | 13 ++++++--
|
||||
2 files changed, 33 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||
index ee7486b..78a7e62 100644
|
||||
--- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||
+++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
|
||||
@@ -284,7 +284,9 @@ static int otm8009a_unprepare(struct drm_panel *panel)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- msleep(120);
|
||||
+ msleep(10);
|
||||
+
|
||||
+ regulator_disable(ctx->supply);
|
||||
|
||||
ctx->prepared = false;
|
||||
|
||||
@@ -299,6 +301,26 @@ static int otm8009a_prepare(struct drm_panel *panel)
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
+ if (ctx->reset_gpio) {
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
+ }
|
||||
+
|
||||
+ msleep(20);
|
||||
+
|
||||
+ ret = regulator_enable(ctx->supply);
|
||||
+ if (ret < 0) {
|
||||
+ DRM_ERROR("failed to enable supply: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ msleep(120);
|
||||
+
|
||||
+ if (ctx->reset_gpio) {
|
||||
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
+ msleep(20);
|
||||
+ }
|
||||
+
|
||||
ret = otm8009a_init_sequence(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -456,20 +478,6 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ret = regulator_enable(ctx->supply);
|
||||
- if (ret < 0) {
|
||||
- DRM_ERROR("failed to enable supply: %d\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- if (ctx->reset_gpio) {
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
- msleep(20);
|
||||
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
- msleep(100);
|
||||
- }
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
|
||||
index b2e5ddc..b80d046 100644
|
||||
--- a/drivers/usb/dwc2/platform.c
|
||||
+++ b/drivers/usb/dwc2/platform.c
|
||||
@@ -568,13 +568,17 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
- if (dwc2_is_device_mode(dwc2))
|
||||
- dwc2_hsotg_suspend(dwc2);
|
||||
-
|
||||
if (dwc2->params.activate_stm_id_vb_detection &&
|
||||
!dwc2->params.force_b_session_valid) {
|
||||
u32 ggpio;
|
||||
|
||||
+ /*
|
||||
+ * Need to force the mode to the current mode to avoid Mode
|
||||
+ * Mismatch Interrupt when ID and VBUS detection will be
|
||||
+ * disabled
|
||||
+ */
|
||||
+ dwc2_force_mode(dwc2, dwc2_is_host_mode(dwc2));
|
||||
+
|
||||
ggpio = dwc2_readl(dwc2, GGPIO);
|
||||
ggpio &= ~GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||
ggpio &= ~GGPIO_STM32_OTG_GCCFG_VBDEN;
|
||||
@@ -583,6 +587,9 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||
regulator_disable(dwc2->usb33d);
|
||||
}
|
||||
|
||||
+ if (dwc2_is_device_mode(dwc2))
|
||||
+ dwc2_hsotg_suspend(dwc2);
|
||||
+
|
||||
if (dwc2->ll_hw_enabled)
|
||||
ret = __dwc2_lowlevel_hw_disable(dwc2);
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
From 771fc61468f4af9f733beb9dbe070033ea2b826a Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Mon, 28 Jan 2019 10:49:58 +0100
|
||||
Subject: [PATCH 62/62] ARM stm32mp1 r0 rc4 hotfix w904.5 DEVICETREE
|
||||
|
||||
---
|
||||
arch/arm/boot/dts/stm32mp157c.dtsi | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
index 694e6e0..9647119 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
@@ -1233,7 +1233,6 @@
|
||||
g-tx-fifo-size = <128 128 64 64 64 64 32 32>;
|
||||
dr_mode = "otg";
|
||||
usb33d-supply = <&usb33>;
|
||||
- power-domains = <&pd_core>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
From 67b204258838dd2c940d5b1508318b4890324a06 Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Tue, 29 Jan 2019 17:31:19 +0100
|
||||
Subject: [PATCH 63/64] ARM stm32mp1 r0 rc4 hotfix w905.2 DRIVERS
|
||||
|
||||
---
|
||||
drivers/dma/stm32-dma.c | 70 ++++++++++++++++++++++++++++++++++++---------
|
||||
drivers/usb/dwc2/platform.c | 38 ++++++++++++++++++------
|
||||
2 files changed, 87 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
|
||||
index 5abfa4f..dc3ba91 100644
|
||||
--- a/drivers/dma/stm32-dma.c
|
||||
+++ b/drivers/dma/stm32-dma.c
|
||||
@@ -1675,37 +1675,81 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
|
||||
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
|
||||
}
|
||||
|
||||
+static bool stm32_dma_is_current_sg(struct stm32_dma_chan *chan)
|
||||
+{
|
||||
+ struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
|
||||
+ struct stm32_dma_sg_req *sg_req;
|
||||
+ u32 dma_scr, dma_smar, id;
|
||||
+
|
||||
+ id = chan->id;
|
||||
+ dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id));
|
||||
+
|
||||
+ if (!(dma_scr & STM32_DMA_SCR_DBM))
|
||||
+ return true;
|
||||
+
|
||||
+ sg_req = &chan->desc->sg_req[chan->next_sg];
|
||||
+
|
||||
+ if (dma_scr & STM32_DMA_SCR_CT) {
|
||||
+ dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM0AR(id));
|
||||
+ return (dma_smar == sg_req->chan_reg.dma_sm0ar);
|
||||
+ }
|
||||
+
|
||||
+ dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(id));
|
||||
+
|
||||
+ return (dma_smar == sg_req->chan_reg.dma_sm1ar);
|
||||
+}
|
||||
+
|
||||
static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
|
||||
struct stm32_dma_desc *desc,
|
||||
u32 next_sg)
|
||||
{
|
||||
u32 modulo, burst_size;
|
||||
- u32 residue = 0;
|
||||
+ u32 residue;
|
||||
+ u32 n_sg = next_sg;
|
||||
+ struct stm32_dma_sg_req *sg_req = &chan->desc->sg_req[chan->next_sg];
|
||||
int i;
|
||||
|
||||
/* Drain case */
|
||||
if (chan->residue_after_drain)
|
||||
return chan->residue_after_drain;
|
||||
|
||||
+ residue = stm32_dma_get_remaining_bytes(chan);
|
||||
+
|
||||
/*
|
||||
- * In cyclic mode, for the last period, residue = remaining bytes from
|
||||
- * NDTR
|
||||
+ * Calculate the residue means compute the descriptors
|
||||
+ * information:
|
||||
+ * - the sg currently transferred
|
||||
+ * - the remaining position in this sg (NDTR).
|
||||
+ *
|
||||
+ * The issue is that a race condition can occur if DMA is
|
||||
+ * running. DMA can have started to transfer the next sg before
|
||||
+ * the position in sg is read. In this case the remaing position
|
||||
+ * can correspond to the new sg position.
|
||||
+ * The strategy implemented in the stm32 driver is to check the
|
||||
+ * sg transition. If detected we can not trust the SxNDTR register value
|
||||
+ * this register can not be up to date during the transition.
|
||||
+ * in this case we can assume that the dma is at the beginning of next
|
||||
+ * sg so we calculate the residue in consequence.
|
||||
*/
|
||||
- if (chan->desc->cyclic && next_sg == 0) {
|
||||
- residue = stm32_dma_get_remaining_bytes(chan);
|
||||
- goto end;
|
||||
+
|
||||
+ if (!stm32_dma_is_current_sg(chan)) {
|
||||
+ n_sg++;
|
||||
+ if (n_sg == chan->desc->num_sgs)
|
||||
+ n_sg = 0;
|
||||
+ residue = sg_dma_len(&sg_req->stm32_sgl_req);
|
||||
}
|
||||
|
||||
/*
|
||||
- * For all other periods in cyclic mode, and in sg mode,
|
||||
- * residue = remaining bytes from NDTR + remaining periods/sg to be
|
||||
- * transferred
|
||||
+ * In cyclic mode, for the last period, residue = remaining bytes
|
||||
+ * from NDTR
|
||||
+ * else for all other periods in cyclic mode, and in sg mode,
|
||||
+ * residue = remaining bytes from NDTR + remaining
|
||||
+ * periods/sg to be transferred
|
||||
*/
|
||||
- for (i = next_sg; i < desc->num_sgs; i++)
|
||||
- residue += sg_dma_len(&desc->sg_req[i].stm32_sgl_req);
|
||||
- residue += stm32_dma_get_remaining_bytes(chan);
|
||||
+ if (!chan->desc->cyclic || n_sg != 0)
|
||||
+ for (i = n_sg; i < desc->num_sgs; i++)
|
||||
+ residue += sg_dma_len(&desc->sg_req[i].stm32_sgl_req);
|
||||
|
||||
-end:
|
||||
if (!chan->mem_burst)
|
||||
return residue;
|
||||
|
||||
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
|
||||
index b80d046..7e6960c 100644
|
||||
--- a/drivers/usb/dwc2/platform.c
|
||||
+++ b/drivers/usb/dwc2/platform.c
|
||||
@@ -568,16 +568,35 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
+ if (dwc2_is_device_mode(dwc2))
|
||||
+ dwc2_hsotg_suspend(dwc2);
|
||||
+
|
||||
if (dwc2->params.activate_stm_id_vb_detection &&
|
||||
!dwc2->params.force_b_session_valid) {
|
||||
- u32 ggpio;
|
||||
+ u32 ggpio, gotgctl;
|
||||
+ int is_host = dwc2_is_host_mode(dwc2);
|
||||
|
||||
/*
|
||||
* Need to force the mode to the current mode to avoid Mode
|
||||
- * Mismatch Interrupt when ID and VBUS detection will be
|
||||
- * disabled
|
||||
+ * Mismatch Interrupt when ID detection will be disabled.
|
||||
*/
|
||||
- dwc2_force_mode(dwc2, dwc2_is_host_mode(dwc2));
|
||||
+ dwc2_force_mode(dwc2, is_host);
|
||||
+
|
||||
+ if (!is_host) {
|
||||
+ gotgctl = dwc2_readl(dwc2, GOTGCTL);
|
||||
+ /*
|
||||
+ * We're about to disable Vbus detection hw before low
|
||||
+ * power mode entry. Then an undesired disconnect
|
||||
+ * interrupt may occur which is racy with low power
|
||||
+ * (low-level hw disable). Then check valid session
|
||||
+ * to force B-peripheral session value.
|
||||
+ */
|
||||
+ if (gotgctl & GOTGCTL_BSESVLD) {
|
||||
+ gotgctl |= GOTGCTL_BVALOVAL;
|
||||
+ gotgctl |= GOTGCTL_BVALOEN;
|
||||
+ dwc2_writel(dwc2, gotgctl, GOTGCTL);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
ggpio = dwc2_readl(dwc2, GGPIO);
|
||||
ggpio &= ~GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||
@@ -587,9 +606,6 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||
regulator_disable(dwc2->usb33d);
|
||||
}
|
||||
|
||||
- if (dwc2_is_device_mode(dwc2))
|
||||
- dwc2_hsotg_suspend(dwc2);
|
||||
-
|
||||
if (dwc2->ll_hw_enabled)
|
||||
ret = __dwc2_lowlevel_hw_disable(dwc2);
|
||||
|
||||
@@ -612,7 +628,7 @@ static int __maybe_unused dwc2_resume(struct device *dev)
|
||||
|
||||
if (dwc2->params.activate_stm_id_vb_detection &&
|
||||
!dwc2->params.force_b_session_valid) {
|
||||
- u32 ggpio;
|
||||
+ u32 ggpio, gotgctl;
|
||||
|
||||
ret = regulator_enable(dwc2->usb33d);
|
||||
if (ret)
|
||||
@@ -625,6 +641,12 @@ static int __maybe_unused dwc2_resume(struct device *dev)
|
||||
|
||||
/* ID/VBUS detection startup time */
|
||||
usleep_range(5000, 7000);
|
||||
+
|
||||
+ /* Unconditionally clear B-Session Valid override */
|
||||
+ gotgctl = dwc2_readl(dwc2, GOTGCTL);
|
||||
+ gotgctl &= ~GOTGCTL_BVALOVAL;
|
||||
+ gotgctl &= ~GOTGCTL_BVALOEN;
|
||||
+ dwc2_writel(dwc2, gotgctl, GOTGCTL);
|
||||
}
|
||||
|
||||
if (dwc2->params.force_b_session_valid) {
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
From cad13a8b78d8d320394dbed545df8e47c199bbd1 Mon Sep 17 00:00:00 2001
|
||||
From: christophe montaud <christophe.montaud@st.com>
|
||||
Date: Tue, 29 Jan 2019 17:31:53 +0100
|
||||
Subject: [PATCH 64/64] ARM stm32mp1 r0 rc4 hotfix w905.2 DEVICETREE
|
||||
|
||||
---
|
||||
arch/arm/boot/dts/stm32mp157c.dtsi | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
index 9647119..5581a1c 100644
|
||||
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
|
||||
@@ -58,6 +58,7 @@
|
||||
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
interrupt-parent = <&intc>;
|
||||
+ always-on;
|
||||
};
|
||||
|
||||
clocks {
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ CONFIG_INET_XFRM_MODE_TUNNEL=m
|
|||
CONFIG_INET_XFRM_MODE_BEET=m
|
||||
CONFIG_INET_DIAG=m
|
||||
CONFIG_INET_UDP_DIAG=m
|
||||
CONFIG_INET_RAW_DIAG=mCONFIG_BPF_SYSCALL=y
|
||||
CONFIG_INET_RAW_DIAG=m
|
||||
CONFIG_INET_DIAG_DESTROY=y
|
||||
CONFIG_TCP_CONG_ADVANCED=y
|
||||
CONFIG_TCP_MD5SIG=y
|
||||
|
|
@ -127,7 +127,7 @@ CONFIG_NF_CONNTRACK_SNMP=m
|
|||
CONFIG_NF_CONNTRACK_PPTP=m
|
||||
CONFIG_NF_CONNTRACK_SIP=m
|
||||
CONFIG_NF_CONNTRACK_TFTP=m
|
||||
CONFIG_NF_CT_NETLINK=mCONFIG_BPF_SYSCALL=y
|
||||
CONFIG_NF_CT_NETLINK=m
|
||||
CONFIG_NF_CT_NETLINK_TIMEOUT=m
|
||||
CONFIG_NF_CT_NETLINK_HELPER=m
|
||||
CONFIG_NETFILTER_NETLINK_GLUE_CT=y
|
||||
|
|
|
|||
|
|
@ -5,87 +5,48 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
|
|||
|
||||
include linux-stm32mp.inc
|
||||
|
||||
SRC_URI = "https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.9.tar.xz"
|
||||
SRC_URI[md5sum] = "d7e09d6be85ec8548c73e8713531e958"
|
||||
SRC_URI[sha256sum] = "fc116cc6829c73944215d3b3ac0fc368dde9e8235b456744afffde001269dbf2"
|
||||
SRC_URI = "https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.49.tar.xz"
|
||||
SRC_URI[md5sum] = "0cb9baf0f5ed8f56d42cccc508d841b0"
|
||||
SRC_URI[sha256sum] = "92d920b3973c0dbca5516271afa405be6e5822a9b831df8c085f9c9eb838bbcd"
|
||||
|
||||
SRC_URI += " \
|
||||
file://${LINUX_VERSION}/4.19.9/0001-ARM-stm32mp1-r0-rc1-MACHINE.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0002-ARM-stm32mp1-r0-rc1-CLOCK.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0003-ARM-stm32mp1-r0-rc1-DMA.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0004-ARM-stm32mp1-r0-rc1-I2C.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0005-ARM-stm32mp1-r0-rc1-IIO.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0006-ARM-stm32mp1-r0-rc1-IRQ-Mailbox.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0007-ARM-stm32mp1-r0-rc1-INPUT-TTY.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0008-ARM-stm32mp1-r0-rc1-MFD.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0009-ARM-stm32mp1-r0-rc1-MMC-MTD.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0010-ARM-stm32mp1-r0-rc1-ETH.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0011-ARM-stm32mp1-r0-rc1-NVMEM.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0012-ARM-stm32mp1-r0-rc1-PINCTRL-PWM-RESET-RTC.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0013-ARM-stm32mp1-r0-rc1-REMOTEPROC-RPMSG.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0014-ARM-stm32mp1-r0-rc1-WATCHDOG.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0015-ARM-stm32mp1-r0-rc1-MISC.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0016-ARM-stm32mp1-r0-rc1-DEVICETREE.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0017-ARM-stm32mp1-r0-rc1-DEFCONFIG.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0018-ARM-stm32mp1-r0-rc2-DRM-KMS.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0019-ARM-stm32mp1-r0-rc2-SOUND.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0020-ARM-stm32mp1-r0-rc2-MEDIA.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0021-ARM-stm32mp1-r0-rc2-PINCTRL.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0022-ARM-stm32mp1-r0-rc2-MFD-IRQ.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0023-ARM-stm32mp1-r0-rc2-USB.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0024-ARM-stm32mp1-r0-rc2-THERMAL.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0025-ARM-stm32mp1-r0-rc2-REMOTEPROC.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0026-ARM-stm32mp1-r0-rc2-NET.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0027-ARM-stm32mp1-r0-rc2-HWCLK-SPI.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0028-ARM-stm32mp1-r0-rc2-MMC.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0029-ARM-stm32mp1-r0-rc2-HWSPINLOCK-IIO-I2C.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0030-ARM-stm32mp1-r0-rc2-DEVICETREE.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0031-ARM-stm32mp1-r0-rc2-DEFCONFIG.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0032-ARM-stm32mp1-r0-rc3-DMA.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0033-ARM-stm32mp1-r0-rc3-DISPLAY.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0034-ARM-stm32mp1-r0-rc3-ETH.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0035-ARM-stm32mp1-r0-rc3-IIO.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0036-ARM-stm32mp1-r0-rc3-INPUT-TTY.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0037-ARM-stm32mp1-r0-rc3-IRQ-Mailbox.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0038-ARM-stm32mp1-r0-rc3-MEDIA.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0039-ARM-stm32mp1-r0-rc3-MMC-MTD.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0040-ARM-stm32mp1-r0-rc3-PINCTRL-PWM-RESET-RTC.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0041-ARM-stm32mp1-r0-rc3-REMOTEPROC-RPMSG.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0042-ARM-stm32mp1-r0-rc3-SOUND.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0043-ARM-stm32mp1-r0-rc3-MISC.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0044-ARM-stm32mp1-r0-rc3-DEVICETREE.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0045-ARM-stm32mp1-r0-rc3-DEFCONFIG.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0046-ARM-stm32mp1-r0-rc4-MMC-MTD.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0047-ARM-stm32mp1-r0-rc4-PINCTRL-PWM-RESET-RTC.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0048-ARM-stm32mp1-r0-rc4-REMOTEPROC-RPMSG.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0049-ARM-stm32mp1-r0-rc4-SOUND.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0050-ARM-stm32mp1-r0-rc4-USB.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0051-ARM-stm32mp1-r0-rc4-DEVICETREE.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0052-ARM-stm32mp1-r0-rc4-DEFCONFIG.patch \
|
||||
\
|
||||
file://${LINUX_VERSION}/4.19.9/0053-ARM-stm32mp1-r0-rc4-hotfix-w903.1-DRIVERS.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0054-ARM-stm32mp1-r0-rc4-hotfix-w903.1-DEVICETREE.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0055-ARM-stm32mp1-r0-rc4-hotfix-w903.1-DEFCONFIG.patch \
|
||||
\
|
||||
file://${LINUX_VERSION}/4.19.9/0056-ARM-stm32mp1-r0-rc4-hotfix-w903.3-DRIVERS.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0057-ARM-stm32mp1-r0-rc4-hotfix-w903.3-DEVICETREE.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0058-ARM-stm32mp1-r0-rc4-hotfix-w903.3-DEFCONFIG.patch \
|
||||
\
|
||||
file://${LINUX_VERSION}/4.19.9/0059-ARM-stm32mp1-r0-rc4-hotfix-w904.3-DRIVERS.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0060-ARM-stm32mp1-r0-rc4-hotfix-w904.3-DEVICETREE.patch \
|
||||
\
|
||||
file://${LINUX_VERSION}/4.19.9/0061-ARM-stm32mp1-r0-rc4-hotfix-w904.5-DRIVERS.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0062-ARM-stm32mp1-r0-rc4-hotfix-w904.5-DEVICETREE.patch \
|
||||
\
|
||||
file://${LINUX_VERSION}/4.19.9/0063-ARM-stm32mp1-r0-rc4-hotfix-w905.2-DRIVERS.patch \
|
||||
file://${LINUX_VERSION}/4.19.9/0064-ARM-stm32mp1-r0-rc4-hotfix-w905.2-DEVICETREE.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0001-ARM-stm32mp1-r2-MACHINE.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0002-ARM-stm32mp1-r2-CRYPTO.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0003-ARM-stm32mp1-r2-BLUETOOTH-CHAR.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0004-ARM-stm32mp1-r2-CLOCK.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0005-ARM-stm32mp1-r2-DMA.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0006-ARM-stm32mp1-r2-DRM.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0007-ARM-stm32mp1-r2-GPIO.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0008-ARM-stm32mp1-r2-HWSPINLOCK.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0009-ARM-stm32mp1-r2-HWTRACING-I2C.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0010-ARM-stm32mp1-r2-IIO.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0011-ARM-stm32mp1-r2-INPUT-IRQ-Mailbox.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0012-ARM-stm32mp1-r2-MEDIA.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0013-ARM-stm32mp1-r2-MFD.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0014-ARM-stm32mp1-r2-MMC-MTD.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0015-ARM-stm32mp1-r2-NET.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0016-ARM-stm32mp1-r2-NVMEM.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0017-ARM-stm32mp1-r2-PERF.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0018-ARM-stm32mp1-r2-PHY-PINCTRL-PWM.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0019-ARM-stm32mp1-r2-REGULATOR.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0020-ARM-stm32mp1-r2-REMOTEPROC-RPMSG-RESET.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0021-ARM-stm32mp1-r2-RTC.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0022-ARM-stm32mp1-r2-SOC.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0023-ARM-stm32mp1-r2-SPI.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0024-ARM-stm32mp1-r2-THERMAL.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0025-ARM-stm32mp1-r2-TTY-USB.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0026-ARM-stm32mp1-r2-WATCHDOG.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0027-ARM-stm32mp1-r2-SOUND.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0028-ARM-stm32mp1-r2-MISC.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0029-ARM-stm32mp1-r2-DEVICETREE.patch \
|
||||
file://${LINUX_VERSION}/4.19.49/0030-ARM-stm32mp1-r2-DEFCONFIG.patch \
|
||||
"
|
||||
|
||||
LINUX_VERSION = "4.19"
|
||||
|
||||
PV = "${LINUX_VERSION}"
|
||||
|
||||
S = "${WORKDIR}/linux-4.19.9"
|
||||
S = "${WORKDIR}/linux-4.19.49"
|
||||
|
||||
# ---------------------------------
|
||||
# Configure devupstream class usage
|
||||
|
|
@ -93,7 +54,7 @@ S = "${WORKDIR}/linux-4.19.9"
|
|||
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_class-devupstream = "9cc80ff80f5ea5f1ff35122f61afaa7b11ad22ae"
|
||||
SRCREV_FORMAT_class-devupstream = "linux"
|
||||
PV_class-devupstream = "${LINUX_VERSION}+github+${SRCPV}"
|
||||
|
||||
|
|
@ -104,6 +65,11 @@ 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
|
||||
#
|
||||
|
|
@ -126,12 +92,3 @@ SRC_URI_class-devupstream += " file://4.19/fragment-05-modules.config;subdir=fra
|
|||
# Kernel Args
|
||||
#
|
||||
KERNEL_EXTRA_ARGS += "LOADADDR=${ST_KERNEL_LOADADDR}"
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Archiver
|
||||
#
|
||||
inherit archiver
|
||||
ARCHIVER_MODE[src] = "${@'original' if d.getVar('ST_ARCHIVER_ENABLE') == '1' else ''}"
|
||||
SRC_URI =+ "file://README.HOW_TO.txt"
|
||||
|
||||
inherit archiver_stm32mp_clean
|
||||
|
|
|
|||
Loading…
Reference in New Issue