* [PATCH 5/8] pinctrl: aspeed: Enable capture of off-SCU pinmux state
From: Andrew Jeffery @ 2016-09-27 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.115463f791b69859c5ce9dafd61a5755ea039f4b.1474986045.git-series.andrew@aj.id.au>
The System Control Unit IP in the Aspeed SoCs is typically where the
pinmux configuration is found.
But not always.
On the AST2400 and AST2500 a number of pins depend on state in one of
the SIO, LPC or GFX IP blocks, so add support to at least capture what
that state is. The pinctrl engine for the Aspeed SoCs doesn't try to
inspect or modify the state of the off-SCU IP blocks. Instead, it logs
the state requirement with the expectation that the platform
designer/maintainer arranges for the appropriate configuration to be
applied through the associated drivers.
The IP block of interest is encoded in the reg member of struct
aspeed_sig_desc. For compatibility with the existing code, the SCU is
defined to have an IP value of 0.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
drivers/pinctrl/aspeed/pinctrl-aspeed.c | 53 +++++++++++++++++++++++---
drivers/pinctrl/aspeed/pinctrl-aspeed.h | 16 +++++++-
2 files changed, 61 insertions(+), 8 deletions(-)
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
index 49aeba912531..21ef195d586f 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
@@ -14,6 +14,8 @@
#include "../core.h"
#include "pinctrl-aspeed.h"
+const char *const aspeed_pinmux_ips[] = { "SCU", "SIO", "GFX", "LPC" };
+
int aspeed_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
{
struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
@@ -78,7 +80,9 @@ int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
static inline void aspeed_sig_desc_print_val(
const struct aspeed_sig_desc *desc, bool enable, u32 rv)
{
- pr_debug("SCU%x[0x%08x]=0x%x, got 0x%x from 0x%08x\n", desc->reg,
+ pr_debug("Want %s%lX[0x%08X]=0x%X, got 0x%X from 0x%08X\n",
+ aspeed_pinmux_ips[SIG_DESC_IP_FROM_REG(desc->reg)],
+ SIG_DESC_OFFSET_FROM_REG(desc->reg),
desc->mask, enable ? desc->enable : desc->disable,
(rv & desc->mask) >> __ffs(desc->mask), rv);
}
@@ -105,6 +109,8 @@ static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
unsigned int raw;
u32 want;
+ WARN_ON(SIG_DESC_IP_FROM_REG(desc->reg) != ASPEED_IP_SCU);
+
if (regmap_read(map, desc->reg, &raw) < 0)
return false;
@@ -142,9 +148,19 @@ static bool aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
for (i = 0; i < expr->ndescs; i++) {
const struct aspeed_sig_desc *desc = &expr->descs[i];
+ size_t ip = SIG_DESC_IP_FROM_REG(desc->reg);
+
+ if (ip == ASPEED_IP_SCU) {
+ if (!aspeed_sig_desc_eval(desc, enabled, map))
+ return false;
+ } else {
+ size_t offset = SIG_DESC_OFFSET_FROM_REG(desc->reg);
+ const char *ip_name = aspeed_pinmux_ips[ip];
+
+ pr_debug("Ignoring configuration of field %s%X[0x%08X]\n",
+ ip_name, offset, desc->mask);
+ }
- if (!aspeed_sig_desc_eval(desc, enabled, map))
- return false;
}
return true;
@@ -170,7 +186,14 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
for (i = 0; i < expr->ndescs; i++) {
bool ret;
const struct aspeed_sig_desc *desc = &expr->descs[i];
+
+ size_t offset = SIG_DESC_OFFSET_FROM_REG(desc->reg);
+ size_t ip = SIG_DESC_IP_FROM_REG(desc->reg);
+ bool is_scu = (ip == ASPEED_IP_SCU);
+ const char *ip_name = aspeed_pinmux_ips[ip];
+
u32 pattern = enable ? desc->enable : desc->disable;
+ u32 val = (pattern << __ffs(desc->mask));
/*
* Strap registers are configured in hardware or by early-boot
@@ -179,11 +202,27 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
* deconfigured and is the reason we re-evaluate after writing
* all descriptor bits.
*/
- if (desc->reg == HW_STRAP1 || desc->reg == HW_STRAP2)
+ if (is_scu && (offset == HW_STRAP1 || offset == HW_STRAP2))
continue;
- ret = regmap_update_bits(map, desc->reg, desc->mask,
- pattern << __ffs(desc->mask)) == 0;
+ /*
+ * Sometimes we need help from IP outside the SCU to activate a
+ * mux request. Report that we need its cooperation.
+ */
+ if (enable && !is_scu) {
+ pr_debug("Pinmux request for %s requires cooperation of %s IP: Need (%s%X[0x%08X] = 0x%08X\n",
+ expr->function, ip_name, ip_name, offset,
+ desc->mask, val);
+ }
+
+ /* And only read/write SCU registers */
+ if (!is_scu) {
+ pr_debug("Skipping configuration of field %s%X[0x%08X]\n",
+ ip_name, offset, desc->mask);
+ continue;
+ }
+
+ ret = regmap_update_bits(map, desc->reg, desc->mask, val) == 0;
if (!ret)
return ret;
@@ -343,6 +382,8 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
const struct aspeed_sig_expr **funcs;
const struct aspeed_sig_expr ***prios;
+ pr_debug("Muxing pin %d for %s\n", pin, pfunc->name);
+
if (!pdesc)
return -EINVAL;
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.h b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
index 3e72ef8c54bf..4384407d77fb 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.h
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
@@ -232,6 +232,15 @@
* group.
*/
+#define ASPEED_IP_SCU 0
+#define ASPEED_IP_SIO 1
+#define ASPEED_IP_GFX 2
+#define ASPEED_IP_LPC 3
+
+#define SIG_DESC_TO_REG(ip, offset) (((ip) << 24) | (offset))
+#define SIG_DESC_IP_FROM_REG(reg) (((reg) >> 24) & GENMASK(7, 0))
+#define SIG_DESC_OFFSET_FROM_REG(reg) ((reg) & GENMASK(11, 0))
+
/*
* The "Multi-function Pins Mapping and Control" table in the SoC datasheet
* references registers by the device/offset mnemonic. The register macros
@@ -261,7 +270,10 @@
* A signal descriptor, which describes the register, bits and the
* enable/disable values that should be compared or written.
*
- * @reg: The register offset from base in bytes
+ * @reg: Split into three fields:
+ * 31:24: IP selector
+ * 23:12: Reserved
+ * 11:0: Register offset
* @mask: The mask to apply to the register. The lowest set bit of the mask is
* used to derive the shift value.
* @enable: The value that enables the function. Value should be in the LSBs,
@@ -270,7 +282,7 @@
* LSBs, not at the position of the mask.
*/
struct aspeed_sig_desc {
- unsigned int reg;
+ u32 reg;
u32 mask;
u32 enable;
u32 disable;
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH 4/8] pinctrl: aspeed-g5: Fix pin association of SPI1 function
From: Andrew Jeffery @ 2016-09-27 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.115463f791b69859c5ce9dafd61a5755ea039f4b.1474986045.git-series.andrew@aj.id.au>
The SPI1 function was associated with the wrong pins: The functions that
those pins provide is either an SPI debug or passthrough function
coupled to SPI1. Make the SPI1 mux function configure the relevant pins
and associate new SPI1DEBUG and SPI1PASSTHRU functions with the pins
that were already defined.
The notation used in the datasheet's multi-function pin table for the SoC is
often creative: in this case the SYS* signals are enabled by a single bit,
which is nothing unusual on its own, but in this case the bit was also
participating in a multi-bit bitfield and therefore represented multiple
functions. This fact was overlooked in the original patch.
Fixes: 56e57cb6c07f (pinctrl: Add pinctrl-aspeed-g5 driver)
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt | 4 +-
drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 86 ++++++-
2 files changed, 81 insertions(+), 9 deletions(-)
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
index 5e60ad18f147..2ad18c4ea55c 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
@@ -43,7 +43,9 @@ aspeed,ast2500-pinctrl, aspeed,g5-pinctrl:
GPID0 GPID2 GPIE0 I2C10 I2C11 I2C12 I2C13 I2C14 I2C3 I2C4 I2C5 I2C6 I2C7 I2C8
I2C9 MAC1LINK MDIO1 MDIO2 OSCCLK PEWAKE PWM0 PWM1 PWM2 PWM3 PWM4 PWM5 PWM6 PWM7
-RGMII1 RGMII2 RMII1 RMII2 SD1 SPI1 TIMER4 TIMER5 TIMER6 TIMER7 TIMER8
+RGMII1 RGMII2 RMII1 RMII2 SD1 SPI1 SPI1DEBUG SPI1PASSTHRU TIMER4 TIMER5 TIMER6
+TIMER7 TIMER8 VGABIOSROM
+
Examples:
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
index 235d929e74fd..c8c72e8259d3 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
@@ -186,24 +186,84 @@ MS_PIN_DECL(C20, GPIOE1, NDCD3, GPIE0OUT);
FUNC_GROUP_DECL(GPIE0, B20, C20);
-#define SPI1_DESC SIG_DESC_SET(HW_STRAP1, 13)
+#define SPI1_DESC { HW_STRAP1, GENMASK(13, 12), 1, 0 }
+#define SPI1DEBUG_DESC { HW_STRAP1, GENMASK(13, 12), 2, 0 }
+#define SPI1PASSTHRU_DESC { HW_STRAP1, GENMASK(13, 12), 3, 0 }
+
#define C18 64
-SIG_EXPR_LIST_DECL_SINGLE(SYSCS, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SYSCS, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SYSCS, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL_DUAL(SYSCS, SPI1DEBUG, SPI1PASSTHRU);
SS_PIN_DECL(C18, GPIOI0, SYSCS);
#define E15 65
-SIG_EXPR_LIST_DECL_SINGLE(SYSCK, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SYSCK, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SYSCK, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL_DUAL(SYSCK, SPI1DEBUG, SPI1PASSTHRU);
SS_PIN_DECL(E15, GPIOI1, SYSCK);
-#define A14 66
-SIG_EXPR_LIST_DECL_SINGLE(SYSMOSI, SPI1, COND1, SPI1_DESC);
-SS_PIN_DECL(A14, GPIOI2, SYSMOSI);
+#define B16 66
+SIG_EXPR_DECL(SYSMOSI, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SYSMOSI, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL_DUAL(SYSMOSI, SPI1DEBUG, SPI1PASSTHRU);
+SS_PIN_DECL(B16, GPIOI2, SYSMOSI);
#define C16 67
-SIG_EXPR_LIST_DECL_SINGLE(SYSMISO, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SYSMISO, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SYSMISO, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL_DUAL(SYSMISO, SPI1DEBUG, SPI1PASSTHRU);
SS_PIN_DECL(C16, GPIOI3, SYSMISO);
-FUNC_GROUP_DECL(SPI1, C18, E15, A14, C16);
+#define VB_DESC SIG_DESC_SET(HW_STRAP1, 5)
+
+#define B15 68
+SIG_EXPR_DECL(SPI1CS0, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SPI1CS0, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SPI1CS0, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL(SPI1CS0, SIG_EXPR_PTR(SPI1CS0, SPI1),
+ SIG_EXPR_PTR(SPI1CS0, SPI1DEBUG),
+ SIG_EXPR_PTR(SPI1CS0, SPI1PASSTHRU));
+SIG_EXPR_LIST_DECL_SINGLE(VBCS, VGABIOSROM, COND1, VB_DESC);
+MS_PIN_DECL(B15, GPIOI4, SPI1CS0, VBCS);
+
+#define C15 69
+SIG_EXPR_DECL(SPI1CK, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SPI1CK, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SPI1CK, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL(SPI1CK, SIG_EXPR_PTR(SPI1CK, SPI1),
+ SIG_EXPR_PTR(SPI1CK, SPI1DEBUG),
+ SIG_EXPR_PTR(SPI1CK, SPI1PASSTHRU));
+SIG_EXPR_LIST_DECL_SINGLE(VBCK, VGABIOSROM, COND1, VB_DESC);
+MS_PIN_DECL(C15, GPIOI5, SPI1CK, VBCK);
+
+#define A14 70
+SIG_EXPR_DECL(SPI1MOSI, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SPI1MOSI, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SPI1MOSI, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL(SPI1MOSI, SIG_EXPR_PTR(SPI1MOSI, SPI1),
+ SIG_EXPR_PTR(SPI1MOSI, SPI1DEBUG),
+ SIG_EXPR_PTR(SPI1MOSI, SPI1PASSTHRU));
+SIG_EXPR_LIST_DECL_SINGLE(VBMOSI, VGABIOSROM, COND1, VB_DESC);
+MS_PIN_DECL(A14, GPIOI6, SPI1MOSI, VBMOSI);
+
+#define A15 71
+SIG_EXPR_DECL(SPI1MISO, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SPI1MISO, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SPI1MISO, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL(SPI1MISO, SIG_EXPR_PTR(SPI1MISO, SPI1),
+ SIG_EXPR_PTR(SPI1MISO, SPI1DEBUG),
+ SIG_EXPR_PTR(SPI1MISO, SPI1PASSTHRU));
+SIG_EXPR_LIST_DECL_SINGLE(VBMISO, VGABIOSROM, COND1, VB_DESC);
+MS_PIN_DECL(A15, GPIOI7, SPI1MISO, VBMISO);
+
+FUNC_GROUP_DECL(SPI1, B15, C15, A14, A15);
+FUNC_GROUP_DECL(SPI1DEBUG, C18, E15, B16, C16, B15, C15, A14, A15);
+FUNC_GROUP_DECL(SPI1PASSTHRU, C18, E15, B16, C16, B15, C15, A14, A15);
+FUNC_GROUP_DECL(VGABIOSROM, B15, C15, A14, A15);
+
+#define R2 72
+SIG_EXPR_LIST_DECL_SINGLE(SGPMCK, SGPM, SIG_DESC_SET(SCU84, 8));
+SS_PIN_DECL(R2, GPIOJ0, SGPMCK);
#define L2 73
SIG_EXPR_LIST_DECL_SINGLE(SGPMLD, SGPM, SIG_DESC_SET(SCU84, 9));
@@ -580,6 +640,7 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
ASPEED_PINCTRL_PIN(A12),
ASPEED_PINCTRL_PIN(A13),
ASPEED_PINCTRL_PIN(A14),
+ ASPEED_PINCTRL_PIN(A15),
ASPEED_PINCTRL_PIN(A2),
ASPEED_PINCTRL_PIN(A3),
ASPEED_PINCTRL_PIN(A4),
@@ -592,6 +653,8 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
ASPEED_PINCTRL_PIN(B12),
ASPEED_PINCTRL_PIN(B13),
ASPEED_PINCTRL_PIN(B14),
+ ASPEED_PINCTRL_PIN(B15),
+ ASPEED_PINCTRL_PIN(B16),
ASPEED_PINCTRL_PIN(B2),
ASPEED_PINCTRL_PIN(B20),
ASPEED_PINCTRL_PIN(B3),
@@ -603,6 +666,7 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
ASPEED_PINCTRL_PIN(C12),
ASPEED_PINCTRL_PIN(C13),
ASPEED_PINCTRL_PIN(C14),
+ ASPEED_PINCTRL_PIN(C15),
ASPEED_PINCTRL_PIN(C16),
ASPEED_PINCTRL_PIN(C18),
ASPEED_PINCTRL_PIN(C2),
@@ -691,11 +755,14 @@ static const struct aspeed_pin_group aspeed_g5_groups[] = {
ASPEED_PINCTRL_GROUP(RMII2),
ASPEED_PINCTRL_GROUP(SD1),
ASPEED_PINCTRL_GROUP(SPI1),
+ ASPEED_PINCTRL_GROUP(SPI1DEBUG),
+ ASPEED_PINCTRL_GROUP(SPI1PASSTHRU),
ASPEED_PINCTRL_GROUP(TIMER4),
ASPEED_PINCTRL_GROUP(TIMER5),
ASPEED_PINCTRL_GROUP(TIMER6),
ASPEED_PINCTRL_GROUP(TIMER7),
ASPEED_PINCTRL_GROUP(TIMER8),
+ ASPEED_PINCTRL_GROUP(VGABIOSROM),
};
static const struct aspeed_pin_function aspeed_g5_functions[] = {
@@ -733,11 +800,14 @@ static const struct aspeed_pin_function aspeed_g5_functions[] = {
ASPEED_PINCTRL_FUNC(RMII2),
ASPEED_PINCTRL_FUNC(SD1),
ASPEED_PINCTRL_FUNC(SPI1),
+ ASPEED_PINCTRL_FUNC(SPI1DEBUG),
+ ASPEED_PINCTRL_FUNC(SPI1PASSTHRU),
ASPEED_PINCTRL_FUNC(TIMER4),
ASPEED_PINCTRL_FUNC(TIMER5),
ASPEED_PINCTRL_FUNC(TIMER6),
ASPEED_PINCTRL_FUNC(TIMER7),
ASPEED_PINCTRL_FUNC(TIMER8),
+ ASPEED_PINCTRL_FUNC(VGABIOSROM),
};
static struct aspeed_pinctrl_data aspeed_g5_pinctrl_data = {
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH 3/8] pinctrl: aspeed-g5: Fix GPIOE1 typo
From: Andrew Jeffery @ 2016-09-27 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.115463f791b69859c5ce9dafd61a5755ea039f4b.1474986045.git-series.andrew@aj.id.au>
This prevented C20 from successfully being muxed as GPIO.
Fixes: 56e57cb6c07f (pinctrl: Add pinctrl-aspeed-g5 driver)
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
index 14639834a5eb..235d929e74fd 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
@@ -182,7 +182,7 @@ SIG_EXPR_LIST_DECL_SINGLE(NDCD3, NDCD3, SIG_DESC_SET(SCU80, 17));
SIG_EXPR_DECL(GPIE0OUT, GPIE0, GPIE0_DESC);
SIG_EXPR_DECL(GPIE0OUT, GPIE, GPIE_DESC);
SIG_EXPR_LIST_DECL_DUAL(GPIE0OUT, GPIE0, GPIE);
-MS_PIN_DECL(C20, GPIE0, NDCD3, GPIE0OUT);
+MS_PIN_DECL(C20, GPIOE1, NDCD3, GPIE0OUT);
FUNC_GROUP_DECL(GPIE0, B20, C20);
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH 2/8] pinctrl: aspeed-g5: Fix names of GPID2 pins
From: Andrew Jeffery @ 2016-09-27 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.115463f791b69859c5ce9dafd61a5755ea039f4b.1474986045.git-series.andrew@aj.id.au>
Fixes simple typos in the initial commit. There is no behavioural
change.
Fixes: 56e57cb6c07f (pinctrl: Add pinctrl-aspeed-g5 driver)
Reported-by: Xo Wang <xow@google.com>
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
index e1ab864e1a7f..14639834a5eb 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
@@ -151,21 +151,21 @@ FUNC_GROUP_DECL(GPID0, F19, E21);
#define GPID2_DESC SIG_DESC_SET(SCU8C, 9)
-#define D20 26
+#define F20 26
SIG_EXPR_LIST_DECL_SINGLE(SD2DAT0, SD2, SD2_DESC);
SIG_EXPR_DECL(GPID2IN, GPID2, GPID2_DESC);
SIG_EXPR_DECL(GPID2IN, GPID, GPID_DESC);
SIG_EXPR_LIST_DECL_DUAL(GPID2IN, GPID2, GPID);
-MS_PIN_DECL(D20, GPIOD2, SD2DAT0, GPID2IN);
+MS_PIN_DECL(F20, GPIOD2, SD2DAT0, GPID2IN);
-#define D21 27
+#define D20 27
SIG_EXPR_LIST_DECL_SINGLE(SD2DAT1, SD2, SD2_DESC);
SIG_EXPR_DECL(GPID2OUT, GPID2, GPID2_DESC);
SIG_EXPR_DECL(GPID2OUT, GPID, GPID_DESC);
SIG_EXPR_LIST_DECL_DUAL(GPID2OUT, GPID2, GPID);
-MS_PIN_DECL(D21, GPIOD3, SD2DAT1, GPID2OUT);
+MS_PIN_DECL(D20, GPIOD3, SD2DAT1, GPID2OUT);
-FUNC_GROUP_DECL(GPID2, D20, D21);
+FUNC_GROUP_DECL(GPID2, F20, D20);
#define GPIE_DESC SIG_DESC_SET(HW_STRAP1, 21)
#define GPIE0_DESC SIG_DESC_SET(SCU8C, 12)
@@ -614,7 +614,6 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
ASPEED_PINCTRL_PIN(D10),
ASPEED_PINCTRL_PIN(D2),
ASPEED_PINCTRL_PIN(D20),
- ASPEED_PINCTRL_PIN(D21),
ASPEED_PINCTRL_PIN(D4),
ASPEED_PINCTRL_PIN(D5),
ASPEED_PINCTRL_PIN(D6),
@@ -630,6 +629,7 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
ASPEED_PINCTRL_PIN(E7),
ASPEED_PINCTRL_PIN(E9),
ASPEED_PINCTRL_PIN(F19),
+ ASPEED_PINCTRL_PIN(F20),
ASPEED_PINCTRL_PIN(F9),
ASPEED_PINCTRL_PIN(H20),
ASPEED_PINCTRL_PIN(L1),
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH 1/8] pinctrl: aspeed: "Not enabled" is a significant mux state
From: Andrew Jeffery @ 2016-09-27 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.115463f791b69859c5ce9dafd61a5755ea039f4b.1474986045.git-series.andrew@aj.id.au>
Consider a scenario with one pin P that has two signals A and B, where A
is defined to be higher priority than B: That is, if the mux IP is in a
state that would consider both A and B to be active on P, then A will be
the active signal.
To instead configure B as the active signal we must configure the mux so
that A is inactive. The mux state for signals can be described by
logical operations on one or more bits from one or more registers (a
"signal expression"), which in some cases leads to aliased mux states for
a particular signal. Further, signals described by multi-bit bitfields
often do not only need to record the states that would make them active
(the "enable" expressions), but also the states that makes them inactive
(the "disable" expressions). All of this combined leads to four possible
states for a signal:
1. A signal is active with respect to an "enable" expression
2. A signal is not active with respect to an "enable" expression
3. A signal is inactive with respect to a "disable" expression
4. A signal is not inactive with respect to a "disable" expression
In the case of P, if we are looking to activate B without explicitly
having configured A it's enough to consider A inactive if all of A's
"enable" signal expressions evaluate to "not active". If any evaluate to
"active" then the corresponding "disable" states must be applied so it
becomes inactive.
For example, on the AST2400 the pins composing GPIO bank H provide
signals ROMD8 through ROMD15 (high priority) and those for UART6 (low
priority). The mux states for ROMD8 through ROMD15 are aliased, i.e.
there are two mux states that result in the respective signals being
configured:
A. SCU90[6]=1
B. Strap[4,1:0]=100
Further, the second mux state is a 3-bit bitfield that explicitly
defines the enabled state but the disabled state is implicit, i.e. if
Strap[4,1:0] is not exactly "100" then ROMD8 through ROMD15 are not
considered active. This requires the mux function evaluation logic to
use approach 2. above, however the existing code was using approach 3.
The problem was brought to light on the Palmetto machines where the
strap register value is 0x120ce416, and prevented GPIO requests in bank
H from succeeding despite the hardware being in a position to allow
them.
Fixes: 318398c09a8d ("pinctrl: Add core pinctrl support for Aspeed SoCs")
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
drivers/pinctrl/aspeed/pinctrl-aspeed.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
index 0391f9f13f3e..49aeba912531 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
@@ -166,13 +166,9 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
bool enable, struct regmap *map)
{
int i;
- bool ret;
-
- ret = aspeed_sig_expr_eval(expr, enable, map);
- if (ret)
- return ret;
for (i = 0; i < expr->ndescs; i++) {
+ bool ret;
const struct aspeed_sig_desc *desc = &expr->descs[i];
u32 pattern = enable ? desc->enable : desc->disable;
@@ -199,12 +195,18 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
static bool aspeed_sig_expr_enable(const struct aspeed_sig_expr *expr,
struct regmap *map)
{
+ if (aspeed_sig_expr_eval(expr, true, map))
+ return true;
+
return aspeed_sig_expr_set(expr, true, map);
}
static bool aspeed_sig_expr_disable(const struct aspeed_sig_expr *expr,
struct regmap *map)
{
+ if (!aspeed_sig_expr_eval(expr, true, map))
+ return true;
+
return aspeed_sig_expr_set(expr, false, map);
}
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH 0/8] pinctrl: aspeed: Fixes for core and g5, implement remaining pins
From: Andrew Jeffery @ 2016-09-27 14:50 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
The initial Aspeed pinctrl patches implemented a subset of pins for each of the
g4 and g5 SoCs. This series provides a number of fixes to the initial patches,
mostly for issues identified in the g5 driver. The fixes account for the first
half of the series (up to and including "pinctrl: aspeed-g5: Fix pin
association of SPI1 function") and should be applied for 4.9.
The second half, from "pinctrl: aspeed: Enable capture of off-SCU pinmux
state", implements some additional functionality in the core engine for the
Aspeed SoCs and follows up with patches implementing mux configuration tables
for all remaining pins. Given the significant additions in the last few
patches, their lateness in the cycle and the light testing they have received
they are best left for 4.10, but I'm keen to get them out for review.
Cheers,
Andrew
Andrew Jeffery (8):
pinctrl: aspeed: "Not enabled" is a significant mux state
pinctrl: aspeed-g5: Fix names of GPID2 pins
pinctrl: aspeed-g5: Fix GPIOE1 typo
pinctrl: aspeed-g5: Fix pin association of SPI1 function
pinctrl: aspeed: Enable capture of off-SCU pinmux state
pinctrl: aspeed-g4: Capture SuperIO pinmux dependency
pinctrl: aspeed-g4: Add mux configuration for all pins
pinctrl: aspeed-g5: Add mux configuration for all pins
Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt | 36 +-
drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c | 1098 ++++-
drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 1574 ++++++-
drivers/pinctrl/aspeed/pinctrl-aspeed.c | 65 +-
drivers/pinctrl/aspeed/pinctrl-aspeed.h | 19 +-
5 files changed, 2737 insertions(+), 55 deletions(-)
base-commit: 8d0a0ac0abcdba5b5d52726055c95f1f6234e85e
--
git-series 0.8.10
^ permalink raw reply
* [PATCH] drm/sun4i: rgb: Enable panel after controller
From: Sean Paul @ 2016-09-27 14:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160924201813.GE16901@lukather>
On Sat, Sep 24, 2016 at 4:18 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Fri, Sep 23, 2016 at 11:43:55PM +1000, Jonathan Liu wrote:
>> Hi Maxime,
>>
>> On 23 September 2016 at 23:16, Maxime Ripard
>> <maxime.ripard@free-electrons.com> wrote:
>> > On Thu, Sep 22, 2016 at 08:03:31AM +1000, Jonathan Liu wrote:
>> >> Hi Maxime,
>> >>
>> >> On Thursday, 22 September 2016, Maxime Ripard <maxime.ripard@free-electrons.
>> >> com> wrote:
>> >>
>> >> > On Wed, Sep 21, 2016 at 11:03:04PM +1000, Jonathan Liu wrote:
>> >> > > The panel should be enabled after the controller so that the panel
>> >> > > prepare/enable delays are properly taken into account. Similarly, the
>> >> > > panel should be disabled before the controller so that the panel
>> >> > > unprepare/disable delays are properly taken into account.
>> >> > >
>> >> > > This is useful for avoiding visual glitches.
>> >> >
>> >> > This is not really taking any delays into account, especially since
>> >> > drm_panel_enable and prepare are suppose to block until their
>> >> > operation is complete.
>> >>
>> >>
>> >> drm_panel_prepare turns on power to the LCD using enable-gpios property of
>> >> the panel and then blocks for prepare delay. The prepare delay for panel
>> >> can be set to how long it takes between the time the panel is powered to
>> >> when it is ready to receive images. If backlight property is specified the
>> >> backlight will be off while the panel is powered on.
>> >>
>> >> drm_panel_enable blocks for enable delay and then turns on the backlight.
>> >> The enable delay can be set to how long it takes for panel to start making
>> >> the image visible after receiving the first valid frame. For example if the
>> >> panel starts off as white and the TFT takes some time to initialize to
>> >> black before it shows the image being received.
>> >>
>> >> Refer to drivers/gpu/drm/panel-panel.simple.c for details.
>> >
>> > From drm_panel.h:
>> >
>> > """
>> > * drm_panel_enable - enable a panel
>> > * @panel: DRM panel
>> > *
>> > * Calling this function will cause the panel display drivers to be turned on
>> > * and the backlight to be enabled. Content will be visible on screen after
>> > * this call completes.
>> > """
>> >
>> > """
>> > * drm_panel_prepare - power on a panel
>> > * @panel: DRM panel
>> > *
>> > * Calling this function will enable power and deassert any reset signals to
>> > * the panel. After this has completed it is possible to communicate with any
>> > * integrated circuitry via a command bus.
>> > """
>> >
>> > Those comments clearly says that the caller should not have to deal
>> > with the delays, even more so by just moving calls around and hoping
>> > that the code running in between is adding enough delay for the panel
>> > to behave properly.
>> >
>> > Maxime
>> >
>> > --
>> > Maxime Ripard, Free Electrons
>> > Embedded Linux and Kernel engineering
>> > http://free-electrons.com
>>
>> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/drm/drm_panel.h#n34
>>
>> In comment for struct drm_panel_funcs:
>> /**
>> * struct drm_panel_funcs - perform operations on a given panel
>> * @disable: disable panel (turn off back light, etc.)
>> * @unprepare: turn off panel
>> * @prepare: turn on panel and perform set up
>> * @enable: enable panel (turn on back light, etc.)
>> * @get_modes: add modes to the connector that the panel is attached to and
>> * return the number of modes added
>> * @get_timings: copy display timings into the provided array and return
>> * the number of display timings available
>> *
>> * The .prepare() function is typically called before the display controller
>> * starts to transmit video data. Panel drivers can use this to turn the panel
>> * on and wait for it to become ready. If additional configuration is required
>> * (via a control bus such as I2C, SPI or DSI for example) this is a good time
>> * to do that.
>> *
>> * After the display controller has started transmitting video data, it's safe
>> * to call the .enable() function. This will typically enable the backlight to
>> * make the image on screen visible. Some panels require a certain amount of
>> * time or frames before the image is displayed. This function is responsible
>> * for taking this into account before enabling the backlight to avoid visual
>> * glitches.
>> *
>> * Before stopping video transmission from the display controller it can be
>> * necessary to turn off the panel to avoid visual glitches. This is done in
>> * the .disable() function. Analogously to .enable() this typically involves
>> * turning off the backlight and waiting for some time to make sure no image
>> * is visible on the panel. It is then safe for the display controller to
>> * cease transmission of video data.
>> *
>> * To save power when no video data is transmitted, a driver can power down
>> * the panel. This is the job of the .unprepare() function.
>> */
>
> It kind of make my point. When drm_panel_enable is called, the content
> is visible, and there's no extra delay needed.
>
> If what you want to fix is that the panel is enabled before the
> controller, hence resulting in garbage on the screen while the
> controller is setup, then your commit log is seriously misleading.
>
This is my interpretation of the patch. In fact, there's nothing that
says a panel must have any delays at all, so bringing up delays in the
commit log is pretty misleading.
That said, it seems like the panel hooks are in the right place after
this patch.
As an aside, it seems like (from the diff, I haven't looked at the
code) the bridge_pre_enable and bridge_post_disable calls are missing,
and the enable/disable calls are in the wrong place.
Sean
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
^ permalink raw reply
* [PATCH 1/3] arm: dts: imx7: Update #pwm-cells for PWM polarity control
From: Bhuvanchandra DV @ 2016-09-27 14:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160923175202.GA2816@rob-hp-laptop>
On 09/23/16 23:22, Rob Herring wrote:
> On Mon, Sep 19, 2016 at 07:53:45PM +0530, Bhuvanchandra DV wrote:
>> Update #pwm-cells to 3 in order to support PWM signal polarity control.
>>
>> Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
>> ---
>> Documentation/devicetree/bindings/pwm/imx-pwm.txt | 6 +++---
>> arch/arm/boot/dts/imx7s.dtsi | 8 ++++----
>> 2 files changed, 7 insertions(+), 7 deletions(-)
> The driver will still work with old DTs, right? If so,
This patchset actually depends on the v6 patchset[1] from Lothar.
Some how that patchset got stalled in ML. I will re-spin the v6
patchset with the suggestions/changes from Lukasz in this patch[2]
after testing.
[1]http://lists.infradead.org/pipermail/linux-arm-kernel/2014-October/294027.html
[2]https://www.spinics.net/lists/arm-kernel/msg530818.html
>
> Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [RFC] irqchip/gic-v3: Implement suspend and resume callbacks
From: Marc Zyngier @ 2016-09-27 14:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <57EA6774.2060807@codeaurora.org>
On Tue, 27 Sep 2016 18:05:00 +0530
Chandra Sekhar Lingutla <clingutla@codeaurora.org> wrote:
> On 09/21/2016 03:40 PM, Marc Zyngier wrote:
> > +Sudeep, Lorenzo,
> >
> > On 21/09/16 09:42, Lingutla Chandrasekhar wrote:
> >> Implement suspend and resume syscore_ops to disable and
> >> enable non wake up capable interrupts.
> >>
> >> When system enters suspend, enable only wakeup capable
> >> interrupts. While resuming, enable previously enabled interrupts
> >> and show triggered/pending interrupts.
> >
> > The fundamental problem (which you're not mentioning at all) is that the
> > GICv3 architecture doesn't mention wake-up interrupts at all, so this
> > has to be entirely handled in firmware. Is that what is happening?
> >
> >>
> >> Signed-off-by: Lingutla Chandrasekhar <clingutla@codeaurora.org>
> >>
> >> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> >> index ede5672..511a5a1 100644
> >> --- a/drivers/irqchip/irq-gic-v3.c
> >> +++ b/drivers/irqchip/irq-gic-v3.c
> >> @@ -33,6 +33,7 @@
> >> #include <linux/irqchip/arm-gic-common.h>
> >> #include <linux/irqchip/arm-gic-v3.h>
> >> #include <linux/irqchip/irq-partition-percpu.h>
> >> +#include <linux/syscore_ops.h>
> >>
> >> #include <asm/cputype.h>
> >> #include <asm/exception.h>
> >> @@ -57,6 +58,10 @@ struct gic_chip_data {
> >> u32 nr_redist_regions;
> >> unsigned int irq_nr;
> >> struct partition_desc *ppi_descs[16];
> >> +#ifdef CONFIG_PM
> >> + unsigned int wakeup_irqs[32];
> >> + unsigned int enabled_irqs[32];
> >
> > Do not use ambiguous types for something that comes from the HW. Where
> > does this '32' comes from?
> Expecting wakeup capable irq can be any of maximum 1024 interrupt lines, so
> used array of size 32 (32 * 32 bits).
And why only 1024? What about the PPIs? What about LPIs? You're
shoehorning your particular platform into something that caters for the
whole architecture, and that's not a very good move.
>
> >
> >> +#endif
> >> };
> >>
> >> static struct gic_chip_data gic_data __read_mostly;
> >> @@ -330,6 +335,81 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
> >> return 0;
> >> }
> >>
> >> +#ifdef CONFIG_PM
> >> +static int gic_suspend(void)
> >> +{
> >> + unsigned int i;
> >> + void __iomem *base = gic_data.dist_base;
> >> +
> >> + for (i = 0; i * 32 < gic->irq_nr; i++) {
> >> + gic->enabled_irqs[i]
> >> + = readl_relaxed(base + GICD_ISENABLER + i * 4);
> >
> > Do you realize that GICD_ISENABLER0 is always zero? What do you do for
> > PPIs? Please keep the assignment on a single line.
> Agreed, will update.
>
> >
> >> + /* disable all of them */
> >> + writel_relaxed(0xffffffff, base + GICD_ICENABLER + i * 4);
> >> + /* enable the wakeup set */
> >> + writel_relaxed(gic->wakeup_irqs[i],
> >> + base + GICD_ISENABLER + i * 4);
> >
> > On a single line as well.
> >
> >> + }
> >> + return 0;
> >> +}
> >> +
> >> +static void gic_show_pending(void)
> >> +{
> >> + unsigned int i;
> >> + u32 enabled;
> >> + u32 pending[32];
> >> + void __iomem *base = gic_data.dist_base;
> >> +
> >> + for (i = 0; i * 32 < gic->irq_nr; i++) {
> >> + enabled = readl_relaxed(base + GICD_ICENABLER + i * 4);
> >> + pending[i] = readl_relaxed(base + GICD_ISPENDR + i * 4);
> >> + pending[i] &= enabled;
> >> + }
> >> +
> >> + for_each_set_bit(i, (unsigned long *)pending, gic->irq_nr) {
> >> + unsigned int irq = irq_find_mapping(gic->domain, i);
> >> + struct irq_desc *desc = irq_to_desc(irq);
> >> + const char *name = "null";
> >> +
> >> + if (desc == NULL)
> >> + name = "stray irq";
> >> + else if (desc->action && desc->action->name)
> >> + name = desc->action->name;
> >> +
> >> + pr_debug("Pending IRQ: %d [%s]\n", __func__, irq, name);
> >> + }
> >> +}
> >
> > Please drop this function from this patch, it doesn't serve any purpose
> > other than your own debugging.
> >
> I think, this function is useful for debugging to know wakeup reason.
> Can we move this function under PM_DEBUG flag or debugfs entry ?
No. I want this code entirely gone. If we need more debugging code than
we already have, then it needs to be added at the generic level, and
not for the perceived benefit of a single interrupt controller.
>
> >> +
> >> +static void gic_resume(void)
> >> +{
> >> + unsigned int i;
> >> + void __iomem *base = gic_data.dist_base;
> >> +
> >> + gic_show_pending();
> >> +
> >> + for (i = 0; i * 32 < gic->irq_nr; i++) {
> >> + /* disable all of them */
> >> + writel_relaxed(0xffffffff, base + GICD_ICENABLER + i * 4);
> >> + /* enable the enabled set */
> >> + writel_relaxed(gic->enabled_irqs[i],
> >> + base + GICD_ISENABLER + i * 4);
> >
> > Same remarks as the suspend side.
> >
> >> + }
> >> +}
> >> +
> >> +static struct syscore_ops gic_syscore_ops = {
> >> + .suspend = gic_suspend,
> >> + .resume = gic_resume,
> >> +};
> >> +
> >> +static int __init gic_init_sys(void)
> >> +{
> >> + register_syscore_ops(&gic_syscore_ops);
> >> + return 0;
> >> +}
> >> +device_initcall(gic_init_sys);
> >> +
> >> +#endif
> >> +
> >> static u64 gic_mpidr_to_affinity(unsigned long mpidr)
> >> {
> >> u64 aff;
> >> @@ -666,6 +746,32 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
> >> #define gic_smp_init() do { } while(0)
> >> #endif
> >>
> >> +#ifdef CONFIG_PM
> >> +int gic_set_wake(struct irq_data *d, unsigned int on)
> >> +{
> >> + int ret = -ENXIO;
> >> + unsigned int reg_offset, bit_offset;
> >> + unsigned int gicirq = gic_irq(d);
> >> + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
> >> +
> >> + /* per-cpu interrupts cannot be wakeup interrupts */
> >> + WARN_ON(gicirq < 32);
> >
> > How did you decide that? There is no such specification anywhere.
> >
> I am basically looking at system suspend, where cores would be in power collapse.
And? Why would that be exclusive of PPIs? Again, you seem to have a
very restrictive view of what should (or shouldn't) be supported.
>
> >> +
> >> + reg_offset = gicirq / 32;
> >> + bit_offset = gicirq % 32;
> >> +
> >> + if (on)
> >> + gic_data->wakeup_irqs[reg_offset] |= 1 << bit_offset;
> >> + else
> >> + gic_data->wakeup_irqs[reg_offset] &= ~(1 << bit_offset);
> >> +
> >> + return ret;
> >> +}
> >> +
> >> +#else
> >> +#define gic_set_wake NULL
> >> +#endif
> >> +
> >> #ifdef CONFIG_CPU_PM
> >> /* Check whether it's single security state view */
> >> static bool gic_dist_security_disabled(void)
> >> @@ -707,6 +813,7 @@ static struct irq_chip gic_chip = {
> >> .irq_eoi = gic_eoi_irq,
> >> .irq_set_type = gic_set_type,
> >> .irq_set_affinity = gic_set_affinity,
> >> + .irq_set_wake = gic_set_wake,
> >> .irq_get_irqchip_state = gic_irq_get_irqchip_state,
> >> .irq_set_irqchip_state = gic_irq_set_irqchip_state,
> >> .flags = IRQCHIP_SET_TYPE_MASKED,
> >> @@ -723,6 +830,7 @@ static struct irq_chip gic_eoimode1_chip = {
> >> .irq_set_irqchip_state = gic_irq_set_irqchip_state,
> >> .irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity,
> >> .flags = IRQCHIP_SET_TYPE_MASKED,
> >> + .irq_set_wake = gic_set_wake,
> >
> > Keep the fields in the same order.
> >
> >> };
> >>
> >> #define GIC_ID_NR (1U << gic_data.rdists.id_bits)
> >>
> >
> > But here's my fundamental objection: None of that should be required and
> > setting (IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND) as part of the
> > irqchip flags should be enough.
> >
> > Can you explain why this doesn't work for you?
> >
> These flags work for me, I will remove suspend/resume functions, but i think
> it is very useful to know the wakeup source for debugging purposes.
> Please let me know, if you have any better way to achieve this.
We already have extensive sysfs features for this. If that's not
enough, please state exactly what is missing and we'll discuss how to
add it at the generic infrastructure level.
Thanks,
M.
--
Jazz is not dead. It just smells funny.
^ permalink raw reply
* [PATCHv3 3/3] tty/serial: at91: fix hardware handshake on SAM9x5 (without GPIOs)
From: Richard Genoud @ 2016-09-27 14:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160927141313.27668-1-richard.genoud@gmail.com>
Commit 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when
hardware handshake is enabled") broke the hardware handshake on SAM9x5
platforms.
On Atmel platforms, the USART can only handle the handware handshake
(ATMEL_US_USMODE_HWHS) if FIFOs or PDC are used.
Thus, ATMEL_US_USMODE_HWHS mode should only be used in this case.
For SAM9x5, there's no FIFOs nor PDC for the USART, so the mode should
be ATMEL_US_USMODE_NORMAL and the RTS pin should be controlled by the
driver.
NB: -stable is not Cced because it doesn't cleanly apply on 4.1+
Tested on SAM9G35-CM with and without DMA
Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
Fixes: 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when hardware handshake is enabled")
---
drivers/tty/serial/atmel_serial.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 14467d5e060b..f644d5dcf6d1 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -2131,19 +2131,23 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
port->rs485.delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485;
} else if ((termios->c_cflag & CRTSCTS) &&
- !mctrl_gpio_use_rtscts(atmel_port->gpios)) {
+ !mctrl_gpio_use_rtscts(atmel_port->gpios) &&
+ (atmel_use_pdc_rx(port) || atmel_use_fifo(port))) {
/*
- * RS232 with hardware handshake (RTS/CTS)
- * handled by the controller.
+ * Automatic hardware handshake (RTS/CTS) only work with
+ * FIFOs or PDC.
+ * Meaning that on SAM9x5 the controller can't handle
+ * the hardware handshake (no FIFOs nor PDC on these platforms).
*/
- if (atmel_use_dma_rx(port) && !atmel_use_fifo(port)) {
- dev_info(port->dev, "not enabling hardware flow control because DMA is used");
- termios->c_cflag &= ~CRTSCTS;
- } else {
- mode |= ATMEL_US_USMODE_HWHS;
- }
+ mode |= ATMEL_US_USMODE_HWHS;
} else {
- /* RS232 without hardware handshake or controlled by GPIOs */
+ /*
+ * Other cases are:
+ * - RS232 without hardware handshake
+ * - RS232 with hardware handshake and:
+ * - controller unable to handle CTS/RTS by itself
+ * - or CTS/RTS handled by GPIOs
+ */
mode |= ATMEL_US_USMODE_NORMAL;
}
^ permalink raw reply related
* [PATCHv3 2/3] tty/serial: at91: fix hardware handshake with GPIOs
From: Richard Genoud @ 2016-09-27 14:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160927141313.27668-1-richard.genoud@gmail.com>
Commit 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when
hardware handshake is enabled") broke the hardware handshake when GPIOs
were used.
Hardware handshake with GPIOs used to work before this commit because
the CRTSCTS flag (termios->c_cflag) was set, but not the
ATMEL_US_USMODE_HWHS flag (controller register) ; so hardware handshake
enabled, but not handled by the controller.
This commit restores this behaviour.
NB: -stable is not Cced because it doesn't cleanly apply on 4.1+
and it will also need previous commit:
"serial: mctrl_gpio: implement mctrl_gpio_use_rtscts"
Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Fixes: 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when hardware handshake is enabled")
---
drivers/tty/serial/atmel_serial.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 5f550d9feed9..14467d5e060b 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -2130,8 +2130,12 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
atmel_uart_writel(port, ATMEL_US_TTGR,
port->rs485.delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485;
- } else if (termios->c_cflag & CRTSCTS) {
- /* RS232 with hardware handshake (RTS/CTS) */
+ } else if ((termios->c_cflag & CRTSCTS) &&
+ !mctrl_gpio_use_rtscts(atmel_port->gpios)) {
+ /*
+ * RS232 with hardware handshake (RTS/CTS)
+ * handled by the controller.
+ */
if (atmel_use_dma_rx(port) && !atmel_use_fifo(port)) {
dev_info(port->dev, "not enabling hardware flow control because DMA is used");
termios->c_cflag &= ~CRTSCTS;
@@ -2139,7 +2143,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
mode |= ATMEL_US_USMODE_HWHS;
}
} else {
- /* RS232 without hadware handshake */
+ /* RS232 without hardware handshake or controlled by GPIOs */
mode |= ATMEL_US_USMODE_NORMAL;
}
^ permalink raw reply related
* [PATCHv3 1/3] serial: mctrl_gpio: implement mctrl_gpio_use_rtscts
From: Richard Genoud @ 2016-09-27 14:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160927141313.27668-1-richard.genoud@gmail.com>
This function returns true if CTS and RTS are used as GPIOs.
Some drivers (like atmel_serial) needs to know if the flow control is
handled by the controller or by GPIOs.
Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
drivers/tty/serial/serial_mctrl_gpio.c | 8 ++++++++
drivers/tty/serial/serial_mctrl_gpio.h | 10 ++++++++++
2 files changed, 18 insertions(+)
diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c
index d2da6aa7f27d..0e5525a64c2a 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.c
+++ b/drivers/tty/serial/serial_mctrl_gpio.c
@@ -17,6 +17,7 @@
#include <linux/err.h>
#include <linux/device.h>
#include <linux/irq.h>
+#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/termios.h>
#include <linux/serial_core.h>
@@ -72,6 +73,13 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
}
EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod);
+bool mctrl_gpio_use_rtscts(struct mctrl_gpios *gpios)
+{
+ return mctrl_gpio_to_gpiod(gpios, UART_GPIO_CTS) &&
+ mctrl_gpio_to_gpiod(gpios, UART_GPIO_RTS);
+}
+EXPORT_SYMBOL_GPL(mctrl_gpio_use_rtscts);
+
unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
{
enum mctrl_gpio_idx i;
diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h
index fa000bcff217..c34269733c62 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.h
+++ b/drivers/tty/serial/serial_mctrl_gpio.h
@@ -101,6 +101,11 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios);
*/
void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios);
+/*
+ * Return true if both CTS and RTS are used with GPIOs
+ */
+bool mctrl_gpio_use_rtscts(struct mctrl_gpios *gpios);
+
#else /* GPIOLIB */
static inline
@@ -152,6 +157,11 @@ static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
{
}
+static inline bool mctrl_gpio_use_rtscts(struct mctrl_gpios *gpios)
+{
+ return false;
+}
+
#endif /* GPIOLIB */
#endif
^ permalink raw reply related
* [PATCHv3 0/3] Fix hardware handshake on SAM9x5 platforms
From: Richard Genoud @ 2016-09-27 14:13 UTC (permalink / raw)
To: linux-arm-kernel
Since commit 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when
hardware handshake is enabled"), hardware handshake is not working
anymore on SAM9x5/SAMA5D3/SAM9 platforms.
The first two patches fix the hardware handshake when CTS/RTS pins are
handled by GPIOs.
The last patch fixes hardware handshake when CTS/RTS pins are not GPIOs.
Changes since v2:
- remove IS_ERR_OR_NULL() test in patch 1/3 as Uwe suggested.
- fix typos in patch 2/3
- rebase on next-20160927
- simplify the logic in patch 3/3.
Changes since v1:
- Correct patch 1 with the error found by kbuild.
- Add Alexandre's Acked-by on patch 2
- Rewrite patch 3 logic in the light of the on-going discussion
with Cyrille and Alexandre.
NB: patch 2 NEEDS patch 1 to compile.
Richard Genoud (3):
serial: mctrl_gpio: implement mctrl_gpio_use_rtscts
tty/serial: at91: fix hardware handshake with GPIOs
tty/serial: at91: fix hardware handshake on SAM9x5 (without GPIOs)
drivers/tty/serial/atmel_serial.c | 26 +++++++++++++++++---------
drivers/tty/serial/serial_mctrl_gpio.c | 8 ++++++++
drivers/tty/serial/serial_mctrl_gpio.h | 10 ++++++++++
3 files changed, 35 insertions(+), 9 deletions(-)
^ permalink raw reply
* [PATCH 5/5] arm64: Add uprobe support
From: Catalin Marinas @ 2016-09-27 13:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160926130359.GA9370@localhost.localdomain>
On Mon, Sep 26, 2016 at 06:33:59PM +0530, Pratyush Anand wrote:
> On 26/09/2016:12:01:59 PM, Catalin Marinas wrote:
> > On Sun, Sep 25, 2016 at 10:32:28PM +0530, Pratyush Anand wrote:
> > > On Fri, Sep 23, 2016 at 6:35 PM, Catalin Marinas
> > > <catalin.marinas@arm.com> wrote:
> > > > On Fri, Sep 23, 2016 at 09:42:30AM +0530, Pratyush Anand wrote:
> > > >> On 22/09/2016:05:50:30 PM, Catalin Marinas wrote:
> > > >> > On Thu, Sep 22, 2016 at 08:53:28AM +0530, Pratyush Anand wrote:
> > > >> > > On 21/09/2016:06:04:04 PM, Catalin Marinas wrote:
> > >
> > > >> > As a quick workaround you could check mm->task_size > TASK_SIZE_32 in
> > > >> > the arch_uprobe_analyze_insn() function.
> > > >>
> > > >> It would be doable. TASK_SIZE_32 is defined only for COMPAT. So, may be I can
> > > >> return -EINVAL when mm->task_size < TASK_SIZE_64.
> > > >
> > > > That's just a temporary workaround. If we ever merge ILP32, this test
> > > > would no longer be enough (as the ISA is AArch64 but with TASK_SIZE_32).
> > >
> > > OK.. So what about doing something similar what x86 is doing.
> > > We can have a flag for task Type in arch specific mm_context_t. We
> > > also set this flag in COMPAT_SET_PERSONALITY() along with setting
> > > thread_info flag, and we clear them in SET_PERSONALITY().
> >
> > This looks like a better approach.
> >
> > > > Looking at prepare_uprobe(), we have a weak is_trap_insn() function.
> > > > This check is meaningless without knowing which instruction set we
> > > > target. A false positive here, however, is not that bad as we wouldn't
> > > > end up inserting the wrong breakpoint in the executable. But it looks to
> > > > me like the core uprobe code needs to pass some additional information
> > > > like the type of task or ELF format to the arch code to make a useful
> > > > choice of breakpoint type.
> > >
> > > It seems that 'strtle r0, [r0], #160' would have the closest matching
> > > aarch32 instruction wrt BRK64_OPCODE_UPROBES(0xd42000A0). But that too
> > > seems a bad instruction. So, may be we can use still weak
> > > is_trap_insn().
> >
> > Even if the is_trap_insn() check passes, we would reject the probe in
> > arch_uprobe_analyze_insn() immediately after based on the mm type check,
> > so not too bad.
>
> OK..I will have an always returning false from arm64 is_trap_insn() in v2.
For the time being, I think the default is_trap_insn() check is still
useful on arm64. The problem gets trickier when we add AArch32 support
as it may return 'true' on an AArch32 instruction that matches the
AArch64 BRK (or vice-versa). That's when we need to either pass the mm
to is_trap_insn() or simply return false and always perform the check in
the arch_uprobe_analyze_insn() (which should, in addition, check for the
trap instruction).
There is also the is_trap_at_addr() function which uses is_trap_insn().
I haven't checked the call paths here, are there any implications if
is_trap_insn() always returns false?
--
Catalin
^ permalink raw reply
* [PATCH 3/3] coresight: tmc: Remove duplicate memset
From: Suzuki K Poulose @ 2016-09-27 13:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474983865-11816-1-git-send-email-suzuki.poulose@arm.com>
The tmc_etr_enable_hw() fills the buffer with 0's before enabling
the hardware. So, we don't need an explicit memset() in
tmc_enable_etr_sink_sysfs() before calling the tmc_etr_enable_hw().
This patch removes the explicit memset from tmc_enable_etr_sink_sysfs.
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc-etr.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 3b84d0d..5d31269 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -150,8 +150,6 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
drvdata->buf = drvdata->vaddr;
}
- memset(drvdata->vaddr, 0, drvdata->size);
-
drvdata->mode = CS_MODE_SYSFS;
tmc_etr_enable_hw(drvdata);
out:
--
2.7.4
^ permalink raw reply related
* [PATCH 2/3] coresight: tmc: Get rid of mode parameter for helper routines
From: Suzuki K Poulose @ 2016-09-27 13:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474983865-11816-1-git-send-email-suzuki.poulose@arm.com>
Get rid of the superfluous mode parameter and the check for
the mode in tmc_etX_enable_sink_{perf/sysfs}. While at it, also
remove the unnecessary WARN_ON() checks.
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc-etf.c | 18 +++++-------------
drivers/hwtracing/coresight/coresight-tmc-etr.c | 15 ++++-----------
2 files changed, 9 insertions(+), 24 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index e80a8f4..1549436 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -103,7 +103,7 @@ static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
CS_LOCK(drvdata->base);
}
-static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
{
int ret = 0;
bool used = false;
@@ -111,10 +111,6 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- /* This shouldn't be happening */
- if (WARN_ON(mode != CS_MODE_SYSFS))
- return -EINVAL;
-
/*
* If we don't have a buffer release the lock and allocate memory.
* Otherwise keep the lock and move along.
@@ -176,16 +172,12 @@ out:
return ret;
}
-static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etf_sink_perf(struct coresight_device *csdev)
{
int ret = 0;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- /* This shouldn't be happening */
- if (WARN_ON(mode != CS_MODE_PERF))
- return -EINVAL;
-
spin_lock_irqsave(&drvdata->spinlock, flags);
if (drvdata->reading) {
ret = -EINVAL;
@@ -202,7 +194,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
goto out;
}
- drvdata->mode = mode;
+ drvdata->mode = CS_MODE_PERF;
tmc_etb_enable_hw(drvdata);
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -214,9 +206,9 @@ static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
{
switch (mode) {
case CS_MODE_SYSFS:
- return tmc_enable_etf_sink_sysfs(csdev, mode);
+ return tmc_enable_etf_sink_sysfs(csdev);
case CS_MODE_PERF:
- return tmc_enable_etf_sink_perf(csdev, mode);
+ return tmc_enable_etf_sink_perf(csdev);
}
/* We shouldn't be here */
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index f23ef0c..3b84d0d 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -93,7 +93,7 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
CS_LOCK(drvdata->base);
}
-static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
{
int ret = 0;
bool used = false;
@@ -102,9 +102,6 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
dma_addr_t paddr;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- /* This shouldn't be happening */
- if (WARN_ON(mode != CS_MODE_SYSFS))
- return -EINVAL;
/*
* If we don't have a buffer release the lock and allocate memory.
@@ -170,16 +167,12 @@ out:
return ret;
}
-static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etr_sink_perf(struct coresight_device *csdev)
{
int ret = 0;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- /* This shouldn't be happening */
- if (WARN_ON(mode != CS_MODE_PERF))
- return -EINVAL;
-
spin_lock_irqsave(&drvdata->spinlock, flags);
if (drvdata->reading) {
ret = -EINVAL;
@@ -208,9 +201,9 @@ static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
{
switch (mode) {
case CS_MODE_SYSFS:
- return tmc_enable_etr_sink_sysfs(csdev, mode);
+ return tmc_enable_etr_sink_sysfs(csdev);
case CS_MODE_PERF:
- return tmc_enable_etr_sink_perf(csdev, mode);
+ return tmc_enable_etr_sink_perf(csdev);
}
/* We shouldn't be here */
--
2.7.4
^ permalink raw reply related
* [PATCH 1/3] coresight: tmc: Cleanup operation mode handling
From: Suzuki K Poulose @ 2016-09-27 13:44 UTC (permalink / raw)
To: linux-arm-kernel
The mode of operation of the TMC tracked in drvdata->mode is defined
as a local_t type. This is always checked and modified under the
drvdata->spinlock and hence we don't need local_t for it and the
unnecessary synchronisation instructions that comes with it. This
change makes the code a bit more cleaner.
Also fixes the order in which we update the drvdata->mode to
CS_MODE_DISABLED. i.e, in tmc_disable_etX_sink we change the
mode to CS_MODE_DISABLED before invoking tmc_disable_etX_hw()
which in turn depends on the mode to decide whether to dump the
trace to a buffer.
Applies on mathieu's coresight/next tree [1]
https://git.linaro.org/kernel/coresight.git next
Reported-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@broadcom.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc-etf.c | 32 +++++++++++--------------
drivers/hwtracing/coresight/coresight-tmc-etr.c | 26 +++++++++-----------
drivers/hwtracing/coresight/coresight-tmc.h | 2 +-
3 files changed, 26 insertions(+), 34 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index d6941ea..e80a8f4 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -70,7 +70,7 @@ static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
* When operating in sysFS mode the content of the buffer needs to be
* read before the TMC is disabled.
*/
- if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+ if (drvdata->mode == CS_MODE_SYSFS)
tmc_etb_dump_hw(drvdata);
tmc_disable_hw(drvdata);
@@ -108,7 +108,6 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
int ret = 0;
bool used = false;
char *buf = NULL;
- long val;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -138,13 +137,12 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
goto out;
}
- val = local_xchg(&drvdata->mode, mode);
/*
* In sysFS mode we can have multiple writers per sink. Since this
* sink is already enabled no memory is needed and the HW need not be
* touched.
*/
- if (val == CS_MODE_SYSFS)
+ if (drvdata->mode == CS_MODE_SYSFS)
goto out;
/*
@@ -163,6 +161,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
drvdata->buf = buf;
}
+ drvdata->mode = CS_MODE_SYSFS;
tmc_etb_enable_hw(drvdata);
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -180,7 +179,6 @@ out:
static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
{
int ret = 0;
- long val;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -194,17 +192,17 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
goto out;
}
- val = local_xchg(&drvdata->mode, mode);
/*
* In Perf mode there can be only one writer per sink. There
* is also no need to continue if the ETB/ETR is already operated
* from sysFS.
*/
- if (val != CS_MODE_DISABLED) {
+ if (drvdata->mode != CS_MODE_DISABLED) {
ret = -EINVAL;
goto out;
}
+ drvdata->mode = mode;
tmc_etb_enable_hw(drvdata);
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -227,7 +225,6 @@ static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
static void tmc_disable_etf_sink(struct coresight_device *csdev)
{
- long val;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -237,10 +234,11 @@ static void tmc_disable_etf_sink(struct coresight_device *csdev)
return;
}
- val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
/* Disable the TMC only if it needs to */
- if (val != CS_MODE_DISABLED)
+ if (drvdata->mode != CS_MODE_DISABLED) {
tmc_etb_disable_hw(drvdata);
+ drvdata->mode = CS_MODE_DISABLED;
+ }
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -260,7 +258,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
}
tmc_etf_enable_hw(drvdata);
- local_set(&drvdata->mode, CS_MODE_SYSFS);
+ drvdata->mode = CS_MODE_SYSFS;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
dev_info(drvdata->dev, "TMC-ETF enabled\n");
@@ -280,7 +278,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
}
tmc_etf_disable_hw(drvdata);
- local_set(&drvdata->mode, CS_MODE_DISABLED);
+ drvdata->mode = CS_MODE_DISABLED;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
dev_info(drvdata->dev, "TMC disabled\n");
@@ -383,7 +381,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
return;
/* This shouldn't happen */
- if (WARN_ON_ONCE(local_read(&drvdata->mode) != CS_MODE_PERF))
+ if (WARN_ON_ONCE(drvdata->mode != CS_MODE_PERF))
return;
CS_UNLOCK(drvdata->base);
@@ -504,7 +502,6 @@ const struct coresight_ops tmc_etf_cs_ops = {
int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
{
- long val;
enum tmc_mode mode;
int ret = 0;
unsigned long flags;
@@ -528,9 +525,8 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
goto out;
}
- val = local_read(&drvdata->mode);
/* Don't interfere if operated from Perf */
- if (val == CS_MODE_PERF) {
+ if (drvdata->mode == CS_MODE_PERF) {
ret = -EINVAL;
goto out;
}
@@ -542,7 +538,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
}
/* Disable the TMC if need be */
- if (val == CS_MODE_SYSFS)
+ if (drvdata->mode == CS_MODE_SYSFS)
tmc_etb_disable_hw(drvdata);
drvdata->reading = true;
@@ -573,7 +569,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
}
/* Re-enable the TMC if need be */
- if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
+ if (drvdata->mode == CS_MODE_SYSFS) {
/*
* The trace run will continue with the same allocated trace
* buffer. As such zero-out the buffer so that we don't end
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 886ea83..f23ef0c 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -86,7 +86,7 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
* When operating in sysFS mode the content of the buffer needs to be
* read before the TMC is disabled.
*/
- if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+ if (drvdata->mode == CS_MODE_SYSFS)
tmc_etr_dump_hw(drvdata);
tmc_disable_hw(drvdata);
@@ -97,7 +97,6 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
{
int ret = 0;
bool used = false;
- long val;
unsigned long flags;
void __iomem *vaddr = NULL;
dma_addr_t paddr;
@@ -134,13 +133,12 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
goto out;
}
- val = local_xchg(&drvdata->mode, mode);
/*
* In sysFS mode we can have multiple writers per sink. Since this
* sink is already enabled no memory is needed and the HW need not be
* touched.
*/
- if (val == CS_MODE_SYSFS)
+ if (drvdata->mode == CS_MODE_SYSFS)
goto out;
/*
@@ -157,6 +155,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
memset(drvdata->vaddr, 0, drvdata->size);
+ drvdata->mode = CS_MODE_SYSFS;
tmc_etr_enable_hw(drvdata);
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -174,7 +173,6 @@ out:
static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
{
int ret = 0;
- long val;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -188,17 +186,17 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
goto out;
}
- val = local_xchg(&drvdata->mode, mode);
/*
* In Perf mode there can be only one writer per sink. There
* is also no need to continue if the ETR is already operated
* from sysFS.
*/
- if (val != CS_MODE_DISABLED) {
+ if (drvdata->mode != CS_MODE_DISABLED) {
ret = -EINVAL;
goto out;
}
+ drvdata->mode = CS_MODE_PERF;
tmc_etr_enable_hw(drvdata);
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -221,7 +219,6 @@ static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
static void tmc_disable_etr_sink(struct coresight_device *csdev)
{
- long val;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -231,10 +228,11 @@ static void tmc_disable_etr_sink(struct coresight_device *csdev)
return;
}
- val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
/* Disable the TMC only if it needs to */
- if (val != CS_MODE_DISABLED)
+ if (drvdata->mode != CS_MODE_DISABLED) {
tmc_etr_disable_hw(drvdata);
+ drvdata->mode = CS_MODE_DISABLED;
+ }
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -253,7 +251,6 @@ const struct coresight_ops tmc_etr_cs_ops = {
int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
{
int ret = 0;
- long val;
unsigned long flags;
/* config types are set a boot time and never change */
@@ -266,9 +263,8 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
goto out;
}
- val = local_read(&drvdata->mode);
/* Don't interfere if operated from Perf */
- if (val == CS_MODE_PERF) {
+ if (drvdata->mode == CS_MODE_PERF) {
ret = -EINVAL;
goto out;
}
@@ -280,7 +276,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
}
/* Disable the TMC if need be */
- if (val == CS_MODE_SYSFS)
+ if (drvdata->mode == CS_MODE_SYSFS)
tmc_etr_disable_hw(drvdata);
drvdata->reading = true;
@@ -303,7 +299,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
spin_lock_irqsave(&drvdata->spinlock, flags);
/* RE-enable the TMC if need be */
- if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
+ if (drvdata->mode == CS_MODE_SYSFS) {
/*
* The trace run will continue with the same allocated trace
* buffer. The trace buffer is cleared in tmc_etr_enable_hw(),
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 44b3ae3..51c0185 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -117,7 +117,7 @@ struct tmc_drvdata {
void __iomem *vaddr;
u32 size;
u32 len;
- local_t mode;
+ u32 mode;
enum tmc_config_type config_type;
enum tmc_mem_intf_width memwidth;
u32 trigger_cntr;
--
2.7.4
^ permalink raw reply related
* [PATCH 2/2] drm/rockchip: analogix_dp: Refuse to enable PSR if panel doesn't support it
From: Sean Paul @ 2016-09-27 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474639600-30090-2-git-send-email-tomeu.vizoso@collabora.com>
On Fri, Sep 23, 2016 at 10:06 AM, Tomeu Vizoso
<tomeu.vizoso@collabora.com> wrote:
> There's no point in enabling PSR when the panel doesn't support it.
>
> This also avoids a problem when PSR gets enabled when a CRTC is being
> disabled, because sometimes in that situation the DSP_HOLD_VALID_INTR
> interrupt on which we wait will never arrive. This was observed on
> RK3288 with a panel without PSR (veyron-jaq Chromebook).
>
> It's very easy to reproduce by running the kms_rmfb test in IGT a few
> times.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Thanks for digging into this.
Reviewed-by: Sean Paul <seanpaul@chromium.org>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: Yakir Yang <ykk@rock-chips.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> ---
> drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
> index e83be157cc2a..8548e8271639 100644
> --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
> @@ -85,6 +85,9 @@ static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
> struct rockchip_dp_device *dp = to_dp(encoder);
> unsigned long flags;
>
> + if (!analogix_dp_psr_supported(dp->dev))
> + return;
> +
> dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
>
> spin_lock_irqsave(&dp->psr_lock, flags);
> --
> 2.7.4
>
^ permalink raw reply
* [RFC] irqchip/gic-v3: Implement suspend and resume callbacks
From: Sudeep Holla @ 2016-09-27 13:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <57EA6774.2060807@codeaurora.org>
On 27/09/16 13:35, Chandra Sekhar Lingutla wrote:
> On 09/21/2016 03:40 PM, Marc Zyngier wrote:
>> +Sudeep, Lorenzo,
[...]
>>
>> But here's my fundamental objection: None of that should be required and
>> setting (IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND) as part of the
>> irqchip flags should be enough.
>>
>> Can you explain why this doesn't work for you?
>>
> These flags work for me, I will remove suspend/resume functions, but i
> think it is very useful to know the wakeup source for debugging purposes.
> Please let me know, if you have any better way to achieve this.
>
I don't understand what's missing ? As the user you can set the wakeup
source if it's wakeup capable. You will find the sysfs entries which can
say if it's enabled or not. You can use the same to enable it.
I am not sure what you mean by "it is very useful to know the wakeup
source for debugging purposes".
--
Regards,
Sudeep
^ permalink raw reply
* [PATCH 5/5] tty: amba-pl011: Add earlycon support for SBSA UART
From: Kefeng Wang @ 2016-09-27 13:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160927105748.GA3847@kroah.com>
On 2016/9/27 18:57, Greg Kroah-Hartman wrote:
> On Sat, Sep 24, 2016 at 05:14:25PM +0800, Kefeng Wang wrote:
>> Declare an OF early console for SBSA UART so that the early console device
>> can be specified via the "stdout-path" property in device-tree.
>>
>> Cc: Russell King <linux@armlinux.org.uk>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
>> ---
>> drivers/tty/serial/amba-pl011.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
>> index 7d9b291..3688d3b 100644
>> --- a/drivers/tty/serial/amba-pl011.c
>> +++ b/drivers/tty/serial/amba-pl011.c
>> @@ -2330,6 +2330,7 @@ static int __init pl011_early_console_setup(struct earlycon_device *device,
>> return 0;
>> }
>> OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
>> +OF_EARLYCON_DECLARE(pl011, "arm,sbsa-uart", pl011_early_console_setup);
>
> Why do you need another option for the same thing?
It is used to support earlycon(without option) for sbsa-uart in bootargs.
chosen {
stdout-path = "serial0:115200n8";
bootargs = "earlycon"
};
uart0: uart at 602b0000 {
compatible = "arm,sbsa-uart";
reg = <0x0 0x602b0000 0x0 0x1000>;
...
};
We setup a unique struct with compatible name by OF_EARLYCON_DECLARE,
#define OF_EARLYCON_DECLARE(_name, compat, fn) \
static const struct earlycon_id __UNIQUE_ID(__earlycon_##_name) \
__used __section(__earlycon_table) \
= { .name = __stringify(_name), \
.compatible = compat, \
.setup = fn }
if without this patch(see drivers/of/fdt.c),
early_init_dt_scan_chosen_serial()
- for (match = __earlycon_table; match < __earlycon_table_end; match++)
-- if (fdt_node_check_compatible(fdt, offset, match->compatible))
countinue;
-- of_setup_earlycon(match, offset, options); // will never touch here.
Thanks,
Kefeng
>
> confused,
>
> greg k-h
>
> .
>
^ permalink raw reply
* [PATCH v2 3/8] i2c: bcm2835: Use ratelimited logging on transfer errors
From: Martin Sperl @ 2016-09-27 13:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474977426-3272-4-git-send-email-noralf@tronnes.org>
> On 27 Sep 2016, at 13:57, Noralf Tr?nnes <noralf@tronnes.org> wrote:
>
> Writing to an AT24C32 generates on average 2x i2c transfer errors per
> 32-byte page write. Which amounts to a lot for a 4k write. This is due
> to the fact that the chip doesn't respond during it's internal write
> cycle when the at24 driver tries and retries the next write.
> Reduce this flooding of the log by using dev_err_ratelimited().
>
> Signed-off-by: Noralf Tr?nnes <noralf@tronnes.org>
> Reviewed-by: Eric Anholt <eric@anholt.net>
> ---
> drivers/i2c/busses/i2c-bcm2835.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
> index df036ed..370a322 100644
> --- a/drivers/i2c/busses/i2c-bcm2835.c
> +++ b/drivers/i2c/busses/i2c-bcm2835.c
> @@ -207,7 +207,8 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
> (msg->flags & I2C_M_IGNORE_NAK))
> return 0;
>
> - dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
> + dev_err_ratelimited(i2c_dev->dev, "i2c transfer failed: %x\n",
> + i2c_dev->msg_err);
Do we really need this error message at all?
Maybe just remove it instead, because error messages during
"normal"/successfull operations of at24 seems strange.
Or make it a debug message instead.
Martin
^ permalink raw reply
* [PATCH] ARM: decompressor: reset ttbcr fields to use TTBR0 on ARMv7
From: Robin Murphy @ 2016-09-27 12:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <57EA632C.3000208@codeaurora.org>
On 27/09/16 13:16, Srinivas Ramana wrote:
> Hi Robin,
Sorry! This one had slipped my mind already...
> On 09/13/2016 08:22 PM, Srinivas Ramana wrote:
>> On 09/12/2016 11:21 PM, Robin Murphy wrote:
>>> On 12/09/16 07:57, Srinivas Ramana wrote:
>>>> If the bootloader uses the long descriptor format and jumps to
>>>> kernel decompressor code, TTBCR may not be in a right state.
>>>> Before enabling the MMU, it is required to clear the TTBCR.PD0
>>>> field to use TTBR0 for translation table walks.
>>>>
>>>> The 'commit dbece45894d3a ("ARM: 7501/1: decompressor:
>>>> reset ttbcr for VMSA ARMv7 cores")' does the reset of TTBCR.N, but
>>>> doesn't consider all the bits for the size of TTBCR.N.
>>>>
>>>> Clear TTBCR.PD0 field and reset all the three bits of TTBCR.N to
>>>> indicate the use of TTBR0 and the correct base address width.
>>>>
>>>> Signed-off-by: Srinivas Ramana <sramana@codeaurora.org>
>>>> ---
>>>> arch/arm/boot/compressed/head.S | 2 +-
>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/arm/boot/compressed/head.S
>>>> b/arch/arm/boot/compressed/head.S
>>>> index af11c2f8f3b7..fc6d541549a2 100644
>>>> --- a/arch/arm/boot/compressed/head.S
>>>> +++ b/arch/arm/boot/compressed/head.S
>>>> @@ -779,7 +779,7 @@ __armv7_mmu_cache_on:
>>>> orrne r0, r0, #1 @ MMU enabled
>>>> movne r1, #0xfffffffd @ domain 0 = client
>>>> bic r6, r6, #1 << 31 @ 32-bit translation system
>>>
>>> Hmm, if TTBCR.EAE _was_ actually set...
>>>
>>>> - bic r6, r6, #3 << 0 @ use only ttbr0
>>>> + bic r6, r6, #(7 << 0) | (1 << 4) @ use only ttbr0
>>>> mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
>>>> mcrne p15, 0, r1, c3, c0, 0 @ load domain access
>>>> control
>>>> mcrne p15, 0, r6, c2, c0, 2 @ load ttb control
>>>
>>> ...then strictly the TLBIALL needs to happen after the ISB following
>>> this update. Otherwise per B3.10.2 of DDI406C.c I think we might be into
>>> unpredictable territory - i.e. if the TLB happens to treat long- and
>>> short-descriptor entries differently then the TLBI beforehand (with EAE
>>> set) may be at liberty to only discard long-descriptor entries and leave
>>> bogus short-descriptor entries sitting around.
>> Yes, it seems this has to be taken care of, along with resetting
>> TTBCR.PD0 and TTBCR.N. Do you say that this needs to be done in the same
>> patch or a different one?
>>>
>>> In other words, something like (completely untested):
>>>
>>> ---8<---
>>> diff --git a/arch/arm/boot/compressed/head.S
>>> b/arch/arm/boot/compressed/head.S
>>> index af11c2f8f3b7..536b7781024a 100644
>>> --- a/arch/arm/boot/compressed/head.S
>>> +++ b/arch/arm/boot/compressed/head.S
>>> @@ -764,7 +764,6 @@ __armv7_mmu_cache_on:
>>> mov r0, #0
>>> mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
>>> tst r11, #0xf @ VMSA
>>> - mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
>>
>> Shouldn't this be still there for the same reason you explained above? I
>> mean to discard the long descriptor entries when EAE was 1 (before we
>> reset it).
>>> #endif
>>> mrc p15, 0, r0, c1, c0, 0 @ read control reg
>>> bic r0, r0, #1 << 28 @ clear SCTLR.TRE
>>> @@ -783,8 +782,11 @@ __armv7_mmu_cache_on:
>>> mcrne p15, 0, r3, c2, c0, 0 @ load page table
>>> pointer
>>> mcrne p15, 0, r1, c3, c0, 0 @ load domain access
>>> control
>>> mcrne p15, 0, r6, c2, c0, 2 @ load ttb control
>>> -#endif
>>> mcr p15, 0, r0, c7, c5, 4 @ ISB
>>> + mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
>>> +#else
>>> + mcr p15, 0, r0, c7, c5, 4 @ ISB
>>> +#endif
>>> mcr p15, 0, r0, c1, c0, 0 @ load control register
>>> mrc p15, 0, r0, c1, c0, 0 @ and read it back
>>> ---8<---
>>>
>>> Robin.
>>>
>> i have tested this change (flush I, D, TLBs after TTB control is
>> written) and don't see any issue. But on my setup decompression is
>> successful even without this (probably not hitting the case in
>> discussion).
>>
>>
>> Thanks,
>> -- Srinivas R
>>
>
> Would like your feedback on the above. Can we get the TTBCR fix merged
> first?(will send final patch with Russell Kings comments fixed)
>
> For testing the TLB flush change we may have to check if we can create a
> failure case.
Yeah, the TLBI being in the wrong place is a separate, pre-existing
problem; as far as this patch goes, it does what it claims to do, and
matches what the ARMv7 (and ARMv6) docs say, so:
Acked-by: Robin Murphy <robin.murphy@arm.com>
>
> Thanks,
> -- Srinivas R
>
^ permalink raw reply
* [PATCH/RFT 0/4] ARM: shmobile: R-Car Gen2: Allow booting secondary CPU cores in debug mode
From: Geert Uytterhoeven @ 2016-09-27 12:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1471877069-4157-1-git-send-email-geert+renesas@glider.be>
Hi Simon, Magnus,
On Mon, Aug 22, 2016 at 4:44 PM, Geert Uytterhoeven
<geert+renesas@glider.be> wrote:
> This patch series is an attempt to allow booting secondary CPU cores on
> R-Car Gen2 when hardware debug mode is enabled. In this mode, reset
> requests derived from power-shutoff to the AP-system CPU cores must be
> enabled before the AP-system cores first resume from power-shutoff. Else
> resume may fail, causing the system to hang during boot. Currently we
> avoid the hang by prohibiting booting secondary CPU cores when hardware
> debug mode is enabled.
>
> On all R-Car Gen2 SoCs, hardware debug mode is enabled by setting
> MD21=1. On both Koelsch and Lager, this is done by setting mode switch
> SW8-4 to OFF.
>
> Unfortunately the hang is not easy to reproduce: I only saw it (on
> Koelsch) during real cold boot (power off during the night), and even
> then it's not guaranteed to trigger. Pressing the reset button
> afterwards recovers the system, and a subsequent boot will succeed
> (incl. secondary CPU core boot).
>
> This series configures the reset requests as documented in the R-Car
> Gen2 datasheet, and removes the check for MD21 during secondary CPU
> bringup. It was inspired by CPU-specific patches in the BSP by
> Nakamura-san.
>
> This series has been boot-tested on r8a7791/koelsch (both debug mode and
> normal mode), on r8a7790/lager and r8a7793/gose (normal mode only), and
> on r8a7794/alt (normal mode UP only).
Any comments?
Any objection to applying this series?
I've been running my Koelsch with MD21=1 since I posted this series,
and it has been included in renesas-drivers since the beginning of September.
My main motivation to push this is that it removes two more users of
rcar_gen2_read_mode_pins(). After this, the only remaining user is the
clock driver, invoked from rcar_gen2_timer_init().
Thanks!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [RFC] irqchip/gic-v3: Implement suspend and resume callbacks
From: Chandra Sekhar Lingutla @ 2016-09-27 12:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <57E25C8E.7080502@arm.com>
On 09/21/2016 03:40 PM, Marc Zyngier wrote:
> +Sudeep, Lorenzo,
>
> On 21/09/16 09:42, Lingutla Chandrasekhar wrote:
>> Implement suspend and resume syscore_ops to disable and
>> enable non wake up capable interrupts.
>>
>> When system enters suspend, enable only wakeup capable
>> interrupts. While resuming, enable previously enabled interrupts
>> and show triggered/pending interrupts.
>
> The fundamental problem (which you're not mentioning at all) is that the
> GICv3 architecture doesn't mention wake-up interrupts at all, so this
> has to be entirely handled in firmware. Is that what is happening?
>
>>
>> Signed-off-by: Lingutla Chandrasekhar <clingutla@codeaurora.org>
>>
>> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
>> index ede5672..511a5a1 100644
>> --- a/drivers/irqchip/irq-gic-v3.c
>> +++ b/drivers/irqchip/irq-gic-v3.c
>> @@ -33,6 +33,7 @@
>> #include <linux/irqchip/arm-gic-common.h>
>> #include <linux/irqchip/arm-gic-v3.h>
>> #include <linux/irqchip/irq-partition-percpu.h>
>> +#include <linux/syscore_ops.h>
>>
>> #include <asm/cputype.h>
>> #include <asm/exception.h>
>> @@ -57,6 +58,10 @@ struct gic_chip_data {
>> u32 nr_redist_regions;
>> unsigned int irq_nr;
>> struct partition_desc *ppi_descs[16];
>> +#ifdef CONFIG_PM
>> + unsigned int wakeup_irqs[32];
>> + unsigned int enabled_irqs[32];
>
> Do not use ambiguous types for something that comes from the HW. Where
> does this '32' comes from?
Expecting wakeup capable irq can be any of maximum 1024 interrupt lines, so
used array of size 32 (32 * 32 bits).
>
>> +#endif
>> };
>>
>> static struct gic_chip_data gic_data __read_mostly;
>> @@ -330,6 +335,81 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
>> return 0;
>> }
>>
>> +#ifdef CONFIG_PM
>> +static int gic_suspend(void)
>> +{
>> + unsigned int i;
>> + void __iomem *base = gic_data.dist_base;
>> +
>> + for (i = 0; i * 32 < gic->irq_nr; i++) {
>> + gic->enabled_irqs[i]
>> + = readl_relaxed(base + GICD_ISENABLER + i * 4);
>
> Do you realize that GICD_ISENABLER0 is always zero? What do you do for
> PPIs? Please keep the assignment on a single line.
Agreed, will update.
>
>> + /* disable all of them */
>> + writel_relaxed(0xffffffff, base + GICD_ICENABLER + i * 4);
>> + /* enable the wakeup set */
>> + writel_relaxed(gic->wakeup_irqs[i],
>> + base + GICD_ISENABLER + i * 4);
>
> On a single line as well.
>
>> + }
>> + return 0;
>> +}
>> +
>> +static void gic_show_pending(void)
>> +{
>> + unsigned int i;
>> + u32 enabled;
>> + u32 pending[32];
>> + void __iomem *base = gic_data.dist_base;
>> +
>> + for (i = 0; i * 32 < gic->irq_nr; i++) {
>> + enabled = readl_relaxed(base + GICD_ICENABLER + i * 4);
>> + pending[i] = readl_relaxed(base + GICD_ISPENDR + i * 4);
>> + pending[i] &= enabled;
>> + }
>> +
>> + for_each_set_bit(i, (unsigned long *)pending, gic->irq_nr) {
>> + unsigned int irq = irq_find_mapping(gic->domain, i);
>> + struct irq_desc *desc = irq_to_desc(irq);
>> + const char *name = "null";
>> +
>> + if (desc == NULL)
>> + name = "stray irq";
>> + else if (desc->action && desc->action->name)
>> + name = desc->action->name;
>> +
>> + pr_debug("Pending IRQ: %d [%s]\n", __func__, irq, name);
>> + }
>> +}
>
> Please drop this function from this patch, it doesn't serve any purpose
> other than your own debugging.
>
I think, this function is useful for debugging to know wakeup reason.
Can we move this function under PM_DEBUG flag or debugfs entry ?
>> +
>> +static void gic_resume(void)
>> +{
>> + unsigned int i;
>> + void __iomem *base = gic_data.dist_base;
>> +
>> + gic_show_pending();
>> +
>> + for (i = 0; i * 32 < gic->irq_nr; i++) {
>> + /* disable all of them */
>> + writel_relaxed(0xffffffff, base + GICD_ICENABLER + i * 4);
>> + /* enable the enabled set */
>> + writel_relaxed(gic->enabled_irqs[i],
>> + base + GICD_ISENABLER + i * 4);
>
> Same remarks as the suspend side.
>
>> + }
>> +}
>> +
>> +static struct syscore_ops gic_syscore_ops = {
>> + .suspend = gic_suspend,
>> + .resume = gic_resume,
>> +};
>> +
>> +static int __init gic_init_sys(void)
>> +{
>> + register_syscore_ops(&gic_syscore_ops);
>> + return 0;
>> +}
>> +device_initcall(gic_init_sys);
>> +
>> +#endif
>> +
>> static u64 gic_mpidr_to_affinity(unsigned long mpidr)
>> {
>> u64 aff;
>> @@ -666,6 +746,32 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
>> #define gic_smp_init() do { } while(0)
>> #endif
>>
>> +#ifdef CONFIG_PM
>> +int gic_set_wake(struct irq_data *d, unsigned int on)
>> +{
>> + int ret = -ENXIO;
>> + unsigned int reg_offset, bit_offset;
>> + unsigned int gicirq = gic_irq(d);
>> + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
>> +
>> + /* per-cpu interrupts cannot be wakeup interrupts */
>> + WARN_ON(gicirq < 32);
>
> How did you decide that? There is no such specification anywhere.
>
I am basically looking at system suspend, where cores would be in power collapse.
>> +
>> + reg_offset = gicirq / 32;
>> + bit_offset = gicirq % 32;
>> +
>> + if (on)
>> + gic_data->wakeup_irqs[reg_offset] |= 1 << bit_offset;
>> + else
>> + gic_data->wakeup_irqs[reg_offset] &= ~(1 << bit_offset);
>> +
>> + return ret;
>> +}
>> +
>> +#else
>> +#define gic_set_wake NULL
>> +#endif
>> +
>> #ifdef CONFIG_CPU_PM
>> /* Check whether it's single security state view */
>> static bool gic_dist_security_disabled(void)
>> @@ -707,6 +813,7 @@ static struct irq_chip gic_chip = {
>> .irq_eoi = gic_eoi_irq,
>> .irq_set_type = gic_set_type,
>> .irq_set_affinity = gic_set_affinity,
>> + .irq_set_wake = gic_set_wake,
>> .irq_get_irqchip_state = gic_irq_get_irqchip_state,
>> .irq_set_irqchip_state = gic_irq_set_irqchip_state,
>> .flags = IRQCHIP_SET_TYPE_MASKED,
>> @@ -723,6 +830,7 @@ static struct irq_chip gic_eoimode1_chip = {
>> .irq_set_irqchip_state = gic_irq_set_irqchip_state,
>> .irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity,
>> .flags = IRQCHIP_SET_TYPE_MASKED,
>> + .irq_set_wake = gic_set_wake,
>
> Keep the fields in the same order.
>
>> };
>>
>> #define GIC_ID_NR (1U << gic_data.rdists.id_bits)
>>
>
> But here's my fundamental objection: None of that should be required and
> setting (IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND) as part of the
> irqchip flags should be enough.
>
> Can you explain why this doesn't work for you?
>
These flags work for me, I will remove suspend/resume functions, but i think
it is very useful to know the wakeup source for debugging purposes.
Please let me know, if you have any better way to achieve this.
> Thanks,
>
> M.
>
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH] ARM: dts: lpc32xx: add pwm-cells to base dts file
From: Sylvain Lemieux (gmail) @ 2016-09-27 12:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <aaf0fc9c-ea2f-0081-cf58-b5024e450030@mleia.com>
Hi Vladimir,
On Tue, 2016-09-27 at 01:07 +0300, Vladimir Zapolskiy wrote:
> Hi Sylvain,
>
> On 26.09.2016 21:47, Sylvain Lemieux wrote:
> > From: Sylvain Lemieux <slemieux@tycoint.com>
> >
> > There is no need to define the "pwm-cells" in the board
> > specific dts file; move the entry to the base dts file.
> >
> > Signed-off-by: Sylvain Lemieux <slemieux@tycoint.com>
> > ---
> > Note:
> > * This patch should be apply after
> > "ARM: dts: lpc32xx: set default parent clock for pwm1 & pwm2"
> > http://www.spinics.net/lists/arm-kernel/msg530277.html
> > - There is no dependency between the patches.
> >
> > arch/arm/boot/dts/lpc32xx.dtsi | 2 ++
> > 1 file changed, 2 insertions(+)
> >
[...]
>
> that's something I have done locally and in a different manner, but I haven't
> published it yet, please find below a draft.
>
> First of all from multiple places in the User's Manual you can find that there
> are "two single output PWM blocks" or "the LPC32x0 provides two 8-bit PWMs" etc.
>
> In this case it does not make sense to set PWM cells to 2 (there is only one
> channel), and 1 cell for frequency is good enough, and that's the proposed
> change to support it:
>
> diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
> index a9b3cff..447ae44 100644
> --- a/drivers/pwm/pwm-lpc32xx.c
> +++ b/drivers/pwm/pwm-lpc32xx.c
> @@ -99,6 +99,22 @@ static const struct pwm_ops lpc32xx_pwm_ops = {
> .owner = THIS_MODULE,
> };
>
> +static struct pwm_device *lpc32xx_pwm_of_xlate(struct pwm_chip *pc,
> + const struct of_phandle_args *args)
> +{
> + struct pwm_device *pwm;
> +
> + pwm = pwm_request_from_chip(pc, 0, NULL);
> + if (IS_ERR(pwm))
> + return pwm;
> +
> + pwm->args.period = args->args[0];
> +
> + return pwm;
> +}
> +
> static int lpc32xx_pwm_probe(struct platform_device *pdev)
> {
> struct lpc32xx_pwm_chip *lpc32xx;
> @@ -123,6 +139,8 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
> lpc32xx->chip.ops = &lpc32xx_pwm_ops;
> lpc32xx->chip.npwm = 1;
> lpc32xx->chip.base = -1;
> + lpc32xx->chip.of_xlate = lpc32xx_pwm_of_xlate;
> + lpc32xx->chip.of_pwm_n_cells = 1;
>
> ret = pwmchip_add(&lpc32xx->chip);
> if (ret < 0) {
>
>
> What is your opinion about this proposal?
>
I agree with you, this clean-up make sense; the PWM cell should be 1.
> If this change is applied, then lpc32xx.dtsi should contain #pwm-cells = <1>.
>
Can you submit your change on the mailing list?
I will send a version 2 of this patch after.
If it is helping, I can take care of submitting a patch
to update the documentation (lpc32xx-pwm.txt).
Did you have a change to look at the 2 others PWM related change:
* clk: lpc32xx: fix pwm clock divider computation
http://www.spinics.net/lists/arm-kernel/msg534048.html
* ARM: dts: lpc32xx: set pwm1 & pwm2 default clock rate
http://www.spinics.net/lists/arm-kernel/msg534051.html
> --
> With best wishes,
> Vladimir
Sylvain
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox