Commit 75d6bc5f authored by Olof Johansson's avatar Olof Johansson

Merge tag 'omap-for-v3.16/l3-noc-signed' of...

Merge tag 'omap-for-v3.16/l3-noc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers

Merge "ARM: omap l3-noc bus driver changes for v3.16 merge window, resend" from
Tony Lindgren:

Improvments to omap l3-noc bus driver for v3.16 merge window
to add support for am347x and dra7.

* tag 'omap-for-v3.16/l3-noc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (25 commits)
  bus: omap_l3_noc: Add AM4372 interconnect error data
  bus: omap_l3_noc: Add DRA7 interconnect error data
  bus: omap_l3_noc: introduce concept of submodule
  bus: omap_l3_noc: Add information about the context of operation
  bus: omap_l3_noc: add information about the type of operation
  bus: omap_l3_noc: ignore masked out unclearable targets
  bus: omap_l3_noc: improve readability by using helper for slave event parsing
  bus: omap_l3_noc: make error reporting and handling common
  bus: omap_l3_noc: fix masterid detection
  bus: omap_l3_noc: convert flagmux information into a structure
  bus: omap_l3_noc: use of_match_data to pick up SoC information
  bus: omap_l3_noc: Add support for discountinous flag mux input numbers
  bus: omap_l3_noc: convert target information into a structure
  bus: omap_l3_noc: move L3 master data structure out
  bus: omap_l3_noc: un-obfuscate l3_targ address computation
  bus: omap_l3_noc: switch over to relaxed variants of readl/writel
  bus: omap_l3_noc: populate l3->dev and use it
  bus: omap_l3_noc: remove iclk from omap_l3 struct
  bus: omap_l3_noc: rename functions and data to omap_l3
  bus: omap_l3_noc: Fix copyright information
  ...
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 1b7f0c7b 27b7d5f3
...@@ -6,6 +6,8 @@ provided by Arteris. ...@@ -6,6 +6,8 @@ provided by Arteris.
Required properties: Required properties:
- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family - compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
Should be "ti,omap4-l3-noc" for OMAP4 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. - reg: Contains L3 register address range for each noc domain.
- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain. - ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.
......
/* /*
* OMAP4XXX L3 Interconnect error handling driver * OMAP L3 Interconnect error handling driver
* *
* Copyright (C) 2011 Texas Corporation * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <santosh.shilimkar@ti.com> * Santosh Shilimkar <santosh.shilimkar@ti.com>
* Sricharan <r.sricharan@ti.com> * Sricharan <r.sricharan@ti.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* the Free Software Foundation; either version 2 of the License, or * published by the Free Software Foundation.
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed "as is" WITHOUT ANY WARRANTY of any
* but WITHOUT ANY WARRANTY; without even the implied warranty of * kind, whether express or implied; without even the implied warranty
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * 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> #include <linux/init.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.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 <linux/slab.h>
#include "omap_l3_noc.h" #include "omap_l3_noc.h"
/* /**
* Interrupt Handler for L3 error detection. * l3_handle_target() - Handle Target specific parse and reporting
* 1) Identify the L3 clockdomain partition to which the error belongs to. * @l3: pointer to l3 struct
* 2) Identify the slave where the error information is logged * @base: base address of clkdm
* 3) Print the logged information. * @flag_mux: flagmux corresponding to the event
* 4) Add dump stack to provide kernel trace. * @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 : * 1) Custom errors in L3 :
* Target like DMM/FW/EMIF generates SRESP=ERR error * Target like DMM/FW/EMIF generates SRESP=ERR error
* 2) Standard L3 error: * 2) Standard L3 error:
...@@ -53,74 +55,172 @@ ...@@ -53,74 +55,172 @@
* can be trapped as well. But the trapping is implemented as part * can be trapped as well. But the trapping is implemented as part
* secure software and hence need not be implemented here. * 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)
{ {
int k;
u32 std_err_main, clear, masterid;
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, *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);
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;
l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_HDR;
l3_targ_info = l3_targ_base + L3_TARG_STDERRLOG_INFO;
break;
case CUSTOM_ERROR:
err_description = "Custom";
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:
/* 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;
}
}
op_code = readl_relaxed(l3_targ_hdr) & 0x7;
struct omap4_l3 *l3 = _l3; m_req_info = readl_relaxed(l3_targ_info) & 0xF;
int inttype, i, k; 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%s\n",
dev_name(l3->dev),
err_description,
master_name, target_name,
l3_transaction_type[op_code],
err_string, info_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; int err_src = 0;
u32 std_err_main, err_reg, clear, masterid; u32 err_reg, mask_val;
void __iomem *base, *l3_targ_base; void __iomem *base, *mask_reg;
char *target_name, *master_name = "UN IDENTIFIED"; struct l3_flagmux_data *flag_mux;
/* Get the Type of interrupt */ /* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR; 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 * Read the regerr register of the clock domain
* to determine the source * to determine the source
*/ */
base = l3->l3_base[i]; base = l3->l3_base[i];
err_reg = __raw_readl(base + l3_flagmux[i] + flag_mux = l3->l3_flagmux[i];
+ L3_FLAGMUX_REGERR0 + (inttype << 3)); 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 */ /* Get the corresponding error and analyse */
if (err_reg) { if (err_reg) {
/* Identify the source from control status register */ /* Identify the source from control status register */
err_src = __ffs(err_reg); err_src = __ffs(err_reg);
/* Read the stderrlog_main_source from clk domain */ ret = l3_handle_target(l3, base, flag_mux, err_src);
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);
switch (std_err_main & CUSTOM_ERROR) { /*
case STANDARD_ERROR: * Certain plaforms may have "undocumented" status
target_name = * pending on boot. So dont generate a severe warning
l3_targ_inst_name[i][err_src]; * here. Just mask it off to prevent the error from
WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n", * reoccuring and locking up the system.
target_name, */
__raw_readl(l3_targ_base + if (ret) {
L3_TARG_STDERRLOG_SLVOFSLSB)); dev_err(l3->dev,
/* clear the std error log*/ "L3 %s error: target %d mod:%d %s\n",
clear = std_err_main | CLEAR_STDERR_LOG; inttype ? "debug" : "application",
writel(clear, l3_targ_base + err_src, i, "(unclearable)");
L3_TARG_STDERRLOG_MAIN);
break;
case CUSTOM_ERROR: mask_reg = base + flag_mux->offset +
target_name = L3_FLAGMUX_MASK0 + (inttype << 3);
l3_targ_inst_name[i][err_src]; mask_val = readl_relaxed(mask_reg);
for (k = 0; k < NUM_OF_L3_MASTERS; k++) { mask_val &= ~(1 << err_src);
if (masterid == l3_masters[k].id) writel_relaxed(mask_val, mask_reg);
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(clear, l3_targ_base +
L3_TARG_STDERRLOG_MAIN);
break;
default: /* Mark these bits as to be ignored */
/* Nothing to be handled here as of now */ if (inttype)
break; flag_mux->mask_app_bits |= 1 << err_src;
else
flag_mux->mask_dbg_bits |= 1 << err_src;
} }
/* Error found so break the for loop */ /* Error found so break the for loop */
break; break;
} }
...@@ -128,139 +228,91 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3) ...@@ -128,139 +228,91 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int omap4_l3_probe(struct platform_device *pdev) 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);
static int omap_l3_probe(struct platform_device *pdev)
{ {
static struct omap4_l3 *l3; const struct of_device_id *of_id;
struct resource *res; static struct omap_l3 *l3;
int ret; int ret, i, res_idx;
of_id = of_match_device(l3_noc_match, &pdev->dev);
if (!of_id) {
dev_err(&pdev->dev, "OF data missing\n");
return -EINVAL;
}
l3 = kzalloc(sizeof(*l3), GFP_KERNEL); l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL);
if (!l3) if (!l3)
return -ENOMEM; return -ENOMEM;
memcpy(l3, of_id->data, sizeof(*l3));
l3->dev = &pdev->dev;
platform_set_drvdata(pdev, l3); platform_set_drvdata(pdev, l3);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "couldn't find resource 0\n");
ret = -ENODEV;
goto err0;
}
l3->l3_base[0] = ioremap(res->start, resource_size(res)); /* Get mem resources */
if (!l3->l3_base[0]) { for (i = 0, res_idx = 0; i < l3->num_modules; i++) {
dev_err(&pdev->dev, "ioremap failed\n"); struct resource *res;
ret = -ENOMEM;
goto err0;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) {
dev_err(&pdev->dev, "couldn't find resource 1\n");
ret = -ENODEV;
goto err1;
}
l3->l3_base[1] = ioremap(res->start, resource_size(res)); if (l3->l3_base[i] == L3_BASE_IS_SUBMODULE) {
if (!l3->l3_base[1]) { /* First entry cannot be submodule */
dev_err(&pdev->dev, "ioremap failed\n"); BUG_ON(i == 0);
ret = -ENOMEM; l3->l3_base[i] = l3->l3_base[i - 1];
goto err1; continue;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2); l3->l3_base[i] = devm_ioremap_resource(&pdev->dev, res);
if (!res) { if (IS_ERR(l3->l3_base[i])) {
dev_err(&pdev->dev, "couldn't find resource 2\n"); dev_err(l3->dev, "ioremap %d failed\n", i);
ret = -ENODEV; return PTR_ERR(l3->l3_base[i]);
goto err2;
} }
res_idx++;
l3->l3_base[2] = ioremap(res->start, resource_size(res));
if (!l3->l3_base[2]) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENOMEM;
goto err2;
} }
/* /*
* Setup interrupt Handlers * Setup interrupt Handlers
*/ */
l3->debug_irq = platform_get_irq(pdev, 0); l3->debug_irq = platform_get_irq(pdev, 0);
ret = request_irq(l3->debug_irq, ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler,
l3_interrupt_handler,
IRQF_DISABLED, "l3-dbg-irq", l3); IRQF_DISABLED, "l3-dbg-irq", l3);
if (ret) { if (ret) {
pr_crit("L3: request_irq failed to register for 0x%x\n", dev_err(l3->dev, "request_irq failed for %d\n",
l3->debug_irq); l3->debug_irq);
goto err3; return ret;
} }
l3->app_irq = platform_get_irq(pdev, 1); l3->app_irq = platform_get_irq(pdev, 1);
ret = request_irq(l3->app_irq, ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler,
l3_interrupt_handler,
IRQF_DISABLED, "l3-app-irq", l3); IRQF_DISABLED, "l3-app-irq", l3);
if (ret) { if (ret)
pr_crit("L3: request_irq failed to register for 0x%x\n", dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq);
l3->app_irq);
goto err4;
}
return 0;
err4:
free_irq(l3->debug_irq, l3);
err3:
iounmap(l3->l3_base[2]);
err2:
iounmap(l3->l3_base[1]);
err1:
iounmap(l3->l3_base[0]);
err0:
kfree(l3);
return ret; return ret;
} }
static int omap4_l3_remove(struct platform_device *pdev) static struct platform_driver omap_l3_driver = {
{ .probe = omap_l3_probe,
struct omap4_l3 *l3 = platform_get_drvdata(pdev);
free_irq(l3->app_irq, l3);
free_irq(l3->debug_irq, l3);
iounmap(l3->l3_base[0]);
iounmap(l3->l3_base[1]);
iounmap(l3->l3_base[2]);
kfree(l3);
return 0;
}
#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 omap4_l3_driver = {
.probe = omap4_l3_probe,
.remove = omap4_l3_remove,
.driver = { .driver = {
.name = "omap_l3_noc", .name = "omap_l3_noc",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = l3_noc_match, .of_match_table = of_match_ptr(l3_noc_match),
}, },
}; };
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);
/* /*
* OMAP4XXX L3 Interconnect error handling driver header * OMAP L3 Interconnect error handling driver header
* *
* Copyright (C) 2011 Texas Corporation * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <santosh.shilimkar@ti.com> * Santosh Shilimkar <santosh.shilimkar@ti.com>
* sricharan <r.sricharan@ti.com> * sricharan <r.sricharan@ti.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* the Free Software Foundation; either version 2 of the License, or * published by the Free Software Foundation.
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed "as is" WITHOUT ANY WARRANTY of any
* but WITHOUT ANY WARRANTY; without even the implied warranty of * kind, whether express or implied; without even the implied warranty
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * 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 #ifndef __OMAP_L3_NOC_H
#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H #define __OMAP_L3_NOC_H
#define MAX_L3_MODULES 3
#define MAX_CLKDM_TARGETS 31
#define L3_MODULES 3
#define CLEAR_STDERR_LOG (1 << 31) #define CLEAR_STDERR_LOG (1 << 31)
#define CUSTOM_ERROR 0x2 #define CUSTOM_ERROR 0x2
#define STANDARD_ERROR 0x0 #define STANDARD_ERROR 0x0
...@@ -33,63 +29,165 @@ ...@@ -33,63 +29,165 @@
/* L3 TARG register offsets */ /* L3 TARG register offsets */
#define L3_TARG_STDERRLOG_MAIN 0x48 #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_SLVOFSLSB 0x5c
#define L3_TARG_STDERRLOG_MSTADDR 0x68 #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 #define L3_FLAGMUX_REGERR0 0xc
#define L3_FLAGMUX_MASK0 0x8
#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",
/* 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",
};
#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0])) /**
* struct l3_masters_data - L3 Master information
static u32 l3_flagmux[L3_MODULES] = { * @id: ID of the L3 Master
0x500, * @name: master name
0x1000, */
0X0200 struct l3_masters_data {
};
/* 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 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 u32 l3_targ_inst_clk3[] = {
0x0100 /* EMUSS */,
0x0300, /* DEBUGSS_CT_TBR */
0x0 /* HOST CLK3 */
};
static struct l3_masters_data {
u32 id; u32 id;
char name[10]; char *name;
} l3_masters[] = { };
/**
* 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;
};
/**
* 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
* @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;
};
/**
* 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 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.
* @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
* @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)
*/
struct omap_l3 {
struct device *dev;
void __iomem *l3_base[MAX_L3_MODULES];
struct l3_flagmux_data **l3_flagmux;
int num_modules;
struct l3_masters_data *l3_masters;
int num_masters;
u32 mst_addr_mask;
int debug_irq;
int app_irq;
};
static struct l3_target_data omap_l3_target_data_clk1[] = {
{0x100, "DMM1",},
{0x200, "DMM2",},
{0x300, "ABE",},
{0x400, "L4CFG",},
{0x600, "CLK2PWRDISC",},
{0x0, "HOSTCLK1",},
{0x900, "L4WAKEUP",},
};
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",},
{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 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"}, { 0x0 , "MPU"},
{ 0x10, "CS_ADP"}, { 0x10, "CS_ADP"},
{ 0x14, "xxx"}, { 0x14, "xxx"},
...@@ -117,60 +215,261 @@ static struct l3_masters_data { ...@@ -117,60 +215,261 @@ static struct l3_masters_data {
{ 0xC8, "USBHOSTFS"} { 0xC8, "USBHOSTFS"}
}; };
static char *l3_targ_inst_name[L3_MODULES][21] = { static struct l3_flagmux_data *omap_l3_flagmux[] = {
{ &omap_l3_flagmux_clk1,
"DMM1", &omap_l3_flagmux_clk2,
"DMM2", &omap_l3_flagmux_clk3,
"ABE", };
"L4CFG",
"CLK2 PWR DISC", static const struct omap_l3 omap_l3_data = {
"HOST CLK1", .l3_flagmux = omap_l3_flagmux,
"L4 WAKEUP" .num_modules = ARRAY_SIZE(omap_l3_flagmux),
}, .l3_masters = omap_l3_masters,
{ .num_masters = ARRAY_SIZE(omap_l3_masters),
"CORTEX M3" , /* The 6 MSBs of register field used to distinguish initiator */
"DSS ", .mst_addr_mask = 0xFC,
"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,
};
struct omap4_l3 {
struct device *dev;
struct clk *ick;
/* memory base */ /* DRA7 data */
void __iomem *l3_base[L3_MODULES]; 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",},
};
int debug_irq; static struct l3_flagmux_data dra_l3_flagmux_clk1 = {
int app_irq; .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" }
}; };
#endif
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,
};
/* 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment