KERNEL: v1.1.0 update

Signed-off-by: Christophe Priouzeau <christophe.priouzeau@st.com>
This commit is contained in:
Christophe Priouzeau 2019-10-09 11:28:29 +02:00
parent 7bc347c769
commit 3d3a8be098
82 changed files with 25872 additions and 26240 deletions

View File

@ -0,0 +1,9 @@
#
# Archiver Configuration
#
SRC_URI_append = " file://README.HOW_TO.txt "
inherit archiver
ARCHIVER_MODE[src] = "original"
inherit archiver_stm32mp_clean

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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,
&ltdc_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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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", &reg)) {
+ 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

View File

@ -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

View File

@ -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),

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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__);
+

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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", &reg)) {
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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";
+};
+
&ethernet0 {
status = "okay";
pinctrl-0 = <&ethernet0_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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 = &ethernet0;
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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