diff mbox series

[v3,4/6] bus: Add Baikal-T1 AXI-bus driver

Message ID 20200526125928.17096-5-Sergey.Semin@baikalelectronics.ru (mailing list archive)
State Mainlined
Headers show
Series bus/memory: Add Baikal-T1 SoC APB/AXI/L2 drivers | expand

Commit Message

Serge Semin May 26, 2020, 12:59 p.m. UTC
AXI3-bus is the main communication bus connecting all high-speed
peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
Interconnect (so called AXI Main Interconnect) routing IO requests from
one SoC block to another. This driver provides a way to detect any bus
protocol errors and device not responding situations by means of an
embedded on top of the interconnect errors handler block (EHB). AXI
Interconnect QoS arbitration tuning is currently unsupported.
The bus doesn't provide a way to detect the interconnected devices,
so they are supposed to be statically defined like by means of the
simple-bus sub-nodes.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Olof Johansson <olof@lixom.net>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: soc@kernel.org
Cc: devicetree@vger.kernel.org

---

Changelog v2:
- Fix commit message and Kconfig help text spelling.
- Move driver from soc to the bus subsystem.
- Convert a simple EHB driver to the Baikal-T1 AXI-bus one.
- Use syscon regmap to access the AXI-bus erroneous address.
- Add interconnect reset line support.
- Remove probe-status info string printout.
- Use generic FIELD_{GET,PREP} macros instead of handwritten ones.
- Since the driver depends on the OF config we can remove of_match_ptr()
  macro utilization.
- Don't print error-message if no platform IRQ found. Just return an error.
- Select MFD_SYSCON config.

Changelog v3:
- Retrieve QoS registers by resource name "qos".
- Discard CONFIG_OF dependency since there is none at compile-time.
---
 drivers/bus/Kconfig   |  15 ++
 drivers/bus/Makefile  |   1 +
 drivers/bus/bt1-axi.c | 318 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 334 insertions(+)
 create mode 100644 drivers/bus/bt1-axi.c

Comments

kernel test robot May 27, 2020, 8:04 p.m. UTC | #1
Hi Serge,

I love your patch! Yet something to improve:

[auto build test ERROR on robh/for-next]
[also build test ERROR on char-misc/char-misc-testing staging/staging-testing linus/master v5.7-rc7 next-20200526]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Serge-Semin/bus-memory-Add-Baikal-T1-SoC-APB-AXI-L2-drivers/20200526-210837
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: i386-allyesconfig (attached as .config)
compiler: gcc-9 (Debian 9.3.0-13) 9.3.0
reproduce (this is a W=1 build):
        # save the attached .config to linux build tree
        make W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> drivers/bus/bt1-axi.c:301:34: error: array type has incomplete element type 'struct of_device_id'
