2014-04-14 16:43:16

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 00/15] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

Hi,
The following series is based on v3.15-rc1 + peter's patch series:
patch #1: https://patchwork.kernel.org/patch/3923141/
(drivers: bus: omap_l3: Convert to use devm_kzalloc)

patch #2: https://patchwork.kernel.org/patch/3923061/
(drivers: bus: omap_l3: Convert to use devm_ioremap_resource() )

patch #3: https://patchwork.kernel.org/patch/3923101/
(drivers: bus: omap_l3: Convert to use devm_request_irq())

patch #4: https://patchwork.kernel.org/patch/3923081/
(drivers: bus: omap_l3: Remove the platform driver's remove function)

patch #5: https://patchwork.kernel.org/patch/3923121/
(drivers: bus: omap_l3: Change pr_crit() to dev_err() when IRQ request
fails)

This series cleansup omap_l3_noc driver and adds data to support DRA7
and AM437x SoCs.

Patches(including Peter's) is available here:
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes

DTS patches (once this series is integrated and related DRA7 memory map fixes are done):
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/dts-fixes

Testing branch: everything integrated:
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/testing

Test log:
am43xx-epos: Boot PASS: http://slexy.org/raw/s2GQJIppWp
DRA7xx-EVM: Boot PASS: http://slexy.org/raw/s20OfeDbO6
pandaboard-es: Boot PASS: http://slexy.org/raw/s2AZSmSYcN
sdp4430: Boot PASS: http://slexy.org/raw/s2IfHAbrJA
OMAP5432uEVM: Boot PASS: http://slexy.org/raw/s21CkL8glk

Afzal Mohammed (1):
bus: omap_l3_noc: Add AM4372 interconnect error data

Nishanth Menon (10):
bus: omap_l3_noc: Fix copyright information
bus: omap_l3_noc: switch over to relaxed variants of readl/writel
bus: omap_l3_noc: un-obfuscate l3_targ address computation
bus: omap_l3_noc: move L3 master data structure out
bus: omap_l3_noc: convert target information into a structure
bus: omap_l3_noc: make error reporting and handling common.
bus: omap_l3_noc: populate l3->dev and use it
bus: omap_l3_noc: remove iclk from omap_l3 struct
bus: omap_l3_noc: convert flagmux information into a structure
bus: omap_l3_noc: introduce concept of submodule

Rajendra Nayak (2):
bus: omap_l3_noc: Add support for discountinous flag mux input
numbers
bus: omap_l3_noc: Add DRA7 interconnect error data

Sricharan R (2):
bus: omap_l3_noc: rename functions and data to omap_l3
bus: omap_l3_noc: use of_match_data to pick up SoC information

.../devicetree/bindings/arm/omap/l3-noc.txt | 2 +
drivers/bus/omap_l3_noc.c | 224 +++++----
drivers/bus/omap_l3_noc.h | 495 +++++++++++++++-----
3 files changed, 517 insertions(+), 204 deletions(-)

--
1.7.9.5


2014-04-14 16:34:07

by Nishanth Menon

[permalink] [raw]
Subject: Re: [PATCH 02/15] bus: omap_l3_noc: switched over to relaxed variants of readl/writel

On 04/14/2014 11:25 AM, Nishanth Menon wrote:

Please ignore this one patch from the series, there is a replacement
patch already posted as part of the series... this stale patch got
through :(

--
Regards,
Nishanth Menon

2014-04-14 16:26:11

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 02/15] bus: omap_l3_noc: switched over to relaxed variants of readl/writel

Currently we use __raw_readl and writel in this driver, however, there
is no strict sequencing needs for this driver, hence we should be good
with the relaxed variants.

While at it, simplify address computation using variables for register.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 1eb6d85..0d346e6 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -55,6 +55,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
int err_src = 0;
u32 std_err_main, err_reg, clear, masterid;
void __iomem *base, *l3_targ_base;
+ void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";

/* Get the Type of interrupt */
@@ -66,8 +67,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = __raw_readl(base + l3_flagmux[i] +
- + L3_FLAGMUX_REGERR0 + (inttype << 3));
+ err_reg = readl_relaxed(base + l3_flagmux[i] +
+ L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
if (err_reg) {
@@ -76,10 +77,14 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Read the stderrlog_main_source from clk domain */
l3_targ_base = base + *(l3_targ[i] + err_src);
- std_err_main = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
- masterid = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MSTADDR);
+ l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
+ l3_targ_slvofslsb = l3_targ_base +
+ L3_TARG_STDERRLOG_SLVOFSLSB;
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_MSTADDR;
+
+ std_err_main = readl_relaxed(l3_targ_stderr);
+ masterid = readl_relaxed(l3_targ_mstaddr);

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
@@ -87,12 +92,10 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
l3_targ_inst_name[i][err_src];
WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
target_name,
- __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_SLVOFSLSB));
+ readl_relaxed(l3_targ_slvofslsb));
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

case CUSTOM_ERROR:
@@ -107,8 +110,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
master_name, target_name);
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

default:
--
1.7.9.5

2014-04-14 16:40:13

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 06/15] bus: omap_l3_noc: make error reporting and handling common.

The logic between handling CUSTOM_ERROR and STANDARD_ERROR
is just the reporting style.

So make it generic, simplify and standardize the reporting
with both master and target information printed to log.

While at it, fix a minor formatting error.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 47 ++++++++++++++++++++++++++++-----------------
1 file changed, 29 insertions(+), 18 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 0ef8b75..0f0417a 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -58,6 +58,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";
struct l3_target_data *l3_targ_inst;
+ char *err_description;
+ char err_string[30] = { 0 };

/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -73,6 +75,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Get the corresponding error and analyse */
if (err_reg) {
+ bool std_err = true;
+
/* Identify the source from control status register */
err_src = __ffs(err_reg);
l3_targ_inst = &l3_targ[i][err_src];
@@ -89,35 +93,42 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
std_err_main = readl_relaxed(l3_targ_stderr);
masterid = readl_relaxed(l3_targ_mstaddr);

+ for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
+ if (masterid == l3_masters[k].id)
+ master_name = l3_masters[k].name;
+ }
+
switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
- WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
- target_name,
- readl_relaxed(l3_targ_slvofslsb));
- /* clear the std error log*/
- clear = std_err_main | CLEAR_STDERR_LOG;
- writel_relaxed(clear, l3_targ_stderr);
+ err_description = "Standard";
+ snprintf(err_string, sizeof(err_string),
+ ": At Address: 0x%08X",
+ readl_relaxed(l3_targ_slvofslsb));
break;

case CUSTOM_ERROR:
- for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
- if (masterid == l3_masters[k].id)
- master_name =
- l3_masters[k].name;
- }
- WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
- master_name, target_name);
- /* clear the std error log*/
- clear = std_err_main | CLEAR_STDERR_LOG;
- writel_relaxed(clear, l3_targ_stderr);
+ err_description = "Custom";
break;

default:
+ std_err = false;
/* Nothing to be handled here as of now */
break;
}
- /* Error found so break the for loop */
- break;
+
+ if (std_err) {
+ WARN(true,
+ "L3 %s Error: MASTER %s TARGET %s %s\n",
+ err_description,
+ master_name, target_name,
+ err_string);
+ /* clear the std error log*/
+ clear = std_err_main | CLEAR_STDERR_LOG;
+ writel_relaxed(clear, l3_targ_stderr);
+ }
+
+ /* Error found so break the for loop */
+ break;
}
}
return IRQ_HANDLED;
--
1.7.9.5

2014-04-14 16:26:06

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 14/15] bus: omap_l3_noc: Add DRA7 interconnect error data

From: Rajendra Nayak <[email protected]>

DRA7 is distinctly different from OMAP4 in terms of masters and clock
domain organization. There two main clock domains which is divided as
follows:
<0x44000000 0x1000000> is clk1 and clk2 is the sub clock domain
<0x45000000 0x1000> is clk3

Add all the data needed to handle L3 error handling on DRA7 devices
and mark clk2 as subdomain and provide a compatible flag for
functionality. Other than the data difference the hardware blocks
involved are essentially the same.

Signed-off-by: Rajendra Nayak <[email protected]>
[[email protected]: bugfixes and generic improvements, documentation]
Signed-off-by: Nishanth Menon <[email protected]>
---
.../devicetree/bindings/arm/omap/l3-noc.txt | 1 +
drivers/bus/omap_l3_noc.c | 1 +
drivers/bus/omap_l3_noc.h | 133 ++++++++++++++++++++
3 files changed, 135 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
index c0105de..45d0fc2 100644
--- a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
+++ b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
@@ -6,6 +6,7 @@ provided by Arteris.
Required properties:
- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
Should be "ti,omap4-l3-noc" for OMAP4 family
+ Should be "ti,dra7-l3-noc" for DRA7 family
- reg: Contains L3 register address range for each noc domain.
- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 5e2a89d..9b32e53 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -176,6 +176,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

static const struct of_device_id l3_noc_match[] = {
{.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
+ {.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
{},
};
MODULE_DEVICE_TABLE(of, l3_noc_match);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 592821f..365a33c 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -206,4 +206,137 @@ static const struct omap_l3 omap_l3_data = {
.num_masters = ARRAY_SIZE(omap_l3_masters),
};

+/* DRA7 data */
+static struct l3_target_data dra_l3_target_data_clk1[] = {
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x0200, "DMM_P1",},
+ {0x0600, "DSP2_SDMA",},
+ {0x0b00, "EVE2",},
+ {0x1300, "DMM_P2",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x0300, "DSP1_SDMA",},
+ {0x0a00, "EVE1",},
+ {0x0c00, "EVE3",},
+ {0x0d00, "EVE4",},
+ {0x2900, "DSS",},
+ {0x0100, "GPMC",},
+ {0x3700, "PCIE1",},
+ {0x1600, "IVA_CONFIG",},
+ {0x1800, "IVA_SL2IF",},
+ {0x0500, "L4_CFG",},
+ {0x1d00, "L4_WKUP",},
+ {0x3800, "PCIE2",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x1200, "GPU",},
+ {0x1000, "IPU1",},
+ {0x1100, "IPU2",},
+ {0x2000, "TPCC_EDMA",},
+ {0x2e00, "TPTC1_EDMA",},
+ {0x2b00, "TPTC2_EDMA",},
+ {0x0700, "VCP1",},
+ {0x2500, "L4_PER2_P3",},
+ {0x0e00, "L4_PER3_P3",},
+ {0x2200, "MMU1",},
+ {0x1400, "PRUSS1",},
+};
+
+static struct l3_flagmux_data dra_l3_flagmux_clk1 = {
+ .offset = 0x803500,
+ .l3_targ = dra_l3_target_data_clk1,
+ .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk1),
+};
+
+static struct l3_target_data dra_l3_target_data_clk2[] = {
+ {0x0, "RT_CLK1_1",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x0900, "BB2D",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x2100, "L4_PER1_P3",},
+ {0x1c00, "L4_PER1_P1",},
+ {0x1f00, "L4_PER1_P2",},
+ {0x2300, "L4_PER2_P1",},
+ {0x2400, "L4_PER2_P2",},
+ {0x2600, "L4_PER3_P1",},
+ {0x2700, "L4_PER3_P2",},
+ {0x2f00, "MCASP1",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x2800, "MMU2",},
+ {0x0f00, "OCMC_RAM1",},
+ {0x1700, "OCMC_RAM2",},
+ {0x1900, "OCMC_RAM3",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x3900, "QSPI",},
+};
+
+static struct l3_flagmux_data dra_l3_flagmux_clk2 = {
+ .offset = 0x803600,
+ .l3_targ = dra_l3_target_data_clk2,
+ .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk2),
+};
+
+static struct l3_target_data dra_l3_target_data_clk3[] = {
+ {0x0100, "L3_INSTR"},
+ {0x0300, "DEBUGSS_CT_TBR"},
+ {0x0, "HOST CLK3"},
+};
+
+static struct l3_flagmux_data dra_l3_flagmux_clk3 = {
+ .offset = 0x200,
+ .l3_targ = dra_l3_target_data_clk3,
+ .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk3),
+};
+
+static struct l3_masters_data dra_l3_masters[] = {
+ { 0x0, "MPU" },
+ { 0x4, "CS_DAP" },
+ { 0x8, "DSP1_MDMA" },
+ { 0x9, "DSP1_CFG" },
+ { 0xA, "DSP1_DMA" },
+ { 0xB, "DSP2_MDMA" },
+ { 0xC, "DSP2_CFG" },
+ { 0xD, "DSP2_DMA" },
+ { 0xE, "IVA" },
+ { 0x10, "EVE1_P1" },
+ { 0x11, "EVE2_P1" },
+ { 0x12, "EVE3_P1" },
+ { 0x13, "EVE4_P1" },
+ { 0x14, "PRU1" },
+ { 0x15, "PRU2" },
+ { 0x18, "IPU1" },
+ { 0x1C, "TC1_EDMA" },
+ { 0x1D, "TC2_EDMA" },
+ { 0x20, "DSS" },
+ { 0x21, "MMU1" },
+ { 0x22, "PCIE1" },
+ { 0x23, "MMU2" },
+ { 0x24, "VIP1" },
+ { 0x25, "VIP2" },
+ { 0x26, "VIP3" },
+ { 0x27, "VPE" },
+ { 0x28, "GPU_P1" },
+ { 0x29, "GPU_P2" },
+ { 0x2B, "GMAC_SW" },
+ { 0x34, "EVE1_P2" },
+ { 0x35, "EVE2_P2" },
+ { 0x36, "EVE3_P2" },
+ { 0x37, "EVE4_P2" }
+};
+
+static struct l3_flagmux_data *dra_l3_flagmux[] = {
+ &dra_l3_flagmux_clk1,
+ &dra_l3_flagmux_clk2,
+ &dra_l3_flagmux_clk3,
+};
+
+static const struct omap_l3 dra_l3_data = {
+ .l3_base = { [1] = L3_BASE_IS_SUBMODULE },
+ .l3_flagmux = dra_l3_flagmux,
+ .num_modules = ARRAY_SIZE(dra_l3_flagmux),
+ .l3_masters = dra_l3_masters,
+ .num_masters = ARRAY_SIZE(dra_l3_masters),
+};
+
#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-14 16:43:13

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 05/15] bus: omap_l3_noc: convert target information into a structure

Currently the target instance information is organized indexed by bit
field offset into multiple arrays.

1. We currently have offsets specific to each target associated with each
clock domains are in seperate arrays:

l3_targ_inst_clk1
l3_targ_inst_clk2
l3_targ_inst_clk3

2. Then they are organized per master index in l3_targ.

3. We have names in l3_targ_inst_name as an array to array of strings
corresponding to the above with offsets.

Simplify the same by defining a structure for information containing
both target offset and name. this is then stored in arrays per domain
and organized into an array indexed off domain.

The array is still indexed based on bit field offset.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 9 ++--
drivers/bus/omap_l3_noc.h | 129 ++++++++++++++++++---------------------------
2 files changed, 54 insertions(+), 84 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index b39ef93..0ef8b75 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -57,6 +57,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
void __iomem *base, *l3_targ_base;
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";
+ struct l3_target_data *l3_targ_inst;

/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -74,9 +75,11 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
if (err_reg) {
/* Identify the source from control status register */
err_src = __ffs(err_reg);
+ l3_targ_inst = &l3_targ[i][err_src];
+ target_name = l3_targ_inst->name;
+ l3_targ_base = base + l3_targ_inst->offset;

/* Read the stderrlog_main_source from clk domain */
- l3_targ_base = base + l3_targ[i][err_src];
l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
l3_targ_slvofslsb = l3_targ_base +
L3_TARG_STDERRLOG_SLVOFSLSB;
@@ -88,8 +91,6 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
- target_name =
- l3_targ_inst_name[i][err_src];
WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
target_name,
readl_relaxed(l3_targ_slvofslsb));
@@ -99,8 +100,6 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
break;

case CUSTOM_ERROR:
- target_name =
- l3_targ_inst_name[i][err_src];
for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
if (masterid == l3_masters[k].id)
master_name =
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 26ad279..25ba99c 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -43,51 +43,62 @@ struct l3_masters_data {
char *name;
};

+/**
+ * struct l3_target_data - L3 Target information
+ * @offset: Offset from base for L3 Target
+ * @name: Target name
+ *
+ * Target information is organized indexed by bit field definitions.
+ */
+struct l3_target_data {
+ u32 offset;
+ char *name;
+};
+
static u32 l3_flagmux[L3_MODULES] = {
0x500,
0x1000,
0X0200
};

-/* L3 Target standard Error register offsets */
-static u32 l3_targ_inst_clk1[] = {
- 0x100, /* DMM1 */
- 0x200, /* DMM2 */
- 0x300, /* ABE */
- 0x400, /* L4CFG */
- 0x600, /* CLK2 PWR DISC */
- 0x0, /* Host CLK1 */
- 0x900 /* L4 Wakeup */
+static struct l3_target_data l3_target_inst_data_clk1[] = {
+ {0x100, "DMM1",},
+ {0x200, "DMM2",},
+ {0x300, "ABE",},
+ {0x400, "L4CFG",},
+ {0x600, "CLK2PWRDISC",},
+ {0x0, "HOSTCLK1",},
+ {0x900, "L4WAKEUP",},
};

-static u32 l3_targ_inst_clk2[] = {
- 0x500, /* CORTEX M3 */
- 0x300, /* DSS */
- 0x100, /* GPMC */
- 0x400, /* ISS */
- 0x700, /* IVAHD */
- 0xD00, /* missing in TRM corresponds to AES1*/
- 0x900, /* L4 PER0*/
- 0x200, /* OCMRAM */
- 0x100, /* missing in TRM corresponds to GPMC sERROR*/
- 0x600, /* SGX */
- 0x800, /* SL2 */
- 0x1600, /* C2C */
- 0x1100, /* missing in TRM corresponds PWR DISC CLK1*/
- 0xF00, /* missing in TRM corrsponds to SHA1*/
- 0xE00, /* missing in TRM corresponds to AES2*/
- 0xC00, /* L4 PER3 */
- 0xA00, /* L4 PER1*/
- 0xB00, /* L4 PER2*/
- 0x0, /* HOST CLK2 */
- 0x1800, /* CAL */
- 0x1700 /* LLI */
+static struct l3_target_data l3_target_inst_data_clk2[] = {
+ {0x500, "CORTEXM3",},
+ {0x300, "DSS",},
+ {0x100, "GPMC",},
+ {0x400, "ISS",},
+ {0x700, "IVAHD",},
+ {0xD00, "AES1",},
+ {0x900, "L4PER0",},
+ {0x200, "OCMRAM",},
+ {0x100, "GPMCsERROR",},
+ {0x600, "SGX",},
+ {0x800, "SL2",},
+ {0x1600, "C2C",},
+ {0x1100, "PWRDISCCLK1",},
+ {0xF00, "SHA1",},
+ {0xE00, "AES2",},
+ {0xC00, "L4PER3",},
+ {0xA00, "L4PER1",},
+ {0xB00, "L4PER2",},
+ {0x0, "HOSTCLK2",},
+ {0x1800, "CAL",},
+ {0x1700, "LLI",},
};

-static u32 l3_targ_inst_clk3[] = {
- 0x0100 /* EMUSS */,
- 0x0300, /* DEBUGSS_CT_TBR */
- 0x0 /* HOST CLK3 */
+static struct l3_target_data l3_target_inst_data_clk3[] = {
+ {0x0100, "EMUSS",},
+ {0x0300, "DEBUG SOURCE",},
+ {0x0, "HOST CLK3",},
};

static struct l3_masters_data l3_masters[] = {
@@ -118,50 +129,10 @@ static struct l3_masters_data l3_masters[] = {
{ 0xC8, "USBHOSTFS"}
};

-static char *l3_targ_inst_name[L3_MODULES][21] = {
- {
- "DMM1",
- "DMM2",
- "ABE",
- "L4CFG",
- "CLK2 PWR DISC",
- "HOST CLK1",
- "L4 WAKEUP"
- },
- {
- "CORTEX M3" ,
- "DSS ",
- "GPMC ",
- "ISS ",
- "IVAHD ",
- "AES1",
- "L4 PER0",
- "OCMRAM ",
- "GPMC sERROR",
- "SGX ",
- "SL2 ",
- "C2C ",
- "PWR DISC CLK1",
- "SHA1",
- "AES2",
- "L4 PER3",
- "L4 PER1",
- "L4 PER2",
- "HOST CLK2",
- "CAL",
- "LLI"
- },
- {
- "EMUSS",
- "DEBUG SOURCE",
- "HOST CLK3"
- },
-};
-
-static u32 *l3_targ[L3_MODULES] = {
- l3_targ_inst_clk1,
- l3_targ_inst_clk2,
- l3_targ_inst_clk3,
+static struct l3_target_data *l3_targ[L3_MODULES] = {
+ l3_target_inst_data_clk1,
+ l3_target_inst_data_clk2,
+ l3_target_inst_data_clk3,
};

struct omap4_l3 {
--
1.7.9.5

2014-04-14 16:43:11

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 11/15] bus: omap_l3_noc: use of_match_data to pick up SoC information

From: Sricharan R <[email protected]>

DRA7xx SoC has the same l3-noc interconnect ip (as OMAP4 and OMAP5), but
AM437x SoC has just 2 modules instead of 3 which other SoCs have.

So, stop using direct access of array indices and use of->match data and
simplify implementation to benefit future usage.

While at it, rename a few very generic variables to make them omap
specific. This helps us differentiate from DRA7 and AM43xx data in the
future.

NOTE: None of the platforms that use omap_l3_noc are non-device tree
anymore. So, it is safe to assume OF match here.

Signed-off-by: Sricharan R <[email protected]>
Signed-off-by: Rajendra Nayak <[email protected]>
[[email protected]: split, refactor and optimize logic]
Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 50 +++++++++++++++++--------------
drivers/bus/omap_l3_noc.h | 72 ++++++++++++++++++++++++++++++++-------------
2 files changed, 80 insertions(+), 42 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 6848822..3819b2f 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -14,12 +14,14 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#include <linux/module.h>
#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>

#include "omap_l3_noc.h"
@@ -64,13 +66,13 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;

- for (i = 0; i < L3_MODULES; i++) {
+ for (i = 0; i < l3->num_modules; i++) {
/*
* Read the regerr register of the clock domain
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = readl_relaxed(base + l3_flagmux[i] +
+ err_reg = readl_relaxed(base + l3->l3_flagmux[i] +
L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
@@ -83,7 +85,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
/* We DONOT expect err_src to go out of bounds */
BUG_ON(err_src >= MAX_CLKDM_TARGETS);

- l3_targ_inst = &l3_targ[i][err_src];
+ l3_targ_inst = &l3->l3_targ[i][err_src];
target_name = l3_targ_inst->name;
l3_targ_base = base + l3_targ_inst->offset;

@@ -105,7 +107,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
inttype ? "debug" : "application",
err_src, i, "(unclearable)");

- mask_reg = base + l3_flagmux[i] +
+ mask_reg = base + l3->l3_flagmux[i] +
L3_FLAGMUX_MASK0 + (inttype << 3);
mask_val = readl(mask_reg);
mask_val &= ~(1 << err_src);
@@ -124,9 +126,9 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
std_err_main = readl_relaxed(l3_targ_stderr);
masterid = readl_relaxed(l3_targ_mstaddr);

- for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
- if (masterid == l3_masters[k].id)
- master_name = l3_masters[k].name;
+ for (k = 0; k < l3->num_masters; k++) {
+ if (masterid == l3->l3_masters[k].id)
+ master_name = l3->l3_masters[k].name;
}

switch (std_err_main & CUSTOM_ERROR) {
@@ -166,20 +168,34 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
return IRQ_HANDLED;
}

+static const struct of_device_id l3_noc_match[] = {
+ {.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
+ {},
+};
+MODULE_DEVICE_TABLE(of, l3_noc_match);
+
static int omap_l3_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id;
static struct omap_l3 *l3;
int ret, i;

+ of_id = of_match_device(l3_noc_match, &pdev->dev);
+ if (!of_id) {
+ dev_err(&pdev->dev, "OF data missing\n");
+ return -EINVAL;
+ }
+
l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL);
if (!l3)
return -ENOMEM;

+ memcpy(l3, of_id->data, sizeof(*l3));
l3->dev = &pdev->dev;
platform_set_drvdata(pdev, l3);

/* Get mem resources */
- for (i = 0; i < L3_MODULES; i++) {
+ for (i = 0; i < l3->num_modules; i++) {
struct resource *res = platform_get_resource(pdev,
IORESOURCE_MEM, i);

@@ -211,22 +227,12 @@ static int omap_l3_probe(struct platform_device *pdev)
return ret;
}

-#if defined(CONFIG_OF)
-static const struct of_device_id l3_noc_match[] = {
- {.compatible = "ti,omap4-l3-noc", },
- {},
-};
-MODULE_DEVICE_TABLE(of, l3_noc_match);
-#else
-#define l3_noc_match NULL
-#endif
-
static struct platform_driver omap_l3_driver = {
.probe = omap_l3_probe,
.driver = {
.name = "omap_l3_noc",
.owner = THIS_MODULE,
- .of_match_table = l3_noc_match,
+ .of_match_table = of_match_ptr(l3_noc_match),
},
};

diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 573e40f..a546870 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -17,7 +17,9 @@
#ifndef __OMAP_L3_NOC_H
#define __OMAP_L3_NOC_H

-#define L3_MODULES 3
+#define OMAP_L3_MODULES 3
+#define MAX_L3_MODULES 3
+
#define CLEAR_STDERR_LOG (1 << 31)
#define CUSTOM_ERROR 0x2
#define STANDARD_ERROR 0x0
@@ -36,8 +38,6 @@

#define MAX_CLKDM_TARGETS 30

-#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0]))
-
/**
* struct l3_masters_data - L3 Master information
* @id: ID of the L3 Master
@@ -60,13 +60,47 @@ struct l3_target_data {
char *name;
};

-static u32 l3_flagmux[L3_MODULES] = {
+
+/**
+ * struct omap_l3 - Description of data relevant for L3 bus.
+ * @dev: device representing the bus (populated runtime)
+ * @l3_base: base addresses of modules (populated runtime)
+ * @l3_flag_mux: array containing offsets to flag mux per module
+ * offset from corresponding module base indexed per
+ * module.
+ * @num_modules: number of clock domains / modules.
+ * @l3_masters: array pointing to master data containing name and register
+ * offset for the master.
+ * @num_master: number of masters
+ * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
+ * target data. unsupported ones are marked with
+ * L3_TARGET_NOT_SUPPORTED
+ * @debug_irq: irq number of the debug interrupt (populated runtime)
+ * @app_irq: irq number of the application interrupt (populated runtime)
+ */
+struct omap_l3 {
+ struct device *dev;
+
+ void __iomem *l3_base[MAX_L3_MODULES];
+ u32 *l3_flagmux;
+ int num_modules;
+
+ struct l3_masters_data *l3_masters;
+ int num_masters;
+
+ struct l3_target_data **l3_targ;
+
+ int debug_irq;
+ int app_irq;
+};
+
+static u32 omap_l3_flagmux[OMAP_L3_MODULES] = {
0x500,
0x1000,
0X0200
};

-static struct l3_target_data l3_target_inst_data_clk1[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = {
{0x100, "DMM1",},
{0x200, "DMM2",},
{0x300, "ABE",},
@@ -76,7 +110,7 @@ static struct l3_target_data l3_target_inst_data_clk1[MAX_CLKDM_TARGETS] = {
{0x900, "L4WAKEUP",},
};

-static struct l3_target_data l3_target_inst_data_clk2[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = {
{0x500, "CORTEXM3",},
{0x300, "DSS",},
{0x100, "GPMC",},
@@ -100,13 +134,13 @@ static struct l3_target_data l3_target_inst_data_clk2[MAX_CLKDM_TARGETS] = {
{0x1700, "LLI",},
};

-static struct l3_target_data l3_target_inst_data_clk3[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk3[MAX_CLKDM_TARGETS] = {
{0x0100, "EMUSS",},
{0x0300, "DEBUG SOURCE",},
{0x0, "HOST CLK3",},
};

-static struct l3_masters_data l3_masters[] = {
+static struct l3_masters_data omap_l3_masters[] = {
{ 0x0 , "MPU"},
{ 0x10, "CS_ADP"},
{ 0x14, "xxx"},
@@ -134,20 +168,18 @@ static struct l3_masters_data l3_masters[] = {
{ 0xC8, "USBHOSTFS"}
};

-static struct l3_target_data *l3_targ[L3_MODULES] = {
- l3_target_inst_data_clk1,
- l3_target_inst_data_clk2,
- l3_target_inst_data_clk3,
+static struct l3_target_data *omap_l3_targ[OMAP_L3_MODULES] = {
+ omap_l3_target_data_clk1,
+ omap_l3_target_data_clk2,
+ omap_l3_target_data_clk3,
};

-struct omap_l3 {
- struct device *dev;
-
- /* memory base */
- void __iomem *l3_base[L3_MODULES];
-
- int debug_irq;
- int app_irq;
+static const struct omap_l3 omap_l3_data = {
+ .l3_flagmux = omap_l3_flagmux,
+ .num_modules = OMAP_L3_MODULES,
+ .l3_masters = omap_l3_masters,
+ .num_masters = ARRAY_SIZE(omap_l3_masters),
+ .l3_targ = omap_l3_targ,
};

#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-14 16:45:20

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 15/15] bus: omap_l3_noc: Add AM4372 interconnect error data

From: Afzal Mohammed <[email protected]>

Add AM4372 information to handle L3 error.

AM4372 has two clk domains 100f and 200s. Provide flagmux and data
associated with it.

NOTE: Timeout doesn't have STDERRLOG_MAIN register. And per hardware
team, L3 timeout error cannot be cleared the normal way (by setting
bit 31 in STDERRLOG_MAIN), instead it may be required to do system
reset. L3 error handler can't help in such scenarios.

Hence indicate timeout target offset as L3_TARGET_NOT_SUPPORTED as
done for undocumented bits.

Signed-off-by: Dave Gerlach <[email protected]>
Signed-off-by: Afzal Mohammed <[email protected]>
Signed-off-by: Sekhar Nori <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
---
.../devicetree/bindings/arm/omap/l3-noc.txt | 1 +
drivers/bus/omap_l3_noc.c | 1 +
drivers/bus/omap_l3_noc.h | 85 ++++++++++++++++++++
3 files changed, 87 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
index 45d0fc2..974624e 100644
--- a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
+++ b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
@@ -7,6 +7,7 @@ Required properties:
- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
Should be "ti,omap4-l3-noc" for OMAP4 family
Should be "ti,dra7-l3-noc" for DRA7 family
+ Should be "ti,am4372-l3-noc" for AM43 family
- reg: Contains L3 register address range for each noc domain.
- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 9b32e53..9853e1d 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -177,6 +177,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
static const struct of_device_id l3_noc_match[] = {
{.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
{.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
+ {.compatible = "ti,am4372-l3-noc", .data = &am4372_l3_data},
{},
};
MODULE_DEVICE_TABLE(of, l3_noc_match);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 365a33c..91814e0 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -339,4 +339,89 @@ static const struct omap_l3 dra_l3_data = {
.num_masters = ARRAY_SIZE(dra_l3_masters),
};

+/* AM4372 data */
+static struct l3_target_data am4372_l3_target_data_200f[] = {
+ {0xf00, "EMIF",},
+ {0x1200, "DES",},
+ {0x400, "OCMCRAM",},
+ {0x700, "TPTC0",},
+ {0x800, "TPTC1",},
+ {0x900, "TPTC2"},
+ {0xb00, "TPCC",},
+ {0xd00, "DEBUGSS",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x200, "SHA",},
+ {0xc00, "SGX530",},
+ {0x500, "AES0",},
+ {0xa00, "L4_FAST",},
+ {0x300, "MPUSS_L2_RAM",},
+ {0x100, "ICSS",},
+};
+
+static struct l3_flagmux_data am4372_l3_flagmux_200f = {
+ .offset = 0x1000,
+ .l3_targ = am4372_l3_target_data_200f,
+ .num_targ_data = ARRAY_SIZE(am4372_l3_target_data_200f),
+};
+
+static struct l3_target_data am4372_l3_target_data_100s[] = {
+ {0x100, "L4_PER_0",},
+ {0x200, "L4_PER_1",},
+ {0x300, "L4_PER_2",},
+ {0x400, "L4_PER_3",},
+ {0x800, "McASP0",},
+ {0x900, "McASP1",},
+ {0xC00, "MMCHS2",},
+ {0x700, "GPMC",},
+ {0xD00, "L4_FW",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x500, "ADCTSC",},
+ {0xE00, "L4_WKUP",},
+ {0xA00, "MAG_CARD",},
+};
+
+static struct l3_flagmux_data am4372_l3_flagmux_100s = {
+ .offset = 0x600,
+ .l3_targ = am4372_l3_target_data_100s,
+ .num_targ_data = ARRAY_SIZE(am4372_l3_target_data_100s),
+};
+
+static struct l3_masters_data am4372_l3_masters[] = {
+ { 0x0, "M1 (128-bit)"},
+ { 0x0, "M2 (64-bit)"},
+ { 0x4, "DAP"},
+ { 0x5, "P1500"},
+ { 0xC, "ICSS0"},
+ { 0xD, "ICSS1"},
+ { 0x18, "TPTC0 Read"},
+ { 0x19, "TPTC0 Write"},
+ { 0x1A, "TPTC1 Read"},
+ { 0x1B, "TPTC1 Write"},
+ { 0x1C, "TPTC2 Read"},
+ { 0x1D, "TPTC2 Write"},
+ { 0x20, "SGX530"},
+ { 0x25, "DSS"},
+ { 0x28, "Crypto DMA RD"},
+ { 0x29, "Crypto DMA WR"},
+ { 0x2C, "VPFE0"},
+ { 0x2D, "VPFE1"},
+ { 0x30, "GEMAC"},
+ { 0x34, "USB0 RD"},
+ { 0x35, "USB0 WR"},
+ { 0x36, "USB1 RD"},
+ { 0x37, "USB1 WR"},
+};
+
+static struct l3_flagmux_data *am4372_l3_flagmux[] = {
+ &am4372_l3_flagmux_200f,
+ &am4372_l3_flagmux_100s,
+};
+
+static const struct omap_l3 am4372_l3_data = {
+ .l3_flagmux = am4372_l3_flagmux,
+ .num_modules = ARRAY_SIZE(am4372_l3_flagmux),
+ .l3_masters = am4372_l3_masters,
+ .num_masters = ARRAY_SIZE(am4372_l3_masters),
+};
+
#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-14 16:45:55

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 04/15] bus: omap_l3_noc: move L3 master data structure out

Move the L3 master structure out of the static definition to enable
reuse for other SoCs.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.h | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index cc4b1b1..26ad279 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -33,6 +33,16 @@

#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0]))

+/**
+ * struct l3_masters_data - L3 Master information
+ * @id: ID of the L3 Master
+ * @name: master name
+ */
+struct l3_masters_data {
+ u32 id;
+ char *name;
+};
+
static u32 l3_flagmux[L3_MODULES] = {
0x500,
0x1000,
@@ -80,10 +90,7 @@ static u32 l3_targ_inst_clk3[] = {
0x0 /* HOST CLK3 */
};

-static struct l3_masters_data {
- u32 id;
- char name[10];
-} l3_masters[] = {
+static struct l3_masters_data l3_masters[] = {
{ 0x0 , "MPU"},
{ 0x10, "CS_ADP"},
{ 0x14, "xxx"},
--
1.7.9.5

2014-04-14 16:45:53

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 10/15] bus: omap_l3_noc: remove iclk from omap_l3 struct

we do not use iclk directly anymore. And, even if we had to, we
should be using pm_runtime APIs to do the same to be completely SoC
independent.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.h | 1 -
1 file changed, 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index a1931e8..573e40f 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -142,7 +142,6 @@ static struct l3_target_data *l3_targ[L3_MODULES] = {

struct omap_l3 {
struct device *dev;
- struct clk *ick;

/* memory base */
void __iomem *l3_base[L3_MODULES];
--
1.7.9.5

2014-04-14 16:47:50

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 12/15] bus: omap_l3_noc: convert flagmux information into a structure

This allows us to encompass target information and flag mux offset that
points to the target information into a singular structure. This saves
us the need to look up two different arrays indexed by module ID for
information.

This allows us to reduce the static target information allocation to
just the ones that are documented.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 16 +++++++----
drivers/bus/omap_l3_noc.h | 70 +++++++++++++++++++++++++++++----------------
2 files changed, 56 insertions(+), 30 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 3819b2f..49b19d5 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -60,6 +60,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";
struct l3_target_data *l3_targ_inst;
+ struct l3_flagmux_data *flag_mux;
char *err_description;
char err_string[30] = { 0 };

@@ -72,7 +73,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = readl_relaxed(base + l3->l3_flagmux[i] +
+ flag_mux = l3->l3_flagmux[i];
+ err_reg = readl_relaxed(base + flag_mux->offset +
L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
@@ -85,9 +87,13 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
/* We DONOT expect err_src to go out of bounds */
BUG_ON(err_src >= MAX_CLKDM_TARGETS);

- l3_targ_inst = &l3->l3_targ[i][err_src];
- target_name = l3_targ_inst->name;
- l3_targ_base = base + l3_targ_inst->offset;
+ if (err_src < flag_mux->num_targ_data) {
+ l3_targ_inst = &flag_mux->l3_targ[err_src];
+ target_name = l3_targ_inst->name;
+ l3_targ_base = base + l3_targ_inst->offset;
+ } else {
+ target_name = L3_TARGET_NOT_SUPPORTED;
+ }

/*
* If we do not know of a register offset to decode
@@ -107,7 +113,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
inttype ? "debug" : "application",
err_src, i, "(unclearable)");

- mask_reg = base + l3->l3_flagmux[i] +
+ mask_reg = base + flag_mux->offset +
L3_FLAGMUX_MASK0 + (inttype << 3);
mask_val = readl(mask_reg);
mask_val &= ~(1 << err_src);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index a546870..af33b6e 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -17,8 +17,8 @@
#ifndef __OMAP_L3_NOC_H
#define __OMAP_L3_NOC_H

-#define OMAP_L3_MODULES 3
#define MAX_L3_MODULES 3
+#define MAX_CLKDM_TARGETS 30

#define CLEAR_STDERR_LOG (1 << 31)
#define CUSTOM_ERROR 0x2
@@ -36,8 +36,6 @@

#define L3_TARGET_NOT_SUPPORTED NULL

-#define MAX_CLKDM_TARGETS 30
-
/**
* struct l3_masters_data - L3 Master information
* @id: ID of the L3 Master
@@ -60,21 +58,32 @@ struct l3_target_data {
char *name;
};

+/**
+ * struct l3_flagmux_data - Flag Mux information
+ * @offset: offset from base for flagmux register
+ * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
+ * target data. unsupported ones are marked with
+ * L3_TARGET_NOT_SUPPORTED
+ * @num_targ_data: number of entries in target data
+ */
+struct l3_flagmux_data {
+ u32 offset;
+ struct l3_target_data *l3_targ;
+ u8 num_targ_data;
+};
+

/**
* struct omap_l3 - Description of data relevant for L3 bus.
* @dev: device representing the bus (populated runtime)
* @l3_base: base addresses of modules (populated runtime)
- * @l3_flag_mux: array containing offsets to flag mux per module
+ * @l3_flag_mux: array containing flag mux data per module
* offset from corresponding module base indexed per
* module.
* @num_modules: number of clock domains / modules.
* @l3_masters: array pointing to master data containing name and register
* offset for the master.
* @num_master: number of masters
- * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
- * target data. unsupported ones are marked with
- * L3_TARGET_NOT_SUPPORTED
* @debug_irq: irq number of the debug interrupt (populated runtime)
* @app_irq: irq number of the application interrupt (populated runtime)
*/
@@ -82,25 +91,17 @@ struct omap_l3 {
struct device *dev;

void __iomem *l3_base[MAX_L3_MODULES];
- u32 *l3_flagmux;
+ struct l3_flagmux_data **l3_flagmux;
int num_modules;

struct l3_masters_data *l3_masters;
int num_masters;

- struct l3_target_data **l3_targ;
-
int debug_irq;
int app_irq;
};

-static u32 omap_l3_flagmux[OMAP_L3_MODULES] = {
- 0x500,
- 0x1000,
- 0X0200
-};
-
-static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk1[] = {
{0x100, "DMM1",},
{0x200, "DMM2",},
{0x300, "ABE",},
@@ -110,7 +111,14 @@ static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = {
{0x900, "L4WAKEUP",},
};

-static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = {
+static struct l3_flagmux_data omap_l3_flagmux_clk1 = {
+ .offset = 0x500,
+ .l3_targ = omap_l3_target_data_clk1,
+ .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk1),
+};
+
+
+static struct l3_target_data omap_l3_target_data_clk2[] = {
{0x500, "CORTEXM3",},
{0x300, "DSS",},
{0x100, "GPMC",},
@@ -134,12 +142,25 @@ static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = {
{0x1700, "LLI",},
};

-static struct l3_target_data omap_l3_target_data_clk3[MAX_CLKDM_TARGETS] = {
+static struct l3_flagmux_data omap_l3_flagmux_clk2 = {
+ .offset = 0x1000,
+ .l3_targ = omap_l3_target_data_clk2,
+ .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk2),
+};
+
+
+static struct l3_target_data omap_l3_target_data_clk3[] = {
{0x0100, "EMUSS",},
{0x0300, "DEBUG SOURCE",},
{0x0, "HOST CLK3",},
};

+static struct l3_flagmux_data omap_l3_flagmux_clk3 = {
+ .offset = 0x0200,
+ .l3_targ = omap_l3_target_data_clk3,
+ .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk3),
+};
+
static struct l3_masters_data omap_l3_masters[] = {
{ 0x0 , "MPU"},
{ 0x10, "CS_ADP"},
@@ -168,18 +189,17 @@ static struct l3_masters_data omap_l3_masters[] = {
{ 0xC8, "USBHOSTFS"}
};

-static struct l3_target_data *omap_l3_targ[OMAP_L3_MODULES] = {
- omap_l3_target_data_clk1,
- omap_l3_target_data_clk2,
- omap_l3_target_data_clk3,
+static struct l3_flagmux_data *omap_l3_flagmux[] = {
+ &omap_l3_flagmux_clk1,
+ &omap_l3_flagmux_clk2,
+ &omap_l3_flagmux_clk3,
};

static const struct omap_l3 omap_l3_data = {
.l3_flagmux = omap_l3_flagmux,
- .num_modules = OMAP_L3_MODULES,
+ .num_modules = ARRAY_SIZE(omap_l3_flagmux),
.l3_masters = omap_l3_masters,
.num_masters = ARRAY_SIZE(omap_l3_masters),
- .l3_targ = omap_l3_targ,
};

#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-14 16:47:48

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 03/15] bus: omap_l3_noc: un-obfuscate l3_targ address computation

just simplify derefencing that is equivalent.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 0d346e6..b39ef93 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -76,7 +76,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
err_src = __ffs(err_reg);

/* Read the stderrlog_main_source from clk domain */
- l3_targ_base = base + *(l3_targ[i] + err_src);
+ l3_targ_base = base + l3_targ[i][err_src];
l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
l3_targ_slvofslsb = l3_targ_base +
L3_TARG_STDERRLOG_SLVOFSLSB;
--
1.7.9.5

2014-04-14 16:47:46

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 07/15] bus: omap_l3_noc: populate l3->dev and use it

l3->dev is not populated, so populate it and use it to print information
relevant to the device instead of using a generic pr_*.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 0f0417a..da4e27c 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -118,7 +118,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

if (std_err) {
WARN(true,
- "L3 %s Error: MASTER %s TARGET %s %s\n",
+ "%s:L3 %s Error: MASTER %s TARGET %s %s\n",
+ dev_name(l3->dev),
err_description,
master_name, target_name,
err_string);
@@ -143,6 +144,7 @@ static int omap4_l3_probe(struct platform_device *pdev)
if (!l3)
return -ENOMEM;

+ l3->dev = &pdev->dev;
platform_set_drvdata(pdev, l3);

/* Get mem resources */
@@ -152,7 +154,7 @@ static int omap4_l3_probe(struct platform_device *pdev)

l3->l3_base[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(l3->l3_base[i])) {
- dev_err(&pdev->dev, "ioremap %d failed\n", i);
+ dev_err(l3->dev, "ioremap %d failed\n", i);
return PTR_ERR(l3->l3_base[i]);
}
}
@@ -161,19 +163,19 @@ static int omap4_l3_probe(struct platform_device *pdev)
* Setup interrupt Handlers
*/
l3->debug_irq = platform_get_irq(pdev, 0);
- ret = devm_request_irq(&pdev->dev, l3->debug_irq, l3_interrupt_handler,
+ ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler,
IRQF_DISABLED, "l3-dbg-irq", l3);
if (ret) {
- dev_err(&pdev->dev, "request_irq failed for %d\n",
+ dev_err(l3->dev, "request_irq failed for %d\n",
l3->debug_irq);
return ret;
}

l3->app_irq = platform_get_irq(pdev, 1);
- ret = devm_request_irq(&pdev->dev, l3->app_irq, l3_interrupt_handler,
+ ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler,
IRQF_DISABLED, "l3-app-irq", l3);
if (ret)
- dev_err(&pdev->dev, "request_irq failed for %d\n", l3->app_irq);
+ dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq);

return ret;
}
--
1.7.9.5

2014-04-14 16:49:57

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 02/15] bus: omap_l3_noc: switch over to relaxed variants of readl/writel

Currently we use __raw_readl and writel in this driver, however, there
is no strict sequencing needs for this driver, hence we should be good
with the relaxed variants.

While at it, simplify address computation using variables for register.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 1eb6d85..0d346e6 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -55,6 +55,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
int err_src = 0;
u32 std_err_main, err_reg, clear, masterid;
void __iomem *base, *l3_targ_base;
+ void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";

/* Get the Type of interrupt */
@@ -66,8 +67,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = __raw_readl(base + l3_flagmux[i] +
- + L3_FLAGMUX_REGERR0 + (inttype << 3));
+ err_reg = readl_relaxed(base + l3_flagmux[i] +
+ L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
if (err_reg) {
@@ -76,10 +77,14 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Read the stderrlog_main_source from clk domain */
l3_targ_base = base + *(l3_targ[i] + err_src);
- std_err_main = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
- masterid = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MSTADDR);
+ l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
+ l3_targ_slvofslsb = l3_targ_base +
+ L3_TARG_STDERRLOG_SLVOFSLSB;
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_MSTADDR;
+
+ std_err_main = readl_relaxed(l3_targ_stderr);
+ masterid = readl_relaxed(l3_targ_mstaddr);

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
@@ -87,12 +92,10 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
l3_targ_inst_name[i][err_src];
WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
target_name,
- __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_SLVOFSLSB));
+ readl_relaxed(l3_targ_slvofslsb));
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

case CUSTOM_ERROR:
@@ -107,8 +110,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
master_name, target_name);
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

default:
--
1.7.9.5

2014-04-14 16:50:52

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 09/15] bus: omap_l3_noc: rename functions and data to omap_l3

From: Sricharan R <[email protected]>

Since omap_l3_noc driver is now being used for OMAP5 and reusable with
DRA7 and AM437x, using omap4 specific naming is misleading.

Signed-off-by: Sricharan R <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 24 ++++++++++++------------
drivers/bus/omap_l3_noc.h | 11 ++++++-----
2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index c2b0cc3..6848822 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -1,5 +1,5 @@
/*
- * OMAP4XXX L3 Interconnect error handling driver
+ * OMAP L3 Interconnect error handling driver
*
* Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
@@ -50,7 +50,7 @@
static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
{

- struct omap4_l3 *l3 = _l3;
+ struct omap_l3 *l3 = _l3;
int inttype, i, k;
int err_src = 0;
u32 std_err_main, err_reg, clear, masterid;
@@ -166,9 +166,9 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
return IRQ_HANDLED;
}

-static int omap4_l3_probe(struct platform_device *pdev)
+static int omap_l3_probe(struct platform_device *pdev)
{
- static struct omap4_l3 *l3;
+ static struct omap_l3 *l3;
int ret, i;

l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL);
@@ -221,8 +221,8 @@ MODULE_DEVICE_TABLE(of, l3_noc_match);
#define l3_noc_match NULL
#endif

-static struct platform_driver omap4_l3_driver = {
- .probe = omap4_l3_probe,
+static struct platform_driver omap_l3_driver = {
+ .probe = omap_l3_probe,
.driver = {
.name = "omap_l3_noc",
.owner = THIS_MODULE,
@@ -230,14 +230,14 @@ static struct platform_driver omap4_l3_driver = {
},
};

-static int __init omap4_l3_init(void)
+static int __init omap_l3_init(void)
{
- return platform_driver_register(&omap4_l3_driver);
+ return platform_driver_register(&omap_l3_driver);
}
-postcore_initcall_sync(omap4_l3_init);
+postcore_initcall_sync(omap_l3_init);

-static void __exit omap4_l3_exit(void)
+static void __exit omap_l3_exit(void)
{
- platform_driver_unregister(&omap4_l3_driver);
+ platform_driver_unregister(&omap_l3_driver);
}
-module_exit(omap4_l3_exit);
+module_exit(omap_l3_exit);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index c4a1760..a1931e8 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -1,5 +1,5 @@
/*
- * OMAP4XXX L3 Interconnect error handling driver header
+ * OMAP L3 Interconnect error handling driver header
*
* Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
@@ -14,8 +14,8 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
-#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#ifndef __OMAP_L3_NOC_H
+#define __OMAP_L3_NOC_H

#define L3_MODULES 3
#define CLEAR_STDERR_LOG (1 << 31)
@@ -140,7 +140,7 @@ static struct l3_target_data *l3_targ[L3_MODULES] = {
l3_target_inst_data_clk3,
};

-struct omap4_l3 {
+struct omap_l3 {
struct device *dev;
struct clk *ick;

@@ -150,4 +150,5 @@ struct omap4_l3 {
int debug_irq;
int app_irq;
};
-#endif
+
+#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-14 16:50:49

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 01/15] bus: omap_l3_noc: Fix copyright information

This is an embarrassing patch :(.

Texas Corporation does not make OMAP. Texas Instruments Inc does.

For that matter I dont seem to be able to find a Texas Corporation on
the internet either.

While at it, update coverage to the current year and update the template
to remove redundant information and use the standard boiler plate
licensing.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 18 ++++++------------
drivers/bus/omap_l3_noc.h | 18 ++++++------------
2 files changed, 12 insertions(+), 24 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 972691a..1eb6d85 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -1,24 +1,18 @@
/*
* OMAP4XXX L3 Interconnect error handling driver
*
- * Copyright (C) 2011 Texas Corporation
+ * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
* Sricharan <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index a6ce34d..cc4b1b1 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -1,24 +1,18 @@
/*
* OMAP4XXX L3 Interconnect error handling driver header
*
- * Copyright (C) 2011 Texas Corporation
+ * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
* sricharan <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
--
1.7.9.5

2014-04-14 16:50:45

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 13/15] bus: omap_l3_noc: introduce concept of submodule

While OMAP4 and OMAP5 had 3 separate clock domains, DRA7 has only 2
and the first one then is internally divided into 2 sub clock domains.

To better represent this in the driver, we use the concept of submodule.

The address defintions in the devicetree is as per the high level
clock domain(module) base, the sub clockdomain/subdomain which shares
the same register space of a clockdomain is marked in the SoC data as
L3_BASE_IS_SUBMODULE.

L3_BASE_IS_SUBMODULE is used as an indication that it's base address is
the same as the parent module and offsets are considered from the same
base address as they are usually intermingled.

Other than the base address, the submodule is same as a module as it is
functionally so.

Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 17 ++++++++++++-----
drivers/bus/omap_l3_noc.h | 6 +++++-
2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 49b19d5..5e2a89d 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -184,7 +184,7 @@ static int omap_l3_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
static struct omap_l3 *l3;
- int ret, i;
+ int ret, i, res_idx;

of_id = of_match_device(l3_noc_match, &pdev->dev);
if (!of_id) {
@@ -201,15 +201,22 @@ static int omap_l3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, l3);

/* Get mem resources */
- for (i = 0; i < l3->num_modules; i++) {
- struct resource *res = platform_get_resource(pdev,
- IORESOURCE_MEM, i);
-
+ for (i = 0, res_idx = 0; i < l3->num_modules; i++) {
+ struct resource *res;
+
+ if (l3->l3_base[i] == L3_BASE_IS_SUBMODULE) {
+ /* First entry cannot be submodule */
+ BUG_ON(i == 0);
+ l3->l3_base[i] = l3->l3_base[i - 1];
+ continue;
+ }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx);
l3->l3_base[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(l3->l3_base[i])) {
dev_err(l3->dev, "ioremap %d failed\n", i);
return PTR_ERR(l3->l3_base[i]);
}
+ res_idx++;
}

/*
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index af33b6e..592821f 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -36,6 +36,8 @@

#define L3_TARGET_NOT_SUPPORTED NULL

+#define L3_BASE_IS_SUBMODULE ((void __iomem *)(1 << 0))
+
/**
* struct l3_masters_data - L3 Master information
* @id: ID of the L3 Master
@@ -76,7 +78,9 @@ struct l3_flagmux_data {
/**
* struct omap_l3 - Description of data relevant for L3 bus.
* @dev: device representing the bus (populated runtime)
- * @l3_base: base addresses of modules (populated runtime)
+ * @l3_base: base addresses of modules (populated runtime if 0)
+ * if set to L3_BASE_IS_SUBMODULE, then uses previous
+ * module index as the base address
* @l3_flag_mux: array containing flag mux data per module
* offset from corresponding module base indexed per
* module.
--
1.7.9.5

2014-04-17 20:50:15

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 07/19] bus: omap_l3_noc: move L3 master data structure out

Move the L3 master structure out of the static definition to enable
reuse for other SoCs.

Signed-off-by: Nishanth Menon <[email protected]>
---
V2: no functional change, just reordering
V1: https://patchwork.kernel.org/patch/3984151/
drivers/bus/omap_l3_noc.h | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 31984cf..059c707 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -33,6 +33,16 @@

#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0]))

+/**
+ * struct l3_masters_data - L3 Master information
+ * @id: ID of the L3 Master
+ * @name: master name
+ */
+struct l3_masters_data {
+ u32 id;
+ char *name;
+};
+
static u32 l3_flagmux[L3_MODULES] = {
0x500,
0x1000,
@@ -80,10 +90,7 @@ static u32 l3_targ_inst_clk3[] = {
0x0 /* HOST CLK3 */
};

-static struct l3_masters_data {
- u32 id;
- char name[10];
-} l3_masters[] = {
+static struct l3_masters_data l3_masters[] = {
{ 0x0 , "MPU"},
{ 0x10, "CS_ADP"},
{ 0x14, "xxx"},
--
1.7.9.5

2014-04-17 20:50:28

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 12/19] bus: omap_l3_noc: fix masterid detection

As per Documentation (OMAP4+), then masterid is infact encoded as
follows:
"L3_TARG_STDERRLOG_MSTADDR[7:0] STDERRLOG_MSTADDR stores the NTTP
master address. The master address is the concatenation of Prefix &
Initiator ConnID. It is defined on 8 bits. The 6 MSBs are used to
distinguish the different initiators."

So when we matchup currently with the master ID list, we never get a
proper match other than when MPU is the master (thanks to 0). Fix this
by using the relevant 6MSBits to identify the master ID for standard
and custom errors.

Reported-by: Darren Etheridge <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
---

New patch.

drivers/bus/omap_l3_noc.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 300e168..29d6206 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -127,7 +127,12 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
L3_TARG_STDERRLOG_MSTADDR;

std_err_main = readl_relaxed(l3_targ_stderr);
- masterid = readl_relaxed(l3_targ_mstaddr);
+ /*
+ * STDERRLOG_MSTADDR Stores the NTTP master address.
+ * The 6 MSBs are used to distinguish the different
+ * initiators
+ */
+ masterid = (readl_relaxed(l3_targ_mstaddr) & 0xFF) >> 2;

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
--
1.7.9.5

2014-04-17 20:50:39

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 15/19] bus: omap_l3_noc: add information about the type of operation

Today we get error such as
L3 Custom Error: MASTER MPU TARGET L4PER2

But since the actual instruction triggerring the error Vs the point
at which we report error may not be aligned, it makes sense to try
and provide additional information - example the type of operation
that was attempted to being performed can help narrow the debug down
further.

This helps provide log such as:
L3 Custom Error: MASTER MPU TARGET L4PER2 (Read)

Signed-off-by: Nishanth Menon <[email protected]>
---

New patch

drivers/bus/omap_l3_noc.c | 9 ++++++++-
drivers/bus/omap_l3_noc.h | 13 +++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index e45b960..0beefb3 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -60,8 +60,10 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
{
int k;
u32 std_err_main, clear, masterid;
+ u8 op_code;
void __iomem *l3_targ_base;
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
+ void __iomem *l3_targ_hdr;
struct l3_target_data *l3_targ_inst;
struct l3_masters_data *master;
char *target_name, *master_name = "UN IDENTIFIED";
@@ -96,6 +98,7 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
readl_relaxed(l3_targ_slvofslsb));

l3_targ_mstaddr = l3_targ_base + L3_TARG_STDERRLOG_MSTADDR;
+ l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_HDR;
break;

case CUSTOM_ERROR:
@@ -103,6 +106,7 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,

l3_targ_mstaddr = l3_targ_base +
L3_TARG_STDERRLOG_CINFO_MSTADDR;
+ l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_CINFO_OPCODE;
break;

default:
@@ -126,11 +130,14 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
}
}

+ op_code = readl_relaxed(l3_targ_hdr) & 0x7;
+
WARN(true,
- "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
+ "%s:L3 %s Error: MASTER %s TARGET %s (%s)%s\n",
dev_name(l3->dev),
err_description,
master_name, target_name,
+ l3_transaction_type[op_code],
err_string);

/* clear the std error log*/
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 18cdc25..8efde7f 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -29,14 +29,27 @@

/* L3 TARG register offsets */
#define L3_TARG_STDERRLOG_MAIN 0x48
+#define L3_TARG_STDERRLOG_HDR 0x4c
#define L3_TARG_STDERRLOG_MSTADDR 0x50
#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c
#define L3_TARG_STDERRLOG_CINFO_MSTADDR 0x68
+#define L3_TARG_STDERRLOG_CINFO_OPCODE 0x6c
#define L3_FLAGMUX_REGERR0 0xc
#define L3_FLAGMUX_MASK0 0x8

#define L3_TARGET_NOT_SUPPORTED NULL

+static const char * const l3_transaction_type[] = {
+ /* 0 0 0 */ "Idle",
+ /* 0 0 1 */ "Write",
+ /* 0 1 0 */ "Read",
+ /* 0 1 1 */ "ReadEx",
+ /* 1 0 0 */ "Read Link",
+ /* 1 0 1 */ "Write Non-Posted",
+ /* 1 1 0 */ "Write Conditional",
+ /* 1 1 1 */ "Write Broadcast",
+};
+
/**
* struct l3_masters_data - L3 Master information
* @id: ID of the L3 Master
--
1.7.9.5

2014-04-17 20:50:51

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 05/19] bus: omap_l3_noc: switch over to relaxed variants of readl/writel

Currently we use __raw_readl and writel in this driver, however, there
is no strict sequencing needs for this driver, hence we should be good
with the relaxed variants.

While at it, simplify address computation using variables for register.

Signed-off-by: Nishanth Menon <[email protected]>
---
V2: no functional change, just reordering
V1: https://patchwork.kernel.org/patch/3984051/
drivers/bus/omap_l3_noc.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 37d71b7..c8facb0 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -55,6 +55,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
int err_src = 0;
u32 std_err_main, err_reg, clear, masterid;
void __iomem *base, *l3_targ_base;
+ void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";

/* Get the Type of interrupt */
@@ -66,8 +67,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = __raw_readl(base + l3_flagmux[i] +
- + L3_FLAGMUX_REGERR0 + (inttype << 3));
+ err_reg = readl_relaxed(base + l3_flagmux[i] +
+ L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
if (err_reg) {
@@ -76,10 +77,14 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Read the stderrlog_main_source from clk domain */
l3_targ_base = base + *(l3_targ[i] + err_src);
- std_err_main = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
- masterid = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MSTADDR);
+ l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
+ l3_targ_slvofslsb = l3_targ_base +
+ L3_TARG_STDERRLOG_SLVOFSLSB;
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_MSTADDR;
+
+ std_err_main = readl_relaxed(l3_targ_stderr);
+ masterid = readl_relaxed(l3_targ_mstaddr);

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
@@ -87,12 +92,10 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
l3_targ_inst_name[i][err_src];
WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
target_name,
- __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_SLVOFSLSB));
+ readl_relaxed(l3_targ_slvofslsb));
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

case CUSTOM_ERROR:
@@ -107,8 +110,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
master_name, target_name);
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

default:
--
1.7.9.5

2014-04-17 20:51:36

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 14/19] bus: omap_l3_noc: improve readability by using helper for slave event parsing

Current interrupt handler does the first level parse to identify the
slave and then handles the slave even identification, reporting and
clearing of event as well. It is hence logical to split the handler
into two where the primary handler just parses the flagmux till it
identifies a slave and the slave handling, reporting and clearing is
done in a helper function.

While at it update the documentation in kerneldoc style.

Signed-off-by: Nishanth Menon <[email protected]>
---

New Patch

drivers/bus/omap_l3_noc.c | 218 ++++++++++++++++++++++++---------------------
1 file changed, 117 insertions(+), 101 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index b03c415..e45b960 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -26,14 +26,20 @@

#include "omap_l3_noc.h"

-/*
- * Interrupt Handler for L3 error detection.
- * 1) Identify the L3 clockdomain partition to which the error belongs to.
- * 2) Identify the slave where the error information is logged
- * 3) Print the logged information.
- * 4) Add dump stack to provide kernel trace.
+/**
+ * l3_handle_target() - Handle Target specific parse and reporting
+ * @l3: pointer to l3 struct
+ * @base: base address of clkdm
+ * @flag_mux: flagmux corresponding to the event
+ * @err_src: error source index of the slave (target)
+ *
+ * This does the second part of the error interrupt handling:
+ * 3) Parse in the slave information
+ * 4) Print the logged information.
+ * 5) Add dump stack to provide kernel trace.
+ * 6) Clear the source if known.
*
- * Two Types of errors :
+ * This handles two types of errors:
* 1) Custom errors in L3 :
* Target like DMM/FW/EMIF generates SRESP=ERR error
* 2) Standard L3 error:
@@ -49,22 +55,111 @@
* can be trapped as well. But the trapping is implemented as part
* secure software and hence need not be implemented here.
*/
-static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
+static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
+ struct l3_flagmux_data *flag_mux, int err_src)
{
-
- struct omap_l3 *l3 = _l3;
- int inttype, i, k;
- int err_src = 0;
- u32 std_err_main, err_reg, clear, masterid;
- void __iomem *base, *l3_targ_base;
+ int k;
+ u32 std_err_main, clear, masterid;
+ void __iomem *l3_targ_base;
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
- char *target_name, *master_name = "UN IDENTIFIED";
struct l3_target_data *l3_targ_inst;
- struct l3_flagmux_data *flag_mux;
struct l3_masters_data *master;
+ char *target_name, *master_name = "UN IDENTIFIED";
char *err_description;
char err_string[30] = { 0 };

+ /* We DONOT expect err_src to go out of bounds */
+ BUG_ON(err_src > MAX_CLKDM_TARGETS);
+
+ if (err_src < flag_mux->num_targ_data) {
+ l3_targ_inst = &flag_mux->l3_targ[err_src];
+ target_name = l3_targ_inst->name;
+ l3_targ_base = base + l3_targ_inst->offset;
+ } else {
+ target_name = L3_TARGET_NOT_SUPPORTED;
+ }
+
+ if (target_name == L3_TARGET_NOT_SUPPORTED)
+ return -ENODEV;
+
+ /* Read the stderrlog_main_source from clk domain */
+ l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
+ l3_targ_slvofslsb = l3_targ_base + L3_TARG_STDERRLOG_SLVOFSLSB;
+
+ std_err_main = readl_relaxed(l3_targ_stderr);
+
+ switch (std_err_main & CUSTOM_ERROR) {
+ case STANDARD_ERROR:
+ err_description = "Standard";
+ snprintf(err_string, sizeof(err_string),
+ ": At Address: 0x%08X ",
+ readl_relaxed(l3_targ_slvofslsb));
+
+ l3_targ_mstaddr = l3_targ_base + L3_TARG_STDERRLOG_MSTADDR;
+ break;
+
+ case CUSTOM_ERROR:
+ err_description = "Custom";
+
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_CINFO_MSTADDR;
+ break;
+
+ default:
+ /* Nothing to be handled here as of now */
+ return 0;
+ }
+
+
+ /*
+ * STDERRLOG_MSTADDR Stores the NTTP master
+ * address. The 6 MSBs are used to distinguish
+ * the different initiators
+ */
+ masterid = (readl_relaxed(l3_targ_mstaddr) & 0xFF) >> 2;
+
+ for (k = 0, master = l3->l3_masters; k < l3->num_masters;
+ k++, master++) {
+ if (masterid == master->id) {
+ master_name = master->name;
+ break;
+ }
+ }
+
+ WARN(true,
+ "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
+ dev_name(l3->dev),
+ err_description,
+ master_name, target_name,
+ err_string);
+
+ /* clear the std error log*/
+ clear = std_err_main | CLEAR_STDERR_LOG;
+ writel_relaxed(clear, l3_targ_stderr);
+
+ return 0;
+}
+
+/**
+ * l3_interrupt_handler() - interrupt handler for l3 events
+ * @irq: irq number
+ * @_l3: pointer to l3 structure
+ *
+ * Interrupt Handler for L3 error detection.
+ * 1) Identify the L3 clockdomain partition to which the error belongs to.
+ * 2) Identify the slave where the error information is logged
+ * ... handle the slave event..
+ * 7) if the slave is unknown, mask out the slave.
+ */
+static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
+{
+ struct omap_l3 *l3 = _l3;
+ int inttype, i, ret;
+ int err_src = 0;
+ u32 err_reg, mask_val;
+ void __iomem *base, *mask_reg;
+ struct l3_flagmux_data *flag_mux;
+
/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;

@@ -80,35 +175,18 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Get the corresponding error and analyse */
if (err_reg) {
- bool std_err = true;
-
/* Identify the source from control status register */
err_src = __ffs(err_reg);

- /* We DONOT expect err_src to go out of bounds */
- BUG_ON(err_src > MAX_CLKDM_TARGETS);
-
- if (err_src < flag_mux->num_targ_data) {
- l3_targ_inst = &flag_mux->l3_targ[err_src];
- target_name = l3_targ_inst->name;
- l3_targ_base = base + l3_targ_inst->offset;
- } else {
- target_name = L3_TARGET_NOT_SUPPORTED;
- }
+ ret = l3_handle_target(l3, base, flag_mux, err_src);

/*
- * If we do not know of a register offset to decode
- * and clear, then mask.
+ * Certain plaforms may have "undocumented" status
+ * pending on boot. So dont generate a severe warning
+ * here. Just mask it off to prevent the error from
+ * reoccuring and locking up the system.
*/
- if (target_name == L3_TARGET_NOT_SUPPORTED) {
- u32 mask_val;
- void __iomem *mask_reg;
-
- /*
- * Certain plaforms may have "undocumented"
- * status pending on boot.. So dont generate
- * a severe warning here.
- */
+ if (ret) {
dev_err(l3->dev,
"L3 %s error: target %d mod:%d %s\n",
inttype ? "debug" : "application",
@@ -119,70 +197,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
mask_val = readl(mask_reg);
mask_val &= ~(1 << err_src);
writel(mask_val, mask_reg);
-
- break;
- }
-
- /* Read the stderrlog_main_source from clk domain */
- l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
- l3_targ_slvofslsb = l3_targ_base +
- L3_TARG_STDERRLOG_SLVOFSLSB;
-
- std_err_main = readl_relaxed(l3_targ_stderr);
-
- switch (std_err_main & CUSTOM_ERROR) {
- case STANDARD_ERROR:
- err_description = "Standard";
- snprintf(err_string, sizeof(err_string),
- ": At Address: 0x%08X ",
- readl_relaxed(l3_targ_slvofslsb));
-
- l3_targ_mstaddr = l3_targ_base +
- L3_TARG_STDERRLOG_MSTADDR;
- break;
-
- case CUSTOM_ERROR:
- err_description = "Custom";
-
- l3_targ_mstaddr = l3_targ_base +
- L3_TARG_STDERRLOG_CINFO_MSTADDR;
- break;
-
- default:
- std_err = false;
- /* Nothing to be handled here as of now */
- break;
- }
-
- if (!std_err)
- break;
-
- /*
- * STDERRLOG_MSTADDR Stores the NTTP master
- * address. The 6 MSBs are used to distinguish
- * the different initiators
- */
- masterid = (readl_relaxed(l3_targ_mstaddr) &
- 0xFF) >> 2;
-
- for (k = 0, master = l3->l3_masters;
- k < l3->num_masters; k++, master++) {
- if (masterid == master->id) {
- master_name = master->name;
- break;
- }
}

- WARN(true,
- "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
- dev_name(l3->dev),
- err_description,
- master_name, target_name,
- err_string);
- /* clear the std error log*/
- clear = std_err_main | CLEAR_STDERR_LOG;
- writel_relaxed(clear, l3_targ_stderr);
-
/* Error found so break the for loop */
break;
}
--
1.7.9.5

2014-04-17 20:51:48

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 10/19] bus: omap_l3_noc: use of_match_data to pick up SoC information

From: Sricharan R <[email protected]>

DRA7xx SoC has the same l3-noc interconnect ip (as OMAP4 and OMAP5), but
AM437x SoC has just 2 modules instead of 3 which other SoCs have.

So, stop using direct access of array indices and use of->match data and
simplify implementation to benefit future usage.

While at it, rename a few very generic variables to make them omap
specific. This helps us differentiate from DRA7 and AM43xx data in the
future.

NOTE: None of the platforms that use omap_l3_noc are non-device tree
anymore. So, it is safe to assume OF match here.

Signed-off-by: Sricharan R <[email protected]>
Signed-off-by: Rajendra Nayak <[email protected]>
[[email protected]: split, refactor and optimize logic]
Signed-off-by: Nishanth Menon <[email protected]>
---
V2: reordering only.
V1: https://patchwork.kernel.org/patch/3984101/
drivers/bus/omap_l3_noc.c | 55 +++++++++++++++++++---------------
drivers/bus/omap_l3_noc.h | 72 ++++++++++++++++++++++++++++++++-------------
2 files changed, 84 insertions(+), 43 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 27c6ce2..fd31d37 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -14,12 +14,14 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#include <linux/module.h>
#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>

#include "omap_l3_noc.h"
@@ -58,17 +60,18 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";
struct l3_target_data *l3_targ_inst;
+ struct l3_masters_data *master;

/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;

- for (i = 0; i < L3_MODULES; i++) {
+ for (i = 0; i < l3->num_modules; i++) {
/*
* Read the regerr register of the clock domain
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = readl_relaxed(base + l3_flagmux[i] +
+ err_reg = readl_relaxed(base + l3->l3_flagmux[i] +
L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
@@ -79,7 +82,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
/* We DONOT expect err_src to go out of bounds */
BUG_ON(err_src > MAX_CLKDM_TARGETS);

- l3_targ_inst = &l3_targ[i][err_src];
+ l3_targ_inst = &l3->l3_targ[i][err_src];
target_name = l3_targ_inst->name;
l3_targ_base = base + l3_targ_inst->offset;

@@ -101,7 +104,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
inttype ? "debug" : "application",
err_src, i, "(unclearable)");

- mask_reg = base + l3_flagmux[i] +
+ mask_reg = base + l3->l3_flagmux[i] +
L3_FLAGMUX_MASK0 + (inttype << 3);
mask_val = readl(mask_reg);
mask_val &= ~(1 << err_src);
@@ -131,10 +134,12 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
break;

case CUSTOM_ERROR:
- for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
- if (masterid == l3_masters[k].id)
- master_name =
- l3_masters[k].name;
+ for (k = 0, master = l3->l3_masters;
+ k < l3->num_masters; k++, master++) {
+ if (masterid == master->id) {
+ master_name = master->name;
+ break;
+ }
}
WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
master_name, target_name);
@@ -154,20 +159,34 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
return IRQ_HANDLED;
}

+static const struct of_device_id l3_noc_match[] = {
+ {.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
+ {},
+};
+MODULE_DEVICE_TABLE(of, l3_noc_match);
+
static int omap_l3_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id;
static struct omap_l3 *l3;
int ret, i;

+ of_id = of_match_device(l3_noc_match, &pdev->dev);
+ if (!of_id) {
+ dev_err(&pdev->dev, "OF data missing\n");
+ return -EINVAL;
+ }
+
l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL);
if (!l3)
return -ENOMEM;

+ memcpy(l3, of_id->data, sizeof(*l3));
l3->dev = &pdev->dev;
platform_set_drvdata(pdev, l3);

/* Get mem resources */
- for (i = 0; i < L3_MODULES; i++) {
+ for (i = 0; i < l3->num_modules; i++) {
struct resource *res = platform_get_resource(pdev,
IORESOURCE_MEM, i);

@@ -199,22 +218,12 @@ static int omap_l3_probe(struct platform_device *pdev)
return ret;
}

-#if defined(CONFIG_OF)
-static const struct of_device_id l3_noc_match[] = {
- {.compatible = "ti,omap4-l3-noc", },
- {},
-};
-MODULE_DEVICE_TABLE(of, l3_noc_match);
-#else
-#define l3_noc_match NULL
-#endif
-
static struct platform_driver omap_l3_driver = {
.probe = omap_l3_probe,
.driver = {
.name = "omap_l3_noc",
.owner = THIS_MODULE,
- .of_match_table = l3_noc_match,
+ .of_match_table = of_match_ptr(l3_noc_match),
},
};

diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 66caece..e60865f 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -17,7 +17,9 @@
#ifndef __OMAP_L3_NOC_H
#define __OMAP_L3_NOC_H

-#define L3_MODULES 3
+#define OMAP_L3_MODULES 3
+#define MAX_L3_MODULES 3
+
#define CLEAR_STDERR_LOG (1 << 31)
#define CUSTOM_ERROR 0x2
#define STANDARD_ERROR 0x0
@@ -36,8 +38,6 @@

#define MAX_CLKDM_TARGETS 31

-#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0]))
-
/**
* struct l3_masters_data - L3 Master information
* @id: ID of the L3 Master
@@ -60,13 +60,47 @@ struct l3_target_data {
char *name;
};

-static u32 l3_flagmux[L3_MODULES] = {
+
+/**
+ * struct omap_l3 - Description of data relevant for L3 bus.
+ * @dev: device representing the bus (populated runtime)
+ * @l3_base: base addresses of modules (populated runtime)
+ * @l3_flag_mux: array containing offsets to flag mux per module
+ * offset from corresponding module base indexed per
+ * module.
+ * @num_modules: number of clock domains / modules.
+ * @l3_masters: array pointing to master data containing name and register
+ * offset for the master.
+ * @num_master: number of masters
+ * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
+ * target data. unsupported ones are marked with
+ * L3_TARGET_NOT_SUPPORTED
+ * @debug_irq: irq number of the debug interrupt (populated runtime)
+ * @app_irq: irq number of the application interrupt (populated runtime)
+ */
+struct omap_l3 {
+ struct device *dev;
+
+ void __iomem *l3_base[MAX_L3_MODULES];
+ u32 *l3_flagmux;
+ int num_modules;
+
+ struct l3_masters_data *l3_masters;
+ int num_masters;
+
+ struct l3_target_data **l3_targ;
+
+ int debug_irq;
+ int app_irq;
+};
+
+static u32 omap_l3_flagmux[OMAP_L3_MODULES] = {
0x500,
0x1000,
0X0200
};

-static struct l3_target_data l3_target_inst_data_clk1[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = {
{0x100, "DMM1",},
{0x200, "DMM2",},
{0x300, "ABE",},
@@ -76,7 +110,7 @@ static struct l3_target_data l3_target_inst_data_clk1[MAX_CLKDM_TARGETS] = {
{0x900, "L4WAKEUP",},
};

-static struct l3_target_data l3_target_inst_data_clk2[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = {
{0x500, "CORTEXM3",},
{0x300, "DSS",},
{0x100, "GPMC",},
@@ -100,13 +134,13 @@ static struct l3_target_data l3_target_inst_data_clk2[MAX_CLKDM_TARGETS] = {
{0x1700, "LLI",},
};

-static struct l3_target_data l3_target_inst_data_clk3[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk3[MAX_CLKDM_TARGETS] = {
{0x0100, "EMUSS",},
{0x0300, "DEBUG SOURCE",},
{0x0, "HOST CLK3",},
};

-static struct l3_masters_data l3_masters[] = {
+static struct l3_masters_data omap_l3_masters[] = {
{ 0x0 , "MPU"},
{ 0x10, "CS_ADP"},
{ 0x14, "xxx"},
@@ -134,20 +168,18 @@ static struct l3_masters_data l3_masters[] = {
{ 0xC8, "USBHOSTFS"}
};

-static struct l3_target_data *l3_targ[L3_MODULES] = {
- l3_target_inst_data_clk1,
- l3_target_inst_data_clk2,
- l3_target_inst_data_clk3,
+static struct l3_target_data *omap_l3_targ[OMAP_L3_MODULES] = {
+ omap_l3_target_data_clk1,
+ omap_l3_target_data_clk2,
+ omap_l3_target_data_clk3,
};

-struct omap_l3 {
- struct device *dev;
-
- /* memory base */
- void __iomem *l3_base[L3_MODULES];
-
- int debug_irq;
- int app_irq;
+static const struct omap_l3 omap_l3_data = {
+ .l3_flagmux = omap_l3_flagmux,
+ .num_modules = OMAP_L3_MODULES,
+ .l3_masters = omap_l3_masters,
+ .num_masters = ARRAY_SIZE(omap_l3_masters),
+ .l3_targ = omap_l3_targ,
};

#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-17 20:52:04

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 01/19] bus: omap_l3_noc: Fix copyright information

This is an embarrassing patch :(.

Texas Corporation does not make OMAP. Texas Instruments Inc does.

For that matter I dont seem to be able to find a Texas Corporation on
the internet either.

While at it, update coverage to the current year and update the template
to remove redundant information and use the standard boiler plate
licensing.

Signed-off-by: Nishanth Menon <[email protected]>
---
V2: no change
v1: https://patchwork.kernel.org/patch/3984341/

drivers/bus/omap_l3_noc.c | 18 ++++++------------
drivers/bus/omap_l3_noc.h | 18 ++++++------------
2 files changed, 12 insertions(+), 24 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 972691a..1eb6d85 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -1,24 +1,18 @@
/*
* OMAP4XXX L3 Interconnect error handling driver
*
- * Copyright (C) 2011 Texas Corporation
+ * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
* Sricharan <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index a6ce34d..cc4b1b1 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -1,24 +1,18 @@
/*
* OMAP4XXX L3 Interconnect error handling driver header
*
- * Copyright (C) 2011 Texas Corporation
+ * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
* sricharan <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
--
1.7.9.5

2014-04-17 20:52:18

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 13/19] bus: omap_l3_noc: make error reporting and handling common

The logic between handling CUSTOM_ERROR and STANDARD_ERROR is just the
reporting style.

So make it generic, simplify and standardize the reporting with both
master and target information printed to log.

Handle the register address difference for master code for standard
error and custom error as well.

While at it, fix a minor indentation error.

Signed-off-by: Nishanth Menon <[email protected]>
---

V2: reordering only
V1: https://patchwork.kernel.org/patch/3983991/

drivers/bus/omap_l3_noc.c | 76 ++++++++++++++++++++++++++++-----------------
drivers/bus/omap_l3_noc.h | 3 +-
2 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 29d6206..b03c415 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -62,6 +62,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
struct l3_target_data *l3_targ_inst;
struct l3_flagmux_data *flag_mux;
struct l3_masters_data *master;
+ char *err_description;
+ char err_string[30] = { 0 };

/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -78,6 +80,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Get the corresponding error and analyse */
if (err_reg) {
+ bool std_err = true;
+
/* Identify the source from control status register */
err_src = __ffs(err_reg);

@@ -123,48 +127,64 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
l3_targ_slvofslsb = l3_targ_base +
L3_TARG_STDERRLOG_SLVOFSLSB;
- l3_targ_mstaddr = l3_targ_base +
- L3_TARG_STDERRLOG_MSTADDR;

std_err_main = readl_relaxed(l3_targ_stderr);
- /*
- * STDERRLOG_MSTADDR Stores the NTTP master address.
- * The 6 MSBs are used to distinguish the different
- * initiators
- */
- masterid = (readl_relaxed(l3_targ_mstaddr) & 0xFF) >> 2;

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
- WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
- target_name,
- readl_relaxed(l3_targ_slvofslsb));
- /* clear the std error log*/
- clear = std_err_main | CLEAR_STDERR_LOG;
- writel_relaxed(clear, l3_targ_stderr);
+ err_description = "Standard";
+ snprintf(err_string, sizeof(err_string),
+ ": At Address: 0x%08X ",
+ readl_relaxed(l3_targ_slvofslsb));
+
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_MSTADDR;
break;

case CUSTOM_ERROR:
- for (k = 0, master = l3->l3_masters;
- k < l3->num_masters; k++, master++) {
- if (masterid == master->id) {
- master_name = master->name;
- break;
- }
- }
- WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
- master_name, target_name);
- /* clear the std error log*/
- clear = std_err_main | CLEAR_STDERR_LOG;
- writel_relaxed(clear, l3_targ_stderr);
+ err_description = "Custom";
+
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_CINFO_MSTADDR;
break;

default:
+ std_err = false;
/* Nothing to be handled here as of now */
break;
}
- /* Error found so break the for loop */
- break;
+
+ if (!std_err)
+ break;
+
+ /*
+ * STDERRLOG_MSTADDR Stores the NTTP master
+ * address. The 6 MSBs are used to distinguish
+ * the different initiators
+ */
+ masterid = (readl_relaxed(l3_targ_mstaddr) &
+ 0xFF) >> 2;
+
+ for (k = 0, master = l3->l3_masters;
+ k < l3->num_masters; k++, master++) {
+ if (masterid == master->id) {
+ master_name = master->name;
+ break;
+ }
+ }
+
+ WARN(true,
+ "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
+ dev_name(l3->dev),
+ err_description,
+ master_name, target_name,
+ err_string);
+ /* clear the std error log*/
+ clear = std_err_main | CLEAR_STDERR_LOG;
+ writel_relaxed(clear, l3_targ_stderr);
+
+ /* Error found so break the for loop */
+ break;
}
}
return IRQ_HANDLED;
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 64869fe..18cdc25 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -29,8 +29,9 @@

/* L3 TARG register offsets */
#define L3_TARG_STDERRLOG_MAIN 0x48
+#define L3_TARG_STDERRLOG_MSTADDR 0x50
#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c
-#define L3_TARG_STDERRLOG_MSTADDR 0x68
+#define L3_TARG_STDERRLOG_CINFO_MSTADDR 0x68
#define L3_FLAGMUX_REGERR0 0xc
#define L3_FLAGMUX_MASK0 0x8

--
1.7.9.5

2014-04-17 20:52:26

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 08/19] bus: omap_l3_noc: convert target information into a structure

Currently the target instance information is organized indexed by bit
field offset into multiple arrays.

1. We currently have offsets specific to each target associated with each
clock domains are in seperate arrays:

l3_targ_inst_clk1
l3_targ_inst_clk2
l3_targ_inst_clk3

2. Then they are organized per master index in l3_targ.

3. We have names in l3_targ_inst_name as an array to array of strings
corresponding to the above with offsets.

Simplify the same by defining a structure for information containing
both target offset and name. this is then stored in arrays per domain
and organized into an array indexed off domain.

The array is still indexed based on bit field offset.

Signed-off-by: Nishanth Menon <[email protected]>
---
V2: reordering changes only. no functional change since previous rev.
V1: https://patchwork.kernel.org/patch/3984091/
drivers/bus/omap_l3_noc.c | 9 ++--
drivers/bus/omap_l3_noc.h | 129 ++++++++++++++++++---------------------------
2 files changed, 54 insertions(+), 84 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index f7d3bf4..343f002 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -57,6 +57,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
void __iomem *base, *l3_targ_base;
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";
+ struct l3_target_data *l3_targ_inst;

/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -74,9 +75,11 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
if (err_reg) {
/* Identify the source from control status register */
err_src = __ffs(err_reg);
+ l3_targ_inst = &l3_targ[i][err_src];
+ target_name = l3_targ_inst->name;
+ l3_targ_base = base + l3_targ_inst->offset;

/* Read the stderrlog_main_source from clk domain */
- l3_targ_base = base + l3_targ[i][err_src];
l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
l3_targ_slvofslsb = l3_targ_base +
L3_TARG_STDERRLOG_SLVOFSLSB;
@@ -88,8 +91,6 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
- target_name =
- l3_targ_inst_name[i][err_src];
WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
target_name,
readl_relaxed(l3_targ_slvofslsb));
@@ -99,8 +100,6 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
break;

case CUSTOM_ERROR:
- target_name =
- l3_targ_inst_name[i][err_src];
for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
if (masterid == l3_masters[k].id)
master_name =
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 059c707..ae28784 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -43,51 +43,62 @@ struct l3_masters_data {
char *name;
};

+/**
+ * struct l3_target_data - L3 Target information
+ * @offset: Offset from base for L3 Target
+ * @name: Target name
+ *
+ * Target information is organized indexed by bit field definitions.
+ */
+struct l3_target_data {
+ u32 offset;
+ char *name;
+};
+
static u32 l3_flagmux[L3_MODULES] = {
0x500,
0x1000,
0X0200
};

-/* L3 Target standard Error register offsets */
-static u32 l3_targ_inst_clk1[] = {
- 0x100, /* DMM1 */
- 0x200, /* DMM2 */
- 0x300, /* ABE */
- 0x400, /* L4CFG */
- 0x600, /* CLK2 PWR DISC */
- 0x0, /* Host CLK1 */
- 0x900 /* L4 Wakeup */
+static struct l3_target_data l3_target_inst_data_clk1[] = {
+ {0x100, "DMM1",},
+ {0x200, "DMM2",},
+ {0x300, "ABE",},
+ {0x400, "L4CFG",},
+ {0x600, "CLK2PWRDISC",},
+ {0x0, "HOSTCLK1",},
+ {0x900, "L4WAKEUP",},
};

-static u32 l3_targ_inst_clk2[] = {
- 0x500, /* CORTEX M3 */
- 0x300, /* DSS */
- 0x100, /* GPMC */
- 0x400, /* ISS */
- 0x700, /* IVAHD */
- 0xD00, /* missing in TRM corresponds to AES1*/
- 0x900, /* L4 PER0*/
- 0x200, /* OCMRAM */
- 0x100, /* missing in TRM corresponds to GPMC sERROR*/
- 0x600, /* SGX */
- 0x800, /* SL2 */
- 0x1600, /* C2C */
- 0x1100, /* missing in TRM corresponds PWR DISC CLK1*/
- 0xF00, /* missing in TRM corrsponds to SHA1*/
- 0xE00, /* missing in TRM corresponds to AES2*/
- 0xC00, /* L4 PER3 */
- 0xA00, /* L4 PER1*/
- 0xB00, /* L4 PER2*/
- 0x0, /* HOST CLK2 */
- 0x1800, /* CAL */
- 0x1700 /* LLI */
+static struct l3_target_data l3_target_inst_data_clk2[] = {
+ {0x500, "CORTEXM3",},
+ {0x300, "DSS",},
+ {0x100, "GPMC",},
+ {0x400, "ISS",},
+ {0x700, "IVAHD",},
+ {0xD00, "AES1",},
+ {0x900, "L4PER0",},
+ {0x200, "OCMRAM",},
+ {0x100, "GPMCsERROR",},
+ {0x600, "SGX",},
+ {0x800, "SL2",},
+ {0x1600, "C2C",},
+ {0x1100, "PWRDISCCLK1",},
+ {0xF00, "SHA1",},
+ {0xE00, "AES2",},
+ {0xC00, "L4PER3",},
+ {0xA00, "L4PER1",},
+ {0xB00, "L4PER2",},
+ {0x0, "HOSTCLK2",},
+ {0x1800, "CAL",},
+ {0x1700, "LLI",},
};

-static u32 l3_targ_inst_clk3[] = {
- 0x0100 /* EMUSS */,
- 0x0300, /* DEBUGSS_CT_TBR */
- 0x0 /* HOST CLK3 */
+static struct l3_target_data l3_target_inst_data_clk3[] = {
+ {0x0100, "EMUSS",},
+ {0x0300, "DEBUG SOURCE",},
+ {0x0, "HOST CLK3",},
};

static struct l3_masters_data l3_masters[] = {
@@ -118,50 +129,10 @@ static struct l3_masters_data l3_masters[] = {
{ 0xC8, "USBHOSTFS"}
};

-static char *l3_targ_inst_name[L3_MODULES][21] = {
- {
- "DMM1",
- "DMM2",
- "ABE",
- "L4CFG",
- "CLK2 PWR DISC",
- "HOST CLK1",
- "L4 WAKEUP"
- },
- {
- "CORTEX M3" ,
- "DSS ",
- "GPMC ",
- "ISS ",
- "IVAHD ",
- "AES1",
- "L4 PER0",
- "OCMRAM ",
- "GPMC sERROR",
- "SGX ",
- "SL2 ",
- "C2C ",
- "PWR DISC CLK1",
- "SHA1",
- "AES2",
- "L4 PER3",
- "L4 PER1",
- "L4 PER2",
- "HOST CLK2",
- "CAL",
- "LLI"
- },
- {
- "EMUSS",
- "DEBUG SOURCE",
- "HOST CLK3"
- },
-};
-
-static u32 *l3_targ[L3_MODULES] = {
- l3_targ_inst_clk1,
- l3_targ_inst_clk2,
- l3_targ_inst_clk3,
+static struct l3_target_data *l3_targ[L3_MODULES] = {
+ l3_target_inst_data_clk1,
+ l3_target_inst_data_clk2,
+ l3_target_inst_data_clk3,
};

struct omap_l3 {
--
1.7.9.5

2014-04-17 20:52:44

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 16/19] bus: omap_l3_noc: Add information about the context of operation

L3 error may be triggered using Debug interface (example JTAG) or
due to other errors, for example an opcode fetch (due to function
pointer or stack corruption) or a data access (due to some other
failure). NOC registers contain additional information to help aid
debug information.

With this, we can enhance the error information to more detailed form:
"
L3 Custom Error: MASTER MPU TARGET L4PER2 (Read): Data Access in User mode
during Functional access
"

Signed-off-by: Nishanth Menon <[email protected]>
---
New Patch

drivers/bus/omap_l3_noc.c | 18 ++++++++++++++----
drivers/bus/omap_l3_noc.h | 2 ++
2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 0beefb3..9e68d6b 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -60,15 +60,16 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
{
int k;
u32 std_err_main, clear, masterid;
- u8 op_code;
+ u8 op_code, m_req_info;
void __iomem *l3_targ_base;
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
- void __iomem *l3_targ_hdr;
+ void __iomem *l3_targ_hdr, *l3_targ_info;
struct l3_target_data *l3_targ_inst;
struct l3_masters_data *master;
char *target_name, *master_name = "UN IDENTIFIED";
char *err_description;
char err_string[30] = { 0 };
+ char info_string[60] = { 0 };

/* We DONOT expect err_src to go out of bounds */
BUG_ON(err_src > MAX_CLKDM_TARGETS);
@@ -99,6 +100,7 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,

l3_targ_mstaddr = l3_targ_base + L3_TARG_STDERRLOG_MSTADDR;
l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_HDR;
+ l3_targ_info = l3_targ_base + L3_TARG_STDERRLOG_INFO;
break;

case CUSTOM_ERROR:
@@ -107,6 +109,7 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
l3_targ_mstaddr = l3_targ_base +
L3_TARG_STDERRLOG_CINFO_MSTADDR;
l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_CINFO_OPCODE;
+ l3_targ_info = l3_targ_base + L3_TARG_STDERRLOG_CINFO_INFO;
break;

default:
@@ -132,13 +135,20 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,

op_code = readl_relaxed(l3_targ_hdr) & 0x7;

+ m_req_info = readl_relaxed(l3_targ_info) & 0xF;
+ snprintf(info_string, sizeof(info_string),
+ ": %s in %s mode during %s access",
+ (m_req_info & BIT(0)) ? "Opcode Fetch" : "Data Access",
+ (m_req_info & BIT(1)) ? "Supervisor" : "User",
+ (m_req_info & BIT(3)) ? "Debug" : "Functional");
+
WARN(true,
- "%s:L3 %s Error: MASTER %s TARGET %s (%s)%s\n",
+ "%s:L3 %s Error: MASTER %s TARGET %s (%s)%s%s\n",
dev_name(l3->dev),
err_description,
master_name, target_name,
l3_transaction_type[op_code],
- err_string);
+ err_string, info_string);

/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 8efde7f..49258bb 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -31,7 +31,9 @@
#define L3_TARG_STDERRLOG_MAIN 0x48
#define L3_TARG_STDERRLOG_HDR 0x4c
#define L3_TARG_STDERRLOG_MSTADDR 0x50
+#define L3_TARG_STDERRLOG_INFO 0x58
#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c
+#define L3_TARG_STDERRLOG_CINFO_INFO 0x64
#define L3_TARG_STDERRLOG_CINFO_MSTADDR 0x68
#define L3_TARG_STDERRLOG_CINFO_OPCODE 0x6c
#define L3_FLAGMUX_REGERR0 0xc
--
1.7.9.5

2014-04-17 20:52:53

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 02/19] bus: omap_l3_noc: rename functions and data to omap_l3

From: Sricharan R <[email protected]>

Since omap_l3_noc driver is now being used for OMAP5 and reusable with
DRA7 and AM437x, using omap4 specific naming is misleading.

Signed-off-by: Sricharan R <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
---

V2: reordered the patch
V1: https://patchwork.kernel.org/patch/3984321/

drivers/bus/omap_l3_noc.c | 24 ++++++++++++------------
drivers/bus/omap_l3_noc.h | 11 ++++++-----
2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 1eb6d85..800486c 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -1,5 +1,5 @@
/*
- * OMAP4XXX L3 Interconnect error handling driver
+ * OMAP L3 Interconnect error handling driver
*
* Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
@@ -50,7 +50,7 @@
static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
{

- struct omap4_l3 *l3 = _l3;
+ struct omap_l3 *l3 = _l3;
int inttype, i, k;
int err_src = 0;
u32 std_err_main, err_reg, clear, masterid;
@@ -122,9 +122,9 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
return IRQ_HANDLED;
}

-static int omap4_l3_probe(struct platform_device *pdev)
+static int omap_l3_probe(struct platform_device *pdev)
{
- static struct omap4_l3 *l3;
+ static struct omap_l3 *l3;
int ret, i;

l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL);
@@ -176,8 +176,8 @@ MODULE_DEVICE_TABLE(of, l3_noc_match);
#define l3_noc_match NULL
#endif

-static struct platform_driver omap4_l3_driver = {
- .probe = omap4_l3_probe,
+static struct platform_driver omap_l3_driver = {
+ .probe = omap_l3_probe,
.driver = {
.name = "omap_l3_noc",
.owner = THIS_MODULE,
@@ -185,14 +185,14 @@ static struct platform_driver omap4_l3_driver = {
},
};

-static int __init omap4_l3_init(void)
+static int __init omap_l3_init(void)
{
- return platform_driver_register(&omap4_l3_driver);
+ return platform_driver_register(&omap_l3_driver);
}
-postcore_initcall_sync(omap4_l3_init);
+postcore_initcall_sync(omap_l3_init);

-static void __exit omap4_l3_exit(void)
+static void __exit omap_l3_exit(void)
{
- platform_driver_unregister(&omap4_l3_driver);
+ platform_driver_unregister(&omap_l3_driver);
}
-module_exit(omap4_l3_exit);
+module_exit(omap_l3_exit);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index cc4b1b1..b3c81f2 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -1,5 +1,5 @@
/*
- * OMAP4XXX L3 Interconnect error handling driver header
+ * OMAP L3 Interconnect error handling driver header
*
* Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
@@ -14,8 +14,8 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
-#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#ifndef __OMAP_L3_NOC_H
+#define __OMAP_L3_NOC_H

#define L3_MODULES 3
#define CLEAR_STDERR_LOG (1 << 31)
@@ -157,7 +157,7 @@ static u32 *l3_targ[L3_MODULES] = {
l3_targ_inst_clk3,
};

-struct omap4_l3 {
+struct omap_l3 {
struct device *dev;
struct clk *ick;

@@ -167,4 +167,5 @@ struct omap4_l3 {
int debug_irq;
int app_irq;
};
-#endif
+
+#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-17 20:53:12

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 17/19] bus: omap_l3_noc: introduce concept of submodule

While OMAP4 and OMAP5 had 3 separate clock domains, DRA7 has only 2
and the first one then is internally divided into 2 sub clock domains.

To better represent this in the driver, we use the concept of submodule.

The address defintions in the devicetree is as per the high level
clock domain(module) base, the sub clockdomain/subdomain which shares
the same register space of a clockdomain is marked in the SoC data as
L3_BASE_IS_SUBMODULE.

L3_BASE_IS_SUBMODULE is used as an indication that it's base address is
the same as the parent module and offsets are considered from the same
base address as they are usually intermingled.

Other than the base address, the submodule is same as a module as it is
functionally so.

Signed-off-by: Nishanth Menon <[email protected]>
---

V2: reordering only. no functional change.

V1: https://patchwork.kernel.org/patch/3984351/
drivers/bus/omap_l3_noc.c | 17 ++++++++++++-----
drivers/bus/omap_l3_noc.h | 6 +++++-
2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 9e68d6b..cf923f1 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -233,7 +233,7 @@ static int omap_l3_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
static struct omap_l3 *l3;
- int ret, i;
+ int ret, i, res_idx;

of_id = of_match_device(l3_noc_match, &pdev->dev);
if (!of_id) {
@@ -250,15 +250,22 @@ static int omap_l3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, l3);

/* Get mem resources */
- for (i = 0; i < l3->num_modules; i++) {
- struct resource *res = platform_get_resource(pdev,
- IORESOURCE_MEM, i);
-
+ for (i = 0, res_idx = 0; i < l3->num_modules; i++) {
+ struct resource *res;
+
+ if (l3->l3_base[i] == L3_BASE_IS_SUBMODULE) {
+ /* First entry cannot be submodule */
+ BUG_ON(i == 0);
+ l3->l3_base[i] = l3->l3_base[i - 1];
+ continue;
+ }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx);
l3->l3_base[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(l3->l3_base[i])) {
dev_err(l3->dev, "ioremap %d failed\n", i);
return PTR_ERR(l3->l3_base[i]);
}
+ res_idx++;
}

/*
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 49258bb..9df9f25 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -41,6 +41,8 @@

#define L3_TARGET_NOT_SUPPORTED NULL

+#define L3_BASE_IS_SUBMODULE ((void __iomem *)(1 << 0))
+
static const char * const l3_transaction_type[] = {
/* 0 0 0 */ "Idle",
/* 0 0 1 */ "Write",
@@ -92,7 +94,9 @@ struct l3_flagmux_data {
/**
* struct omap_l3 - Description of data relevant for L3 bus.
* @dev: device representing the bus (populated runtime)
- * @l3_base: base addresses of modules (populated runtime)
+ * @l3_base: base addresses of modules (populated runtime if 0)
+ * if set to L3_BASE_IS_SUBMODULE, then uses previous
+ * module index as the base address
* @l3_flag_mux: array containing flag mux data per module
* offset from corresponding module base indexed per
* module.
--
1.7.9.5

2014-04-17 20:53:17

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 18/19] bus: omap_l3_noc: Add DRA7 interconnect error data

From: Rajendra Nayak <[email protected]>

DRA7 is distinctly different from OMAP4 in terms of masters and clock
domain organization. There two main clock domains which is divided as
follows:
<0x44000000 0x1000000> is clk1 and clk2 is the sub clock domain
<0x45000000 0x1000> is clk3

Add all the data needed to handle L3 error handling on DRA7 devices
and mark clk2 as subdomain and provide a compatible flag for
functionality. Other than the data difference the hardware blocks
involved are essentially the same.

Signed-off-by: Rajendra Nayak <[email protected]>
[[email protected]: bugfixes and generic improvements, documentation]
Signed-off-by: Nishanth Menon <[email protected]>
---

V2: Updated with missing information from master internal doc common
for all DRA7 SoC variations

V1: https://patchwork.kernel.org/patch/3983551/
.../devicetree/bindings/arm/omap/l3-noc.txt | 1 +
drivers/bus/omap_l3_noc.c | 1 +
drivers/bus/omap_l3_noc.h | 149 ++++++++++++++++++++
3 files changed, 151 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
index c0105de..45d0fc2 100644
--- a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
+++ b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
@@ -6,6 +6,7 @@ provided by Arteris.
Required properties:
- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
Should be "ti,omap4-l3-noc" for OMAP4 family
+ Should be "ti,dra7-l3-noc" for DRA7 family
- reg: Contains L3 register address range for each noc domain.
- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index cf923f1..aa7a759 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -225,6 +225,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

static const struct of_device_id l3_noc_match[] = {
{.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
+ {.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
{},
};
MODULE_DEVICE_TABLE(of, l3_noc_match);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 9df9f25..acfeb5e 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -222,4 +222,153 @@ static const struct omap_l3 omap_l3_data = {
.num_masters = ARRAY_SIZE(omap_l3_masters),
};

+/* DRA7 data */
+static struct l3_target_data dra_l3_target_data_clk1[] = {
+ {0x2a00, "AES1",},
+ {0x0200, "DMM_P1",},
+ {0x0600, "DSP2_SDMA",},
+ {0x0b00, "EVE2",},
+ {0x1300, "DMM_P2",},
+ {0x2c00, "AES2",},
+ {0x0300, "DSP1_SDMA",},
+ {0x0a00, "EVE1",},
+ {0x0c00, "EVE3",},
+ {0x0d00, "EVE4",},
+ {0x2900, "DSS",},
+ {0x0100, "GPMC",},
+ {0x3700, "PCIE1",},
+ {0x1600, "IVA_CONFIG",},
+ {0x1800, "IVA_SL2IF",},
+ {0x0500, "L4_CFG",},
+ {0x1d00, "L4_WKUP",},
+ {0x3800, "PCIE2",},
+ {0x3300, "SHA2_1",},
+ {0x1200, "GPU",},
+ {0x1000, "IPU1",},
+ {0x1100, "IPU2",},
+ {0x2000, "TPCC_EDMA",},
+ {0x2e00, "TPTC1_EDMA",},
+ {0x2b00, "TPTC2_EDMA",},
+ {0x0700, "VCP1",},
+ {0x2500, "L4_PER2_P3",},
+ {0x0e00, "L4_PER3_P3",},
+ {0x2200, "MMU1",},
+ {0x1400, "PRUSS1",},
+ {0x1500, "PRUSS2"},
+ {0x0800, "VCP1",},
+};
+
+static struct l3_flagmux_data dra_l3_flagmux_clk1 = {
+ .offset = 0x803500,
+ .l3_targ = dra_l3_target_data_clk1,
+ .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk1),
+};
+
+static struct l3_target_data dra_l3_target_data_clk2[] = {
+ {0x0, "HOST CLK1",},
+ {0x0, "HOST CLK2",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x3400, "SHA2_2",},
+ {0x0900, "BB2D",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x2100, "L4_PER1_P3",},
+ {0x1c00, "L4_PER1_P1",},
+ {0x1f00, "L4_PER1_P2",},
+ {0x2300, "L4_PER2_P1",},
+ {0x2400, "L4_PER2_P2",},
+ {0x2600, "L4_PER3_P1",},
+ {0x2700, "L4_PER3_P2",},
+ {0x2f00, "MCASP1",},
+ {0x3000, "MCASP2",},
+ {0x3100, "MCASP3",},
+ {0x2800, "MMU2",},
+ {0x0f00, "OCMC_RAM1",},
+ {0x1700, "OCMC_RAM2",},
+ {0x1900, "OCMC_RAM3",},
+ {0x1e00, "OCMC_ROM",},
+ {0x3900, "QSPI",},
+};
+
+static struct l3_flagmux_data dra_l3_flagmux_clk2 = {
+ .offset = 0x803600,
+ .l3_targ = dra_l3_target_data_clk2,
+ .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk2),
+};
+
+static struct l3_target_data dra_l3_target_data_clk3[] = {
+ {0x0100, "L3_INSTR"},
+ {0x0300, "DEBUGSS_CT_TBR"},
+ {0x0, "HOST CLK3"},
+};
+
+static struct l3_flagmux_data dra_l3_flagmux_clk3 = {
+ .offset = 0x200,
+ .l3_targ = dra_l3_target_data_clk3,
+ .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk3),
+};
+
+static struct l3_masters_data dra_l3_masters[] = {
+ { 0x0, "MPU" },
+ { 0x4, "CS_DAP" },
+ { 0x5, "IEEE1500_2_OCP" },
+ { 0x8, "DSP1_MDMA" },
+ { 0x9, "DSP1_CFG" },
+ { 0xA, "DSP1_DMA" },
+ { 0xB, "DSP2_MDMA" },
+ { 0xC, "DSP2_CFG" },
+ { 0xD, "DSP2_DMA" },
+ { 0xE, "IVA" },
+ { 0x10, "EVE1_P1" },
+ { 0x11, "EVE2_P1" },
+ { 0x12, "EVE3_P1" },
+ { 0x13, "EVE4_P1" },
+ { 0x14, "PRUSS1 PRU1" },
+ { 0x15, "PRUSS1 PRU2" },
+ { 0x16, "PRUSS2 PRU1" },
+ { 0x17, "PRUSS2 PRU2" },
+ { 0x18, "IPU1" },
+ { 0x19, "IPU2" },
+ { 0x1A, "SDMA" },
+ { 0x1B, "CDMA" },
+ { 0x1C, "TC1_EDMA" },
+ { 0x1D, "TC2_EDMA" },
+ { 0x20, "DSS" },
+ { 0x21, "MMU1" },
+ { 0x22, "PCIE1" },
+ { 0x23, "MMU2" },
+ { 0x24, "VIP1" },
+ { 0x25, "VIP2" },
+ { 0x26, "VIP3" },
+ { 0x27, "VPE" },
+ { 0x28, "GPU_P1" },
+ { 0x29, "BB2D" },
+ { 0x29, "GPU_P2" },
+ { 0x2B, "GMAC_SW" },
+ { 0x2C, "USB3" },
+ { 0x2D, "USB2_SS" },
+ { 0x2E, "USB2_ULPI_SS1" },
+ { 0x2F, "USB2_ULPI_SS2" },
+ { 0x30, "CSI2_1" },
+ { 0x31, "CSI2_2" },
+ { 0x33, "SATA" },
+ { 0x34, "EVE1_P2" },
+ { 0x35, "EVE2_P2" },
+ { 0x36, "EVE3_P2" },
+ { 0x37, "EVE4_P2" }
+};
+
+static struct l3_flagmux_data *dra_l3_flagmux[] = {
+ &dra_l3_flagmux_clk1,
+ &dra_l3_flagmux_clk2,
+ &dra_l3_flagmux_clk3,
+};
+
+static const struct omap_l3 dra_l3_data = {
+ .l3_base = { [1] = L3_BASE_IS_SUBMODULE },
+ .l3_flagmux = dra_l3_flagmux,
+ .num_modules = ARRAY_SIZE(dra_l3_flagmux),
+ .l3_masters = dra_l3_masters,
+ .num_masters = ARRAY_SIZE(dra_l3_masters),
+};
+
#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-17 20:53:31

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 11/19] bus: omap_l3_noc: convert flagmux information into a structure

This allows us to encompass target information and flag mux offset that
points to the target information into a singular structure. This saves
us the need to look up two different arrays indexed by module ID for
information.

This allows us to reduce the static target information allocation to
just the ones that are documented.

Signed-off-by: Nishanth Menon <[email protected]>
---
V2: reordering changes only
V1: https://patchwork.kernel.org/patch/3984171/
drivers/bus/omap_l3_noc.c | 16 +++++++----
drivers/bus/omap_l3_noc.h | 70 +++++++++++++++++++++++++++++----------------
2 files changed, 56 insertions(+), 30 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index fd31d37..300e168 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -60,6 +60,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";
struct l3_target_data *l3_targ_inst;
+ struct l3_flagmux_data *flag_mux;
struct l3_masters_data *master;

/* Get the Type of interrupt */
@@ -71,7 +72,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = readl_relaxed(base + l3->l3_flagmux[i] +
+ flag_mux = l3->l3_flagmux[i];
+ err_reg = readl_relaxed(base + flag_mux->offset +
L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
@@ -82,9 +84,13 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
/* We DONOT expect err_src to go out of bounds */
BUG_ON(err_src > MAX_CLKDM_TARGETS);

- l3_targ_inst = &l3->l3_targ[i][err_src];
- target_name = l3_targ_inst->name;
- l3_targ_base = base + l3_targ_inst->offset;
+ if (err_src < flag_mux->num_targ_data) {
+ l3_targ_inst = &flag_mux->l3_targ[err_src];
+ target_name = l3_targ_inst->name;
+ l3_targ_base = base + l3_targ_inst->offset;
+ } else {
+ target_name = L3_TARGET_NOT_SUPPORTED;
+ }

/*
* If we do not know of a register offset to decode
@@ -104,7 +110,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
inttype ? "debug" : "application",
err_src, i, "(unclearable)");

- mask_reg = base + l3->l3_flagmux[i] +
+ mask_reg = base + flag_mux->offset +
L3_FLAGMUX_MASK0 + (inttype << 3);
mask_val = readl(mask_reg);
mask_val &= ~(1 << err_src);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index e60865f..64869fe 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -17,8 +17,8 @@
#ifndef __OMAP_L3_NOC_H
#define __OMAP_L3_NOC_H

-#define OMAP_L3_MODULES 3
#define MAX_L3_MODULES 3
+#define MAX_CLKDM_TARGETS 31

#define CLEAR_STDERR_LOG (1 << 31)
#define CUSTOM_ERROR 0x2
@@ -36,8 +36,6 @@

#define L3_TARGET_NOT_SUPPORTED NULL

-#define MAX_CLKDM_TARGETS 31
-
/**
* struct l3_masters_data - L3 Master information
* @id: ID of the L3 Master
@@ -60,21 +58,32 @@ struct l3_target_data {
char *name;
};

+/**
+ * struct l3_flagmux_data - Flag Mux information
+ * @offset: offset from base for flagmux register
+ * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
+ * target data. unsupported ones are marked with
+ * L3_TARGET_NOT_SUPPORTED
+ * @num_targ_data: number of entries in target data
+ */
+struct l3_flagmux_data {
+ u32 offset;
+ struct l3_target_data *l3_targ;
+ u8 num_targ_data;
+};
+

/**
* struct omap_l3 - Description of data relevant for L3 bus.
* @dev: device representing the bus (populated runtime)
* @l3_base: base addresses of modules (populated runtime)
- * @l3_flag_mux: array containing offsets to flag mux per module
+ * @l3_flag_mux: array containing flag mux data per module
* offset from corresponding module base indexed per
* module.
* @num_modules: number of clock domains / modules.
* @l3_masters: array pointing to master data containing name and register
* offset for the master.
* @num_master: number of masters
- * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
- * target data. unsupported ones are marked with
- * L3_TARGET_NOT_SUPPORTED
* @debug_irq: irq number of the debug interrupt (populated runtime)
* @app_irq: irq number of the application interrupt (populated runtime)
*/
@@ -82,25 +91,17 @@ struct omap_l3 {
struct device *dev;

void __iomem *l3_base[MAX_L3_MODULES];
- u32 *l3_flagmux;
+ struct l3_flagmux_data **l3_flagmux;
int num_modules;

struct l3_masters_data *l3_masters;
int num_masters;

- struct l3_target_data **l3_targ;
-
int debug_irq;
int app_irq;
};

-static u32 omap_l3_flagmux[OMAP_L3_MODULES] = {
- 0x500,
- 0x1000,
- 0X0200
-};
-
-static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk1[] = {
{0x100, "DMM1",},
{0x200, "DMM2",},
{0x300, "ABE",},
@@ -110,7 +111,14 @@ static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = {
{0x900, "L4WAKEUP",},
};

-static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = {
+static struct l3_flagmux_data omap_l3_flagmux_clk1 = {
+ .offset = 0x500,
+ .l3_targ = omap_l3_target_data_clk1,
+ .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk1),
+};
+
+
+static struct l3_target_data omap_l3_target_data_clk2[] = {
{0x500, "CORTEXM3",},
{0x300, "DSS",},
{0x100, "GPMC",},
@@ -134,12 +142,25 @@ static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = {
{0x1700, "LLI",},
};

-static struct l3_target_data omap_l3_target_data_clk3[MAX_CLKDM_TARGETS] = {
+static struct l3_flagmux_data omap_l3_flagmux_clk2 = {
+ .offset = 0x1000,
+ .l3_targ = omap_l3_target_data_clk2,
+ .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk2),
+};
+
+
+static struct l3_target_data omap_l3_target_data_clk3[] = {
{0x0100, "EMUSS",},
{0x0300, "DEBUG SOURCE",},
{0x0, "HOST CLK3",},
};

+static struct l3_flagmux_data omap_l3_flagmux_clk3 = {
+ .offset = 0x0200,
+ .l3_targ = omap_l3_target_data_clk3,
+ .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk3),
+};
+
static struct l3_masters_data omap_l3_masters[] = {
{ 0x0 , "MPU"},
{ 0x10, "CS_ADP"},
@@ -168,18 +189,17 @@ static struct l3_masters_data omap_l3_masters[] = {
{ 0xC8, "USBHOSTFS"}
};

-static struct l3_target_data *omap_l3_targ[OMAP_L3_MODULES] = {
- omap_l3_target_data_clk1,
- omap_l3_target_data_clk2,
- omap_l3_target_data_clk3,
+static struct l3_flagmux_data *omap_l3_flagmux[] = {
+ &omap_l3_flagmux_clk1,
+ &omap_l3_flagmux_clk2,
+ &omap_l3_flagmux_clk3,
};

static const struct omap_l3 omap_l3_data = {
.l3_flagmux = omap_l3_flagmux,
- .num_modules = OMAP_L3_MODULES,
+ .num_modules = ARRAY_SIZE(omap_l3_flagmux),
.l3_masters = omap_l3_masters,
.num_masters = ARRAY_SIZE(omap_l3_masters),
- .l3_targ = omap_l3_targ,
};

#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-17 20:53:51

by Santosh Shilimkar

[permalink] [raw]
Subject: Re: [PATCH V2 01/19] bus: omap_l3_noc: Fix copyright information

On Thursday 17 April 2014 04:49 PM, Nishanth Menon wrote:
> This is an embarrassing patch :(.
>
> Texas Corporation does not make OMAP. Texas Instruments Inc does.
>
Yeah..

> For that matter I dont seem to be able to find a Texas Corporation on
> the internet either.
>
:D

> While at it, update coverage to the current year and update the template
> to remove redundant information and use the standard boiler plate
> licensing.
>
> Signed-off-by: Nishanth Menon <[email protected]>
> ---
Acked-by: Santosh Shilimkar <[email protected]>

2014-04-17 20:54:00

by Santosh Shilimkar

[permalink] [raw]
Subject: Re: [PATCH V2 02/19] bus: omap_l3_noc: rename functions and data to omap_l3

On Thursday 17 April 2014 04:49 PM, Nishanth Menon wrote:
> From: Sricharan R <[email protected]>
>
> Since omap_l3_noc driver is now being used for OMAP5 and reusable with
> DRA7 and AM437x, using omap4 specific naming is misleading.
>
> Signed-off-by: Sricharan R <[email protected]>
> Signed-off-by: Nishanth Menon <[email protected]>
> ---
>
Acked-by: Santosh Shilimkar <[email protected]>

2014-04-17 20:53:07

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

The following V2 of the series is based on v3.15-rc1 + peter's patch series:
patch #1: https://patchwork.kernel.org/patch/3923141/
(drivers: bus: omap_l3: Convert to use devm_kzalloc)

patch #2: https://patchwork.kernel.org/patch/3923061/
(drivers: bus: omap_l3: Convert to use devm_ioremap_resource() )

patch #3: https://patchwork.kernel.org/patch/3923101/
(drivers: bus: omap_l3: Convert to use devm_request_irq())

patch #4: https://patchwork.kernel.org/patch/3923081/
(drivers: bus: omap_l3: Remove the platform driver's remove function)

patch #5: https://patchwork.kernel.org/patch/3923121/
(drivers: bus: omap_l3: Change pr_crit() to dev_err() when IRQ request
fails)

V1 was originally posted here: http://marc.info/?l=linux-omap&m=139749383932575&w=2

V2 introduces the following changes:
- Additional bug fix detected during additional testing (all tests complete now). patch #12
- reordering of patches to order logical changes and reduce code churn.
- interrupt handler split up and additional information now provided in log to aid debug when error occur
- patches are marked where new (12,14,15,16).
- DRA7 updated from master document for all DRA7 variants.

This series cleansup omap_l3_noc driver and adds data to support DRA7
and AM437x SoCs.

Patches(including Peter's) is available here:
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2

DTS patches (once this series is integrated and related DRA7 memory map fixes are done):
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/dts-fixes
(posted here: http://marc.info/?l=linux-omap&m=139750288003978&w=2)
- no change in dts.

Testing branch: everything integrated:
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/testing-v2

Test logs: (DES enabled to trigger the bug fixed by https://patchwork.kernel.org/patch/3994211/)
am43xx-epos: http://slexy.org/raw/s2zPoMnkiM
DRA7xx-EVM: http://slexy.org/raw/s20H3aHsNv
pandaboard-es: http://slexy.org/raw/s21gREgRKi
sdp4430: http://slexy.org/raw/s20hDTF5Y6
OMAP5432uEVM: http://slexy.org/raw/s21dk0Qshx

Afzal Mohammed (1):
bus: omap_l3_noc: Add AM4372 interconnect error data

Nishanth Menon (14):
bus: omap_l3_noc: Fix copyright information
bus: omap_l3_noc: remove iclk from omap_l3 struct
bus: omap_l3_noc: populate l3->dev and use it
bus: omap_l3_noc: switch over to relaxed variants of readl/writel
bus: omap_l3_noc: un-obfuscate l3_targ address computation
bus: omap_l3_noc: move L3 master data structure out
bus: omap_l3_noc: convert target information into a structure
bus: omap_l3_noc: convert flagmux information into a structure
bus: omap_l3_noc: fix masterid detection
bus: omap_l3_noc: make error reporting and handling common
bus: omap_l3_noc: improve readability by using helper for slave event
parsing
bus: omap_l3_noc: add information about the type of operation
bus: omap_l3_noc: Add information about the context of operation
bus: omap_l3_noc: introduce concept of submodule

Rajendra Nayak (2):
bus: omap_l3_noc: Add support for discountinous flag mux input
numbers
bus: omap_l3_noc: Add DRA7 interconnect error data

Sricharan R (2):
bus: omap_l3_noc: rename functions and data to omap_l3
bus: omap_l3_noc: use of_match_data to pick up SoC information

.../devicetree/bindings/arm/omap/l3-noc.txt | 2 +
drivers/bus/omap_l3_noc.c | 317 ++++++++----
drivers/bus/omap_l3_noc.h | 529 +++++++++++++++-----
3 files changed, 621 insertions(+), 227 deletions(-)

--
1.7.9.5

2014-04-17 20:55:58

by Santosh Shilimkar

[permalink] [raw]
Subject: Re: [PATCH V2 03/19] bus: omap_l3_noc: remove iclk from omap_l3 struct

On Thursday 17 April 2014 04:49 PM, Nishanth Menon wrote:
> we do not use iclk directly anymore. And, even if we had to, we
> should be using pm_runtime APIs to do the same to be completely SoC
> independent.
>
> Signed-off-by: Nishanth Menon <[email protected]>
> ---
Acked-by: Santosh Shilimkar <[email protected]>

2014-04-17 20:52:37

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 04/19] bus: omap_l3_noc: populate l3->dev and use it

l3->dev is not populated, so populate it and use it to print information
relevant to the device instead of using a generic pr_*.

Signed-off-by: Nishanth Menon <[email protected]>
---
v2: reordering, dropped the warn change as centralizing patch follows
v1: https://patchwork.kernel.org/patch/3984221/
drivers/bus/omap_l3_noc.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 800486c..37d71b7 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -131,6 +131,7 @@ static int omap_l3_probe(struct platform_device *pdev)
if (!l3)
return -ENOMEM;

+ l3->dev = &pdev->dev;
platform_set_drvdata(pdev, l3);

/* Get mem resources */
@@ -140,7 +141,7 @@ static int omap_l3_probe(struct platform_device *pdev)

l3->l3_base[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(l3->l3_base[i])) {
- dev_err(&pdev->dev, "ioremap %d failed\n", i);
+ dev_err(l3->dev, "ioremap %d failed\n", i);
return PTR_ERR(l3->l3_base[i]);
}
}
@@ -149,19 +150,19 @@ static int omap_l3_probe(struct platform_device *pdev)
* Setup interrupt Handlers
*/
l3->debug_irq = platform_get_irq(pdev, 0);
- ret = devm_request_irq(&pdev->dev, l3->debug_irq, l3_interrupt_handler,
+ ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler,
IRQF_DISABLED, "l3-dbg-irq", l3);
if (ret) {
- dev_err(&pdev->dev, "request_irq failed for %d\n",
+ dev_err(l3->dev, "request_irq failed for %d\n",
l3->debug_irq);
return ret;
}

l3->app_irq = platform_get_irq(pdev, 1);
- ret = devm_request_irq(&pdev->dev, l3->app_irq, l3_interrupt_handler,
+ ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler,
IRQF_DISABLED, "l3-app-irq", l3);
if (ret)
- dev_err(&pdev->dev, "request_irq failed for %d\n", l3->app_irq);
+ dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq);

return ret;
}
--
1.7.9.5

2014-04-17 20:58:20

by Santosh Shilimkar

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

Nishant,

On Thursday 17 April 2014 04:49 PM, Nishanth Menon wrote:
> The following V2 of the series is based on v3.15-rc1 + peter's patch series:
> patch #1: https://patchwork.kernel.org/patch/3923141/
> (drivers: bus: omap_l3: Convert to use devm_kzalloc)
>
> patch #2: https://patchwork.kernel.org/patch/3923061/
> (drivers: bus: omap_l3: Convert to use devm_ioremap_resource() )
>
> patch #3: https://patchwork.kernel.org/patch/3923101/
> (drivers: bus: omap_l3: Convert to use devm_request_irq())
>
> patch #4: https://patchwork.kernel.org/patch/3923081/
> (drivers: bus: omap_l3: Remove the platform driver's remove function)
>
> patch #5: https://patchwork.kernel.org/patch/3923121/
> (drivers: bus: omap_l3: Change pr_crit() to dev_err() when IRQ request
> fails)
>
> V1 was originally posted here: http://marc.info/?l=linux-omap&m=139749383932575&w=2
>
> V2 introduces the following changes:
> - Additional bug fix detected during additional testing (all tests complete now). patch #12
> - reordering of patches to order logical changes and reduce code churn.
> - interrupt handler split up and additional information now provided in log to aid debug when error occur
> - patches are marked where new (12,14,15,16).
> - DRA7 updated from master document for all DRA7 variants.
>
> This series cleansup omap_l3_noc driver and adds data to support DRA7
> and AM437x SoCs.
>
I looked at the series and its looks pretty good. Thanks for fixups, updates.
For whole series,
Acked-by: Santosh Shilimkar <[email protected]>

> Patches(including Peter's) is available here:
> https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2
>
Can Tony pull this branch for 3.16 then which includes Peter's series as well ?

Tony, Will you be able to line these up via arm-soc tree ?

Regards,
Santosh

2014-04-17 20:51:03

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 06/19] bus: omap_l3_noc: un-obfuscate l3_targ address computation

just simplify derefencing that is equivalent.

Signed-off-by: Nishanth Menon <[email protected]>
---
V2: just ordering change
V1: https://patchwork.kernel.org/patch/3984201/
drivers/bus/omap_l3_noc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index c8facb0..f7d3bf4 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -76,7 +76,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
err_src = __ffs(err_reg);

/* Read the stderrlog_main_source from clk domain */
- l3_targ_base = base + *(l3_targ[i] + err_src);
+ l3_targ_base = base + l3_targ[i][err_src];
l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
l3_targ_slvofslsb = l3_targ_base +
L3_TARG_STDERRLOG_SLVOFSLSB;
--
1.7.9.5

2014-04-17 21:00:07

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 03/19] bus: omap_l3_noc: remove iclk from omap_l3 struct

we do not use iclk directly anymore. And, even if we had to, we
should be using pm_runtime APIs to do the same to be completely SoC
independent.

Signed-off-by: Nishanth Menon <[email protected]>
---
V2: no change, just reorder
V1: https://patchwork.kernel.org/patch/3984161/
drivers/bus/omap_l3_noc.h | 1 -
1 file changed, 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index b3c81f2..31984cf 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -159,7 +159,6 @@ static u32 *l3_targ[L3_MODULES] = {

struct omap_l3 {
struct device *dev;
- struct clk *ick;

/* memory base */
void __iomem *l3_base[L3_MODULES];
--
1.7.9.5

2014-04-17 21:01:39

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V2 19/19] bus: omap_l3_noc: Add AM4372 interconnect error data

From: Afzal Mohammed <[email protected]>

Add AM4372 information to handle L3 error.

AM4372 has two clk domains 100f and 200s. Provide flagmux and data
associated with it.

NOTE: Timeout doesn't have STDERRLOG_MAIN register. And per hardware
team, L3 timeout error cannot be cleared the normal way (by setting
bit 31 in STDERRLOG_MAIN), instead it may be required to do system
reset. L3 error handler can't help in such scenarios.

Hence indicate timeout target offset as L3_TARGET_NOT_SUPPORTED as
done for undocumented bits.

Signed-off-by: Dave Gerlach <[email protected]>
Signed-off-by: Afzal Mohammed <[email protected]>
Signed-off-by: Sekhar Nori <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
---
V2: no change.
V1: https://patchwork.kernel.org/patch/3984121/
.../devicetree/bindings/arm/omap/l3-noc.txt | 1 +
drivers/bus/omap_l3_noc.c | 1 +
drivers/bus/omap_l3_noc.h | 85 ++++++++++++++++++++
3 files changed, 87 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
index 45d0fc2..974624e 100644
--- a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
+++ b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
@@ -7,6 +7,7 @@ Required properties:
- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
Should be "ti,omap4-l3-noc" for OMAP4 family
Should be "ti,dra7-l3-noc" for DRA7 family
+ Should be "ti,am4372-l3-noc" for AM43 family
- reg: Contains L3 register address range for each noc domain.
- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index aa7a759..440bf22 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -226,6 +226,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
static const struct of_device_id l3_noc_match[] = {
{.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
{.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
+ {.compatible = "ti,am4372-l3-noc", .data = &am4372_l3_data},
{},
};
MODULE_DEVICE_TABLE(of, l3_noc_match);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index acfeb5e..e0e02a2 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -371,4 +371,89 @@ static const struct omap_l3 dra_l3_data = {
.num_masters = ARRAY_SIZE(dra_l3_masters),
};

+/* AM4372 data */
+static struct l3_target_data am4372_l3_target_data_200f[] = {
+ {0xf00, "EMIF",},
+ {0x1200, "DES",},
+ {0x400, "OCMCRAM",},
+ {0x700, "TPTC0",},
+ {0x800, "TPTC1",},
+ {0x900, "TPTC2"},
+ {0xb00, "TPCC",},
+ {0xd00, "DEBUGSS",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x200, "SHA",},
+ {0xc00, "SGX530",},
+ {0x500, "AES0",},
+ {0xa00, "L4_FAST",},
+ {0x300, "MPUSS_L2_RAM",},
+ {0x100, "ICSS",},
+};
+
+static struct l3_flagmux_data am4372_l3_flagmux_200f = {
+ .offset = 0x1000,
+ .l3_targ = am4372_l3_target_data_200f,
+ .num_targ_data = ARRAY_SIZE(am4372_l3_target_data_200f),
+};
+
+static struct l3_target_data am4372_l3_target_data_100s[] = {
+ {0x100, "L4_PER_0",},
+ {0x200, "L4_PER_1",},
+ {0x300, "L4_PER_2",},
+ {0x400, "L4_PER_3",},
+ {0x800, "McASP0",},
+ {0x900, "McASP1",},
+ {0xC00, "MMCHS2",},
+ {0x700, "GPMC",},
+ {0xD00, "L4_FW",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x500, "ADCTSC",},
+ {0xE00, "L4_WKUP",},
+ {0xA00, "MAG_CARD",},
+};
+
+static struct l3_flagmux_data am4372_l3_flagmux_100s = {
+ .offset = 0x600,
+ .l3_targ = am4372_l3_target_data_100s,
+ .num_targ_data = ARRAY_SIZE(am4372_l3_target_data_100s),
+};
+
+static struct l3_masters_data am4372_l3_masters[] = {
+ { 0x0, "M1 (128-bit)"},
+ { 0x0, "M2 (64-bit)"},
+ { 0x4, "DAP"},
+ { 0x5, "P1500"},
+ { 0xC, "ICSS0"},
+ { 0xD, "ICSS1"},
+ { 0x18, "TPTC0 Read"},
+ { 0x19, "TPTC0 Write"},
+ { 0x1A, "TPTC1 Read"},
+ { 0x1B, "TPTC1 Write"},
+ { 0x1C, "TPTC2 Read"},
+ { 0x1D, "TPTC2 Write"},
+ { 0x20, "SGX530"},
+ { 0x25, "DSS"},
+ { 0x28, "Crypto DMA RD"},
+ { 0x29, "Crypto DMA WR"},
+ { 0x2C, "VPFE0"},
+ { 0x2D, "VPFE1"},
+ { 0x30, "GEMAC"},
+ { 0x34, "USB0 RD"},
+ { 0x35, "USB0 WR"},
+ { 0x36, "USB1 RD"},
+ { 0x37, "USB1 WR"},
+};
+
+static struct l3_flagmux_data *am4372_l3_flagmux[] = {
+ &am4372_l3_flagmux_200f,
+ &am4372_l3_flagmux_100s,
+};
+
+static const struct omap_l3 am4372_l3_data = {
+ .l3_flagmux = am4372_l3_flagmux,
+ .num_modules = ARRAY_SIZE(am4372_l3_flagmux),
+ .l3_masters = am4372_l3_masters,
+ .num_masters = ARRAY_SIZE(am4372_l3_masters),
+};
+
#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-17 21:01:48

by Nishanth Menon

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

On 04/17/2014 03:57 PM, Santosh Shilimkar wrote:
> I looked at the series and its looks pretty good. Thanks for fixups, updates.
> For whole series,
> Acked-by: Santosh Shilimkar <[email protected]>
>

Thanks.

>> Patches(including Peter's) is available here:
>> https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2
>>
> Can Tony pull this branch for 3.16 then which includes Peter's series as well ?

there is just an empty commit with information about peter's patches
that i lined up to differentiate the series.. I can drop it if Tony
would like me to.



--
Regards,
Nishanth Menon

2014-04-17 21:55:10

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH V2 05/19] bus: omap_l3_noc: switch over to relaxed variants of readl/writel

Hi,

On Thu, Apr 17, 2014 at 03:49:21PM -0500, Nishanth Menon wrote:
> Currently we use __raw_readl and writel in this driver, however, there

__raw_* and *_relaxed variants are the same, just have a look <asm/io.h>

297 #define readb_relaxed(c) ({ u8 __r = __raw_readb(c); __r; })
298 #define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
299 __raw_readw(c)); __r; })
300 #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
301 __raw_readl(c)); __r; })
302
303 #define writeb_relaxed(v,c) __raw_writeb(v,c)
304 #define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c)
305 #define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c)

--
balbi


Attachments:
(No filename) (799.00 B)
signature.asc (819.00 B)
Digital signature
Download all attachments

2014-04-17 21:56:43

by Santosh Shilimkar

[permalink] [raw]
Subject: Re: [PATCH V2 05/19] bus: omap_l3_noc: switch over to relaxed variants of readl/writel

On Thursday 17 April 2014 05:52 PM, Felipe Balbi wrote:
> Hi,
>
> On Thu, Apr 17, 2014 at 03:49:21PM -0500, Nishanth Menon wrote:
>> Currently we use __raw_readl and writel in this driver, however, there
>
> __raw_* and *_relaxed variants are the same, just have a look <asm/io.h>
>
Except the relaxed version can take care of endian conversion if
needed. :-)

> 297 #define readb_relaxed(c) ({ u8 __r = __raw_readb(c); __r; })
> 298 #define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
> 299 __raw_readw(c)); __r; })
> 300 #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
> 301 __raw_readl(c)); __r; })
> 302
> 303 #define writeb_relaxed(v,c) __raw_writeb(v,c)
> 304 #define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c)
> 305 #define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c)
>

2014-04-17 22:03:18

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH V2 06/19] bus: omap_l3_noc: un-obfuscate l3_targ address computation

Hi,

On Thu, Apr 17, 2014 at 03:49:22PM -0500, Nishanth Menon wrote:
> just simplify derefencing that is equivalent.
>
> Signed-off-by: Nishanth Menon <[email protected]>
> ---
> V2: just ordering change
> V1: https://patchwork.kernel.org/patch/3984201/
> drivers/bus/omap_l3_noc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
> index c8facb0..f7d3bf4 100644
> --- a/drivers/bus/omap_l3_noc.c
> +++ b/drivers/bus/omap_l3_noc.c
> @@ -76,7 +76,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
> err_src = __ffs(err_reg);
>
> /* Read the stderrlog_main_source from clk domain */
> - l3_targ_base = base + *(l3_targ[i] + err_src);
> + l3_targ_base = base + l3_targ[i][err_src];

hmmm, wasn't it so that pointer arithmetic was slightly faster than
array indexing ? In that case would it be best to:

l3_targ_base = base + *(l3_targ + i + err_src);

--
balbi


Attachments:
(No filename) (964.00 B)
signature.asc (819.00 B)
Digital signature
Download all attachments

2014-04-17 22:06:16

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH V2 05/19] bus: omap_l3_noc: switch over to relaxed variants of readl/writel

On Thu, Apr 17, 2014 at 05:56:15PM -0400, Santosh Shilimkar wrote:
> On Thursday 17 April 2014 05:52 PM, Felipe Balbi wrote:
> > Hi,
> >
> > On Thu, Apr 17, 2014 at 03:49:21PM -0500, Nishanth Menon wrote:
> >> Currently we use __raw_readl and writel in this driver, however, there
> >
> > __raw_* and *_relaxed variants are the same, just have a look <asm/io.h>
> >
> Except the relaxed version can take care of endian conversion if
> needed. :-)

right, but according to commit log, this commit is more concerned about
the memory barriers which writel()/readl() add, not endianness. Just a
matter of fixing up commit log.

--
balbi


Attachments:
(No filename) (637.00 B)
signature.asc (819.00 B)
Digital signature
Download all attachments

2014-04-21 13:09:11

by Nishanth Menon

[permalink] [raw]
Subject: Re: [PATCH V2 06/19] bus: omap_l3_noc: un-obfuscate l3_targ address computation

On 04/17/2014 05:00 PM, Felipe Balbi wrote:
> On Thu, Apr 17, 2014 at 03:49:22PM -0500, Nishanth Menon wrote:
>> just simplify derefencing that is equivalent.
>>
>> Signed-off-by: Nishanth Menon <[email protected]>
>> ---
>> V2: just ordering change
>> V1: https://patchwork.kernel.org/patch/3984201/
>> drivers/bus/omap_l3_noc.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
>> index c8facb0..f7d3bf4 100644
>> --- a/drivers/bus/omap_l3_noc.c
>> +++ b/drivers/bus/omap_l3_noc.c
>> @@ -76,7 +76,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
>> err_src = __ffs(err_reg);
>>
>> /* Read the stderrlog_main_source from clk domain */
>> - l3_targ_base = base + *(l3_targ[i] + err_src);
>> + l3_targ_base = base + l3_targ[i][err_src];
>
> hmmm, wasn't it so that pointer arithmetic was slightly faster than
> array indexing ? In that case would it be best to:
>
> l3_targ_base = base + *(l3_targ + i + err_src);
>
Yes, if this was a hot path (example: interrupt handler that gets
invoked very often), I would probably have preferred optimization at
this point.

However, the patch is just a step away from patches that converts the
target information into a structure under flagmux structure allowing
us to get rid of multiple array operations.

This patch just makes the further changes a bit readable.

--
Regards,
Nishanth Menon

2014-04-21 13:17:05

by Nishanth Menon

[permalink] [raw]
Subject: Re: [PATCH V2 05/19] bus: omap_l3_noc: switch over to relaxed variants of readl/writel

On 04/17/2014 05:03 PM, Felipe Balbi wrote:
> On Thu, Apr 17, 2014 at 05:56:15PM -0400, Santosh Shilimkar wrote:
>> On Thursday 17 April 2014 05:52 PM, Felipe Balbi wrote:
>>> Hi,
>>>
>>> On Thu, Apr 17, 2014 at 03:49:21PM -0500, Nishanth Menon wrote:
>>>> Currently we use __raw_readl and writel in this driver, however, there
>>>
>>> __raw_* and *_relaxed variants are the same, just have a look <asm/io.h>
>>>
>> Except the relaxed version can take care of endian conversion if
>> needed. :-)
>
> right, but according to commit log, this commit is more concerned about
> the memory barriers which writel()/readl() add, not endianness. Just a
> matter of fixing up commit log.
>

yep, this patch does replace writel with writel_relaxed there is no
strong need for barriers in the operations that we perform here.

I agree that the commit message should probably be a little more
detailed at this point.


How about:
Currently we use __raw_readl and writel in this driver. Considering
there is no specific need for a memory barrier, replacing writel with
endian-neutral writel_relaxed and replacing __raw_readls with the
corresponding endian-neutral readl_relaxed allows us to have a
standard set of register operations for the driver.

While at it, simplify address computation using variables for register.


--
Regards,
Nishanth Menon

2014-04-21 15:12:11

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH V2 05/19] bus: omap_l3_noc: switch over to relaxed variants of readl/writel

On Mon, Apr 21, 2014 at 08:16:28AM -0500, Nishanth Menon wrote:
> On 04/17/2014 05:03 PM, Felipe Balbi wrote:
> > On Thu, Apr 17, 2014 at 05:56:15PM -0400, Santosh Shilimkar wrote:
> >> On Thursday 17 April 2014 05:52 PM, Felipe Balbi wrote:
> >>> Hi,
> >>>
> >>> On Thu, Apr 17, 2014 at 03:49:21PM -0500, Nishanth Menon wrote:
> >>>> Currently we use __raw_readl and writel in this driver, however, there
> >>>
> >>> __raw_* and *_relaxed variants are the same, just have a look <asm/io.h>
> >>>
> >> Except the relaxed version can take care of endian conversion if
> >> needed. :-)
> >
> > right, but according to commit log, this commit is more concerned about
> > the memory barriers which writel()/readl() add, not endianness. Just a
> > matter of fixing up commit log.
> >
>
> yep, this patch does replace writel with writel_relaxed there is no
> strong need for barriers in the operations that we perform here.
>
> I agree that the commit message should probably be a little more
> detailed at this point.
>
>
> How about:
> Currently we use __raw_readl and writel in this driver. Considering
> there is no specific need for a memory barrier, replacing writel with
> endian-neutral writel_relaxed and replacing __raw_readls with the
> corresponding endian-neutral readl_relaxed allows us to have a
> standard set of register operations for the driver.
>
> While at it, simplify address computation using variables for register.

reads a lot better, thanks

Acked-by: Felipe Balbi <[email protected]>


--
balbi


Attachments:
(No filename) (1.49 kB)
signature.asc (819.00 B)
Digital signature
Download all attachments

2014-04-21 15:14:04

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH V2 06/19] bus: omap_l3_noc: un-obfuscate l3_targ address computation

On Mon, Apr 21, 2014 at 08:08:43AM -0500, Nishanth Menon wrote:
> On 04/17/2014 05:00 PM, Felipe Balbi wrote:
> > On Thu, Apr 17, 2014 at 03:49:22PM -0500, Nishanth Menon wrote:
> >> just simplify derefencing that is equivalent.
> >>
> >> Signed-off-by: Nishanth Menon <[email protected]>
> >> ---
> >> V2: just ordering change
> >> V1: https://patchwork.kernel.org/patch/3984201/
> >> drivers/bus/omap_l3_noc.c | 2 +-
> >> 1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
> >> index c8facb0..f7d3bf4 100644
> >> --- a/drivers/bus/omap_l3_noc.c
> >> +++ b/drivers/bus/omap_l3_noc.c
> >> @@ -76,7 +76,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
> >> err_src = __ffs(err_reg);
> >>
> >> /* Read the stderrlog_main_source from clk domain */
> >> - l3_targ_base = base + *(l3_targ[i] + err_src);
> >> + l3_targ_base = base + l3_targ[i][err_src];
> >
> > hmmm, wasn't it so that pointer arithmetic was slightly faster than
> > array indexing ? In that case would it be best to:
> >
> > l3_targ_base = base + *(l3_targ + i + err_src);
> >
> Yes, if this was a hot path (example: interrupt handler that gets
> invoked very often), I would probably have preferred optimization at
> this point.
>
> However, the patch is just a step away from patches that converts the
> target information into a structure under flagmux structure allowing
> us to get rid of multiple array operations.
>
> This patch just makes the further changes a bit readable.

alright, the error IRQ doesn't fire very often indeed.

--
balbi


Attachments:
(No filename) (1.58 kB)
signature.asc (819.00 B)
Digital signature
Download all attachments

2014-04-21 15:31:57

by Nishanth Menon

[permalink] [raw]
Subject: Re: [PATCH V2 05/19] bus: omap_l3_noc: switch over to relaxed variants of readl/writel

On 10:09-20140421, Felipe Balbi wrote:
> On Mon, Apr 21, 2014 at 08:16:28AM -0500, Nishanth Menon wrote:
> > On 04/17/2014 05:03 PM, Felipe Balbi wrote:
> > > On Thu, Apr 17, 2014 at 05:56:15PM -0400, Santosh Shilimkar wrote:
> > >> On Thursday 17 April 2014 05:52 PM, Felipe Balbi wrote:
> > >>> Hi,
> > >>>
> > >>> On Thu, Apr 17, 2014 at 03:49:21PM -0500, Nishanth Menon wrote:
> > >>>> Currently we use __raw_readl and writel in this driver, however, there
> > >>>
> > >>> __raw_* and *_relaxed variants are the same, just have a look <asm/io.h>
> > >>>
> > >> Except the relaxed version can take care of endian conversion if
> > >> needed. :-)
> > >
> > > right, but according to commit log, this commit is more concerned about
> > > the memory barriers which writel()/readl() add, not endianness. Just a
> > > matter of fixing up commit log.
> > >
> >
> > yep, this patch does replace writel with writel_relaxed there is no
> > strong need for barriers in the operations that we perform here.
> >
> > I agree that the commit message should probably be a little more
> > detailed at this point.
> >
> >
> > How about:
> > Currently we use __raw_readl and writel in this driver. Considering
> > there is no specific need for a memory barrier, replacing writel with
> > endian-neutral writel_relaxed and replacing __raw_readls with the
> > corresponding endian-neutral readl_relaxed allows us to have a
> > standard set of register operations for the driver.
> >
> > While at it, simplify address computation using variables for register.
>
> reads a lot better, thanks
>
> Acked-by: Felipe Balbi <[email protected]>

Thanks.
Updated branch with patches with Acked-bys pickedup is available here:
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2-repost

I have dropped the empty commit while at it.

Updated patch below for the record:
------------------8<-----------------8<----------------------------
>From a8198b8c78f2a2731fdd4df1ac540887a4c464be Mon Sep 17 00:00:00 2001
From: Nishanth Menon <[email protected]>
Date: Fri, 11 Apr 2014 11:21:47 -0500
Subject: [PATCH V2 UPDATE 05/19] bus: omap_l3_noc: switch over to relaxed variants of
readl/writel

Currently we use __raw_readl and writel in this driver. Considering
there is no specific need for a memory barrier, replacing writel
with endian-neutral writel_relaxed and replacing __raw_readls with
the corresponding endian-neutral readl_relaxed allows us to have a
standard set of register operations for the driver.

While at it, simplify address computation using variables for
register.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
---
drivers/bus/omap_l3_noc.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 37d71b7..c8facb0 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -55,6 +55,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
int err_src = 0;
u32 std_err_main, err_reg, clear, masterid;
void __iomem *base, *l3_targ_base;
+ void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";

/* Get the Type of interrupt */
@@ -66,8 +67,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = __raw_readl(base + l3_flagmux[i] +
- + L3_FLAGMUX_REGERR0 + (inttype << 3));
+ err_reg = readl_relaxed(base + l3_flagmux[i] +
+ L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
if (err_reg) {
@@ -76,10 +77,14 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Read the stderrlog_main_source from clk domain */
l3_targ_base = base + *(l3_targ[i] + err_src);
- std_err_main = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
- masterid = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MSTADDR);
+ l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
+ l3_targ_slvofslsb = l3_targ_base +
+ L3_TARG_STDERRLOG_SLVOFSLSB;
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_MSTADDR;
+
+ std_err_main = readl_relaxed(l3_targ_stderr);
+ masterid = readl_relaxed(l3_targ_mstaddr);

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
@@ -87,12 +92,10 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
l3_targ_inst_name[i][err_src];
WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
target_name,
- __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_SLVOFSLSB));
+ readl_relaxed(l3_targ_slvofslsb));
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

case CUSTOM_ERROR:
@@ -107,8 +110,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
master_name, target_name);
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

default:
--
1.7.9.5




--
Regards,
Nishanth Menon

2014-04-24 09:31:40

by Peter Ujfalusi

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

On 04/18/2014 12:00 AM, Nishanth Menon wrote:
> On 04/17/2014 03:57 PM, Santosh Shilimkar wrote:
>> I looked at the series and its looks pretty good. Thanks for fixups, updates.
>> For whole series,
>> Acked-by: Santosh Shilimkar <[email protected]>
>>
>
> Thanks.
>
>>> Patches(including Peter's) is available here:
>>> https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2
>>>
>> Can Tony pull this branch for 3.16 then which includes Peter's series as well ?
>
> there is just an empty commit with information about peter's patches
> that i lined up to differentiate the series.. I can drop it if Tony
> would like me to.

Looking at the branch I see my patches underneath so they are in the branch.
It would be great if Tony pulls this... Will be a great present to my patches
(omap_l3 patches in the branch) for their 1 year anniversary of being out on
the mailing list ;)

--
P?ter

2014-04-24 14:19:52

by Nishanth Menon

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

On 04/24/2014 03:55 AM, Peter Ujfalusi wrote:
> On 04/18/2014 12:00 AM, Nishanth Menon wrote:
>> On 04/17/2014 03:57 PM, Santosh Shilimkar wrote:
>>> I looked at the series and its looks pretty good. Thanks for fixups, updates.
>>> For whole series,
>>> Acked-by: Santosh Shilimkar <[email protected]>
>>>
>>
>> Thanks.
>>
>>>> Patches(including Peter's) is available here:
>>>> https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2
>>>>
>>> Can Tony pull this branch for 3.16 then which includes Peter's series as well ?
>>
>> there is just an empty commit with information about peter's patches
>> that i lined up to differentiate the series.. I can drop it if Tony
>> would like me to.
>
> Looking at the branch I see my patches underneath so they are in the branch.
> It would be great if Tony pulls this... Will be a great present to my patches
> (omap_l3 patches in the branch) for their 1 year anniversary of being out on
> the mailing list ;)
>
Peter, can I take this as an Ack for this series? if yes, I can repost
a v3 with all the acks, updates together.

--
Regards,
Nishanth Menon

2014-04-24 15:55:00

by Etheridge, Darren

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

Nishanth,

Nishanth Menon <[email protected]> wrote on Thu [2014-Apr-17 15:49:16 -0500]:
>
> V2 introduces the following changes:
> - Additional bug fix detected during additional testing (all tests complete now). patch #12
> - reordering of patches to order logical changes and reduce code churn.
> - interrupt handler split up and additional information now provided in log to aid debug when error occur
> - patches are marked where new (12,14,15,16).
> - DRA7 updated from master document for all DRA7 variants.
>
> This series cleansup omap_l3_noc driver and adds data to support DRA7
> and AM437x SoCs.
>
This L3 noc driver patch series is working great for me and has already
flagged a very difficult to detect problem in a driver I am working on
with a DMA access to an invalid memory address on DRA7.

Tested-by: Darren Etheridge <[email protected]>


Darren

2014-04-24 16:07:01

by Nishanth Menon

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

On 04/24/2014 10:54 AM, Darren Etheridge wrote:
> Nishanth,
>
> Nishanth Menon <[email protected]> wrote on Thu [2014-Apr-17 15:49:16 -0500]:
>>
>> V2 introduces the following changes:
>> - Additional bug fix detected during additional testing (all tests complete now). patch #12
>> - reordering of patches to order logical changes and reduce code churn.
>> - interrupt handler split up and additional information now provided in log to aid debug when error occur
>> - patches are marked where new (12,14,15,16).
>> - DRA7 updated from master document for all DRA7 variants.
>>
>> This series cleansup omap_l3_noc driver and adds data to support DRA7
>> and AM437x SoCs.
>>
> This L3 noc driver patch series is working great for me and has already
> flagged a very difficult to detect problem in a driver I am working on
> with a DMA access to an invalid memory address on DRA7.

Glad it was of use. All the more reason why this should be in upstream
kernel and not just in "evil vendor" kernel.

>
> Tested-by: Darren Etheridge <[email protected]>
>
Thanks. will pick this up for v3 post.


--
Regards,
Nishanth Menon

2014-04-24 16:25:45

by Tony Lindgren

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

* Peter Ujfalusi <[email protected]> [140424 01:55]:
> On 04/18/2014 12:00 AM, Nishanth Menon wrote:
> > On 04/17/2014 03:57 PM, Santosh Shilimkar wrote:
> >> I looked at the series and its looks pretty good. Thanks for fixups, updates.
> >> For whole series,
> >> Acked-by: Santosh Shilimkar <[email protected]>
> >>
> >
> > Thanks.
> >
> >>> Patches(including Peter's) is available here:
> >>> https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2
> >>>
> >> Can Tony pull this branch for 3.16 then which includes Peter's series as well ?
> >
> > there is just an empty commit with information about peter's patches
> > that i lined up to differentiate the series.. I can drop it if Tony
> > would like me to.
>
> Looking at the branch I see my patches underneath so they are in the branch.
> It would be great if Tony pulls this... Will be a great present to my patches
> (omap_l3 patches in the branch) for their 1 year anniversary of being out on
> the mailing list ;)

If you insist :) Maybe we should have some cake or something with it?
Seriously, I always thought that's a nice clean-up set, but never thought
I'm supposed to merge it. Will merge it as soon as I'm out of the fixes
and regressions land as that way I can easier test for any kind of
new regressions that might occur related to PM at least.

Regards,

Tony

2014-04-24 16:31:31

by Nishanth Menon

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

On Thu, Apr 24, 2014 at 11:25 AM, Tony Lindgren <[email protected]> wrote:
> * Peter Ujfalusi <[email protected]> [140424 01:55]:
>> On 04/18/2014 12:00 AM, Nishanth Menon wrote:
>> > On 04/17/2014 03:57 PM, Santosh Shilimkar wrote:
>> >> I looked at the series and its looks pretty good. Thanks for fixups, updates.
>> >> For whole series,
>> >> Acked-by: Santosh Shilimkar <[email protected]>
>> >>
>> >
>> > Thanks.
>> >
>> >>> Patches(including Peter's) is available here:
>> >>> https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2
>> >>>
>> >> Can Tony pull this branch for 3.16 then which includes Peter's series as well ?
>> >
>> > there is just an empty commit with information about peter's patches
>> > that i lined up to differentiate the series.. I can drop it if Tony
>> > would like me to.
>>
>> Looking at the branch I see my patches underneath so they are in the branch.
>> It would be great if Tony pulls this... Will be a great present to my patches
>> (omap_l3 patches in the branch) for their 1 year anniversary of being out on
>> the mailing list ;)
>
> If you insist :) Maybe we should have some cake or something with it?
> Seriously, I always thought that's a nice clean-up set, but never thought
> I'm supposed to merge it. Will merge it as soon as I'm out of the fixes
> and regressions land as that way I can easier test for any kind of
> new regressions that might occur related to PM at least.

Thanks Tony. I will try and post a v3 tomorrow as a clean set of
patches and a v3.15-rc1 based branch to ease integration.

This should also give additional time for any further comments as well.

Regards,
Nishanth Menon

2014-04-25 06:27:49

by Peter Ujfalusi

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

On 04/24/2014 05:19 PM, Nishanth Menon wrote:
> On 04/24/2014 03:55 AM, Peter Ujfalusi wrote:
>> On 04/18/2014 12:00 AM, Nishanth Menon wrote:
>>> On 04/17/2014 03:57 PM, Santosh Shilimkar wrote:
>>>> I looked at the series and its looks pretty good. Thanks for fixups, updates.
>>>> For whole series,
>>>> Acked-by: Santosh Shilimkar <[email protected]>
>>>>
>>>
>>> Thanks.
>>>
>>>>> Patches(including Peter's) is available here:
>>>>> https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2
>>>>>
>>>> Can Tony pull this branch for 3.16 then which includes Peter's series as well ?
>>>
>>> there is just an empty commit with information about peter's patches
>>> that i lined up to differentiate the series.. I can drop it if Tony
>>> would like me to.
>>
>> Looking at the branch I see my patches underneath so they are in the branch.
>> It would be great if Tony pulls this... Will be a great present to my patches
>> (omap_l3 patches in the branch) for their 1 year anniversary of being out on
>> the mailing list ;)
>>
> Peter, can I take this as an Ack for this series? if yes, I can repost
> a v3 with all the acks, updates together.

Nishanth, sure you can add my Ack or Reviewed-by.

--
P?ter

2014-04-25 13:45:27

by Nishanth Menon

[permalink] [raw]
Subject: Re: [PATCH V2 00/19] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

On 04/25/2014 01:27 AM, Peter Ujfalusi wrote:
> On 04/24/2014 05:19 PM, Nishanth Menon wrote:
>> On 04/24/2014 03:55 AM, Peter Ujfalusi wrote:
>>> On 04/18/2014 12:00 AM, Nishanth Menon wrote:
>>>> On 04/17/2014 03:57 PM, Santosh Shilimkar wrote:
>>>>> I looked at the series and its looks pretty good. Thanks for fixups, updates.
>>>>> For whole series,
>>>>> Acked-by: Santosh Shilimkar <[email protected]>
>>>>>
>>>>
>>>> Thanks.
>>>>
>>>>>> Patches(including Peter's) is available here:
>>>>>> https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v2
>>>>>>
>>>>> Can Tony pull this branch for 3.16 then which includes Peter's series as well ?
>>>>
>>>> there is just an empty commit with information about peter's patches
>>>> that i lined up to differentiate the series.. I can drop it if Tony
>>>> would like me to.
>>>
>>> Looking at the branch I see my patches underneath so they are in the branch.
>>> It would be great if Tony pulls this... Will be a great present to my patches
>>> (omap_l3 patches in the branch) for their 1 year anniversary of being out on
>>> the mailing list ;)
>>>
>> Peter, can I take this as an Ack for this series? if yes, I can repost
>> a v3 with all the acks, updates together.
>
> Nishanth, sure you can add my Ack or Reviewed-by.
>
Thanks Peter. i will pick up your ack. Seems that I have to respin the
series given a few further updates for AM437x - some, ummm...
variations in definition that we did not expect but Sekhar found when
reviewing internal functional specs :(

--
Regards,
Nishanth Menon

2014-04-28 15:16:03

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 18/20] bus: omap_l3_noc: introduce concept of submodule

While OMAP4 and OMAP5 had 3 separate clock domains, DRA7 has only 2
and the first one then is internally divided into 2 sub clock domains.

To better represent this in the driver, we use the concept of submodule.

The address defintions in the devicetree is as per the high level
clock domain(module) base, the sub clockdomain/subdomain which shares
the same register space of a clockdomain is marked in the SoC data as
L3_BASE_IS_SUBMODULE.

L3_BASE_IS_SUBMODULE is used as an indication that it's base address is
the same as the parent module and offsets are considered from the same
base address as they are usually intermingled.

Other than the base address, the submodule is same as a module as it is
functionally so.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change
drivers/bus/omap_l3_noc.c | 17 ++++++++++++-----
drivers/bus/omap_l3_noc.h | 6 +++++-
2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 08344b0..0eba07a 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -238,7 +238,7 @@ static int omap_l3_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
static struct omap_l3 *l3;
- int ret, i;
+ int ret, i, res_idx;

of_id = of_match_device(l3_noc_match, &pdev->dev);
if (!of_id) {
@@ -255,15 +255,22 @@ static int omap_l3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, l3);

/* Get mem resources */
- for (i = 0; i < l3->num_modules; i++) {
- struct resource *res = platform_get_resource(pdev,
- IORESOURCE_MEM, i);
-
+ for (i = 0, res_idx = 0; i < l3->num_modules; i++) {
+ struct resource *res;
+
+ if (l3->l3_base[i] == L3_BASE_IS_SUBMODULE) {
+ /* First entry cannot be submodule */
+ BUG_ON(i == 0);
+ l3->l3_base[i] = l3->l3_base[i - 1];
+ continue;
+ }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx);
l3->l3_base[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(l3->l3_base[i])) {
dev_err(l3->dev, "ioremap %d failed\n", i);
return PTR_ERR(l3->l3_base[i]);
}
+ res_idx++;
}

/*
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 36dc48b..aced4c5 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -41,6 +41,8 @@

#define L3_TARGET_NOT_SUPPORTED NULL

+#define L3_BASE_IS_SUBMODULE ((void __iomem *)(1 << 0))
+
static const char * const l3_transaction_type[] = {
/* 0 0 0 */ "Idle",
/* 0 0 1 */ "Write",
@@ -96,7 +98,9 @@ struct l3_flagmux_data {
/**
* struct omap_l3 - Description of data relevant for L3 bus.
* @dev: device representing the bus (populated runtime)
- * @l3_base: base addresses of modules (populated runtime)
+ * @l3_base: base addresses of modules (populated runtime if 0)
+ * if set to L3_BASE_IS_SUBMODULE, then uses previous
+ * module index as the base address
* @l3_flag_mux: array containing flag mux data per module
* offset from corresponding module base indexed per
* module.
--
1.7.9.5

2014-04-28 15:16:00

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 15/20] bus: omap_l3_noc: ignore masked out unclearable targets

From: Afzal Mohammed <[email protected]>

Errors that cannot be cleared (determined by reading REGERR register)
are currently handled by masking it. Documentation states that REGERR
"Checks which application/debug error sources are active" - it does not
indicate that this is "interrupt status" - masked out status represented
eventually in the irq line to MPU.
For example:

Lets say module 0 bit 8(0x100) was unclearable, we do the mask it from
generating further errors. However in the following cases:
a) bit 9 of Module 0
OR
b) any bit of Module 1+
occur, the interrupt handler wrongly assumes that the raw interrupt
status of module 0 bit 8 is the root cause of the interrupt, and
returns. This causes unhandled interrupt and resultant infinite
interrupts.

Fix this scenario by storing the events we masked out and masking raw
status with masked ones before identifying and handling the error.

Reported-by: Vaibhav Hiremath <[email protected]>
Signed-off-by: Afzal Mohammed <[email protected]>
Tested-by: Vaibhav Hiremath <[email protected]>
Signed-off-by: Sekhar Nori <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
---
V3: new patch

drivers/bus/omap_l3_noc.c | 9 +++++++++
drivers/bus/omap_l3_noc.h | 4 ++++
2 files changed, 13 insertions(+)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 0691e6d..00e4fed 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -169,6 +169,9 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
err_reg = readl_relaxed(base + flag_mux->offset +
L3_FLAGMUX_REGERR0 + (inttype << 3));

+ err_reg &= ~(inttype ? flag_mux->mask_app_bits :
+ flag_mux->mask_dbg_bits);
+
/* Get the corresponding error and analyse */
if (err_reg) {
/* Identify the source from control status register */
@@ -193,6 +196,12 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
mask_val = readl_relaxed(mask_reg);
mask_val &= ~(1 << err_src);
writel_relaxed(mask_val, mask_reg);
+
+ /* Mark these bits as to be ignored */
+ if (inttype)
+ flag_mux->mask_app_bits |= 1 << err_src;
+ else
+ flag_mux->mask_dbg_bits |= 1 << err_src;
}

/* Error found so break the for loop */
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index ea2f51c..4e18307 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -66,11 +66,15 @@ struct l3_target_data {
* target data. unsupported ones are marked with
* L3_TARGET_NOT_SUPPORTED
* @num_targ_data: number of entries in target data
+ * @mask_app_bits: ignore these from raw application irq status
+ * @mask_dbg_bits: ignore these from raw debug irq status
*/
struct l3_flagmux_data {
u32 offset;
struct l3_target_data *l3_targ;
u8 num_targ_data;
+ u32 mask_app_bits;
+ u32 mask_dbg_bits;
};


--
1.7.9.5

2014-04-28 15:17:12

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 04/20] bus: omap_l3_noc: populate l3->dev and use it

l3->dev is not populated, so populate it and use it to print information
relevant to the device instead of using a generic pr_*.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
change in V3: none
drivers/bus/omap_l3_noc.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 800486c..37d71b7 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -131,6 +131,7 @@ static int omap_l3_probe(struct platform_device *pdev)
if (!l3)
return -ENOMEM;

+ l3->dev = &pdev->dev;
platform_set_drvdata(pdev, l3);

/* Get mem resources */
@@ -140,7 +141,7 @@ static int omap_l3_probe(struct platform_device *pdev)

l3->l3_base[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(l3->l3_base[i])) {
- dev_err(&pdev->dev, "ioremap %d failed\n", i);
+ dev_err(l3->dev, "ioremap %d failed\n", i);
return PTR_ERR(l3->l3_base[i]);
}
}
@@ -149,19 +150,19 @@ static int omap_l3_probe(struct platform_device *pdev)
* Setup interrupt Handlers
*/
l3->debug_irq = platform_get_irq(pdev, 0);
- ret = devm_request_irq(&pdev->dev, l3->debug_irq, l3_interrupt_handler,
+ ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler,
IRQF_DISABLED, "l3-dbg-irq", l3);
if (ret) {
- dev_err(&pdev->dev, "request_irq failed for %d\n",
+ dev_err(l3->dev, "request_irq failed for %d\n",
l3->debug_irq);
return ret;
}

l3->app_irq = platform_get_irq(pdev, 1);
- ret = devm_request_irq(&pdev->dev, l3->app_irq, l3_interrupt_handler,
+ ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler,
IRQF_DISABLED, "l3-app-irq", l3);
if (ret)
- dev_err(&pdev->dev, "request_irq failed for %d\n", l3->app_irq);
+ dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq);

return ret;
}
--
1.7.9.5