301 | static const struct of_device_id bt1_axi_of_match[] = {
|                                  ^~~~~~~~~~~~~~~~
>> drivers/bus/bt1-axi.c:302:4: error: field name not in record or union initializer
302 |  { .compatible = "baikal,bt1-axi" },
|    ^
drivers/bus/bt1-axi.c:302:4: note: (near initialization for 'bt1_axi_of_match')
drivers/bus/bt1-axi.c:301:34: warning: 'bt1_axi_of_match' defined but not used [-Wunused-variable]
301 | static const struct of_device_id bt1_axi_of_match[] = {
|                                  ^~~~~~~~~~~~~~~~

vim +301 drivers/bus/bt1-axi.c

   300	
 > 301	static const struct of_device_id bt1_axi_of_match[] = {
 > 302		{ .compatible = "baikal,bt1-axi" },
   303		{ }
   304	};
   305	MODULE_DEVICE_TABLE(of, bt1_axi_of_match);
   306	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Andy Shevchenko May 27, 2020, 10 p.m. UTC | #2
On Tuesday, May 26, 2020, Serge Semin <Sergey.Semin@baikalelectronics.ru>
wrote:

> AXI3-bus is the main communication bus connecting all high-speed
> peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
> SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
> Interconnect (so called AXI Main Interconnect) routing IO requests from
> one SoC block to another. This driver provides a way to detect any bus
> protocol errors and device not responding situations by means of an
> embedded on top of the interconnect errors handler block (EHB). AXI
> Interconnect QoS arbitration tuning is currently unsupported.
> The bus doesn't provide a way to detect the interconnected devices,
> so they are supposed to be statically defined like by means of the
> simple-bus sub-nodes.



Few comments in case if you need a new version. Main point is about
sysfs_streq().


> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> Cc: Paul Burton <paulburton@kernel.org>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: linux-mips@vger.kernel.org
> Cc: soc@kernel.org
> Cc: devicetree@vger.kernel.org
>
> ---
>
> Changelog v2:
> - Fix commit message and Kconfig help text spelling.
> - Move driver from soc to the bus subsystem.
> - Convert a simple EHB driver to the Baikal-T1 AXI-bus one.
> - Use syscon regmap to access the AXI-bus erroneous address.
> - Add interconnect reset line support.
> - Remove probe-status info string printout.
> - Use generic FIELD_{GET,PREP} macros instead of handwritten ones.
> - Since the driver depends on the OF config we can remove of_match_ptr()
>   macro utilization.
> - Don't print error-message if no platform IRQ found. Just return an error.
> - Select MFD_SYSCON config.
>
> Changelog v3:
> - Retrieve QoS registers by resource name "qos".
> - Discard CONFIG_OF dependency since there is none at compile-time.
> ---
>  drivers/bus/Kconfig   |  15 ++
>  drivers/bus/Makefile  |   1 +
>  drivers/bus/bt1-axi.c | 318 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 334 insertions(+)
>  create mode 100644 drivers/bus/bt1-axi.c
>
> diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
> index 6d4e4497b59b..1080dd26e268 100644
> --- a/drivers/bus/Kconfig
> +++ b/drivers/bus/Kconfig
> @@ -29,6 +29,21 @@ config BRCMSTB_GISB_ARB
>           arbiter. This driver provides timeout and target abort error
> handling
>           and internal bus master decoding.
>
> +config BT1_AXI
> +       tristate "Baikal-T1 AXI-bus driver"
> +       depends on MIPS_BAIKAL_T1 || COMPILE_TEST
> +       select MFD_SYSCON
> +       help
> +         AXI3-bus is the main communication bus connecting all high-speed
> +         peripheral IP-cores with RAM controller and with MIPS P5600
> cores on
> +         Baikal-T1 SoC. Traffic arbitration is done by means of DW AMBA 3
> AXI
> +         Interconnect (so called AXI Main Interconnect) routing IO
> requests
> +         from one SoC block to another. This driver provides a way to
> detect
> +         any bus protocol errors and device not responding situations by
> +         means of an embedded on top of the interconnect errors handler
> +         block (EHB). AXI Interconnect QoS arbitration tuning is currently
> +         unsupported.
> +
>  config MOXTET
>         tristate "CZ.NIC Turris Mox module configuration bus"
>         depends on SPI_MASTER && OF
> diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
> index 05f32cd694a4..eaa25d171ebd 100644
> --- a/drivers/bus/Makefile
> +++ b/drivers/bus/Makefile
> @@ -13,6 +13,7 @@ obj-$(CONFIG_MOXTET)          += moxtet.o
>  # DPAA2 fsl-mc bus
>  obj-$(CONFIG_FSL_MC_BUS)       += fsl-mc/
>
> +obj-$(CONFIG_BT1_AXI)          += bt1-axi.o
>  obj-$(CONFIG_IMX_WEIM)         += imx-weim.o
>  obj-$(CONFIG_MIPS_CDMM)                += mips_cdmm.o
>  obj-$(CONFIG_MVEBU_MBUS)       += mvebu-mbus.o
> diff --git a/drivers/bus/bt1-axi.c b/drivers/bus/bt1-axi.c
> new file mode 100644
> index 000000000000..a52a5b9bbaf5
> --- /dev/null
> +++ b/drivers/bus/bt1-axi.c
> @@ -0,0 +1,318 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
> + *
> + * Authors:
> + *   Serge Semin <Sergey.Semin@baikalelectronics.ru>
> + *
> + * Baikal-T1 AXI-bus driver
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/bitfield.h>
> +#include <linux/device.h>
> +#include <linux/atomic.h>
> +#include <linux/regmap.h>
> +#include <linux/platform_device.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/interrupt.h>
> +#include <linux/nmi.h>
> +#include <linux/clk.h>
> +#include <linux/reset.h>
> +#include <linux/sysfs.h>
> +
> +#define BT1_AXI_WERRL                  0x110
> +#define BT1_AXI_WERRH                  0x114
> +#define BT1_AXI_WERRH_TYPE             BIT(23)
> +#define BT1_AXI_WERRH_ADDR_FLD         24
> +#define BT1_AXI_WERRH_ADDR_MASK                GENMASK(31,
> BT1_AXI_WERRH_ADDR_FLD)
> +
> +/*
> + * struct bt1_axi - Baikal-T1 AXI-bus private data
> + * @dev: Pointer to the device structure.
> + * @qos_regs: AXI Interconnect QoS tuning registers.
> + * @sys_regs: Baikal-T1 System Controller registers map.
> + * @irq: Errors IRQ number.
> + * @aclk: AXI reference clock.
> + * @arst: AXI Interconnect reset line.
> + * @count: Number of errors detected.
> + */
> +struct bt1_axi {
> +       struct device *dev;
> +
> +       void __iomem *qos_regs;
> +       struct regmap *sys_regs;
> +       int irq;
> +
> +       struct clk *aclk;
> +
> +       struct reset_control *arst;
> +
> +       atomic_t count;
> +};
> +
> +static irqreturn_t bt1_axi_isr(int irq, void *data)
> +{
> +       struct bt1_axi *axi = data;
> +       u32 low = 0, high = 0;
> +
> +       regmap_read(axi->sys_regs, BT1_AXI_WERRL, &low);
> +       regmap_read(axi->sys_regs, BT1_AXI_WERRH, &high);
> +
> +       dev_crit_ratelimited(axi->dev,
> +               "AXI-bus fault %d: %s at 0x%x%08x\n",
> +               atomic_inc_return(&axi->count),
> +               high & BT1_AXI_WERRH_TYPE ? "no slave" : "slave protocol
> error",
> +               high, low);
> +
> +       /*
> +        * Print backtrace on each CPU. This might be pointless if the
> fault
> +        * has happened on the same CPU as the IRQ handler is executed or
> +        * the other core proceeded further execution despite the error.
> +        * But if it's not, by looking at the trace we would get straight
> to
> +        * the cause of the problem.
> +        */
> +       trigger_all_cpu_backtrace();
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static void bt1_axi_clear_data(void *data)
> +{
> +       struct bt1_axi *axi = data;
> +       struct platform_device *pdev = to_platform_device(axi->dev);
> +
> +       platform_set_drvdata(pdev, NULL);


Doesn't device driver core do this already?


> +}
> +
> +static struct bt1_axi *bt1_axi_create_data(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct bt1_axi *axi;
> +       int ret;
> +
> +       axi = devm_kzalloc(dev, sizeof(*axi), GFP_KERNEL);
> +       if (!axi)
> +               return ERR_PTR(-ENOMEM);
> +
> +       ret = devm_add_action(dev, bt1_axi_clear_data, axi);
> +       if (ret) {
> +               dev_err(dev, "Can't add AXI EHB data clear action\n");
> +               return ERR_PTR(ret);
> +       }
> +
> +       axi->dev = dev;
> +       atomic_set(&axi->count, 0);
> +       platform_set_drvdata(pdev, axi);
> +
> +       return axi;
> +}
> +
> +static int bt1_axi_request_regs(struct bt1_axi *axi)
> +{
> +       struct platform_device *pdev = to_platform_device(axi->dev);
> +       struct device *dev = axi->dev;
> +
> +       axi->sys_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
> "syscon");
> +       if (IS_ERR(axi->sys_regs)) {
> +               dev_err(dev, "Couldn't find syscon registers\n");
> +               return PTR_ERR(axi->sys_regs);
> +       }
> +
> +       axi->qos_regs = devm_platform_ioremap_resource_byname(pdev,
> "qos");
> +       if (IS_ERR(axi->qos_regs)) {
> +               dev_err(dev, "Couldn't map AXI-bus QoS registers\n");



> +               return PTR_ERR(axi->qos_regs);
> +       }
> +
> +       return 0;


return PTR_ERR_OR_ZERO(...);?


> +}
> +
> +static int bt1_axi_request_rst(struct bt1_axi *axi)
> +{
> +       int ret;
> +
> +       axi->arst = devm_reset_control_get_optional_exclusive(axi->dev,
> "arst");
> +       if (IS_ERR(axi->arst)) {
> +               dev_warn(axi->dev, "Couldn't get reset control line\n");
> +               return PTR_ERR(axi->arst);
> +       }
> +
> +       ret = reset_control_deassert(axi->arst);
> +       if (ret)
> +               dev_err(axi->dev, "Failed to deassert the reset line\n");
> +
> +       return ret;
> +}
> +
> +static void bt1_axi_disable_clk(void *data)
> +{
> +       struct bt1_axi *axi = data;
> +
> +       clk_disable_unprepare(axi->aclk);
> +}
> +
> +static int bt1_axi_request_clk(struct bt1_axi *axi)
> +{
> +       int ret;
> +
> +       axi->aclk = devm_clk_get(axi->dev, "aclk");
> +       if (IS_ERR(axi->aclk)) {
> +               dev_err(axi->dev, "Couldn't get AXI Interconnect clock\n");
> +               return PTR_ERR(axi->aclk);
> +       }
> +
> +       ret = clk_prepare_enable(axi->aclk);
> +       if (ret) {
> +               dev_err(axi->dev, "Couldn't enable the AXI clock\n");
> +               return ret;
> +       }
> +
> +       ret = devm_add_action_or_reset(axi->dev, bt1_axi_disable_clk,
> axi);
> +       if (ret) {
> +               dev_err(axi->dev, "Can't add AXI clock disable action\n");



> +               return ret;
> +       }
> +
> +       return 0;


 return ret; ?

+}
> +
> +static int bt1_axi_request_irq(struct bt1_axi *axi)
> +{
> +       struct platform_device *pdev = to_platform_device(axi->dev);
> +       int ret;
> +
> +       axi->irq = platform_get_irq(pdev, 0);
> +       if (axi->irq < 0)
> +               return axi->irq;
> +
> +       ret = devm_request_irq(axi->dev, axi->irq, bt1_axi_isr,
> IRQF_SHARED,
> +                              "bt1-axi", axi);
> +       if (ret) {
> +               dev_err(axi->dev, "Couldn't request AXI EHB IRQ\n");




> +               return ret;
> +       }
> +
> +       return 0;


return ret; ?


> +}
> +
> +static ssize_t count_show(struct device *dev,
> +                         struct device_attribute *attr, char *buf)
> +{
> +       struct bt1_axi *axi = dev_get_drvdata(dev);
> +
> +       return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&axi->count));
> +}
> +static DEVICE_ATTR_RO(count);
> +
> +static int inject_error_show(struct device *dev, struct device_attribute
> *attr,
> +                            char *buf)
> +{
> +       return scnprintf(buf, PAGE_SIZE, "Error injection: bus
> unaligned\n");
> +}
> +
> +static int inject_error_store(struct device *dev,
> +                             struct device_attribute *attr,
> +                             const char *data, size_t count)
> +{
> +       struct bt1_axi *axi = dev_get_drvdata(dev);
> +
> +       /*
> +        * Performing unaligned read from the memory will cause the CM2 bus
> +        * error while unaligned writing - the AXI bus write error handled
> +        * by this driver.
> +        */
> +       if (!strncmp(data, "bus", 3))
> +               readb(axi->qos_regs);
> +       else if (!strncmp(data, "unaligned", 9))
> +               writeb(0, axi->qos_regs);
> +       else
> +               return -EINVAL;


sysfs_streq() / sysfs_match_string() ?


> +
> +       return count;
> +}
> +static DEVICE_ATTR_RW(inject_error);
> +
> +static struct attribute *bt1_axi_sysfs_attrs[] = {
> +       &dev_attr_count.attr,
> +       &dev_attr_inject_error.attr,
> +       NULL
> +};
> +ATTRIBUTE_GROUPS(bt1_axi_sysfs);
> +
> +static void bt1_axi_remove_sysfs(void *data)
> +{
> +       struct bt1_axi *axi = data;
> +
> +       device_remove_groups(axi->dev, bt1_axi_sysfs_groups);
> +}
> +
> +static int bt1_axi_init_sysfs(struct bt1_axi *axi)
> +{
> +       int ret;
> +
> +       ret = device_add_groups(axi->dev, bt1_axi_sysfs_groups);
> +       if (ret) {
> +               dev_err(axi->dev, "Failed to add sysfs files group\n");
> +               return ret;
> +       }
> +
> +       ret = devm_add_action_or_reset(axi->dev, bt1_axi_remove_sysfs,
> axi);
> +       if (ret)
> +               dev_err(axi->dev, "Can't add AXI EHB sysfs remove
> action\n");
> +
> +       return ret;
> +}
> +
> +static int bt1_axi_probe(struct platform_device *pdev)
> +{
> +       struct bt1_axi *axi;
> +       int ret;
> +
> +       axi = bt1_axi_create_data(pdev);
> +       if (IS_ERR(axi))
> +               return PTR_ERR(axi);
> +
> +       ret = bt1_axi_request_regs(axi);
> +       if (ret)
> +               return ret;
> +
> +       ret = bt1_axi_request_rst(axi);
> +       if (ret)
> +               return ret;
> +
> +       ret = bt1_axi_request_clk(axi);
> +       if (ret)
> +               return ret;
> +
> +       ret = bt1_axi_request_irq(axi);
> +       if (ret)
> +               return ret;
> +
> +       ret = bt1_axi_init_sysfs(axi);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id bt1_axi_of_match[] = {
> +       { .compatible = "baikal,bt1-axi" },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, bt1_axi_of_match);
> +
> +static struct platform_driver bt1_axi_driver = {
> +       .probe = bt1_axi_probe,
> +       .driver = {
> +               .name = "bt1-axi",
> +               .of_match_table = bt1_axi_of_match
> +       }
> +};
> +module_platform_driver(bt1_axi_driver);
> +
> +MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
> +MODULE_DESCRIPTION("Baikal-T1 AXI-bus driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.26.2
>
>
Andy Shevchenko May 27, 2020, 10:04 p.m. UTC | #3
On Wednesday, May 27, 2020, kbuild test robot <lkp@intel.com> wrote:

> Hi Serge,
>
> I love your patch! Yet something to improve:
>
> [auto build test ERROR on robh/for-next]
> [also build test ERROR on char-misc/char-misc-testing
> staging/staging-testing linus/master v5.7-rc7 next-20200526]
> [if your patch is applied to the wrong git tree, please drop us a note to
> help
> improve the system. BTW, we also suggest to use '--base' option to specify
> the
> base tree in git format-patch, please see https://stackoverflow.com/a/
> 37406982]
>
> url:    https://github.com/0day-ci/linux/commits/Serge-Semin/bus-
> memory-Add-Baikal-T1-SoC-APB-AXI-L2-drivers/20200526-210837
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
> for-next
> config: i386-allyesconfig (attached as .config)
> compiler: gcc-9 (Debian 9.3.0-13) 9.3.0
> reproduce (this is a W=1 build):
>         # save the attached .config to linux build tree
>         make W=1 ARCH=i386
>
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kbuild test robot <lkp@intel.com>
>
> All errors (new ones prefixed by >>, old ones prefixed by <<):
>
> >> drivers/bus/bt1-axi.c:301:34: error: array type has incomplete element
> type 'struct of_device_id'
> 301 | static const struct of_device_id bt1_axi_of_match[] = {
> |                                  ^~~~~~~~~~~~~~~~
> >> drivers/bus/bt1-axi.c:302:4: error: field name not in record or union
> initializer
> 302 |  { .compatible = "baikal,bt1-axi" },
> |    ^
> drivers/bus/bt1-axi.c:302:4: note: (near initialization for
> 'bt1_axi_of_match')
> drivers/bus/bt1-axi.c:301:34: warning: 'bt1_axi_of_match' defined but not
> used [-Wunused-variable]
> 301 | static const struct of_device_id bt1_axi_of_match[] = {
> |                                  ^~~~~~~~~~~~~~~~
>
>
I wish kbuild bot be intelligent for such cases ;)

#include <linux/mod_devicetable.h>
 will fix this.

vim +301 drivers/bus/bt1-axi.c
>
>    300
>  > 301  static const struct of_device_id bt1_axi_of_match[] = {
>  > 302          { .compatible = "baikal,bt1-axi" },
>    303          { }
>    304  };
>    305  MODULE_DEVICE_TABLE(of, bt1_axi_of_match);
>    306
>
> ---
> 0-DAY CI Kernel Test Service, Intel Corporation
> https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
>
kernel test robot May 27, 2020, 10:31 p.m. UTC | #4
Hi Serge,

I love your patch! Yet something to improve:

[auto build test ERROR on robh/for-next]
[also build test ERROR on char-misc/char-misc-testing staging/staging-testing linus/master v5.7-rc7 next-20200526]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Serge-Semin/bus-memory-Add-Baikal-T1-SoC-APB-AXI-L2-drivers/20200526-210837
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: sparc-allyesconfig (attached as .config)
compiler: sparc64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=sparc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>, old ones prefixed by <<):

drivers/bus/bt1-axi.c: In function 'inject_error_store':
drivers/bus/bt1-axi.c:228:3: error: implicit declaration of function 'readb' [-Werror=implicit-function-declaration]
228 |   readb(axi->qos_regs);
|   ^~~~~
drivers/bus/bt1-axi.c:230:3: error: implicit declaration of function 'writeb' [-Werror=implicit-function-declaration]
230 |   writeb(0, axi->qos_regs);
|   ^~~~~~
In file included from include/linux/kobject.h:20,
from include/linux/module.h:20,
from drivers/bus/bt1-axi.c:12:
drivers/bus/bt1-axi.c: At top level:
>> drivers/bus/bt1-axi.c:236:23: error: initialization of 'ssize_t (*)(struct device *, struct device_attribute *, char *)' {aka 'long int (*)(struct device *, struct device_attribute *, char *)'} from incompatible pointer type 'int (*)(struct device *, struct device_attribute *, char *)' [-Werror=incompatible-pointer-types]
236 | static DEVICE_ATTR_RW(inject_error);
|                       ^~~~~~~~~~~~
include/linux/sysfs.h:104:10: note: in definition of macro '__ATTR'
104 |  .show = _show,               |          ^~~~~
>> include/linux/device.h:130:45: note: in expansion of macro '__ATTR_RW'
130 |  struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
|                                             ^~~~~~~~~
>> drivers/bus/bt1-axi.c:236:8: note: in expansion of macro 'DEVICE_ATTR_RW'
236 | static DEVICE_ATTR_RW(inject_error);
|        ^~~~~~~~~~~~~~
drivers/bus/bt1-axi.c:236:23: note: (near initialization for 'dev_attr_inject_error.show')
236 | static DEVICE_ATTR_RW(inject_error);
|                       ^~~~~~~~~~~~
include/linux/sysfs.h:104:10: note: in definition of macro '__ATTR'
104 |  .show = _show,               |          ^~~~~
>> include/linux/device.h:130:45: note: in expansion of macro '__ATTR_RW'
130 |  struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
|                                             ^~~~~~~~~
>> drivers/bus/bt1-axi.c:236:8: note: in expansion of macro 'DEVICE_ATTR_RW'
236 | static DEVICE_ATTR_RW(inject_error);
|        ^~~~~~~~~~~~~~
>> drivers/bus/bt1-axi.c:236:23: error: initialization of 'ssize_t (*)(struct device *, struct device_attribute *, const char *, size_t)' {aka 'long int (*)(struct device *, struct device_attribute *, const char *, long unsigned int)'} from incompatible pointer type 'int (*)(struct device *, struct device_attribute *, const char *, size_t)' {aka 'int (*)(struct device *, struct device_attribute *, const char *, long unsigned int)'} [-Werror=incompatible-pointer-types]
236 | static DEVICE_ATTR_RW(inject_error);
|                       ^~~~~~~~~~~~
include/linux/sysfs.h:105:11: note: in definition of macro '__ATTR'
105 |  .store = _store,               |           ^~~~~~
>> include/linux/device.h:130:45: note: in expansion of macro '__ATTR_RW'
130 |  struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
|                                             ^~~~~~~~~
>> drivers/bus/bt1-axi.c:236:8: note: in expansion of macro 'DEVICE_ATTR_RW'
236 | static DEVICE_ATTR_RW(inject_error);
|        ^~~~~~~~~~~~~~
drivers/bus/bt1-axi.c:236:23: note: (near initialization for 'dev_attr_inject_error.store')
236 | static DEVICE_ATTR_RW(inject_error);
|                       ^~~~~~~~~~~~
include/linux/sysfs.h:105:11: note: in definition of macro '__ATTR'
105 |  .store = _store,               |           ^~~~~~
>> include/linux/device.h:130:45: note: in expansion of macro '__ATTR_RW'
130 |  struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
|                                             ^~~~~~~~~
>> drivers/bus/bt1-axi.c:236:8: note: in expansion of macro 'DEVICE_ATTR_RW'
236 | static DEVICE_ATTR_RW(inject_error);
|        ^~~~~~~~~~~~~~
cc1: some warnings being treated as errors

vim +236 drivers/bus/bt1-axi.c

   215	
   216	static int inject_error_store(struct device *dev,
   217				      struct device_attribute *attr,
   218				      const char *data, size_t count)
   219	{
   220		struct bt1_axi *axi = dev_get_drvdata(dev);
   221	
   222		/*
   223		 * Performing unaligned read from the memory will cause the CM2 bus
   224		 * error while unaligned writing - the AXI bus write error handled
   225		 * by this driver.
   226		 */
   227		if (!strncmp(data, "bus", 3))
   228			readb(axi->qos_regs);
   229		else if (!strncmp(data, "unaligned", 9))
   230			writeb(0, axi->qos_regs);
   231		else
   232			return -EINVAL;
   233	
   234		return count;
   235	}
 > 236	static DEVICE_ATTR_RW(inject_error);
   237	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Arnd Bergmann May 28, 2020, 12:14 p.m. UTC | #5
On Thu, May 28, 2020 at 12:01 AM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Tuesday, May 26, 2020, Serge Semin <Sergey.Semin@baikalelectronics.ru> wrote:
>>
>> AXI3-bus is the main communication bus connecting all high-speed
>> peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
>> SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
>> Interconnect (so called AXI Main Interconnect) routing IO requests from
>> one SoC block to another. This driver provides a way to detect any bus
>> protocol errors and device not responding situations by means of an
>> embedded on top of the interconnect errors handler block (EHB). AXI
>> Interconnect QoS arbitration tuning is currently unsupported.
>> The bus doesn't provide a way to detect the interconnected devices,
>> so they are supposed to be statically defined like by means of the
>> simple-bus sub-nodes.
>
>
>
> Few comments in case if you need a new version. Main point is about sysfs_streq().

I've applied the patch now and folded in fixes for the build warnings and
errors pointed out by the test robot, but I did not include the changes you
suggested.

Serge, could you send a follow-up patch to address those?

     Arnd
Serge Semin May 28, 2020, 12:27 p.m. UTC | #6
On Thu, May 28, 2020 at 02:14:58PM +0200, Arnd Bergmann wrote:
> On Thu, May 28, 2020 at 12:01 AM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
> > On Tuesday, May 26, 2020, Serge Semin <Sergey.Semin@baikalelectronics.ru> wrote:
> >>
> >> AXI3-bus is the main communication bus connecting all high-speed
> >> peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
> >> SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
> >> Interconnect (so called AXI Main Interconnect) routing IO requests from
> >> one SoC block to another. This driver provides a way to detect any bus
> >> protocol errors and device not responding situations by means of an
> >> embedded on top of the interconnect errors handler block (EHB). AXI
> >> Interconnect QoS arbitration tuning is currently unsupported.
> >> The bus doesn't provide a way to detect the interconnected devices,
> >> so they are supposed to be statically defined like by means of the
> >> simple-bus sub-nodes.
> >
> >
> >
> > Few comments in case if you need a new version. Main point is about sysfs_streq().
> 
> I've applied the patch now and folded in fixes for the build warnings and
> errors pointed out by the test robot, but I did not include the changes you
> suggested.

Are you saying that the build-errors and warnings have already been fixed by
you, right? If so could you please give me a link to the repo with those
commits, so I'd work with the up-to-date code?

> 
> Serge, could you send a follow-up patch to address those?

Ok.

-Sergey

> 
>      Arnd
Serge Semin May 28, 2020, 12:37 p.m. UTC | #7
On Thu, May 28, 2020 at 02:14:58PM +0200, Arnd Bergmann wrote:
> On Thu, May 28, 2020 at 12:01 AM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
> > On Tuesday, May 26, 2020, Serge Semin <Sergey.Semin@baikalelectronics.ru> wrote:
> >>
> >> AXI3-bus is the main communication bus connecting all high-speed
> >> peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
> >> SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
> >> Interconnect (so called AXI Main Interconnect) routing IO requests from
> >> one SoC block to another. This driver provides a way to detect any bus
> >> protocol errors and device not responding situations by means of an
> >> embedded on top of the interconnect errors handler block (EHB). AXI
> >> Interconnect QoS arbitration tuning is currently unsupported.
> >> The bus doesn't provide a way to detect the interconnected devices,
> >> so they are supposed to be statically defined like by means of the
> >> simple-bus sub-nodes.
> >
> >
> >
> > Few comments in case if you need a new version. Main point is about sysfs_streq().
> 
> I've applied the patch now and folded in fixes for the build warnings and
> errors pointed out by the test robot, but I did not include the changes you
> suggested.

On the other hand if you haven't pushed the patches to the public repo yet,
I could just resend the series. So have you?

-Sergey

> 
> Serge, could you send a follow-up patch to address those?


> 
>      Arnd
Arnd Bergmann May 28, 2020, 12:44 p.m. UTC | #8
On Thu, May 28, 2020 at 2:27 PM Serge Semin
<Sergey.Semin@baikalelectronics.ru> wrote:
>
> On Thu, May 28, 2020 at 02:14:58PM +0200, Arnd Bergmann wrote:
> > On Thu, May 28, 2020 at 12:01 AM Andy Shevchenko
> > <andy.shevchenko@gmail.com> wrote:
> > > On Tuesday, May 26, 2020, Serge Semin <Sergey.Semin@baikalelectronics.ru> wrote:
> > >>
> > >> AXI3-bus is the main communication bus connecting all high-speed
> > >> peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
> > >> SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
> > >> Interconnect (so called AXI Main Interconnect) routing IO requests from
> > >> one SoC block to another. This driver provides a way to detect any bus
> > >> protocol errors and device not responding situations by means of an
> > >> embedded on top of the interconnect errors handler block (EHB). AXI
> > >> Interconnect QoS arbitration tuning is currently unsupported.
> > >> The bus doesn't provide a way to detect the interconnected devices,
> > >> so they are supposed to be statically defined like by means of the
> > >> simple-bus sub-nodes.
> > >
> > >
> > >
> > > Few comments in case if you need a new version. Main point is about sysfs_streq().
> >
> > I've applied the patch now and folded in fixes for the build warnings and
> > errors pointed out by the test robot, but I did not include the changes you
> > suggested.
>
> Are you saying that the build-errors and warnings have already been fixed by
> you, right? If so could you please give me a link to the repo with those
> commits, so I'd work with the up-to-date code?

I've pushed it to https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/,

I made a local "baikal/drivers" branch with just your patches, updated
to address the build reports. This is merged into the "arm/drivers"
branch that contains all driver specific changes across all SoCs and
this is what I'll send to Linus next week.

There is also the "for-next" branch that contains all arm/* branches,
and this is what gets pulled into linux-next, so your patches will show
up there tomorrow as well.

You can normally check the status of any submission to soc@kernel.org
at https://patchwork.kernel.org/project/linux-soc/list/, but it seems that
has not picked up the status yet, and I'll have to update it manually.

       Arnd
Serge Semin May 28, 2020, 1 p.m. UTC | #9
On Thu, May 28, 2020 at 02:44:32PM +0200, Arnd Bergmann wrote:
> On Thu, May 28, 2020 at 2:27 PM Serge Semin
> <Sergey.Semin@baikalelectronics.ru> wrote:
> >
> > On Thu, May 28, 2020 at 02:14:58PM +0200, Arnd Bergmann wrote:
> > > On Thu, May 28, 2020 at 12:01 AM Andy Shevchenko
> > > <andy.shevchenko@gmail.com> wrote:
> > > > On Tuesday, May 26, 2020, Serge Semin <Sergey.Semin@baikalelectronics.ru> wrote:
> > > >>
> > > >> AXI3-bus is the main communication bus connecting all high-speed
> > > >> peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
> > > >> SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
> > > >> Interconnect (so called AXI Main Interconnect) routing IO requests from
> > > >> one SoC block to another. This driver provides a way to detect any bus
> > > >> protocol errors and device not responding situations by means of an
> > > >> embedded on top of the interconnect errors handler block (EHB). AXI
> > > >> Interconnect QoS arbitration tuning is currently unsupported.
> > > >> The bus doesn't provide a way to detect the interconnected devices,
> > > >> so they are supposed to be statically defined like by means of the
> > > >> simple-bus sub-nodes.
> > > >
> > > >
> > > >
> > > > Few comments in case if you need a new version. Main point is about sysfs_streq().
> > >
> > > I've applied the patch now and folded in fixes for the build warnings and
> > > errors pointed out by the test robot, but I did not include the changes you
> > > suggested.
> >
> > Are you saying that the build-errors and warnings have already been fixed by
> > you, right? If so could you please give me a link to the repo with those
> > commits, so I'd work with the up-to-date code?
> 

> I've pushed it to https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/,
> 
> I made a local "baikal/drivers" branch with just your patches, updated
> to address the build reports. This is merged into the "arm/drivers"
> branch that contains all driver specific changes across all SoCs and
> this is what I'll send to Linus next week.
> 
> There is also the "for-next" branch that contains all arm/* branches,
> and this is what gets pulled into linux-next, so your patches will show
> up there tomorrow as well.

I see. Thanks for explanation. I've monitored the soc/soc.git a few minutes
ago, but the gitolite web-interface showed me that the last update was made
9 hours ago. So I thought you could be using some another repo. Now I see
the fresh updates and the drivers being merges.

I'll address the Andy's comments and send a follow-up patches with fixes shortly
today.

BTW I don't see the next commit:
[PATCH v3 3/6] dt-bindings: memory: Add Baikal-T1 L2-cache Control Block binding
in the baikal/drivers, so the l2-ctl binding hasn't been merged into the
arm/drivers and for-next branches. You must have missed that patch. Could you
please make sure it's also merged in?

Thanks
-Sergey

> 
> You can normally check the status of any submission to soc@kernel.org
> at https://patchwork.kernel.org/project/linux-soc/list/, but it seems that
> has not picked up the status yet, and I'll have to update it manually.
> 
>        Arnd
Serge Semin May 28, 2020, 1:40 p.m. UTC | #10
On Thu, May 28, 2020 at 01:00:57AM +0300, Andy Shevchenko wrote:
> On Tuesday, May 26, 2020, Serge Semin <Sergey.Semin@baikalelectronics.ru>
> wrote:
> 
> > AXI3-bus is the main communication bus connecting all high-speed
> > peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
> > SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
> > Interconnect (so called AXI Main Interconnect) routing IO requests from
> > one SoC block to another. This driver provides a way to detect any bus
> > protocol errors and device not responding situations by means of an
> > embedded on top of the interconnect errors handler block (EHB). AXI
> > Interconnect QoS arbitration tuning is currently unsupported.
> > The bus doesn't provide a way to detect the interconnected devices,
> > so they are supposed to be statically defined like by means of the
> > simple-bus sub-nodes.
> 
> 
> 
> Few comments in case if you need a new version. Main point is about
> sysfs_streq().

Hello, Andy. Thanks for your comments. I'll address most of them in a follow-up
patches. See just one note below.

> 
> 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> > Cc: Paul Burton <paulburton@kernel.org>
> > Cc: Olof Johansson <olof@lixom.net>
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: linux-mips@vger.kernel.org
> > Cc: soc@kernel.org
> > Cc: devicetree@vger.kernel.org
> >

[nip]

> > +
> > +static void bt1_axi_clear_data(void *data)
> > +{
> > +       struct bt1_axi *axi = data;
> > +       struct platform_device *pdev = to_platform_device(axi->dev);
> > +
> > +       platform_set_drvdata(pdev, NULL);
> 
> 

> Doesn't device driver core do this already?

It doesn't on remove. This cleanups the drvdata pointer when the driver is
unloaded at the moment of remove() callback calling. This is a good
practice to leave the device the same as it has been before usage including
the pointer value. In this case if theoretically someone (though very
unlikely, but anyway) would try to use the pointer without having it
initialized, the NULL-dereference would pop up, otherwise we may
corrupt someones memory, which is very nasty.

-Sergey
Andy Shevchenko May 28, 2020, 1:51 p.m. UTC | #11
On Thu, May 28, 2020 at 4:40 PM Serge Semin
<Sergey.Semin@baikalelectronics.ru> wrote:
>
> On Thu, May 28, 2020 at 01:00:57AM +0300, Andy Shevchenko wrote:
> > On Tuesday, May 26, 2020, Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > wrote:
> >
> > > AXI3-bus is the main communication bus connecting all high-speed
> > > peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
> > > SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
> > > Interconnect (so called AXI Main Interconnect) routing IO requests from
> > > one SoC block to another. This driver provides a way to detect any bus
> > > protocol errors and device not responding situations by means of an
> > > embedded on top of the interconnect errors handler block (EHB). AXI
> > > Interconnect QoS arbitration tuning is currently unsupported.
> > > The bus doesn't provide a way to detect the interconnected devices,
> > > so they are supposed to be statically defined like by means of the
> > > simple-bus sub-nodes.
> >
> >
> >
> > Few comments in case if you need a new version. Main point is about
> > sysfs_streq().
>
> Hello, Andy. Thanks for your comments. I'll address most of them in a follow-up
> patches. See just one note below.
>
> >
> >
> > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > > Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> > > Cc: Paul Burton <paulburton@kernel.org>
> > > Cc: Olof Johansson <olof@lixom.net>
> > > Cc: Rob Herring <robh+dt@kernel.org>
> > > Cc: linux-mips@vger.kernel.org
> > > Cc: soc@kernel.org
> > > Cc: devicetree@vger.kernel.org
> > >
>
> [nip]
>
> > > +
> > > +static void bt1_axi_clear_data(void *data)
> > > +{
> > > +       struct bt1_axi *axi = data;
> > > +       struct platform_device *pdev = to_platform_device(axi->dev);
> > > +
> > > +       platform_set_drvdata(pdev, NULL);
> >
> >
>
> > Doesn't device driver core do this already?
>
> It doesn't on remove.

__device_release_driver() calls dev_set_drvdata(dev, NULL);
What did I miss?

> This cleanups the drvdata pointer when the driver is
> unloaded at the moment of remove() callback calling. This is a good
> practice to leave the device the same as it has been before usage including
> the pointer value. In this case if theoretically someone (though very
> unlikely, but anyway) would try to use the pointer without having it
> initialized, the NULL-dereference would pop up, otherwise we may
> corrupt someones memory, which is very nasty.

The above is right and I agree with.
Serge Semin May 28, 2020, 1:56 p.m. UTC | #12
On Thu, May 28, 2020 at 04:51:03PM +0300, Andy Shevchenko wrote:
> On Thu, May 28, 2020 at 4:40 PM Serge Semin
> <Sergey.Semin@baikalelectronics.ru> wrote:
> >
> > On Thu, May 28, 2020 at 01:00:57AM +0300, Andy Shevchenko wrote:
> > > On Tuesday, May 26, 2020, Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > > wrote:
> > >
> > > > AXI3-bus is the main communication bus connecting all high-speed
> > > > peripheral IP-cores with RAM controller and MIPS P5600 cores on Baikal-T1
> > > > SoC. Bus traffic arbitration is done by means of DW AMBA 3 AXI
> > > > Interconnect (so called AXI Main Interconnect) routing IO requests from
> > > > one SoC block to another. This driver provides a way to detect any bus
> > > > protocol errors and device not responding situations by means of an
> > > > embedded on top of the interconnect errors handler block (EHB). AXI
> > > > Interconnect QoS arbitration tuning is currently unsupported.
> > > > The bus doesn't provide a way to detect the interconnected devices,
> > > > so they are supposed to be statically defined like by means of the
> > > > simple-bus sub-nodes.
> > >
> > >
> > >
> > > Few comments in case if you need a new version. Main point is about
> > > sysfs_streq().
> >
> > Hello, Andy. Thanks for your comments. I'll address most of them in a follow-up
> > patches. See just one note below.
> >
> > >
> > >
> > > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > > > Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> > > > Cc: Paul Burton <paulburton@kernel.org>
> > > > Cc: Olof Johansson <olof@lixom.net>
> > > > Cc: Rob Herring <robh+dt@kernel.org>
> > > > Cc: linux-mips@vger.kernel.org
> > > > Cc: soc@kernel.org
> > > > Cc: devicetree@vger.kernel.org
> > > >
> >
> > [nip]
> >
> > > > +
> > > > +static void bt1_axi_clear_data(void *data)
> > > > +{
> > > > +       struct bt1_axi *axi = data;
> > > > +       struct platform_device *pdev = to_platform_device(axi->dev);
> > > > +
> > > > +       platform_set_drvdata(pdev, NULL);
> > >
> > >
> >
> > > Doesn't device driver core do this already?
> >
> > It doesn't on remove.
> 

> __device_release_driver() calls dev_set_drvdata(dev, NULL);
> What did I miss?
> 
> > This cleanups the drvdata pointer when the driver is
> > unloaded at the moment of remove() callback calling. This is a good
> > practice to leave the device the same as it has been before usage including
> > the pointer value. In this case if theoretically someone (though very
> > unlikely, but anyway) would try to use the pointer without having it
> > initialized, the NULL-dereference would pop up, otherwise we may
> > corrupt someones memory, which is very nasty.
> 
> The above is right and I agree with.

Hm, good point. I missed that part of __device_release_driver(). So do you
suggest to remove that cleanup?

-Sergey

> 
> -- 
> With Best Regards,
> Andy Shevchenko
diff mbox series

Patch

diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 6d4e4497b59b..1080dd26e268 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -29,6 +29,21 @@  config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config BT1_AXI
+	tristate "Baikal-T1 AXI-bus driver"
+	depends on MIPS_BAIKAL_T1 || COMPILE_TEST
+	select MFD_SYSCON
+	help
+	  AXI3-bus is the main communication bus connecting all high-speed
+	  peripheral IP-cores with RAM controller and with MIPS P5600 cores on
+	  Baikal-T1 SoC. Traffic arbitration is done by means of DW AMBA 3 AXI
+	  Interconnect (so called AXI Main Interconnect) routing IO requests
+	  from one SoC block to another. This driver provides a way to detect
+	  any bus protocol errors and device not responding situations by
+	  means of an embedded on top of the interconnect errors handler
+	  block (EHB). AXI Interconnect QoS arbitration tuning is currently
+	  unsupported.
+
 config MOXTET
 	tristate "CZ.NIC Turris Mox module configuration bus"
 	depends on SPI_MASTER && OF
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 05f32cd694a4..eaa25d171ebd 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -13,6 +13,7 @@  obj-$(CONFIG_MOXTET)		+= moxtet.o
 # DPAA2 fsl-mc bus
 obj-$(CONFIG_FSL_MC_BUS)	+= fsl-mc/
 
+obj-$(CONFIG_BT1_AXI)		+= bt1-axi.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
 obj-$(CONFIG_MVEBU_MBUS) 	+= mvebu-mbus.o
diff --git a/drivers/bus/bt1-axi.c b/drivers/bus/bt1-axi.c
new file mode 100644
index 000000000000..a52a5b9bbaf5
--- /dev/null
+++ b/drivers/bus/bt1-axi.c
@@ -0,0 +1,318 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
+ *
+ * Authors:
+ *   Serge Semin <Sergey.Semin@baikalelectronics.ru>
+ *
+ * Baikal-T1 AXI-bus driver
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/atomic.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/interrupt.h>
+#include <linux/nmi.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/sysfs.h>
+
+#define BT1_AXI_WERRL			0x110
+#define BT1_AXI_WERRH			0x114
+#define BT1_AXI_WERRH_TYPE		BIT(23)
+#define BT1_AXI_WERRH_ADDR_FLD		24
+#define BT1_AXI_WERRH_ADDR_MASK		GENMASK(31, BT1_AXI_WERRH_ADDR_FLD)
+
+/*
+ * struct bt1_axi - Baikal-T1 AXI-bus private data
+ * @dev: Pointer to the device structure.
+ * @qos_regs: AXI Interconnect QoS tuning registers.
+ * @sys_regs: Baikal-T1 System Controller registers map.
+ * @irq: Errors IRQ number.
+ * @aclk: AXI reference clock.
+ * @arst: AXI Interconnect reset line.
+ * @count: Number of errors detected.
+ */
+struct bt1_axi {
+	struct device *dev;
+
+	void __iomem *qos_regs;
+	struct regmap *sys_regs;
+	int irq;
+
+	struct clk *aclk;
+
+	struct reset_control *arst;
+
+	atomic_t count;
+};
+
+static irqreturn_t bt1_axi_isr(int irq, void *data)
+{
+	struct bt1_axi *axi = data;
+	u32 low = 0, high = 0;
+
+	regmap_read(axi->sys_regs, BT1_AXI_WERRL, &low);
+	regmap_read(axi->sys_regs, BT1_AXI_WERRH, &high);
+
+	dev_crit_ratelimited(axi->dev,
+		"AXI-bus fault %d: %s at 0x%x%08x\n",
+		atomic_inc_return(&axi->count),
+		high & BT1_AXI_WERRH_TYPE ? "no slave" : "slave protocol error",
+		high, low);
+
+	/*
+	 * Print backtrace on each CPU. This might be pointless if the fault
+	 * has happened on the same CPU as the IRQ handler is executed or
+	 * the other core proceeded further execution despite the error.
+	 * But if it's not, by looking at the trace we would get straight to
+	 * the cause of the problem.
+	 */
+	trigger_all_cpu_backtrace();
+
+	return IRQ_HANDLED;
+}
+
+static void bt1_axi_clear_data(void *data)
+{
+	struct bt1_axi *axi = data;
+	struct platform_device *pdev = to_platform_device(axi->dev);
+
+	platform_set_drvdata(pdev, NULL);
+}
+
+static struct bt1_axi *bt1_axi_create_data(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct bt1_axi *axi;
+	int ret;
+
+	axi = devm_kzalloc(dev, sizeof(*axi), GFP_KERNEL);
+	if (!axi)
+		return ERR_PTR(-ENOMEM);
+
+	ret = devm_add_action(dev, bt1_axi_clear_data, axi);
+	if (ret) {
+		dev_err(dev, "Can't add AXI EHB data clear action\n");
+		return ERR_PTR(ret);
+	}
+
+	axi->dev = dev;
+	atomic_set(&axi->count, 0);
+	platform_set_drvdata(pdev, axi);
+
+	return axi;
+}
+
+static int bt1_axi_request_regs(struct bt1_axi *axi)
+{
+	struct platform_device *pdev = to_platform_device(axi->dev);
+	struct device *dev = axi->dev;
+
+	axi->sys_regs = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
+	if (IS_ERR(axi->sys_regs)) {
+		dev_err(dev, "Couldn't find syscon registers\n");
+		return PTR_ERR(axi->sys_regs);
+	}
+
+	axi->qos_regs = devm_platform_ioremap_resource_byname(pdev, "qos");
+	if (IS_ERR(axi->qos_regs)) {
+		dev_err(dev, "Couldn't map AXI-bus QoS registers\n");
+		return PTR_ERR(axi->qos_regs);
+	}
+
+	return 0;
+}
+
+static int bt1_axi_request_rst(struct bt1_axi *axi)
+{
+	int ret;
+
+	axi->arst = devm_reset_control_get_optional_exclusive(axi->dev, "arst");
+	if (IS_ERR(axi->arst)) {
+		dev_warn(axi->dev, "Couldn't get reset control line\n");
+		return PTR_ERR(axi->arst);
+	}
+
+	ret = reset_control_deassert(axi->arst);
+	if (ret)
+		dev_err(axi->dev, "Failed to deassert the reset line\n");
+
+	return ret;
+}
+
+static void bt1_axi_disable_clk(void *data)
+{
+	struct bt1_axi *axi = data;
+
+	clk_disable_unprepare(axi->aclk);
+}
+
+static int bt1_axi_request_clk(struct bt1_axi *axi)
+{
+	int ret;
+
+	axi->aclk = devm_clk_get(axi->dev, "aclk");
+	if (IS_ERR(axi->aclk)) {
+		dev_err(axi->dev, "Couldn't get AXI Interconnect clock\n");
+		return PTR_ERR(axi->aclk);
+	}
+
+	ret = clk_prepare_enable(axi->aclk);
+	if (ret) {
+		dev_err(axi->dev, "Couldn't enable the AXI clock\n");
+		return ret;
+	}
+
+	ret = devm_add_action_or_reset(axi->dev, bt1_axi_disable_clk, axi);
+	if (ret) {
+		dev_err(axi->dev, "Can't add AXI clock disable action\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int bt1_axi_request_irq(struct bt1_axi *axi)
+{
+	struct platform_device *pdev = to_platform_device(axi->dev);
+	int ret;
+
+	axi->irq = platform_get_irq(pdev, 0);
+	if (axi->irq < 0)
+		return axi->irq;
+
+	ret = devm_request_irq(axi->dev, axi->irq, bt1_axi_isr, IRQF_SHARED,
+			       "bt1-axi", axi);
+	if (ret) {
+		dev_err(axi->dev, "Couldn't request AXI EHB IRQ\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static ssize_t count_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct bt1_axi *axi = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&axi->count));
+}
+static DEVICE_ATTR_RO(count);
+
+static int inject_error_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "Error injection: bus unaligned\n");
+}
+
+static int inject_error_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *data, size_t count)
+{
+	struct bt1_axi *axi = dev_get_drvdata(dev);
+
+	/*
+	 * Performing unaligned read from the memory will cause the CM2 bus
+	 * error while unaligned writing - the AXI bus write error handled
+	 * by this driver.
+	 */
+	if (!strncmp(data, "bus", 3))
+		readb(axi->qos_regs);
+	else if (!strncmp(data, "unaligned", 9))
+		writeb(0, axi->qos_regs);
+	else
+		return -EINVAL;
+
+	return count;
+}
+static DEVICE_ATTR_RW(inject_error);
+
+static struct attribute *bt1_axi_sysfs_attrs[] = {
+	&dev_attr_count.attr,
+	&dev_attr_inject_error.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(bt1_axi_sysfs);
+
+static void bt1_axi_remove_sysfs(void *data)
+{
+	struct bt1_axi *axi = data;
+
+	device_remove_groups(axi->dev, bt1_axi_sysfs_groups);
+}
+
+static int bt1_axi_init_sysfs(struct bt1_axi *axi)
+{
+	int ret;
+
+	ret = device_add_groups(axi->dev, bt1_axi_sysfs_groups);
+	if (ret) {
+		dev_err(axi->dev, "Failed to add sysfs files group\n");
+		return ret;
+	}
+
+	ret = devm_add_action_or_reset(axi->dev, bt1_axi_remove_sysfs, axi);
+	if (ret)
+		dev_err(axi->dev, "Can't add AXI EHB sysfs remove action\n");
+
+	return ret;
+}
+
+static int bt1_axi_probe(struct platform_device *pdev)
+{
+	struct bt1_axi *axi;
+	int ret;
+
+	axi = bt1_axi_create_data(pdev);
+	if (IS_ERR(axi))
+		return PTR_ERR(axi);
+
+	ret = bt1_axi_request_regs(axi);
+	if (ret)
+		return ret;
+
+	ret = bt1_axi_request_rst(axi);
+	if (ret)
+		return ret;
+
+	ret = bt1_axi_request_clk(axi);
+	if (ret)
+		return ret;
+
+	ret = bt1_axi_request_irq(axi);
+	if (ret)
+		return ret;
+
+	ret = bt1_axi_init_sysfs(axi);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct of_device_id bt1_axi_of_match[] = {
+	{ .compatible = "baikal,bt1-axi" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, bt1_axi_of_match);
+
+static struct platform_driver bt1_axi_driver = {
+	.probe = bt1_axi_probe,
+	.driver = {
+		.name = "bt1-axi",
+		.of_match_table = bt1_axi_of_match
+	}
+};
+module_platform_driver(bt1_axi_driver);
+
+MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
+MODULE_DESCRIPTION("Baikal-T1 AXI-bus driver");
+MODULE_LICENSE("GPL v2");