2014-04-28 15:15:57

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 10/20] bus: omap_l3_noc: use of_match_data to pick up SoC information

From: Sricharan R <[email protected]>

DRA7xx SoC has the same l3-noc interconnect ip (as OMAP4 and OMAP5), but
AM437x SoC has just 2 modules instead of 3 which other SoCs have.

So, stop using direct access of array indices and use of->match data and
simplify implementation to benefit future usage.

While at it, rename a few very generic variables to make them omap
specific. This helps us differentiate from DRA7 and AM43xx data in the
future.

NOTE: None of the platforms that use omap_l3_noc are non-device tree
anymore. So, it is safe to assume OF match here.

Signed-off-by: Sricharan R <[email protected]>
Signed-off-by: Rajendra Nayak <[email protected]>
[[email protected]: split, refactor and optimize logic]
Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change
drivers/bus/omap_l3_noc.c | 55 +++++++++++++++++++---------------
drivers/bus/omap_l3_noc.h | 72 ++++++++++++++++++++++++++++++++-------------
2 files changed, 84 insertions(+), 43 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 7743e86..7e0a988 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -14,12 +14,14 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#include <linux/module.h>
#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>

#include "omap_l3_noc.h"
@@ -58,17 +60,18 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";
struct l3_target_data *l3_targ_inst;
+ struct l3_masters_data *master;

/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;

- for (i = 0; i < L3_MODULES; i++) {
+ for (i = 0; i < l3->num_modules; i++) {
/*
* Read the regerr register of the clock domain
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = readl_relaxed(base + l3_flagmux[i] +
+ err_reg = readl_relaxed(base + l3->l3_flagmux[i] +
L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
@@ -79,7 +82,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
/* We DONOT expect err_src to go out of bounds */
BUG_ON(err_src > MAX_CLKDM_TARGETS);

- l3_targ_inst = &l3_targ[i][err_src];
+ l3_targ_inst = &l3->l3_targ[i][err_src];
target_name = l3_targ_inst->name;
l3_targ_base = base + l3_targ_inst->offset;

@@ -101,7 +104,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
inttype ? "debug" : "application",
err_src, i, "(unclearable)");

- mask_reg = base + l3_flagmux[i] +
+ mask_reg = base + l3->l3_flagmux[i] +
L3_FLAGMUX_MASK0 + (inttype << 3);
mask_val = readl_relaxed(mask_reg);
mask_val &= ~(1 << err_src);
@@ -131,10 +134,12 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
break;

case CUSTOM_ERROR:
- for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
- if (masterid == l3_masters[k].id)
- master_name =
- l3_masters[k].name;
+ for (k = 0, master = l3->l3_masters;
+ k < l3->num_masters; k++, master++) {
+ if (masterid == master->id) {
+ master_name = master->name;
+ break;
+ }
}
WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
master_name, target_name);
@@ -154,20 +159,34 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
return IRQ_HANDLED;
}

+static const struct of_device_id l3_noc_match[] = {
+ {.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
+ {},
+};
+MODULE_DEVICE_TABLE(of, l3_noc_match);
+
static int omap_l3_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id;
static struct omap_l3 *l3;
int ret, i;

+ of_id = of_match_device(l3_noc_match, &pdev->dev);
+ if (!of_id) {
+ dev_err(&pdev->dev, "OF data missing\n");
+ return -EINVAL;
+ }
+
l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL);
if (!l3)
return -ENOMEM;

+ memcpy(l3, of_id->data, sizeof(*l3));
l3->dev = &pdev->dev;
platform_set_drvdata(pdev, l3);

/* Get mem resources */
- for (i = 0; i < L3_MODULES; i++) {
+ for (i = 0; i < l3->num_modules; i++) {
struct resource *res = platform_get_resource(pdev,
IORESOURCE_MEM, i);

@@ -199,22 +218,12 @@ static int omap_l3_probe(struct platform_device *pdev)
return ret;
}

-#if defined(CONFIG_OF)
-static const struct of_device_id l3_noc_match[] = {
- {.compatible = "ti,omap4-l3-noc", },
- {},
-};
-MODULE_DEVICE_TABLE(of, l3_noc_match);
-#else
-#define l3_noc_match NULL
-#endif
-
static struct platform_driver omap_l3_driver = {
.probe = omap_l3_probe,
.driver = {
.name = "omap_l3_noc",
.owner = THIS_MODULE,
- .of_match_table = l3_noc_match,
+ .of_match_table = of_match_ptr(l3_noc_match),
},
};

diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 66caece..e60865f 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -17,7 +17,9 @@
#ifndef __OMAP_L3_NOC_H
#define __OMAP_L3_NOC_H

-#define L3_MODULES 3
+#define OMAP_L3_MODULES 3
+#define MAX_L3_MODULES 3
+
#define CLEAR_STDERR_LOG (1 << 31)
#define CUSTOM_ERROR 0x2
#define STANDARD_ERROR 0x0
@@ -36,8 +38,6 @@

#define MAX_CLKDM_TARGETS 31

-#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0]))
-
/**
* struct l3_masters_data - L3 Master information
* @id: ID of the L3 Master
@@ -60,13 +60,47 @@ struct l3_target_data {
char *name;
};

-static u32 l3_flagmux[L3_MODULES] = {
+
+/**
+ * struct omap_l3 - Description of data relevant for L3 bus.
+ * @dev: device representing the bus (populated runtime)
+ * @l3_base: base addresses of modules (populated runtime)
+ * @l3_flag_mux: array containing offsets to flag mux per module
+ * offset from corresponding module base indexed per
+ * module.
+ * @num_modules: number of clock domains / modules.
+ * @l3_masters: array pointing to master data containing name and register
+ * offset for the master.
+ * @num_master: number of masters
+ * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
+ * target data. unsupported ones are marked with
+ * L3_TARGET_NOT_SUPPORTED
+ * @debug_irq: irq number of the debug interrupt (populated runtime)
+ * @app_irq: irq number of the application interrupt (populated runtime)
+ */
+struct omap_l3 {
+ struct device *dev;
+
+ void __iomem *l3_base[MAX_L3_MODULES];
+ u32 *l3_flagmux;
+ int num_modules;
+
+ struct l3_masters_data *l3_masters;
+ int num_masters;
+
+ struct l3_target_data **l3_targ;
+
+ int debug_irq;
+ int app_irq;
+};
+
+static u32 omap_l3_flagmux[OMAP_L3_MODULES] = {
0x500,
0x1000,
0X0200
};

-static struct l3_target_data l3_target_inst_data_clk1[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = {
{0x100, "DMM1",},
{0x200, "DMM2",},
{0x300, "ABE",},
@@ -76,7 +110,7 @@ static struct l3_target_data l3_target_inst_data_clk1[MAX_CLKDM_TARGETS] = {
{0x900, "L4WAKEUP",},
};

-static struct l3_target_data l3_target_inst_data_clk2[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = {
{0x500, "CORTEXM3",},
{0x300, "DSS",},
{0x100, "GPMC",},
@@ -100,13 +134,13 @@ static struct l3_target_data l3_target_inst_data_clk2[MAX_CLKDM_TARGETS] = {
{0x1700, "LLI",},
};

-static struct l3_target_data l3_target_inst_data_clk3[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk3[MAX_CLKDM_TARGETS] = {
{0x0100, "EMUSS",},
{0x0300, "DEBUG SOURCE",},
{0x0, "HOST CLK3",},
};

-static struct l3_masters_data l3_masters[] = {
+static struct l3_masters_data omap_l3_masters[] = {
{ 0x0 , "MPU"},
{ 0x10, "CS_ADP"},
{ 0x14, "xxx"},
@@ -134,20 +168,18 @@ static struct l3_masters_data l3_masters[] = {
{ 0xC8, "USBHOSTFS"}
};

-static struct l3_target_data *l3_targ[L3_MODULES] = {
- l3_target_inst_data_clk1,
- l3_target_inst_data_clk2,
- l3_target_inst_data_clk3,
+static struct l3_target_data *omap_l3_targ[OMAP_L3_MODULES] = {
+ omap_l3_target_data_clk1,
+ omap_l3_target_data_clk2,
+ omap_l3_target_data_clk3,
};

-struct omap_l3 {
- struct device *dev;
-
- /* memory base */
- void __iomem *l3_base[L3_MODULES];
-
- int debug_irq;
- int app_irq;
+static const struct omap_l3 omap_l3_data = {
+ .l3_flagmux = omap_l3_flagmux,
+ .num_modules = OMAP_L3_MODULES,
+ .l3_masters = omap_l3_masters,
+ .num_masters = ARRAY_SIZE(omap_l3_masters),
+ .l3_targ = omap_l3_targ,
};

#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-28 15:15:54

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 01/20] bus: omap_l3_noc: Fix copyright information

This is an embarrassing patch :(.

Texas Corporation does not make OMAP. Texas Instruments Inc does.

For that matter I dont seem to be able to find a Texas Corporation on
the internet either.

While at it, update coverage to the current year and update the template
to remove redundant information and use the standard boiler plate
licensing.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
change in V3: none
drivers/bus/omap_l3_noc.c | 18 ++++++------------
drivers/bus/omap_l3_noc.h | 18 ++++++------------
2 files changed, 12 insertions(+), 24 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 972691a..1eb6d85 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -1,24 +1,18 @@
/*
* OMAP4XXX L3 Interconnect error handling driver
*
- * Copyright (C) 2011 Texas Corporation
+ * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
* Sricharan <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index a6ce34d..cc4b1b1 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -1,24 +1,18 @@
/*
* OMAP4XXX L3 Interconnect error handling driver header
*
- * Copyright (C) 2011 Texas Corporation
+ * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
* sricharan <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
--
1.7.9.5

2014-04-28 15:19:50

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 05/20] bus: omap_l3_noc: switch over to relaxed variants of readl/writel

Currently we use __raw_readl and writel in this driver. Considering
there is no specific need for a memory barrier, replacing writel
with endian-neutral writel_relaxed and replacing __raw_readls with
the corresponding endian-neutral readl_relaxed allows us to have a
standard set of register operations for the driver.

While at it, simplify address computation using variables for
register.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---

change in V3: commit message improvement based on Felipe's feedback.
no change since V2 repost.

drivers/bus/omap_l3_noc.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 37d71b7..c8facb0 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -55,6 +55,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
int err_src = 0;
u32 std_err_main, err_reg, clear, masterid;
void __iomem *base, *l3_targ_base;
+ void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";

/* Get the Type of interrupt */
@@ -66,8 +67,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = __raw_readl(base + l3_flagmux[i] +
- + L3_FLAGMUX_REGERR0 + (inttype << 3));
+ err_reg = readl_relaxed(base + l3_flagmux[i] +
+ L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
if (err_reg) {
@@ -76,10 +77,14 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Read the stderrlog_main_source from clk domain */
l3_targ_base = base + *(l3_targ[i] + err_src);
- std_err_main = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
- masterid = __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_MSTADDR);
+ l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
+ l3_targ_slvofslsb = l3_targ_base +
+ L3_TARG_STDERRLOG_SLVOFSLSB;
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_MSTADDR;
+
+ std_err_main = readl_relaxed(l3_targ_stderr);
+ masterid = readl_relaxed(l3_targ_mstaddr);

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
@@ -87,12 +92,10 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
l3_targ_inst_name[i][err_src];
WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
target_name,
- __raw_readl(l3_targ_base +
- L3_TARG_STDERRLOG_SLVOFSLSB));
+ readl_relaxed(l3_targ_slvofslsb));
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

case CUSTOM_ERROR:
@@ -107,8 +110,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
master_name, target_name);
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, l3_targ_base +
- L3_TARG_STDERRLOG_MAIN);
+ writel_relaxed(clear, l3_targ_stderr);
break;

default:
--
1.7.9.5

2014-04-28 15:28:35

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 17/20] bus: omap_l3_noc: Add information about the context of operation

L3 error may be triggered using Debug interface (example JTAG) or
due to other errors, for example an opcode fetch (due to function
pointer or stack corruption) or a data access (due to some other
failure). NOC registers contain additional information to help aid
debug information.

With this, we can enhance the error information to more detailed form:
"
L3 Custom Error: MASTER MPU TARGET L4PER2 (Read): Data Access in User mode
during Functional access
"

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change
drivers/bus/omap_l3_noc.c | 18 ++++++++++++++----
drivers/bus/omap_l3_noc.h | 2 ++
2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 9d021d0..08344b0 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -60,15 +60,16 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
{
int k;
u32 std_err_main, clear, masterid;
- u8 op_code;
+ u8 op_code, m_req_info;
void __iomem *l3_targ_base;
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
- void __iomem *l3_targ_hdr;
+ void __iomem *l3_targ_hdr, *l3_targ_info;
struct l3_target_data *l3_targ_inst;
struct l3_masters_data *master;
char *target_name, *master_name = "UN IDENTIFIED";
char *err_description;
char err_string[30] = { 0 };
+ char info_string[60] = { 0 };

/* We DONOT expect err_src to go out of bounds */
BUG_ON(err_src > MAX_CLKDM_TARGETS);
@@ -99,6 +100,7 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,

l3_targ_mstaddr = l3_targ_base + L3_TARG_STDERRLOG_MSTADDR;
l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_HDR;
+ l3_targ_info = l3_targ_base + L3_TARG_STDERRLOG_INFO;
break;

case CUSTOM_ERROR:
@@ -107,6 +109,7 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
l3_targ_mstaddr = l3_targ_base +
L3_TARG_STDERRLOG_CINFO_MSTADDR;
l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_CINFO_OPCODE;
+ l3_targ_info = l3_targ_base + L3_TARG_STDERRLOG_CINFO_INFO;
break;

default:
@@ -128,13 +131,20 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,

op_code = readl_relaxed(l3_targ_hdr) & 0x7;

+ m_req_info = readl_relaxed(l3_targ_info) & 0xF;
+ snprintf(info_string, sizeof(info_string),
+ ": %s in %s mode during %s access",
+ (m_req_info & BIT(0)) ? "Opcode Fetch" : "Data Access",
+ (m_req_info & BIT(1)) ? "Supervisor" : "User",
+ (m_req_info & BIT(3)) ? "Debug" : "Functional");
+
WARN(true,
- "%s:L3 %s Error: MASTER %s TARGET %s (%s)%s\n",
+ "%s:L3 %s Error: MASTER %s TARGET %s (%s)%s%s\n",
dev_name(l3->dev),
err_description,
master_name, target_name,
l3_transaction_type[op_code],
- err_string);
+ err_string, info_string);

/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 6670fd9..36dc48b 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -31,7 +31,9 @@
#define L3_TARG_STDERRLOG_MAIN 0x48
#define L3_TARG_STDERRLOG_HDR 0x4c
#define L3_TARG_STDERRLOG_MSTADDR 0x50
+#define L3_TARG_STDERRLOG_INFO 0x58
#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c
+#define L3_TARG_STDERRLOG_CINFO_INFO 0x64
#define L3_TARG_STDERRLOG_CINFO_MSTADDR 0x68
#define L3_TARG_STDERRLOG_CINFO_OPCODE 0x6c
#define L3_FLAGMUX_REGERR0 0xc
--
1.7.9.5

2014-04-28 15:15:52

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 00/20] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

The following V3 of the series is based on v3.15-rc1 + peter's patch series:
patch #1: https://patchwork.kernel.org/patch/3923141/
(drivers: bus: omap_l3: Convert to use devm_kzalloc)

patch #2: https://patchwork.kernel.org/patch/3923061/
(drivers: bus: omap_l3: Convert to use devm_ioremap_resource() )

patch #3: https://patchwork.kernel.org/patch/3923101/
(drivers: bus: omap_l3: Convert to use devm_request_irq())

patch #4: https://patchwork.kernel.org/patch/3923081/
(drivers: bus: omap_l3: Remove the platform driver's remove function)

patch #5: https://patchwork.kernel.org/patch/3923121/
(drivers: bus: omap_l3: Change pr_crit() to dev_err() when IRQ request
fails)

V1 was originally posted here: http://marc.info/?l=linux-omap&m=139749383932575&w=2
V2 was originally posted here: http://marc.info/?l=linux-kernel&m=139776814925544&w=2

V3: has the following changes (w.r.t v2):
- fixed relaxed commit message and usage.
- AM437x internal documents showed that:
- new master information updated into the data
- masterid register definition is different from OMAP4-DRA7 - some
additional parsing is done in hardware to "avoid s/w parsing"
- Additional testing information showed logic fail for masking "unclearable"
new patch added to series - patch #15
- Picked up previous acks and tested by - minor changes verified

This series cleansup omap_l3_noc driver and adds data to support DRA7
and AM437x SoCs.

Patches(including Peter's) is available here:(based on v3.15-rc1):
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/driver-fixes-v3

DTS patches (once this series is integrated and related DRA7 memory map fixes are done):
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/dts-fixes
(posted here: http://marc.info/?l=linux-omap&m=139750288003978&w=2)
- no change in dts.

Testing branch: everything integrated:
https://github.com/nmenon/linux-2.6-playground/commits/l3noc/testing-v3

Test log (omap2plus_defconfig + CONFIG_CRYPTO_DEV_OMAP_DES=y):
am43xx-epos: http://slexy.org/raw/s28LkG186D
dra7xx-evm: http://slexy.org/raw/s2UV0v7fwn
pandaboard-es: http://slexy.org/raw/s213lc55PY
pandaboard-vanilla: http://slexy.org/raw/s20AvyGNrA
sdp4430: http://slexy.org/raw/s2E0exblmN
OMAP5432uEVM: http://slexy.org/raw/s20TRRtKzf

Afzal Mohammed (2):
bus: omap_l3_noc: ignore masked out unclearable targets
bus: omap_l3_noc: Add AM4372 interconnect error data

Nishanth Menon (14):
bus: omap_l3_noc: Fix copyright information
bus: omap_l3_noc: remove iclk from omap_l3 struct
bus: omap_l3_noc: populate l3->dev and use it
bus: omap_l3_noc: switch over to relaxed variants of readl/writel
bus: omap_l3_noc: un-obfuscate l3_targ address computation
bus: omap_l3_noc: move L3 master data structure out
bus: omap_l3_noc: convert target information into a structure
bus: omap_l3_noc: convert flagmux information into a structure
bus: omap_l3_noc: fix masterid detection
bus: omap_l3_noc: make error reporting and handling common
bus: omap_l3_noc: improve readability by using helper for slave event
parsing
bus: omap_l3_noc: add information about the type of operation
bus: omap_l3_noc: Add information about the context of operation
bus: omap_l3_noc: introduce concept of submodule

Rajendra Nayak (2):
bus: omap_l3_noc: Add support for discountinous flag mux input
numbers
bus: omap_l3_noc: Add DRA7 interconnect error data

Sricharan R (2):
bus: omap_l3_noc: rename functions and data to omap_l3
bus: omap_l3_noc: use of_match_data to pick up SoC information

.../devicetree/bindings/arm/omap/l3-noc.txt | 2 +
drivers/bus/omap_l3_noc.c | 322 ++++++++----
drivers/bus/omap_l3_noc.h | 545 +++++++++++++++-----
3 files changed, 642 insertions(+), 227 deletions(-)

--
1.7.9.5

2014-04-28 15:29:45

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 14/20] bus: omap_l3_noc: improve readability by using helper for slave event parsing

Current interrupt handler does the first level parse to identify the
slave and then handles the slave even identification, reporting and
clearing of event as well. It is hence logical to split the handler
into two where the primary handler just parses the flagmux till it
identifies a slave and the slave handling, reporting and clearing is
done in a helper function.

While at it update the documentation in kerneldoc style.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change
drivers/bus/omap_l3_noc.c | 211 ++++++++++++++++++++++++---------------------
1 file changed, 113 insertions(+), 98 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 42e4114..0691e6d 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -26,14 +26,20 @@

#include "omap_l3_noc.h"

-/*
- * Interrupt Handler for L3 error detection.
- * 1) Identify the L3 clockdomain partition to which the error belongs to.
- * 2) Identify the slave where the error information is logged
- * 3) Print the logged information.
- * 4) Add dump stack to provide kernel trace.
+/**
+ * l3_handle_target() - Handle Target specific parse and reporting
+ * @l3: pointer to l3 struct
+ * @base: base address of clkdm
+ * @flag_mux: flagmux corresponding to the event
+ * @err_src: error source index of the slave (target)
*
- * Two Types of errors :
+ * This does the second part of the error interrupt handling:
+ * 3) Parse in the slave information
+ * 4) Print the logged information.
+ * 5) Add dump stack to provide kernel trace.
+ * 6) Clear the source if known.
+ *
+ * This handles two types of errors:
* 1) Custom errors in L3 :
* Target like DMM/FW/EMIF generates SRESP=ERR error
* 2) Standard L3 error:
@@ -49,22 +55,107 @@
* can be trapped as well. But the trapping is implemented as part
* secure software and hence need not be implemented here.
*/
-static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
+static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
+ struct l3_flagmux_data *flag_mux, int err_src)
{
-
- struct omap_l3 *l3 = _l3;
- int inttype, i, k;
- int err_src = 0;
- u32 std_err_main, err_reg, clear, masterid;
- void __iomem *base, *l3_targ_base;
+ int k;
+ u32 std_err_main, clear, masterid;
+ void __iomem *l3_targ_base;
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
- char *target_name, *master_name = "UN IDENTIFIED";
struct l3_target_data *l3_targ_inst;
- struct l3_flagmux_data *flag_mux;
struct l3_masters_data *master;
+ char *target_name, *master_name = "UN IDENTIFIED";
char *err_description;
char err_string[30] = { 0 };

+ /* We DONOT expect err_src to go out of bounds */
+ BUG_ON(err_src > MAX_CLKDM_TARGETS);
+
+ if (err_src < flag_mux->num_targ_data) {
+ l3_targ_inst = &flag_mux->l3_targ[err_src];
+ target_name = l3_targ_inst->name;
+ l3_targ_base = base + l3_targ_inst->offset;
+ } else {
+ target_name = L3_TARGET_NOT_SUPPORTED;
+ }
+
+ if (target_name == L3_TARGET_NOT_SUPPORTED)
+ return -ENODEV;
+
+ /* Read the stderrlog_main_source from clk domain */
+ l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
+ l3_targ_slvofslsb = l3_targ_base + L3_TARG_STDERRLOG_SLVOFSLSB;
+
+ std_err_main = readl_relaxed(l3_targ_stderr);
+
+ switch (std_err_main & CUSTOM_ERROR) {
+ case STANDARD_ERROR:
+ err_description = "Standard";
+ snprintf(err_string, sizeof(err_string),
+ ": At Address: 0x%08X ",
+ readl_relaxed(l3_targ_slvofslsb));
+
+ l3_targ_mstaddr = l3_targ_base + L3_TARG_STDERRLOG_MSTADDR;
+ break;
+
+ case CUSTOM_ERROR:
+ err_description = "Custom";
+
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_CINFO_MSTADDR;
+ break;
+
+ default:
+ /* Nothing to be handled here as of now */
+ return 0;
+ }
+
+ /* STDERRLOG_MSTADDR Stores the NTTP master address. */
+ masterid = (readl_relaxed(l3_targ_mstaddr) &
+ l3->mst_addr_mask) >> __ffs(l3->mst_addr_mask);
+
+ for (k = 0, master = l3->l3_masters; k < l3->num_masters;
+ k++, master++) {
+ if (masterid == master->id) {
+ master_name = master->name;
+ break;
+ }
+ }
+
+ WARN(true,
+ "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
+ dev_name(l3->dev),
+ err_description,
+ master_name, target_name,
+ err_string);
+
+ /* clear the std error log*/
+ clear = std_err_main | CLEAR_STDERR_LOG;
+ writel_relaxed(clear, l3_targ_stderr);
+
+ return 0;
+}
+
+/**
+ * l3_interrupt_handler() - interrupt handler for l3 events
+ * @irq: irq number
+ * @_l3: pointer to l3 structure
+ *
+ * Interrupt Handler for L3 error detection.
+ * 1) Identify the L3 clockdomain partition to which the error belongs to.
+ * 2) Identify the slave where the error information is logged
+ * ... handle the slave event..
+ * 7) if the slave is unknown, mask out the slave.
+ */
+static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
+{
+ struct omap_l3 *l3 = _l3;
+ int inttype, i, ret;
+ int err_src = 0;
+ u32 err_reg, mask_val;
+ void __iomem *base, *mask_reg;
+ struct l3_flagmux_data *flag_mux;
+
/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;

@@ -80,35 +171,18 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Get the corresponding error and analyse */
if (err_reg) {
- bool std_err = true;
-
/* Identify the source from control status register */
err_src = __ffs(err_reg);

- /* We DONOT expect err_src to go out of bounds */
- BUG_ON(err_src > MAX_CLKDM_TARGETS);
-
- if (err_src < flag_mux->num_targ_data) {
- l3_targ_inst = &flag_mux->l3_targ[err_src];
- target_name = l3_targ_inst->name;
- l3_targ_base = base + l3_targ_inst->offset;
- } else {
- target_name = L3_TARGET_NOT_SUPPORTED;
- }
+ ret = l3_handle_target(l3, base, flag_mux, err_src);

/*
- * If we do not know of a register offset to decode
- * and clear, then mask.
+ * Certain plaforms may have "undocumented" status
+ * pending on boot. So dont generate a severe warning
+ * here. Just mask it off to prevent the error from
+ * reoccuring and locking up the system.
*/
- if (target_name == L3_TARGET_NOT_SUPPORTED) {
- u32 mask_val;
- void __iomem *mask_reg;
-
- /*
- * Certain plaforms may have "undocumented"
- * status pending on boot.. So dont generate
- * a severe warning here.
- */
+ if (ret) {
dev_err(l3->dev,
"L3 %s error: target %d mod:%d %s\n",
inttype ? "debug" : "application",
@@ -119,67 +193,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
mask_val = readl_relaxed(mask_reg);
mask_val &= ~(1 << err_src);
writel_relaxed(mask_val, mask_reg);
-
- break;
}

- /* Read the stderrlog_main_source from clk domain */
- l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
- l3_targ_slvofslsb = l3_targ_base +
- L3_TARG_STDERRLOG_SLVOFSLSB;
-
- std_err_main = readl_relaxed(l3_targ_stderr);
-
- switch (std_err_main & CUSTOM_ERROR) {
- case STANDARD_ERROR:
- err_description = "Standard";
- snprintf(err_string, sizeof(err_string),
- ": At Address: 0x%08X ",
- readl_relaxed(l3_targ_slvofslsb));
-
- l3_targ_mstaddr = l3_targ_base +
- L3_TARG_STDERRLOG_MSTADDR;
- break;
-
- case CUSTOM_ERROR:
- err_description = "Custom";
-
- l3_targ_mstaddr = l3_targ_base +
- L3_TARG_STDERRLOG_CINFO_MSTADDR;
- break;
-
- default:
- std_err = false;
- /* Nothing to be handled here as of now */
- break;
- }
-
- if (!std_err)
- break;
-
- /* STDERRLOG_MSTADDR Stores the NTTP master address. */
- masterid = (readl_relaxed(l3_targ_mstaddr) &
- l3->mst_addr_mask) >>
- __ffs(l3->mst_addr_mask);
-
- for (k = 0, master = l3->l3_masters;
- k < l3->num_masters; k++, master++) {
- if (masterid == master->id) {
- master_name = master->name;
- break;
- }
- }
-
- WARN(true,
- "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
- dev_name(l3->dev),
- err_description,
- master_name, target_name,
- err_string);
- /* clear the std error log*/
- clear = std_err_main | CLEAR_STDERR_LOG;
- writel_relaxed(clear, l3_targ_stderr);
-
/* Error found so break the for loop */
break;
}
--
1.7.9.5

2014-04-28 15:15:49

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 20/20] bus: omap_l3_noc: Add AM4372 interconnect error data

From: Afzal Mohammed <[email protected]>

Add AM4372 information to handle L3 error.

AM4372 has two clk domains 100f and 200s. Provide flagmux and data
associated with it.

NOTE: Timeout doesn't have STDERRLOG_MAIN register. And per hardware
team, L3 timeout error cannot be cleared the normal way (by setting
bit 31 in STDERRLOG_MAIN), instead it may be required to do system
reset. L3 error handler can't help in such scenarios.

Hence indicate timeout target offset as L3_TARGET_NOT_SUPPORTED as
done for undocumented bits.

Signed-off-by: Dave Gerlach <[email protected]>
Signed-off-by: Afzal Mohammed <[email protected]>
Signed-off-by: Sekhar Nori <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: New master information + masterid parse information update

.../devicetree/bindings/arm/omap/l3-noc.txt | 1 +
drivers/bus/omap_l3_noc.c | 1 +
drivers/bus/omap_l3_noc.h | 91 ++++++++++++++++++++
3 files changed, 93 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
index 45d0fc2..974624e 100644
--- a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
+++ b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
@@ -7,6 +7,7 @@ Required properties:
- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
Should be "ti,omap4-l3-noc" for OMAP4 family
Should be "ti,dra7-l3-noc" for DRA7 family
+ Should be "ti,am4372-l3-noc" for AM43 family
- reg: Contains L3 register address range for each noc domain.
- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 6cdd02e..531ae59 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -231,6 +231,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
static const struct of_device_id l3_noc_match[] = {
{.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
{.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
+ {.compatible = "ti,am4372-l3-noc", .data = &am4372_l3_data},
{},
};
MODULE_DEVICE_TABLE(of, l3_noc_match);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 9562a75..551e010 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -381,4 +381,95 @@ static const struct omap_l3 dra_l3_data = {
.mst_addr_mask = 0xFC,
};

+/* AM4372 data */
+static struct l3_target_data am4372_l3_target_data_200f[] = {
+ {0xf00, "EMIF",},
+ {0x1200, "DES",},
+ {0x400, "OCMCRAM",},
+ {0x700, "TPTC0",},
+ {0x800, "TPTC1",},
+ {0x900, "TPTC2"},
+ {0xb00, "TPCC",},
+ {0xd00, "DEBUGSS",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x200, "SHA",},
+ {0xc00, "SGX530",},
+ {0x500, "AES0",},
+ {0xa00, "L4_FAST",},
+ {0x300, "MPUSS_L2_RAM",},
+ {0x100, "ICSS",},
+};
+
+static struct l3_flagmux_data am4372_l3_flagmux_200f = {
+ .offset = 0x1000,
+ .l3_targ = am4372_l3_target_data_200f,
+ .num_targ_data = ARRAY_SIZE(am4372_l3_target_data_200f),
+};
+
+static struct l3_target_data am4372_l3_target_data_100s[] = {
+ {0x100, "L4_PER_0",},
+ {0x200, "L4_PER_1",},
+ {0x300, "L4_PER_2",},
+ {0x400, "L4_PER_3",},
+ {0x800, "McASP0",},
+ {0x900, "McASP1",},
+ {0xC00, "MMCHS2",},
+ {0x700, "GPMC",},
+ {0xD00, "L4_FW",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x500, "ADCTSC",},
+ {0xE00, "L4_WKUP",},
+ {0xA00, "MAG_CARD",},
+};
+
+static struct l3_flagmux_data am4372_l3_flagmux_100s = {
+ .offset = 0x600,
+ .l3_targ = am4372_l3_target_data_100s,
+ .num_targ_data = ARRAY_SIZE(am4372_l3_target_data_100s),
+};
+
+static struct l3_masters_data am4372_l3_masters[] = {
+ { 0x0, "M1 (128-bit)"},
+ { 0x1, "M2 (64-bit)"},
+ { 0x4, "DAP"},
+ { 0x5, "P1500"},
+ { 0xC, "ICSS0"},
+ { 0xD, "ICSS1"},
+ { 0x14, "Wakeup Processor"},
+ { 0x18, "TPTC0 Read"},
+ { 0x19, "TPTC0 Write"},
+ { 0x1A, "TPTC1 Read"},
+ { 0x1B, "TPTC1 Write"},
+ { 0x1C, "TPTC2 Read"},
+ { 0x1D, "TPTC2 Write"},
+ { 0x20, "SGX530"},
+ { 0x21, "OCP WP Traffic Probe"},
+ { 0x22, "OCP WP DMA Profiling"},
+ { 0x23, "OCP WP Event Trace"},
+ { 0x25, "DSS"},
+ { 0x28, "Crypto DMA RD"},
+ { 0x29, "Crypto DMA WR"},
+ { 0x2C, "VPFE0"},
+ { 0x2D, "VPFE1"},
+ { 0x30, "GEMAC"},
+ { 0x34, "USB0 RD"},
+ { 0x35, "USB0 WR"},
+ { 0x36, "USB1 RD"},
+ { 0x37, "USB1 WR"},
+};
+
+static struct l3_flagmux_data *am4372_l3_flagmux[] = {
+ &am4372_l3_flagmux_200f,
+ &am4372_l3_flagmux_100s,
+};
+
+static const struct omap_l3 am4372_l3_data = {
+ .l3_flagmux = am4372_l3_flagmux,
+ .num_modules = ARRAY_SIZE(am4372_l3_flagmux),
+ .l3_masters = am4372_l3_masters,
+ .num_masters = ARRAY_SIZE(am4372_l3_masters),
+ /* All 6 bits of register field used to distinguish initiator */
+ .mst_addr_mask = 0x3F,
+};
+
#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-28 15:30:26

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 13/20] bus: omap_l3_noc: make error reporting and handling common

The logic between handling CUSTOM_ERROR and STANDARD_ERROR is just the
reporting style.

So make it generic, simplify and standardize the reporting with both
master and target information printed to log.

Handle the register address difference for master code for standard
error and custom error as well.

While at it, fix a minor indentation error.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change

drivers/bus/omap_l3_noc.c | 72 ++++++++++++++++++++++++++++-----------------
drivers/bus/omap_l3_noc.h | 3 +-
2 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 8a1926d..42e4114 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -62,6 +62,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
struct l3_target_data *l3_targ_inst;
struct l3_flagmux_data *flag_mux;
struct l3_masters_data *master;
+ char *err_description;
+ char err_string[30] = { 0 };

/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -78,6 +80,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Get the corresponding error and analyse */
if (err_reg) {
+ bool std_err = true;
+
/* Identify the source from control status register */
err_src = __ffs(err_reg);

@@ -123,47 +127,61 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
l3_targ_slvofslsb = l3_targ_base +
L3_TARG_STDERRLOG_SLVOFSLSB;
- l3_targ_mstaddr = l3_targ_base +
- L3_TARG_STDERRLOG_MSTADDR;

std_err_main = readl_relaxed(l3_targ_stderr);

- /* STDERRLOG_MSTADDR Stores the NTTP master address. */
- masterid = (readl_relaxed(l3_targ_mstaddr) &
- l3->mst_addr_mask) >>
- __ffs(l3->mst_addr_mask);
-
switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
- WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
- target_name,
- readl_relaxed(l3_targ_slvofslsb));
- /* clear the std error log*/
- clear = std_err_main | CLEAR_STDERR_LOG;
- writel_relaxed(clear, l3_targ_stderr);
+ err_description = "Standard";
+ snprintf(err_string, sizeof(err_string),
+ ": At Address: 0x%08X ",
+ readl_relaxed(l3_targ_slvofslsb));
+
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_MSTADDR;
break;

case CUSTOM_ERROR:
- for (k = 0, master = l3->l3_masters;
- k < l3->num_masters; k++, master++) {
- if (masterid == master->id) {
- master_name = master->name;
- break;
- }
- }
- WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
- master_name, target_name);
- /* clear the std error log*/
- clear = std_err_main | CLEAR_STDERR_LOG;
- writel_relaxed(clear, l3_targ_stderr);
+ err_description = "Custom";
+
+ l3_targ_mstaddr = l3_targ_base +
+ L3_TARG_STDERRLOG_CINFO_MSTADDR;
break;

default:
+ std_err = false;
/* Nothing to be handled here as of now */
break;
}
- /* Error found so break the for loop */
- break;
+
+ if (!std_err)
+ break;
+
+ /* STDERRLOG_MSTADDR Stores the NTTP master address. */
+ masterid = (readl_relaxed(l3_targ_mstaddr) &
+ l3->mst_addr_mask) >>
+ __ffs(l3->mst_addr_mask);
+
+ for (k = 0, master = l3->l3_masters;
+ k < l3->num_masters; k++, master++) {
+ if (masterid == master->id) {
+ master_name = master->name;
+ break;
+ }
+ }
+
+ WARN(true,
+ "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
+ dev_name(l3->dev),
+ err_description,
+ master_name, target_name,
+ err_string);
+ /* clear the std error log*/
+ clear = std_err_main | CLEAR_STDERR_LOG;
+ writel_relaxed(clear, l3_targ_stderr);
+
+ /* Error found so break the for loop */
+ break;
}
}
return IRQ_HANDLED;
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index ba86924..ea2f51c 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -29,8 +29,9 @@

/* L3 TARG register offsets */
#define L3_TARG_STDERRLOG_MAIN 0x48
+#define L3_TARG_STDERRLOG_MSTADDR 0x50
#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c
-#define L3_TARG_STDERRLOG_MSTADDR 0x68
+#define L3_TARG_STDERRLOG_CINFO_MSTADDR 0x68
#define L3_FLAGMUX_REGERR0 0xc
#define L3_FLAGMUX_MASK0 0x8

--
1.7.9.5

2014-04-28 15:15:46

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 03/20] bus: omap_l3_noc: remove iclk from omap_l3 struct

we do not use iclk directly anymore. And, even if we had to, we
should be using pm_runtime APIs to do the same to be completely SoC
independent.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
change in V3: none
drivers/bus/omap_l3_noc.h | 1 -
1 file changed, 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index b3c81f2..31984cf 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -159,7 +159,6 @@ static u32 *l3_targ[L3_MODULES] = {

struct omap_l3 {
struct device *dev;
- struct clk *ick;

/* memory base */
void __iomem *l3_base[L3_MODULES];
--
1.7.9.5

2014-04-28 15:15:43

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 11/20] bus: omap_l3_noc: convert flagmux information into a structure

This allows us to encompass target information and flag mux offset that
points to the target information into a singular structure. This saves
us the need to look up two different arrays indexed by module ID for
information.

This allows us to reduce the static target information allocation to
just the ones that are documented.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change

drivers/bus/omap_l3_noc.c | 16 +++++++----
drivers/bus/omap_l3_noc.h | 70 +++++++++++++++++++++++++++++----------------
2 files changed, 56 insertions(+), 30 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 7e0a988..9524452 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -60,6 +60,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";
struct l3_target_data *l3_targ_inst;
+ struct l3_flagmux_data *flag_mux;
struct l3_masters_data *master;

/* Get the Type of interrupt */
@@ -71,7 +72,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
* to determine the source
*/
base = l3->l3_base[i];
- err_reg = readl_relaxed(base + l3->l3_flagmux[i] +
+ flag_mux = l3->l3_flagmux[i];
+ err_reg = readl_relaxed(base + flag_mux->offset +
L3_FLAGMUX_REGERR0 + (inttype << 3));

/* Get the corresponding error and analyse */
@@ -82,9 +84,13 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
/* We DONOT expect err_src to go out of bounds */
BUG_ON(err_src > MAX_CLKDM_TARGETS);

- l3_targ_inst = &l3->l3_targ[i][err_src];
- target_name = l3_targ_inst->name;
- l3_targ_base = base + l3_targ_inst->offset;
+ if (err_src < flag_mux->num_targ_data) {
+ l3_targ_inst = &flag_mux->l3_targ[err_src];
+ target_name = l3_targ_inst->name;
+ l3_targ_base = base + l3_targ_inst->offset;
+ } else {
+ target_name = L3_TARGET_NOT_SUPPORTED;
+ }

/*
* If we do not know of a register offset to decode
@@ -104,7 +110,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
inttype ? "debug" : "application",
err_src, i, "(unclearable)");

- mask_reg = base + l3->l3_flagmux[i] +
+ mask_reg = base + flag_mux->offset +
L3_FLAGMUX_MASK0 + (inttype << 3);
mask_val = readl_relaxed(mask_reg);
mask_val &= ~(1 << err_src);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index e60865f..64869fe 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -17,8 +17,8 @@
#ifndef __OMAP_L3_NOC_H
#define __OMAP_L3_NOC_H

-#define OMAP_L3_MODULES 3
#define MAX_L3_MODULES 3
+#define MAX_CLKDM_TARGETS 31

#define CLEAR_STDERR_LOG (1 << 31)
#define CUSTOM_ERROR 0x2
@@ -36,8 +36,6 @@

#define L3_TARGET_NOT_SUPPORTED NULL

-#define MAX_CLKDM_TARGETS 31
-
/**
* struct l3_masters_data - L3 Master information
* @id: ID of the L3 Master
@@ -60,21 +58,32 @@ struct l3_target_data {
char *name;
};

+/**
+ * struct l3_flagmux_data - Flag Mux information
+ * @offset: offset from base for flagmux register
+ * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
+ * target data. unsupported ones are marked with
+ * L3_TARGET_NOT_SUPPORTED
+ * @num_targ_data: number of entries in target data
+ */
+struct l3_flagmux_data {
+ u32 offset;
+ struct l3_target_data *l3_targ;
+ u8 num_targ_data;
+};
+

/**
* struct omap_l3 - Description of data relevant for L3 bus.
* @dev: device representing the bus (populated runtime)
* @l3_base: base addresses of modules (populated runtime)
- * @l3_flag_mux: array containing offsets to flag mux per module
+ * @l3_flag_mux: array containing flag mux data per module
* offset from corresponding module base indexed per
* module.
* @num_modules: number of clock domains / modules.
* @l3_masters: array pointing to master data containing name and register
* offset for the master.
* @num_master: number of masters
- * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
- * target data. unsupported ones are marked with
- * L3_TARGET_NOT_SUPPORTED
* @debug_irq: irq number of the debug interrupt (populated runtime)
* @app_irq: irq number of the application interrupt (populated runtime)
*/
@@ -82,25 +91,17 @@ struct omap_l3 {
struct device *dev;

void __iomem *l3_base[MAX_L3_MODULES];
- u32 *l3_flagmux;
+ struct l3_flagmux_data **l3_flagmux;
int num_modules;

struct l3_masters_data *l3_masters;
int num_masters;

- struct l3_target_data **l3_targ;
-
int debug_irq;
int app_irq;
};

-static u32 omap_l3_flagmux[OMAP_L3_MODULES] = {
- 0x500,
- 0x1000,
- 0X0200
-};
-
-static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = {
+static struct l3_target_data omap_l3_target_data_clk1[] = {
{0x100, "DMM1",},
{0x200, "DMM2",},
{0x300, "ABE",},
@@ -110,7 +111,14 @@ static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = {
{0x900, "L4WAKEUP",},
};

-static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = {
+static struct l3_flagmux_data omap_l3_flagmux_clk1 = {
+ .offset = 0x500,
+ .l3_targ = omap_l3_target_data_clk1,
+ .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk1),
+};
+
+
+static struct l3_target_data omap_l3_target_data_clk2[] = {
{0x500, "CORTEXM3",},
{0x300, "DSS",},
{0x100, "GPMC",},
@@ -134,12 +142,25 @@ static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = {
{0x1700, "LLI",},
};

-static struct l3_target_data omap_l3_target_data_clk3[MAX_CLKDM_TARGETS] = {
+static struct l3_flagmux_data omap_l3_flagmux_clk2 = {
+ .offset = 0x1000,
+ .l3_targ = omap_l3_target_data_clk2,
+ .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk2),
+};
+
+
+static struct l3_target_data omap_l3_target_data_clk3[] = {
{0x0100, "EMUSS",},
{0x0300, "DEBUG SOURCE",},
{0x0, "HOST CLK3",},
};

+static struct l3_flagmux_data omap_l3_flagmux_clk3 = {
+ .offset = 0x0200,
+ .l3_targ = omap_l3_target_data_clk3,
+ .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk3),
+};
+
static struct l3_masters_data omap_l3_masters[] = {
{ 0x0 , "MPU"},
{ 0x10, "CS_ADP"},
@@ -168,18 +189,17 @@ static struct l3_masters_data omap_l3_masters[] = {
{ 0xC8, "USBHOSTFS"}
};

-static struct l3_target_data *omap_l3_targ[OMAP_L3_MODULES] = {
- omap_l3_target_data_clk1,
- omap_l3_target_data_clk2,
- omap_l3_target_data_clk3,
+static struct l3_flagmux_data *omap_l3_flagmux[] = {
+ &omap_l3_flagmux_clk1,
+ &omap_l3_flagmux_clk2,
+ &omap_l3_flagmux_clk3,
};

static const struct omap_l3 omap_l3_data = {
.l3_flagmux = omap_l3_flagmux,
- .num_modules = OMAP_L3_MODULES,
+ .num_modules = ARRAY_SIZE(omap_l3_flagmux),
.l3_masters = omap_l3_masters,
.num_masters = ARRAY_SIZE(omap_l3_masters),
- .l3_targ = omap_l3_targ,
};

#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-28 15:15:38

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 08/20] bus: omap_l3_noc: convert target information into a structure

Currently the target instance information is organized indexed by bit
field offset into multiple arrays.

1. We currently have offsets specific to each target associated with each
clock domains are in seperate arrays:

l3_targ_inst_clk1
l3_targ_inst_clk2
l3_targ_inst_clk3

2. Then they are organized per master index in l3_targ.

3. We have names in l3_targ_inst_name as an array to array of strings
corresponding to the above with offsets.

Simplify the same by defining a structure for information containing
both target offset and name. this is then stored in arrays per domain
and organized into an array indexed off domain.

The array is still indexed based on bit field offset.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change
drivers/bus/omap_l3_noc.c | 9 ++--
drivers/bus/omap_l3_noc.h | 129 ++++++++++++++++++---------------------------
2 files changed, 54 insertions(+), 84 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index f7d3bf4..343f002 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -57,6 +57,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
void __iomem *base, *l3_targ_base;
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
char *target_name, *master_name = "UN IDENTIFIED";
+ struct l3_target_data *l3_targ_inst;

/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -74,9 +75,11 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
if (err_reg) {
/* Identify the source from control status register */
err_src = __ffs(err_reg);
+ l3_targ_inst = &l3_targ[i][err_src];
+ target_name = l3_targ_inst->name;
+ l3_targ_base = base + l3_targ_inst->offset;

/* Read the stderrlog_main_source from clk domain */
- l3_targ_base = base + l3_targ[i][err_src];
l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
l3_targ_slvofslsb = l3_targ_base +
L3_TARG_STDERRLOG_SLVOFSLSB;
@@ -88,8 +91,6 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
- target_name =
- l3_targ_inst_name[i][err_src];
WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
target_name,
readl_relaxed(l3_targ_slvofslsb));
@@ -99,8 +100,6 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
break;

case CUSTOM_ERROR:
- target_name =
- l3_targ_inst_name[i][err_src];
for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
if (masterid == l3_masters[k].id)
master_name =
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 059c707..ae28784 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -43,51 +43,62 @@ struct l3_masters_data {
char *name;
};

+/**
+ * struct l3_target_data - L3 Target information
+ * @offset: Offset from base for L3 Target
+ * @name: Target name
+ *
+ * Target information is organized indexed by bit field definitions.
+ */
+struct l3_target_data {
+ u32 offset;
+ char *name;
+};
+
static u32 l3_flagmux[L3_MODULES] = {
0x500,
0x1000,
0X0200
};

-/* L3 Target standard Error register offsets */
-static u32 l3_targ_inst_clk1[] = {
- 0x100, /* DMM1 */
- 0x200, /* DMM2 */
- 0x300, /* ABE */
- 0x400, /* L4CFG */
- 0x600, /* CLK2 PWR DISC */
- 0x0, /* Host CLK1 */
- 0x900 /* L4 Wakeup */
+static struct l3_target_data l3_target_inst_data_clk1[] = {
+ {0x100, "DMM1",},
+ {0x200, "DMM2",},
+ {0x300, "ABE",},
+ {0x400, "L4CFG",},
+ {0x600, "CLK2PWRDISC",},
+ {0x0, "HOSTCLK1",},
+ {0x900, "L4WAKEUP",},
};

-static u32 l3_targ_inst_clk2[] = {
- 0x500, /* CORTEX M3 */
- 0x300, /* DSS */
- 0x100, /* GPMC */
- 0x400, /* ISS */
- 0x700, /* IVAHD */
- 0xD00, /* missing in TRM corresponds to AES1*/
- 0x900, /* L4 PER0*/
- 0x200, /* OCMRAM */
- 0x100, /* missing in TRM corresponds to GPMC sERROR*/
- 0x600, /* SGX */
- 0x800, /* SL2 */
- 0x1600, /* C2C */
- 0x1100, /* missing in TRM corresponds PWR DISC CLK1*/
- 0xF00, /* missing in TRM corrsponds to SHA1*/
- 0xE00, /* missing in TRM corresponds to AES2*/
- 0xC00, /* L4 PER3 */
- 0xA00, /* L4 PER1*/
- 0xB00, /* L4 PER2*/
- 0x0, /* HOST CLK2 */
- 0x1800, /* CAL */
- 0x1700 /* LLI */
+static struct l3_target_data l3_target_inst_data_clk2[] = {
+ {0x500, "CORTEXM3",},
+ {0x300, "DSS",},
+ {0x100, "GPMC",},
+ {0x400, "ISS",},
+ {0x700, "IVAHD",},
+ {0xD00, "AES1",},
+ {0x900, "L4PER0",},
+ {0x200, "OCMRAM",},
+ {0x100, "GPMCsERROR",},
+ {0x600, "SGX",},
+ {0x800, "SL2",},
+ {0x1600, "C2C",},
+ {0x1100, "PWRDISCCLK1",},
+ {0xF00, "SHA1",},
+ {0xE00, "AES2",},
+ {0xC00, "L4PER3",},
+ {0xA00, "L4PER1",},
+ {0xB00, "L4PER2",},
+ {0x0, "HOSTCLK2",},
+ {0x1800, "CAL",},
+ {0x1700, "LLI",},
};

-static u32 l3_targ_inst_clk3[] = {
- 0x0100 /* EMUSS */,
- 0x0300, /* DEBUGSS_CT_TBR */
- 0x0 /* HOST CLK3 */
+static struct l3_target_data l3_target_inst_data_clk3[] = {
+ {0x0100, "EMUSS",},
+ {0x0300, "DEBUG SOURCE",},
+ {0x0, "HOST CLK3",},
};

static struct l3_masters_data l3_masters[] = {
@@ -118,50 +129,10 @@ static struct l3_masters_data l3_masters[] = {
{ 0xC8, "USBHOSTFS"}
};

-static char *l3_targ_inst_name[L3_MODULES][21] = {
- {
- "DMM1",
- "DMM2",
- "ABE",
- "L4CFG",
- "CLK2 PWR DISC",
- "HOST CLK1",
- "L4 WAKEUP"
- },
- {
- "CORTEX M3" ,
- "DSS ",
- "GPMC ",
- "ISS ",
- "IVAHD ",
- "AES1",
- "L4 PER0",
- "OCMRAM ",
- "GPMC sERROR",
- "SGX ",
- "SL2 ",
- "C2C ",
- "PWR DISC CLK1",
- "SHA1",
- "AES2",
- "L4 PER3",
- "L4 PER1",
- "L4 PER2",
- "HOST CLK2",
- "CAL",
- "LLI"
- },
- {
- "EMUSS",
- "DEBUG SOURCE",
- "HOST CLK3"
- },
-};
-
-static u32 *l3_targ[L3_MODULES] = {
- l3_targ_inst_clk1,
- l3_targ_inst_clk2,
- l3_targ_inst_clk3,
+static struct l3_target_data *l3_targ[L3_MODULES] = {
+ l3_target_inst_data_clk1,
+ l3_target_inst_data_clk2,
+ l3_target_inst_data_clk3,
};

struct omap_l3 {
--
1.7.9.5

2014-04-28 15:35:04

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 16/20] bus: omap_l3_noc: add information about the type of operation

Today we get error such as
L3 Custom Error: MASTER MPU TARGET L4PER2

But since the actual instruction triggerring the error Vs the point
at which we report error may not be aligned, it makes sense to try
and provide additional information - example the type of operation
that was attempted to being performed can help narrow the debug down
further.

This helps provide log such as:
L3 Custom Error: MASTER MPU TARGET L4PER2 (Read)

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change
drivers/bus/omap_l3_noc.c | 9 ++++++++-
drivers/bus/omap_l3_noc.h | 13 +++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 00e4fed..9d021d0 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -60,8 +60,10 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
{
int k;
u32 std_err_main, clear, masterid;
+ u8 op_code;
void __iomem *l3_targ_base;
void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
+ void __iomem *l3_targ_hdr;
struct l3_target_data *l3_targ_inst;
struct l3_masters_data *master;
char *target_name, *master_name = "UN IDENTIFIED";
@@ -96,6 +98,7 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
readl_relaxed(l3_targ_slvofslsb));

l3_targ_mstaddr = l3_targ_base + L3_TARG_STDERRLOG_MSTADDR;
+ l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_HDR;
break;

case CUSTOM_ERROR:
@@ -103,6 +106,7 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,

l3_targ_mstaddr = l3_targ_base +
L3_TARG_STDERRLOG_CINFO_MSTADDR;
+ l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_CINFO_OPCODE;
break;

default:
@@ -122,11 +126,14 @@ static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
}
}

+ op_code = readl_relaxed(l3_targ_hdr) & 0x7;
+
WARN(true,
- "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
+ "%s:L3 %s Error: MASTER %s TARGET %s (%s)%s\n",
dev_name(l3->dev),
err_description,
master_name, target_name,
+ l3_transaction_type[op_code],
err_string);

/* clear the std error log*/
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 4e18307..6670fd9 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -29,14 +29,27 @@

/* L3 TARG register offsets */
#define L3_TARG_STDERRLOG_MAIN 0x48
+#define L3_TARG_STDERRLOG_HDR 0x4c
#define L3_TARG_STDERRLOG_MSTADDR 0x50
#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c
#define L3_TARG_STDERRLOG_CINFO_MSTADDR 0x68
+#define L3_TARG_STDERRLOG_CINFO_OPCODE 0x6c
#define L3_FLAGMUX_REGERR0 0xc
#define L3_FLAGMUX_MASK0 0x8

#define L3_TARGET_NOT_SUPPORTED NULL

+static const char * const l3_transaction_type[] = {
+ /* 0 0 0 */ "Idle",
+ /* 0 0 1 */ "Write",
+ /* 0 1 0 */ "Read",
+ /* 0 1 1 */ "ReadEx",
+ /* 1 0 0 */ "Read Link",
+ /* 1 0 1 */ "Write Non-Posted",
+ /* 1 1 0 */ "Write Conditional",
+ /* 1 1 1 */ "Write Broadcast",
+};
+
/**
* struct l3_masters_data - L3 Master information
* @id: ID of the L3 Master
--
1.7.9.5

2014-04-28 15:36:36

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 06/20] bus: omap_l3_noc: un-obfuscate l3_targ address computation

just simplify derefencing that is equivalent.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change
drivers/bus/omap_l3_noc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index c8facb0..f7d3bf4 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -76,7 +76,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
err_src = __ffs(err_reg);

/* Read the stderrlog_main_source from clk domain */
- l3_targ_base = base + *(l3_targ[i] + err_src);
+ l3_targ_base = base + l3_targ[i][err_src];
l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
l3_targ_slvofslsb = l3_targ_base +
L3_TARG_STDERRLOG_SLVOFSLSB;
--
1.7.9.5

2014-04-28 15:36:34

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 12/20] bus: omap_l3_noc: fix masterid detection

As per Documentation (OMAP4+), then masterid is infact encoded as
follows:
"L3_TARG_STDERRLOG_MSTADDR[7:0] STDERRLOG_MSTADDR stores the NTTP
master address. The master address is the concatenation of Prefix &
Initiator ConnID. It is defined on 8 bits. The 6 MSBs are used to
distinguish the different initiators."

So, when we matchup currently with the master ID list, we never get a
proper match other than when MPU is the master (thanks to 0).

Now, on other platforms such as AM437x, this tends to be bits[5:0].

Fix this by using the relevant 6MSBits to identify the master ID for
standard and custom errors.

Reported-by: Darren Etheridge <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---

V3: made master id information into a structure field thanks to AM437x
information recently recieved.

drivers/bus/omap_l3_noc.c | 6 +++++-
drivers/bus/omap_l3_noc.h | 4 ++++
2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 9524452..8a1926d 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -127,7 +127,11 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
L3_TARG_STDERRLOG_MSTADDR;

std_err_main = readl_relaxed(l3_targ_stderr);
- masterid = readl_relaxed(l3_targ_mstaddr);
+
+ /* STDERRLOG_MSTADDR Stores the NTTP master address. */
+ masterid = (readl_relaxed(l3_targ_mstaddr) &
+ l3->mst_addr_mask) >>
+ __ffs(l3->mst_addr_mask);

switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 64869fe..ba86924 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -84,6 +84,7 @@ struct l3_flagmux_data {
* @l3_masters: array pointing to master data containing name and register
* offset for the master.
* @num_master: number of masters
+ * @mst_addr_mask: Mask representing MSTADDR information of NTTP packet
* @debug_irq: irq number of the debug interrupt (populated runtime)
* @app_irq: irq number of the application interrupt (populated runtime)
*/
@@ -96,6 +97,7 @@ struct omap_l3 {

struct l3_masters_data *l3_masters;
int num_masters;
+ u32 mst_addr_mask;

int debug_irq;
int app_irq;
@@ -200,6 +202,8 @@ static const struct omap_l3 omap_l3_data = {
.num_modules = ARRAY_SIZE(omap_l3_flagmux),
.l3_masters = omap_l3_masters,
.num_masters = ARRAY_SIZE(omap_l3_masters),
+ /* The 6 MSBs of register field used to distinguish initiator */
+ .mst_addr_mask = 0xFC,
};

#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-28 15:15:34

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 07/20] bus: omap_l3_noc: move L3 master data structure out

Move the L3 master structure out of the static definition to enable
reuse for other SoCs.

Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: no change
drivers/bus/omap_l3_noc.h | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 31984cf..059c707 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -33,6 +33,16 @@

#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0]))

+/**
+ * struct l3_masters_data - L3 Master information
+ * @id: ID of the L3 Master
+ * @name: master name
+ */
+struct l3_masters_data {
+ u32 id;
+ char *name;
+};
+
static u32 l3_flagmux[L3_MODULES] = {
0x500,
0x1000,
@@ -80,10 +90,7 @@ static u32 l3_targ_inst_clk3[] = {
0x0 /* HOST CLK3 */
};

-static struct l3_masters_data {
- u32 id;
- char name[10];
-} l3_masters[] = {
+static struct l3_masters_data l3_masters[] = {
{ 0x0 , "MPU"},
{ 0x10, "CS_ADP"},
{ 0x14, "xxx"},
--
1.7.9.5

2014-04-28 15:38:47

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 02/20] bus: omap_l3_noc: rename functions and data to omap_l3

From: Sricharan R <[email protected]>

Since omap_l3_noc driver is now being used for OMAP5 and reusable with
DRA7 and AM437x, using omap4 specific naming is misleading.

Signed-off-by: Sricharan R <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
change in V3: none
drivers/bus/omap_l3_noc.c | 24 ++++++++++++------------
drivers/bus/omap_l3_noc.h | 11 ++++++-----
2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 1eb6d85..800486c 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -1,5 +1,5 @@
/*
- * OMAP4XXX L3 Interconnect error handling driver
+ * OMAP L3 Interconnect error handling driver
*
* Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
@@ -50,7 +50,7 @@
static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
{

- struct omap4_l3 *l3 = _l3;
+ struct omap_l3 *l3 = _l3;
int inttype, i, k;
int err_src = 0;
u32 std_err_main, err_reg, clear, masterid;
@@ -122,9 +122,9 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
return IRQ_HANDLED;
}

-static int omap4_l3_probe(struct platform_device *pdev)
+static int omap_l3_probe(struct platform_device *pdev)
{
- static struct omap4_l3 *l3;
+ static struct omap_l3 *l3;
int ret, i;

l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL);
@@ -176,8 +176,8 @@ MODULE_DEVICE_TABLE(of, l3_noc_match);
#define l3_noc_match NULL
#endif

-static struct platform_driver omap4_l3_driver = {
- .probe = omap4_l3_probe,
+static struct platform_driver omap_l3_driver = {
+ .probe = omap_l3_probe,
.driver = {
.name = "omap_l3_noc",
.owner = THIS_MODULE,
@@ -185,14 +185,14 @@ static struct platform_driver omap4_l3_driver = {
},
};

-static int __init omap4_l3_init(void)
+static int __init omap_l3_init(void)
{
- return platform_driver_register(&omap4_l3_driver);
+ return platform_driver_register(&omap_l3_driver);
}
-postcore_initcall_sync(omap4_l3_init);
+postcore_initcall_sync(omap_l3_init);

-static void __exit omap4_l3_exit(void)
+static void __exit omap_l3_exit(void)
{
- platform_driver_unregister(&omap4_l3_driver);
+ platform_driver_unregister(&omap_l3_driver);
}
-module_exit(omap4_l3_exit);
+module_exit(omap_l3_exit);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index cc4b1b1..b3c81f2 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -1,5 +1,5 @@
/*
- * OMAP4XXX L3 Interconnect error handling driver header
+ * OMAP L3 Interconnect error handling driver header
*
* Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <[email protected]>
@@ -14,8 +14,8 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
-#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#ifndef __OMAP_L3_NOC_H
+#define __OMAP_L3_NOC_H

#define L3_MODULES 3
#define CLEAR_STDERR_LOG (1 << 31)
@@ -157,7 +157,7 @@ static u32 *l3_targ[L3_MODULES] = {
l3_targ_inst_clk3,
};

-struct omap4_l3 {
+struct omap_l3 {
struct device *dev;
struct clk *ick;

@@ -167,4 +167,5 @@ struct omap4_l3 {
int debug_irq;
int app_irq;
};
-#endif
+
+#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-28 15:38:46

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH V3 19/20] bus: omap_l3_noc: Add DRA7 interconnect error data

From: Rajendra Nayak <[email protected]>

DRA7 is distinctly different from OMAP4 in terms of masters and clock
domain organization. There two main clock domains which is divided as
follows:
<0x44000000 0x1000000> is clk1 and clk2 is the sub clock domain
<0x45000000 0x1000> is clk3

Add all the data needed to handle L3 error handling on DRA7 devices
and mark clk2 as subdomain and provide a compatible flag for
functionality. Other than the data difference the hardware blocks
involved are essentially the same.

Signed-off-by: Rajendra Nayak <[email protected]>
[[email protected]: bugfixes and generic improvements, documentation]
Signed-off-by: Nishanth Menon <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Acked-by: Peter Ujfalusi <[email protected]>
Tested-by: Darren Etheridge <[email protected]>
---
V3: update based on masterID register information

.../devicetree/bindings/arm/omap/l3-noc.txt | 1 +
drivers/bus/omap_l3_noc.c | 1 +
drivers/bus/omap_l3_noc.h | 151 ++++++++++++++++++++
3 files changed, 153 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
index c0105de..45d0fc2 100644
--- a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
+++ b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
@@ -6,6 +6,7 @@ provided by Arteris.
Required properties:
- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
Should be "ti,omap4-l3-noc" for OMAP4 family
+ Should be "ti,dra7-l3-noc" for DRA7 family
- reg: Contains L3 register address range for each noc domain.
- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 0eba07a..6cdd02e 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -230,6 +230,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

static const struct of_device_id l3_noc_match[] = {
{.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
+ {.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
{},
};
MODULE_DEVICE_TABLE(of, l3_noc_match);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index aced4c5..9562a75 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -230,4 +230,155 @@ static const struct omap_l3 omap_l3_data = {
.mst_addr_mask = 0xFC,
};

+/* DRA7 data */
+static struct l3_target_data dra_l3_target_data_clk1[] = {
+ {0x2a00, "AES1",},
+ {0x0200, "DMM_P1",},
+ {0x0600, "DSP2_SDMA",},
+ {0x0b00, "EVE2",},
+ {0x1300, "DMM_P2",},
+ {0x2c00, "AES2",},
+ {0x0300, "DSP1_SDMA",},
+ {0x0a00, "EVE1",},
+ {0x0c00, "EVE3",},
+ {0x0d00, "EVE4",},
+ {0x2900, "DSS",},
+ {0x0100, "GPMC",},
+ {0x3700, "PCIE1",},
+ {0x1600, "IVA_CONFIG",},
+ {0x1800, "IVA_SL2IF",},
+ {0x0500, "L4_CFG",},
+ {0x1d00, "L4_WKUP",},
+ {0x3800, "PCIE2",},
+ {0x3300, "SHA2_1",},
+ {0x1200, "GPU",},
+ {0x1000, "IPU1",},
+ {0x1100, "IPU2",},
+ {0x2000, "TPCC_EDMA",},
+ {0x2e00, "TPTC1_EDMA",},
+ {0x2b00, "TPTC2_EDMA",},
+ {0x0700, "VCP1",},
+ {0x2500, "L4_PER2_P3",},
+ {0x0e00, "L4_PER3_P3",},
+ {0x2200, "MMU1",},
+ {0x1400, "PRUSS1",},
+ {0x1500, "PRUSS2"},
+ {0x0800, "VCP1",},
+};
+
+static struct l3_flagmux_data dra_l3_flagmux_clk1 = {
+ .offset = 0x803500,
+ .l3_targ = dra_l3_target_data_clk1,
+ .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk1),
+};
+
+static struct l3_target_data dra_l3_target_data_clk2[] = {
+ {0x0, "HOST CLK1",},
+ {0x0, "HOST CLK2",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x3400, "SHA2_2",},
+ {0x0900, "BB2D",},
+ {0xdead, L3_TARGET_NOT_SUPPORTED,},
+ {0x2100, "L4_PER1_P3",},
+ {0x1c00, "L4_PER1_P1",},
+ {0x1f00, "L4_PER1_P2",},
+ {0x2300, "L4_PER2_P1",},
+ {0x2400, "L4_PER2_P2",},
+ {0x2600, "L4_PER3_P1",},
+ {0x2700, "L4_PER3_P2",},
+ {0x2f00, "MCASP1",},
+ {0x3000, "MCASP2",},
+ {0x3100, "MCASP3",},
+ {0x2800, "MMU2",},
+ {0x0f00, "OCMC_RAM1",},
+ {0x1700, "OCMC_RAM2",},
+ {0x1900, "OCMC_RAM3",},
+ {0x1e00, "OCMC_ROM",},
+ {0x3900, "QSPI",},
+};
+
+static struct l3_flagmux_data dra_l3_flagmux_clk2 = {
+ .offset = 0x803600,
+ .l3_targ = dra_l3_target_data_clk2,
+ .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk2),
+};
+
+static struct l3_target_data dra_l3_target_data_clk3[] = {
+ {0x0100, "L3_INSTR"},
+ {0x0300, "DEBUGSS_CT_TBR"},
+ {0x0, "HOST CLK3"},
+};
+
+static struct l3_flagmux_data dra_l3_flagmux_clk3 = {
+ .offset = 0x200,
+ .l3_targ = dra_l3_target_data_clk3,
+ .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk3),
+};
+
+static struct l3_masters_data dra_l3_masters[] = {
+ { 0x0, "MPU" },
+ { 0x4, "CS_DAP" },
+ { 0x5, "IEEE1500_2_OCP" },
+ { 0x8, "DSP1_MDMA" },
+ { 0x9, "DSP1_CFG" },
+ { 0xA, "DSP1_DMA" },
+ { 0xB, "DSP2_MDMA" },
+ { 0xC, "DSP2_CFG" },
+ { 0xD, "DSP2_DMA" },
+ { 0xE, "IVA" },
+ { 0x10, "EVE1_P1" },
+ { 0x11, "EVE2_P1" },
+ { 0x12, "EVE3_P1" },
+ { 0x13, "EVE4_P1" },
+ { 0x14, "PRUSS1 PRU1" },
+ { 0x15, "PRUSS1 PRU2" },
+ { 0x16, "PRUSS2 PRU1" },
+ { 0x17, "PRUSS2 PRU2" },
+ { 0x18, "IPU1" },
+ { 0x19, "IPU2" },
+ { 0x1A, "SDMA" },
+ { 0x1B, "CDMA" },
+ { 0x1C, "TC1_EDMA" },
+ { 0x1D, "TC2_EDMA" },
+ { 0x20, "DSS" },
+ { 0x21, "MMU1" },
+ { 0x22, "PCIE1" },
+ { 0x23, "MMU2" },
+ { 0x24, "VIP1" },
+ { 0x25, "VIP2" },
+ { 0x26, "VIP3" },
+ { 0x27, "VPE" },
+ { 0x28, "GPU_P1" },
+ { 0x29, "BB2D" },
+ { 0x29, "GPU_P2" },
+ { 0x2B, "GMAC_SW" },
+ { 0x2C, "USB3" },
+ { 0x2D, "USB2_SS" },
+ { 0x2E, "USB2_ULPI_SS1" },
+ { 0x2F, "USB2_ULPI_SS2" },
+ { 0x30, "CSI2_1" },
+ { 0x31, "CSI2_2" },
+ { 0x33, "SATA" },
+ { 0x34, "EVE1_P2" },
+ { 0x35, "EVE2_P2" },
+ { 0x36, "EVE3_P2" },
+ { 0x37, "EVE4_P2" }
+};
+
+static struct l3_flagmux_data *dra_l3_flagmux[] = {
+ &dra_l3_flagmux_clk1,
+ &dra_l3_flagmux_clk2,
+ &dra_l3_flagmux_clk3,
+};
+
+static const struct omap_l3 dra_l3_data = {
+ .l3_base = { [1] = L3_BASE_IS_SUBMODULE },
+ .l3_flagmux = dra_l3_flagmux,
+ .num_modules = ARRAY_SIZE(dra_l3_flagmux),
+ .l3_masters = dra_l3_masters,
+ .num_masters = ARRAY_SIZE(dra_l3_masters),
+ /* The 6 MSBs of register field used to distinguish initiator */
+ .mst_addr_mask = 0xFC,
+};
+
#endif /* __OMAP_L3_NOC_H */
--
1.7.9.5

2014-04-29 13:42:44

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH V3 00/20] bus: omap_l3_noc: driver cleanups and support for DRA7/AM4372

On Monday 28 April 2014 08:44 PM, Nishanth Menon wrote:
> V3: has the following changes (w.r.t v2):
> - fixed relaxed commit message and usage.
> - AM437x internal documents showed that:
> - new master information updated into the data
> - masterid register definition is different from OMAP4-DRA7 - some
> additional parsing is done in hardware to "avoid s/w parsing"
> - Additional testing information showed logic fail for masking "unclearable"
> new patch added to series - patch #15
> - Picked up previous acks and tested by - minor changes verified

Tested the series on AM437x ePOS EVM and works great.

Tested-by: Sekhar Nori <[email protected]>

Thanks,
Sekhar

2014-04-14 16:40:11

by Nishanth Menon

[permalink] [raw]
Subject: [PATCH 08/15] bus: omap_l3_noc: Add support for discountinous flag mux input numbers

From: Rajendra Nayak <[email protected]>

On DRA7, unlike on OMAP4 and OMAP5, the flag mux input numbers used
to indicate the source of errors are not continous. Have a way in the
driver to catch these and WARN the user of the flag mux input thats
either undocumented or wrong.

In the similar vein, Timeout errors in AM43x can't be cleared per h/w
team, neither does it have a STDERRLOG_MAIN to clear the error.

Further, the mux bit offset might not even be indexed into our array
of known mux input description, in which case we'd have a abort.

So, define a static range check for bit description and any definition
which has target_name set to NULL (the ones that are not populated or
ones that are specifically marked in the case of discontinous input
numbers), can handle the same gracefully. Upon occurance of error from
such sources, mask it. Otherwise, we'd have an infinite interrupt
source without any means to clear it.

[[email protected]: rebase, squash and improve]
Signed-off-by: Rajendra Nayak <[email protected]>
Signed-off-by: Afzal Mohammed <[email protected]>
Signed-off-by: Nishanth Menon <[email protected]>
---
drivers/bus/omap_l3_noc.c | 31 +++++++++++++++++++++++++++++++
drivers/bus/omap_l3_noc.h | 11 ++++++++---
2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index da4e27c..c2b0cc3 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -79,10 +79,41 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)

/* Identify the source from control status register */
err_src = __ffs(err_reg);
+
+ /* We DONOT expect err_src to go out of bounds */
+ BUG_ON(err_src >= MAX_CLKDM_TARGETS);
+
l3_targ_inst = &l3_targ[i][err_src];
target_name = l3_targ_inst->name;
l3_targ_base = base + l3_targ_inst->offset;

+ /*
+ * If we do not know of a register offset to decode
+ * and clear, then mask.
+ */
+ if (target_name == L3_TARGET_NOT_SUPPORTED) {
+ u32 mask_val;
+ void __iomem *mask_reg;
+
+ /*
+ * Certain plaforms may have "undocumented"
+ * status pending on boot.. So dont generate
+ * a severe warning here.
+ */
+ dev_err(l3->dev,
+ "L3 %s error: target %d mod:%d %s\n",
+ inttype ? "debug" : "application",
+ err_src, i, "(unclearable)");
+
+ mask_reg = base + l3_flagmux[i] +
+ L3_FLAGMUX_MASK0 + (inttype << 3);
+ mask_val = readl(mask_reg);
+ mask_val &= ~(1 << err_src);
+ writel(mask_val, mask_reg);
+
+ break;
+ }
+
/* Read the stderrlog_main_source from clk domain */
l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
l3_targ_slvofslsb = l3_targ_base +
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index 25ba99c..c4a1760 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -30,6 +30,11 @@
#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c
#define L3_TARG_STDERRLOG_MSTADDR 0x68
#define L3_FLAGMUX_REGERR0 0xc
+#define L3_FLAGMUX_MASK0 0x8
+
+#define L3_TARGET_NOT_SUPPORTED NULL
+
+#define MAX_CLKDM_TARGETS 30

#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0]))

@@ -61,7 +66,7 @@ static u32 l3_flagmux[L3_MODULES] = {
0X0200
};

-static struct l3_target_data l3_target_inst_data_clk1[] = {
+static struct l3_target_data l3_target_inst_data_clk1[MAX_CLKDM_TARGETS] = {
{0x100, "DMM1",},
{0x200, "DMM2",},
{0x300, "ABE",},
@@ -71,7 +76,7 @@ static struct l3_target_data l3_target_inst_data_clk1[] = {
{0x900, "L4WAKEUP",},
};

-static struct l3_target_data l3_target_inst_data_clk2[] = {
+static struct l3_target_data l3_target_inst_data_clk2[MAX_CLKDM_TARGETS] = {
{0x500, "CORTEXM3",},
{0x300, "DSS",},
{0x100, "GPMC",},
@@ -95,7 +100,7 @@ static struct l3_target_data l3_target_inst_data_clk2[] = {
{0x1700, "LLI",},
};

-static struct l3_target_data l3_target_inst_data_clk3[] = {
+static struct l3_target_data l3_target_inst_data_clk3[MAX_CLKDM_TARGETS] = {
{0x0100, "EMUSS",},
{0x0300, "DEBUG SOURCE",},
{0x0, "HOST CLK3",},
--
1.7.9.5