* Re: [PATCH 3/3] drm/bridge: Add NWL MIPI DSI host controller support
From: Guido Günther @ 2019-08-09 16:25 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Mark Rutland, devicetree, Jernej Skrabec, Pengutronix Kernel Team,
Neil Armstrong, David Airlie, Fabio Estevam, Sascha Hauer,
Jonas Karlman, linux-kernel, dri-devel, Andrzej Hajda,
Rob Herring, NXP Linux Team, Daniel Vetter, Robert Chiras,
Lee Jones, Shawn Guo, linux-arm-kernel
In-Reply-To: <20190727024700.GD4902@pendragon.ideasonboard.com>
Hi Laurent,
thanks for the review! Most of it seemed clear how to fix for the rest
i've put some questions below:
On Sat, Jul 27, 2019 at 05:47:00AM +0300, Laurent Pinchart wrote:
> Hello Guido,
>
> Thank you for the patch.
>
> On Wed, Jul 24, 2019 at 05:52:26PM +0200, Guido Günther wrote:
> > This adds initial support for the NWL MIPI DSI Host controller found on
> > i.MX8 SoCs.
> >
> > It adds support for the i.MX8MQ but the same IP can be found on
> > e.g. the i.MX8QXP.
> >
> > It has been tested on the Librem 5 devkit using mxsfb.
> >
> > Signed-off-by: Guido Günther <agx@sigxcpu.org>
> > Co-developed-by: Robert Chiras <robert.chiras@nxp.com>
> > ---
> > drivers/gpu/drm/bridge/Kconfig | 2 +
> > drivers/gpu/drm/bridge/Makefile | 1 +
> > drivers/gpu/drm/bridge/imx-nwl/Kconfig | 15 +
> > drivers/gpu/drm/bridge/imx-nwl/Makefile | 2 +
> > drivers/gpu/drm/bridge/imx-nwl/nwl-drv.c | 529 ++++++++++++++++
> > drivers/gpu/drm/bridge/imx-nwl/nwl-drv.h | 72 +++
> > drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.c | 745 +++++++++++++++++++++++
> > drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.h | 111 ++++
> > 8 files changed, 1477 insertions(+)
> > create mode 100644 drivers/gpu/drm/bridge/imx-nwl/Kconfig
> > create mode 100644 drivers/gpu/drm/bridge/imx-nwl/Makefile
> > create mode 100644 drivers/gpu/drm/bridge/imx-nwl/nwl-drv.c
> > create mode 100644 drivers/gpu/drm/bridge/imx-nwl/nwl-drv.h
> > create mode 100644 drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.c
> > create mode 100644 drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.h
> >
> > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> > index a6eec908c43e..38c3145a7e57 100644
> > --- a/drivers/gpu/drm/bridge/Kconfig
> > +++ b/drivers/gpu/drm/bridge/Kconfig
> > @@ -152,6 +152,8 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig"
> >
> > source "drivers/gpu/drm/bridge/adv7511/Kconfig"
> >
> > +source "drivers/gpu/drm/bridge/imx-nwl/Kconfig"
> > +
>
> As this doesn't seem to be an i.MX-specific IP, I wouldn't use the name
> imx in file names or in the code, at least in the parts that are not
> NXP-specific.
O.k. Since i've not seen other SoCs using this ip core I wasn't sure
what would be sharable but we'll figure that out. Renamed to nwl-dsi/
> > source "drivers/gpu/drm/bridge/synopsys/Kconfig"
> >
> > endmenu
> > diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> > index 4934fcf5a6f8..904a9eb3a20a 100644
> > --- a/drivers/gpu/drm/bridge/Makefile
> > +++ b/drivers/gpu/drm/bridge/Makefile
> > @@ -16,4 +16,5 @@ obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
> > obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
> > obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
> > obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
> > +obj-y += imx-nwl/
> > obj-y += synopsys/
> > diff --git a/drivers/gpu/drm/bridge/imx-nwl/Kconfig b/drivers/gpu/drm/bridge/imx-nwl/Kconfig
> > new file mode 100644
> > index 000000000000..822dba1b380a
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/imx-nwl/Kconfig
> > @@ -0,0 +1,15 @@
> > +config DRM_IMX_NWL_DSI
> > + tristate "Support for Northwest Logic MIPI DSI Host controller"
> > + depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM || COMPILE_TEST)
> > + depends on COMMON_CLK
> > + depends on OF && HAS_IOMEM
> > + select DRM_KMS_HELPER
> > + select DRM_MIPI_DSI
> > + select DRM_PANEL_BRIDGE
> > + select GENERIC_PHY_MIPI_DPHY
> > + select MFD_SYSCON
> > + select REGMAP_MMIO
> > + help
> > + This enables the Northwest Logic MIPI DSI Host controller as
> > + found on NXP's i.MX8 Processors.
> > +
> > diff --git a/drivers/gpu/drm/bridge/imx-nwl/Makefile b/drivers/gpu/drm/bridge/imx-nwl/Makefile
> > new file mode 100644
> > index 000000000000..9fa63483da5b
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/imx-nwl/Makefile
> > @@ -0,0 +1,2 @@
> > +imx-nwl-objs := nwl-drv.o nwl-dsi.o
> > +obj-$(CONFIG_DRM_IMX_NWL_DSI) += imx-nwl.o
> > diff --git a/drivers/gpu/drm/bridge/imx-nwl/nwl-drv.c b/drivers/gpu/drm/bridge/imx-nwl/nwl-drv.c
> > new file mode 100644
> > index 000000000000..451f8f067c6f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/imx-nwl/nwl-drv.c
> > @@ -0,0 +1,529 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * i.MX8 NWL MIPI DSI host driver
> > + *
> > + * Copyright (C) 2017 NXP
> > + * Copyright (C) 2019 Purism SPC
> > + */
> > +
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_of.h>
> > +#include <drm/drm_panel.h>
> > +#include <drm/drm_print.h>
> > +#include <drm/drm_probe_helper.h>
> > +#include <linux/clk-provider.h>
>
> This doesn't seem to be needed.
Dropped.
>
> > +#include <linux/clk.h>
> > +#include <linux/component.h>
>
> Same here.
Dropped (it was a component driver before).
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/irq.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/mfd/syscon/imx8mq-iomuxc-gpr.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/regmap.h>
> > +#include <linux/sys_soc.h>
> > +#include <video/videomode.h>
> > +
> > +#include "nwl-drv.h"
> > +#include "nwl-dsi.h"
> > +
> > +#define DRV_NAME "imx-nwl-dsi"
> > +
> > +/* 8MQ SRC specific registers */
> > +#define SRC_MIPIPHY_RCR 0x28
> > +#define RESET_BYTE_N BIT(1)
> > +#define RESET_N BIT(2)
> > +#define DPI_RESET_N BIT(3)
> > +#define ESC_RESET_N BIT(4)
> > +#define PCLK_RESET_N BIT(5)
> > +
> > +/* Possible clocks */
> > +#define CLK_PIXEL "pixel"
> > +#define CLK_CORE "core"
> > +#define CLK_BYPASS "bypass"
> > +
> > +enum imx_ext_regs {
> > + IMX_REG_CSR = BIT(1),
> > + IMX_REG_SRC = BIT(2),
> > + IMX_REG_GPR = BIT(3),
> > +};
> > +
> > +static const struct regmap_config nwl_dsi_regmap_config = {
> > + .reg_bits = 16,
> > + .val_bits = 32,
> > + .reg_stride = 4,
> > + .max_register = IRQ_MASK2,
> > + .name = DRV_NAME,
> > +};
> > +
> > +struct imx_nwl_platform_data {
> > + int (*poweron)(struct imx_nwl_dsi *dsi);
> > + int (*poweroff)(struct imx_nwl_dsi *dsi);
> > + u32 ext_regs; /* required external registers */
> > + struct imx_nwl_clk_config clk_config[NWL_MAX_PLATFORM_CLOCKS];
> > +};
> > +
> > +static inline struct imx_nwl_dsi *bridge_to_dsi(struct drm_bridge *bridge)
> > +{
> > + return container_of(bridge, struct imx_nwl_dsi, bridge);
> > +}
> > +
> > +static void imx_nwl_dsi_set_clocks(struct imx_nwl_dsi *dsi, bool enable)
> > +{
> > + struct device *dev = dsi->dev;
> > + const char *id;
> > + struct clk *clk;
> > + unsigned long new_rate, cur_rate;
> > + bool enabled;
> > + size_t i;
> > + int ret;
> > +
> > + DRM_DEV_DEBUG_DRIVER(dev, "%sabling platform clocks",
> > + enable ? "en" : "dis");
> > + for (i = 0; i < ARRAY_SIZE(dsi->pdata->clk_config); i++) {
> > + if (!dsi->clk_config[i].present)
> > + continue;
> > + id = dsi->clk_config[i].id;
> > + clk = dsi->clk_config[i].clk;
> > + new_rate = dsi->clk_config[i].rate;
> > + cur_rate = clk_get_rate(clk);
> > + enabled = dsi->clk_config[i].enabled;
> > +
> > + /* BYPASS clk must have the same rate as PHY_REF clk */
> > + if (!strcmp(id, CLK_BYPASS))
> > + new_rate = clk_get_rate(dsi->phy_ref_clk);
> > +
> > + if (enable) {
> > + if (enabled && new_rate != cur_rate)
> > + clk_disable_unprepare(clk);
> > + else if (enabled && new_rate == cur_rate)
> > + continue;
> > + if (new_rate > 0)
> > + clk_set_rate(clk, new_rate);
> > + ret = clk_prepare_enable(clk);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to enable clock %s",
> > + id);
> > + }
> > + dsi->clk_config[i].enabled = true;
> > + cur_rate = clk_get_rate(clk);
> > + DRM_DEV_DEBUG_DRIVER(
> > + dev, "Enabled %s clk (rate: req=%lu act=%lu)\n",
> > + id, new_rate, cur_rate);
> > + } else if (enabled) {
> > + clk_disable_unprepare(clk);
> > + dsi->clk_config[i].enabled = false;
> > + DRM_DEV_DEBUG_DRIVER(dev, "Disabled %s clk\n", id);
> > + }
> > + }
> > +}
> > +
> > +static void imx_nwl_dsi_enable(struct imx_nwl_dsi *dsi)
> > +{
> > + struct device *dev = dsi->dev;
> > + int ret;
> > +
> > + imx_nwl_dsi_set_clocks(dsi, true);
> > +
> > + ret = dsi->pdata->poweron(dsi);
> > + if (ret < 0)
> > + DRM_DEV_ERROR(dev, "Failed to power on DSI (%d)\n", ret);
> > +}
> > +
> > +static void imx_nwl_dsi_disable(struct imx_nwl_dsi *dsi)
> > +{
> > + struct device *dev = dsi->dev;
> > +
> > + if (dsi->dpms_mode != DRM_MODE_DPMS_ON)
> > + return;
> > +
>
> The DRM core should guarantee that the bridge won't be disabled twice,
> so I don't think you need this check. Similarly I think the enabled flag
> in the imx_nwl_clk_config structure can be removed.
Dropped and i also simplified the imx_nwl_clk_config - rates are supplied
via DT here anyway.
>
> > + DRM_DEV_DEBUG_DRIVER(dev, "Disabling encoder");
>
> Is this really needed ?
Dropped.
> > + dsi->pdata->poweroff(dsi);
> > + imx_nwl_dsi_set_clocks(dsi, false);
> > +}
> > +
> > +static void imx_nwl_select_input_source(struct imx_nwl_dsi *dsi)
> > +{
> > + struct device_node *remote;
> > + u32 mux_val = IMX8MQ_GPR13_MIPI_MUX_SEL;
> > +
> > + remote = of_graph_get_remote_node(dsi->dev->of_node, 0, 0);
> > + if (strcmp(remote->name, "lcdif") == 0)
> > + mux_val = 0;
> > +
Getting it from dt spares us carrying around more platform specific
state. Should i change it anyway?
>
> Can't you check the remote node at probe time instead of every time the
> bridge gets enabled, and program the IO mux accordingly there ?
>
> This code is i.MX-specific, so it should be isolated in an operation in
> struct imx_nwl_platform_data.
Done.
>
> > + DRM_DEV_INFO(dsi->dev, "Using %s as input source\n",
> > + (mux_val) ? "DCSS" : "LCDIF");
> > + regmap_update_bits(dsi->mux_sel, IOMUXC_GPR13,
> > + IMX8MQ_GPR13_MIPI_MUX_SEL, mux_val);
> > + of_node_put(remote);
> > +}
> > +
> > +static void imx_nwl_dsi_bridge_disable(struct drm_bridge *bridge)
> > +{
> > + struct imx_nwl_dsi *dsi = bridge_to_dsi(bridge);
> > +
> > + if (dsi->dpms_mode != DRM_MODE_DPMS_ON)
> > + return;
> > +
> > + nwl_dsi_disable(dsi);
> > + imx_nwl_dsi_disable(dsi);
> > + pm_runtime_put_sync(dsi->dev);
>
> Do you need a put_sync, wouldn't a put do ?
Switched to put() only.
>
> > + dsi->dpms_mode = DRM_MODE_DPMS_OFF;
> > +}
> > +
> > +static bool
> > +imx_nwl_dsi_bridge_mode_fixup(struct drm_bridge *bridge,
> > + const struct drm_display_mode *mode,
> > + struct drm_display_mode *adjusted_mode)
> > +{
> > + struct imx_nwl_dsi *dsi = bridge_to_dsi(bridge);
> > + struct device *dev = dsi->dev;
> > + union phy_configure_opts new_cfg;
> > + unsigned long phy_ref_rate;
> > + int ret;
> > +
> > + ret = nwl_dsi_get_dphy_params(dsi, adjusted_mode, &new_cfg);
> > + if (ret < 0)
> > + return ret;
> > +
> > + /*
> > + * If hs clock is unchanged, we're all good - all parameters are
> > + * derived from it atm.
> > + */
> > + if (new_cfg.mipi_dphy.hs_clk_rate == dsi->phy_cfg.mipi_dphy.hs_clk_rate)
> > + return true;
> > +
> > + phy_ref_rate = clk_get_rate(dsi->phy_ref_clk);
> > + DRM_DEV_DEBUG_DRIVER(dev, "PHY at ref rate: %lu\n", phy_ref_rate);
> > + if (ret < 0) {
>
> This can't happen. Or are you missing a function call before the check
> ?
The code used that a long time ago, fixed that path.
>
> > + DRM_DEV_ERROR(dsi->dev,
> > + "Cannot setup PHY for mode: %ux%u @%d Hz\n",
> > + adjusted_mode->hdisplay, adjusted_mode->vdisplay,
> > + adjusted_mode->clock);
> > + DRM_DEV_ERROR(dsi->dev, "PHY ref clk: %lu, bit clk: %lu\n",
> > + phy_ref_rate, new_cfg.mipi_dphy.hs_clk_rate);
> > + } else {
> > + /* Save the new desired phy config */
> > + memcpy(&dsi->phy_cfg, &new_cfg, sizeof(new_cfg));
>
> The mode_fixup operation shall not change the device state, it can be
> called multiple times when trying modes.
Moved the parts to 'mode_set' instead.
>
> > + }
> > +
> > + /* LCDIF + NWL needs active high sync */
> > + adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
> > + adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
> > +
> > + drm_display_mode_to_videomode(adjusted_mode, &dsi->vm);
> > + drm_mode_debug_printmodeline(adjusted_mode);
> > +
> > + return ret == 0;
>
> return 0;
mode_fixup wants a bool but that code is gone anyways.
>
> > +}
> > +
> > +static enum drm_mode_status
> > +imx_nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge,
> > + const struct drm_display_mode *mode)
> > +{
> > + struct imx_nwl_dsi *dsi = bridge_to_dsi(bridge);
> > + int bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> > +
> > + if (bpp < 0) {
> > + DRM_DEV_ERROR(dsi->dev, "Invalid pixel format: %d\n",
> > + dsi->format);
> > + return MODE_BAD;
> > + }
>
> The format isn't part of the mode, so this doesn't belong here. You
> should here instead check that the mode clock and other timing data
> (especially the visible resolution) are within the range supported by
> the device.
O.k. I've added a clock check derived from the spec instead.
> > +
> > + return MODE_OK;
> > +}
> > +
> > +static void imx_nwl_dsi_bridge_pre_enable(struct drm_bridge *bridge)
> > +{
> > + struct imx_nwl_dsi *dsi = bridge_to_dsi(bridge);
> > +
> > + if (dsi->dpms_mode == DRM_MODE_DPMS_ON)
> > + return;
> > +
> > + imx_nwl_select_input_source(dsi);
> > + pm_runtime_get_sync(dsi->dev);
> > + imx_nwl_dsi_enable(dsi);
> > + nwl_dsi_enable(dsi);
> > + dsi->dpms_mode = DRM_MODE_DPMS_ON;
> > +}
> > +
> > +static int imx_nwl_dsi_bridge_attach(struct drm_bridge *bridge)
> > +{
> > + struct imx_nwl_dsi *dsi = bridge->driver_private;
> > + struct drm_encoder *encoder = bridge->encoder;
> > +
> > + if (!encoder) {
> > + DRM_DEV_ERROR(dsi->dev, "Parent encoder object not found\n");
> > + return -ENODEV;
> > + }
>
> Can't this happen ?
Dropped.
>
> > +
> > + /* Set the encoder type as caller does not know it */
> > + bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI;
>
> The encoder type is quite meaningless and userspace should not depend on
> it, so I wouldn't set it here, especially that the encoder may not
> expect the bridge to override its type.
Dropped.
>
> > +
> > + /* Attach the panel-bridge to the dsi bridge */
> > + return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge);
> > +}
> > +
> > +static void imx_nwl_dsi_bridge_detach(struct drm_bridge *bridge)
> > +{
> > + struct imx_nwl_dsi *dsi = bridge->driver_private;
> > +
> > + drm_of_panel_bridge_remove(dsi->dev->of_node, 1, 0);
>
> This is already done in nwl_dsi_host_detach().
Dropped the whole detach.
>
> > +}
> > +
> > +/* see dw-mipi-dsi.c */
>
> What for ? :-)
Dropped.
>
> > +static const struct drm_bridge_funcs imx_nwl_dsi_bridge_funcs = {
> > + .pre_enable = imx_nwl_dsi_bridge_pre_enable,
> > + .disable = imx_nwl_dsi_bridge_disable,
> > + .mode_fixup = imx_nwl_dsi_bridge_mode_fixup,
> > + .mode_valid = imx_nwl_dsi_bridge_mode_valid,
> > + .attach = imx_nwl_dsi_bridge_attach,
> > + .detach = imx_nwl_dsi_bridge_detach,
> > +};
> > +
> > +static int imx_nwl_dsi_parse_dt(struct imx_nwl_dsi *dsi)
> > +{
> > + struct device_node *np = dsi->dev->of_node;
> > + struct platform_device *pdev = to_platform_device(dsi->dev);
> > + struct resource *res;
> > + struct clk *clk;
> > + const char *clk_id;
> > + void __iomem *base;
> > + int i, ret;
> > +
> > + dsi->phy = devm_phy_get(dsi->dev, "dphy");
> > + if (IS_ERR(dsi->phy)) {
> > + ret = PTR_ERR(dsi->phy);
> > + dev_err(dsi->dev, "Could not get PHY (%d)\n", ret);
> > + return ret;
> > + }
> > +
> > + /* Platform dependent clocks */
> > + memcpy(dsi->clk_config, dsi->pdata->clk_config,
> > + sizeof(dsi->pdata->clk_config));
> > +
> > + for (i = 0; i < ARRAY_SIZE(dsi->pdata->clk_config); i++) {
> > + if (!dsi->clk_config[i].present)
> > + continue;
> > +
> > + clk_id = dsi->clk_config[i].id;
> > + clk = devm_clk_get(dsi->dev, clk_id);
> > + if (IS_ERR(clk)) {
> > + ret = PTR_ERR(clk);
> > + dev_err(dsi->dev, "Failed to get %s clock (%d)\n",
> > + clk_id, ret);
> > + return ret;
> > + }
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "Setup clk %s (rate: %lu)\n",
> > + clk_id, clk_get_rate(clk));
> > + dsi->clk_config[i].clk = clk;
> > + }
> > +
> > + /* DSI clocks */
> > + clk = devm_clk_get(dsi->dev, "phy_ref");
> > + if (IS_ERR(clk)) {
> > + ret = PTR_ERR(clk);
> > + dev_err(dsi->dev, "Failed to get phy_ref clock: %d\n", ret);
> > + return ret;
> > + }
> > + dsi->phy_ref_clk = clk;
> > +
> > + clk = devm_clk_get(dsi->dev, "rx_esc");
> > + if (IS_ERR(clk)) {
> > + ret = PTR_ERR(clk);
> > + dev_err(dsi->dev, "Failed to get rx_esc clock: %d\n", ret);
> > + return ret;
> > + }
> > + dsi->rx_esc_clk = clk;
> > +
> > + clk = devm_clk_get(dsi->dev, "tx_esc");
> > + if (IS_ERR(clk)) {
> > + ret = PTR_ERR(clk);
> > + dev_err(dsi->dev, "Failed to get tx_esc clock: %d\n", ret);
> > + return ret;
> > + }
> > + dsi->tx_esc_clk = clk;
> > +
> > + dsi->csr = syscon_regmap_lookup_by_phandle(np, "csr");
> > + if (IS_ERR(dsi->csr) && dsi->pdata->ext_regs & IMX_REG_CSR) {
> > + ret = PTR_ERR(dsi->csr);
> > + DRM_DEV_ERROR(dsi->dev, "Failed to get CSR regmap: %d\n",
> > + ret);
> > + return ret;
> > + }
>
> This doesn't seem to be used anywhere.
That's true. i had it in for the imx8q*, dropped that (and some other
parts) until support for that soc is added.
>
> > + dsi->reset = syscon_regmap_lookup_by_phandle(np, "src");
> > + if (IS_ERR(dsi->reset) && (dsi->pdata->ext_regs & IMX_REG_SRC)) {
> > + ret = PTR_ERR(dsi->reset);
> > + DRM_DEV_ERROR(dsi->dev, "Failed to get SRC regmap: %d\n",
> > + ret);
> > + return ret;
> > + }
>
> Couldn't you model a reset controller in that syscon, and use the reset
> controller API here ? It would allow moving the i.MX-specific power on
> and off functions from this driver, making it more generic.
In fact the reset controller is already there, wired it up accordingly.
>
> > + dsi->mux_sel = syscon_regmap_lookup_by_phandle(np, "mux-sel");
> > + if (IS_ERR(dsi->mux_sel) && (dsi->pdata->ext_regs & IMX_REG_GPR)) {
> > + ret = PTR_ERR(dsi->mux_sel);
> > + DRM_DEV_ERROR(dsi->dev, "Failed to get GPR regmap: %d\n",
> > + ret);
> > + return ret;
> > + }
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + base = devm_ioremap_resource(dsi->dev, res);
>
> You can replace those two calls with devm_platform_ioremap_resource().
Done.
>
> > + if (IS_ERR(base))
> > + return PTR_ERR(base);
> > +
> > + dsi->regmap =
> > + devm_regmap_init_mmio(dsi->dev, base, &nwl_dsi_regmap_config);
> > + if (IS_ERR(dsi->regmap)) {
> > + ret = PTR_ERR(dsi->regmap);
> > + DRM_DEV_ERROR(dsi->dev,
> > + "Failed to create NWL DSI regmap: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + dsi->irq = platform_get_irq(pdev, 0);
> > + if (dsi->irq < 0) {
> > + DRM_DEV_ERROR(dsi->dev, "Failed to get device IRQ: %d\n",
> > + dsi->irq);
> > + return dsi->irq;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int imx8mq_dsi_poweron(struct imx_nwl_dsi *dsi)
> > +{
> > + /* otherwise the display stays blank */
> > + usleep_range(200, 300);
> > +
> > + regmap_update_bits(dsi->reset, SRC_MIPIPHY_RCR, PCLK_RESET_N,
> > + PCLK_RESET_N);
> > + regmap_update_bits(dsi->reset, SRC_MIPIPHY_RCR, ESC_RESET_N,
> > + ESC_RESET_N);
> > + regmap_update_bits(dsi->reset, SRC_MIPIPHY_RCR, RESET_BYTE_N,
> > + RESET_BYTE_N);
> > + regmap_update_bits(dsi->reset, SRC_MIPIPHY_RCR, DPI_RESET_N,
> > + DPI_RESET_N);
> > +
> > + return 0;
> > +}
> > +
> > +static int imx8mq_dsi_poweroff(struct imx_nwl_dsi *dsi)
> > +{
> > + if (USE_SRC_RESET_QUIRK(dsi->quirks))
> > + return 0;
> > +
> > + regmap_update_bits(dsi->reset, SRC_MIPIPHY_RCR, PCLK_RESET_N, 0);
> > + regmap_update_bits(dsi->reset, SRC_MIPIPHY_RCR, ESC_RESET_N, 0);
> > + regmap_update_bits(dsi->reset, SRC_MIPIPHY_RCR, RESET_BYTE_N, 0);
> > + regmap_update_bits(dsi->reset, SRC_MIPIPHY_RCR, DPI_RESET_N, 0);
> > + return 0;
> > +}
> > +
> > +static const struct drm_bridge_timings imx_nwl_timings = {
> > + .input_bus_flags = DRM_BUS_FLAG_DE_LOW,
> > +};
> > +
> > +static struct imx_nwl_platform_data imx8mq_dev = {
>
> This structure should be const, especially as it contains function
> pointers.
Done.
>
> > + .poweron = &imx8mq_dsi_poweron,
> > + .poweroff = &imx8mq_dsi_poweroff,
> > + .clk_config = {
> > + { .id = CLK_CORE, .present = true },
> > + { .id = CLK_PIXEL, .present = false },
> > + { .id = CLK_BYPASS, .present = false },
> > + },
> > + .ext_regs = IMX_REG_SRC | IMX_REG_GPR,
> > +};
> > +
> > +static const struct of_device_id imx_nwl_dsi_dt_ids[] = {
> > + { .compatible = "fsl,imx8mq-nwl-dsi", .data = &imx8mq_dev, },
> > + { /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, imx_nwl_dsi_dt_ids);
> > +
> > +static const struct soc_device_attribute imx_nwl_quirks_match[] = {
> > + { .soc_id = "i.MX8MQ", .revision = "2.0",
> > + .data = (void *)(E11418_HS_MODE_QUIRK | SRC_RESET_QUIRK) },
> > + { /* sentinel. */ },
> > +};
> > +
> > +static int imx_nwl_dsi_probe(struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + const struct of_device_id *of_id =
> > + of_match_device(imx_nwl_dsi_dt_ids, dev);
> > + const struct imx_nwl_platform_data *pdata = of_id->data;
> > + const struct soc_device_attribute *attr;
> > + struct imx_nwl_dsi *dsi;
> > + int ret;
> > +
> > + dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
> > + if (!dsi)
> > + return -ENOMEM;
> > +
> > + dsi->dev = dev;
> > + dsi->pdata = pdata;
> > + dsi->dpms_mode = DRM_MODE_DPMS_OFF;
>
> DPMS is legacy, let's not use it within the driver.
Removed that since the drm layer keeps the state for us.
> > +
> > + ret = imx_nwl_dsi_parse_dt(dsi);
> > + if (ret)
> > + return ret;
> > +
> > + ret = devm_request_irq(dev, dsi->irq, nwl_dsi_irq_handler, 0,
> > + dev_name(dev), dsi);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to request IRQ: %d (%d)\n", dsi->irq,
> > + ret);
> > + return ret;
> > + }
> > +
> > + dsi->dsi_host.ops = &nwl_dsi_host_ops;
> > + dsi->dsi_host.dev = dev;
> > + ret = mipi_dsi_host_register(&dsi->dsi_host);
> > + if (ret) {
> > + DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret);
> > + goto err_cleanup;
> > + }
> > +
> > + attr = soc_device_match(imx_nwl_quirks_match);
> > + if (attr)
> > + dsi->quirks = (uintptr_t)attr->data;
> > +
> > + dsi->bridge.driver_private = dsi;
> > + dsi->bridge.funcs = &imx_nwl_dsi_bridge_funcs;
> > + dsi->bridge.of_node = dev->of_node;
> > + dsi->bridge.timings = &imx_nwl_timings;
> > +
> > + drm_bridge_add(&dsi->bridge);
> > +
> > + dev_set_drvdata(dev, dsi);
> > + pm_runtime_enable(dev);
> > + return 0;
> > +
> > +err_cleanup:
> > + devm_free_irq(dev, dsi->irq, dsi);
> > + return ret;
> > +}
> > +
> > +static int imx_nwl_dsi_remove(struct platform_device *pdev)
> > +{
> > + pm_runtime_disable(&pdev->dev);
>
> You should call drm_bridge_remove() here, not in
> nwl_dsi_host_detach().
I opted to call `mipi_dsi_host_unregister(&dsi->dsi_host)` which would
keep the removal in `nwl_dsi_host_detach()` but would also make sure
it's called on removal (modelled like cdns-dsi).
>
> > + return 0;
> > +}
> > +
> > +static struct platform_driver imx_nwl_dsi_driver = {
> > + .probe = imx_nwl_dsi_probe,
> > + .remove = imx_nwl_dsi_remove,
> > + .driver = {
> > + .of_match_table = imx_nwl_dsi_dt_ids,
> > + .name = DRV_NAME,
> > + },
> > +};
> > +
> > +module_platform_driver(imx_nwl_dsi_driver);
> > +
> > +MODULE_AUTHOR("NXP Semiconductor");
> > +MODULE_AUTHOR("Purism SPC");
> > +MODULE_DESCRIPTION("i.MX8 Northwest Logic MIPI-DSI driver");
> > +MODULE_LICENSE("GPL"); /* GPLv2 or later */
> > diff --git a/drivers/gpu/drm/bridge/imx-nwl/nwl-drv.h b/drivers/gpu/drm/bridge/imx-nwl/nwl-drv.h
> > new file mode 100644
> > index 000000000000..a1e30c58b627
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/imx-nwl/nwl-drv.h
> > @@ -0,0 +1,72 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * i.MX8 NWL MIPI DSI host driver
> > + *
> > + * Copyright (C) 2017 NXP
> > + * Copyright (C) 2019 Purism SPC
> > + */
> > +
> > +#ifndef __NWL_DRV_H__
> > +#define __NWL_DRV_H__
> > +
> > +#include <drm/drm_mipi_dsi.h>
> > +#include <linux/phy/phy.h>
> > +
> > +struct imx_nwl_platform_data;
> > +
> > +/* i.MX8 NWL quirks */
> > +/* i.MX8MQ errata E11418 */
> > +#define E11418_HS_MODE_QUIRK BIT(0)
> > +#define USE_E11418_HS_MODE_QUIRK(x) ((x) & E11418_HS_MODE_QUIRK)
> > +
> > +/* Skip DSI bits in SRC on disable to avoid blank display on enable */
> > +#define SRC_RESET_QUIRK BIT(1)
> > +#define USE_SRC_RESET_QUIRK(x) ((x) & SRC_RESET_QUIRK)
>
> The USE_* macros are not shorter to type, so I would type out the &
> check explicitly.
Dropped.
> > +
> > +#define NWL_MAX_PLATFORM_CLOCKS 3
> > +struct imx_nwl_clk_config {
> > + const char *id;
> > + struct clk *clk;
> > + bool present;
> > + bool enabled;
> > + u32 rate;
> > +};
> > +
> > +struct imx_nwl_dsi {
> > + struct drm_bridge bridge;
> > + struct mipi_dsi_host dsi_host;
> > + struct drm_bridge *panel_bridge;
> > + struct device *dev;
> > + struct phy *phy;
> > + union phy_configure_opts phy_cfg;
> > + unsigned int quirks;
> > +
> > + struct regmap *regmap;
> > + int irq;
> > +
> > + /* External registers */
> > + struct regmap *csr;
> > + struct regmap *mux_sel;
> > + struct regmap *reset;
> > +
> > + /* Platform dependent clocks */
> > + struct imx_nwl_clk_config clk_config[3];
>
> I would use NWL_MAX_PLATFORM_CLOCKS instead of 3 as
> imx_nwl_platform_data uses the macro.
That was an omission, fixed.
>
> > + /* DSI clocks */
> > + struct clk *phy_ref_clk;
> > + struct clk *rx_esc_clk;
> > + struct clk *tx_esc_clk;
> > +
> > + /* dsi lanes */
> > + u32 lanes;
> > + enum mipi_dsi_pixel_format format;
> > + struct videomode vm;
> > + unsigned long dsi_mode_flags;
> > +
> > + int dpms_mode;
> > +
> > + struct mipi_dsi_transfer *xfer;
> > +
> > + const struct imx_nwl_platform_data *pdata;
> > +};
> > +
> > +#endif /* __NWL_DRV_H__ */
> > diff --git a/drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.c b/drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.c
> > new file mode 100644
> > index 000000000000..0e1463af162f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.c
> > @@ -0,0 +1,745 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * NWL DSI host driver
> > + *
> > + * Copyright (C) 2017 NXP
> > + * Copyright (C) 2019 Purism SPC
> > + */
> > +
> > +#include <asm/unaligned.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_of.h>
> > +#include <drm/drm_panel.h>
> > +#include <drm/drm_print.h>
> > +#include <linux/clk.h>
> > +#include <linux/irq.h>
> > +#include <linux/regmap.h>
> > +#include <video/mipi_display.h>
> > +#include <video/videomode.h>
> > +
> > +#include "nwl-drv.h"
> > +#include "nwl-dsi.h"
> > +
> > +#define MIPI_FIFO_TIMEOUT msecs_to_jiffies(500)
> > +
> > +/* PKT reg bit manipulation */
> > +#define REG_MASK(e, s) (((1 << ((e) - (s) + 1)) - 1) << (s))
> > +#define REG_PUT(x, e, s) (((x) << (s)) & REG_MASK(e, s))
> > +#define REG_GET(x, e, s) (((x) & REG_MASK(e, s)) >> (s))
>
> Let's not reinvent the wheel, linux/bits.h and linux/bitfield.h can be
> used instead.
Done.
>
> > +
> > +/*
> > + * PKT_CONTROL format:
> > + * [15: 0] - word count
> > + * [17:16] - virtual channel
> > + * [23:18] - data type
> > + * [24] - LP or HS select (0 - LP, 1 - HS)
> > + * [25] - perform BTA after packet is sent
> > + * [26] - perform BTA only, no packet tx
> > + */
> > +#define WC(x) REG_PUT((x), 15, 0)
> > +#define TX_VC(x) REG_PUT((x), 17, 16)
> > +#define TX_DT(x) REG_PUT((x), 23, 18)
> > +#define HS_SEL(x) REG_PUT((x), 24, 24)
> > +#define BTA_TX(x) REG_PUT((x), 25, 25)
> > +#define BTA_NO_TX(x) REG_PUT((x), 26, 26)
> > +
> > +/*
> > + * RX_PKT_HEADER format:
> > + * [15: 0] - word count
> > + * [21:16] - data type
> > + * [23:22] - virtual channel
> > + */
> > +#define RX_DT(x) REG_GET((x), 21, 16)
> > +#define RX_VC(x) REG_GET((x), 23, 22)
> > +
> > +/*
> > + * DSI Video mode
> > + */
> > +#define VIDEO_MODE_BURST_MODE_WITH_SYNC_PULSES 0
> > +#define VIDEO_MODE_NON_BURST_MODE_WITH_SYNC_EVENTS BIT(0)
> > +#define VIDEO_MODE_BURST_MODE BIT(1)
> > +
> > +/*
> > + * DPI color coding
> > + */
> > +#define DPI_16_BIT_565_PACKED 0
> > +#define DPI_16_BIT_565_ALIGNED 1
> > +#define DPI_16_BIT_565_SHIFTED 2
> > +#define DPI_18_BIT_PACKED 3
> > +#define DPI_18_BIT_ALIGNED 4
> > +#define DPI_24_BIT 5
> > +
> > +/*
> > + * DPI Pixel format
> > + */
> > +#define PIXEL_FORMAT_16 0
> > +#define PIXEL_FORMAT_18 BIT(0)
> > +#define PIXEL_FORMAT_18L BIT(1)
> > +#define PIXEL_FORMAT_24 (BIT(0) | BIT(1))
> > +
> > +enum transfer_direction { DSI_PACKET_SEND, DSI_PACKET_RECEIVE };
>
> Line breaks please.
Done.
>
> > +
> > +struct mipi_dsi_transfer {
>
> Let's not use such a generic name for a driver-specific structure. You
> should name is nwl_dsi_transfer.
Fixed.
>
> > + const struct mipi_dsi_msg *msg;
> > + struct mipi_dsi_packet packet;
> > + struct completion completed;
> > +
> > + int status; /* status of transmission */
> > + enum transfer_direction direction;
> > + bool need_bta;
> > + u8 cmd;
> > + u16 rx_word_count;
> > + size_t tx_len; /* bytes sent */
> > + size_t rx_len; /* bytes received */
> > +};
> > +
> > +static inline int nwl_dsi_write(struct imx_nwl_dsi *dsi, unsigned int reg,
> > + u32 val)
> > +{
> > + int ret;
> > +
> > + ret = regmap_write(dsi->regmap, reg, val);
> > + if (ret < 0)
> > + DRM_DEV_ERROR(dsi->dev,
> > + "Failed to write NWL DSI reg 0x%x: %d\n", reg,
> > + ret);
> > + return ret;
> > +}
> > +
> > +static inline u32 nwl_dsi_read(struct imx_nwl_dsi *dsi, u32 reg)
> > +{
> > + unsigned int val;
> > + int ret;
> > +
> > + ret = regmap_read(dsi->regmap, reg, &val);
> > + if (ret < 0)
> > + DRM_DEV_ERROR(dsi->dev, "Failed to read NWL DSI reg 0x%x: %d\n",
> > + reg, ret);
> > +
> > + return val;
>
> You're loosing the error...
Looking at other drivers they often just ignore the return value of
regmap_read. The places we use this can't do much to recover from errors
so i figured it'd be best to at least log it so it becomes debuggable
instead of just dropping it to the floor.
> > +}
> > +
> > +static u32 nwl_dsi_get_dpi_pixel_format(enum mipi_dsi_pixel_format format)
> > +{
> > + switch (format) {
> > + case MIPI_DSI_FMT_RGB565:
> > + return PIXEL_FORMAT_16;
> > + case MIPI_DSI_FMT_RGB666:
> > + return PIXEL_FORMAT_18L;
> > + case MIPI_DSI_FMT_RGB666_PACKED:
> > + return PIXEL_FORMAT_18;
> > + case MIPI_DSI_FMT_RGB888:
> > + return PIXEL_FORMAT_24;
> > + default:
> > + return -EINVAL;
> > + }
> > +}
> > +
> > +int nwl_dsi_get_dphy_params(struct imx_nwl_dsi *dsi,
> > + const struct drm_display_mode *mode,
> > + union phy_configure_opts *phy_opts)
> > +{
> > + unsigned long rate;
> > +
> > + if (dsi->lanes < 1 || dsi->lanes > 4)
> > + return -EINVAL;
> > +
> > + /*
> > + * So far the DPHY spec minimal timings work for both mixel
> > + * dphy and nwl dsi host
> > + */
> > + phy_mipi_dphy_get_default_config(
> > + mode->crtc_clock * 1000,
> > + mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes,
> > + &phy_opts->mipi_dphy);
> > + rate = clk_get_rate(dsi->tx_esc_clk);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "LP clk is @%lu Hz\n", rate);
> > + phy_opts->mipi_dphy.lp_clk_rate = rate;
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(nwl_dsi_get_dphy_params);
>
> No need to export symbols, those fubctions are only meant to be called
> from within the same module.
Removed (also left overs when i had these in two modules).
>
> > +
> > +#define PSEC_PER_SEC 1000000000000LL
> > +/*
> > + * ps2bc - Picoseconds to byte clock cycles
> > + */
> > +static u32 ps2bc(struct imx_nwl_dsi *dsi, unsigned long long ps)
> > +{
> > + int bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> > +
> > + return DIV_ROUND_UP(ps * dsi->vm.pixelclock * bpp,
> > + dsi->lanes * 8 * PSEC_PER_SEC);
> > +}
> > +
> > +/**
> > + * ui2bc - UI time periods to byte clock cycles
> > + */
> > +static u32 ui2bc(struct imx_nwl_dsi *dsi, unsigned long long ui)
> > +{
> > + int bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> > +
> > + return DIV_ROUND_UP(ui * dsi->lanes, dsi->vm.pixelclock * bpp);
> > +}
> > +
> > +#define USEC_PER_SEC 1000000L
> > +/*
> > + * us2bc - micro seconds to lp clock cycles
> > + */
> > +static u32 us2lp(u32 lp_clk_rate, unsigned long us)
> > +{
> > + return DIV_ROUND_UP(us * lp_clk_rate, USEC_PER_SEC);
> > +}
> > +
> > +static int nwl_dsi_config_host(struct imx_nwl_dsi *dsi)
> > +{
> > + u32 cycles;
> > + struct phy_configure_opts_mipi_dphy *cfg = &dsi->phy_cfg.mipi_dphy;
> > +
> > + if (dsi->lanes < 1 || dsi->lanes > 4)
> > + return -EINVAL;
> > +
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "DSI Lanes %d\n", dsi->lanes);
> > + nwl_dsi_write(dsi, CFG_NUM_LANES, dsi->lanes - 1);
> > +
> > + if (dsi->dsi_mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
> > + nwl_dsi_write(dsi, CFG_NONCONTINUOUS_CLK, 0x01);
> > + nwl_dsi_write(dsi, CFG_AUTOINSERT_EOTP, 0x01);
> > + } else {
> > + nwl_dsi_write(dsi, CFG_NONCONTINUOUS_CLK, 0x00);
> > + nwl_dsi_write(dsi, CFG_AUTOINSERT_EOTP, 0x00);
> > + }
> > +
> > + /* values in byte clock cycles */
> > + cycles = ui2bc(dsi, cfg->clk_pre);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_t_pre: 0x%x\n", cycles);
> > + nwl_dsi_write(dsi, CFG_T_PRE, cycles);
> > + cycles = ps2bc(dsi, cfg->lpx + cfg->clk_prepare + cfg->clk_zero);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_tx_gap (pre): 0x%x\n", cycles);
> > + cycles += ui2bc(dsi, cfg->clk_pre);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_tx_gap: 0x%x\n", cycles);
> > + nwl_dsi_write(dsi, CFG_T_POST, cycles);
> > + cycles = ps2bc(dsi, cfg->hs_exit);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_tx_gap: 0x%x\n", cycles);
> > + nwl_dsi_write(dsi, CFG_TX_GAP, cycles);
> > +
> > + nwl_dsi_write(dsi, CFG_EXTRA_CMDS_AFTER_EOTP, 0x01);
> > + nwl_dsi_write(dsi, CFG_HTX_TO_COUNT, 0x00);
> > + nwl_dsi_write(dsi, CFG_LRX_H_TO_COUNT, 0x00);
> > + nwl_dsi_write(dsi, CFG_BTA_H_TO_COUNT, 0x00);
> > + /* In LP clock cycles */
> > + cycles = us2lp(cfg->lp_clk_rate, cfg->wakeup);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_twakeup: 0x%x\n", cycles);
> > + nwl_dsi_write(dsi, CFG_TWAKEUP, cycles);
> > +
> > + return 0;
> > +}
> > +
> > +static int nwl_dsi_config_dpi(struct imx_nwl_dsi *dsi)
> > +{
> > + struct videomode *vm = &dsi->vm;
> > + u32 color_format, mode;
> > + bool burst_mode;
> > +
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "hfront_porch = %d\n", vm->hfront_porch);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "hback_porch = %d\n", vm->hback_porch);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "hsync_len = %d\n", vm->hsync_len);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "hactive = %d\n", vm->hactive);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "vfront_porch = %d\n", vm->vfront_porch);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "vback_porch = %d\n", vm->vback_porch);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "vsync_len = %d\n", vm->vsync_len);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "vactive = %d\n", vm->vactive);
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "clock = %lu kHz\n",
> > + vm->pixelclock / 1000);
> > +
> > + color_format = nwl_dsi_get_dpi_pixel_format(dsi->format);
> > + if (color_format < 0) {
> > + DRM_DEV_ERROR(dsi->dev, "Invalid color format 0x%x\n",
> > + dsi->format);
> > + return color_format;
> > + }
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev, "pixel fmt = %d\n", dsi->format);
> > +
> > + nwl_dsi_write(dsi, INTERFACE_COLOR_CODING, DPI_24_BIT);
> > + nwl_dsi_write(dsi, PIXEL_FORMAT, color_format);
> > + /*
> > + * Adjusting input polarity based on the video mode results in
> > + * a black screen so always pick active low:
> > + */
> > + nwl_dsi_write(dsi, VSYNC_POLARITY, VSYNC_POLARITY_ACTIVE_LOW);
> > + nwl_dsi_write(dsi, HSYNC_POLARITY, HSYNC_POLARITY_ACTIVE_LOW);
> > +
> > + burst_mode = (dsi->dsi_mode_flags & MIPI_DSI_MODE_VIDEO_BURST) &&
> > + !(dsi->dsi_mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE);
> > +
> > + if (burst_mode) {
> > + nwl_dsi_write(dsi, VIDEO_MODE, VIDEO_MODE_BURST_MODE);
> > + nwl_dsi_write(dsi, PIXEL_FIFO_SEND_LEVEL, 256);
> > + } else {
> > + mode = ((dsi->dsi_mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) ?
> > + VIDEO_MODE_BURST_MODE_WITH_SYNC_PULSES :
> > + VIDEO_MODE_NON_BURST_MODE_WITH_SYNC_EVENTS);
> > + nwl_dsi_write(dsi, VIDEO_MODE, mode);
> > + nwl_dsi_write(dsi, PIXEL_FIFO_SEND_LEVEL, vm->hactive);
> > + }
> > +
> > + nwl_dsi_write(dsi, HFP, vm->hfront_porch);
> > + nwl_dsi_write(dsi, HBP, vm->hback_porch);
> > + nwl_dsi_write(dsi, HSA, vm->hsync_len);
> > +
> > + nwl_dsi_write(dsi, ENABLE_MULT_PKTS, 0x0);
> > + nwl_dsi_write(dsi, BLLP_MODE, 0x1);
> > + nwl_dsi_write(dsi, ENABLE_MULT_PKTS, 0x0);
> > + nwl_dsi_write(dsi, USE_NULL_PKT_BLLP, 0x0);
> > + nwl_dsi_write(dsi, VC, 0x0);
> > +
> > + nwl_dsi_write(dsi, PIXEL_PAYLOAD_SIZE, vm->hactive);
> > + nwl_dsi_write(dsi, VACTIVE, vm->vactive - 1);
> > + nwl_dsi_write(dsi, VBP, vm->vback_porch);
> > + nwl_dsi_write(dsi, VFP, vm->vfront_porch);
> > +
> > + return 0;
> > +}
> > +
> > +static int nwl_dsi_enable_tx_clock(struct imx_nwl_dsi *dsi)
> > +{
> > + struct device *dev = dsi->dev;
> > + int ret;
> > +
> > + ret = clk_prepare_enable(dsi->tx_esc_clk);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to enable tx_esc clk: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + DRM_DEV_DEBUG_DRIVER(dev, "Enabled tx_esc clk @%lu Hz\n",
> > + clk_get_rate(dsi->tx_esc_clk));
> > + return 0;
> > +}
> > +
> > +static int nwl_dsi_enable_rx_clock(struct imx_nwl_dsi *dsi)
> > +{
> > + struct device *dev = dsi->dev;
> > + int ret;
> > +
> > + ret = clk_prepare_enable(dsi->rx_esc_clk);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to enable rx_esc clk: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + DRM_DEV_DEBUG_DRIVER(dev, "Enabled rx_esc clk @%lu Hz\n",
> > + clk_get_rate(dsi->rx_esc_clk));
> > + return 0;
> > +}
> > +
> > +static void nwl_dsi_init_interrupts(struct imx_nwl_dsi *dsi)
> > +{
> > + u32 irq_enable;
> > +
> > + nwl_dsi_write(dsi, IRQ_MASK, 0xffffffff);
> > + nwl_dsi_write(dsi, IRQ_MASK2, 0x7);
> > +
> > + irq_enable = ~(u32)(TX_PKT_DONE_MASK | RX_PKT_HDR_RCVD_MASK |
> > + TX_FIFO_OVFLW_MASK | HS_TX_TIMEOUT_MASK);
> > +
> > + nwl_dsi_write(dsi, IRQ_MASK, irq_enable);
> > +}
> > +
> > +static int nwl_dsi_host_attach(struct mipi_dsi_host *dsi_host,
> > + struct mipi_dsi_device *device)
> > +{
> > + struct imx_nwl_dsi *dsi =
> > + container_of(dsi_host, struct imx_nwl_dsi, dsi_host);
> > + struct device *dev = dsi->dev;
> > + struct drm_bridge *bridge;
> > + struct drm_panel *panel;
> > + int ret;
> > +
> > + DRM_DEV_INFO(dev, "lanes=%u, format=0x%x flags=0x%lx\n", device->lanes,
> > + device->format, device->mode_flags);
> > +
> > + if (device->lanes < 1 || device->lanes > 4)
> > + return -EINVAL;
> > +
> > + dsi->lanes = device->lanes;
> > + dsi->format = device->format;
> > + dsi->dsi_mode_flags = device->mode_flags;
> > +
> > + ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, &panel,
> > + &bridge);
> > + if (ret)
> > + return ret;
> > +
> > + if (panel) {
> > + bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DSI);
> > + if (IS_ERR(bridge))
> > + return PTR_ERR(bridge);
> > + }
> > +
> > + dsi->panel_bridge = bridge;
> > + drm_bridge_add(&dsi->bridge);
> > +
> > + return 0;
> > +}
> > +
> > +static int nwl_dsi_host_detach(struct mipi_dsi_host *dsi_host,
> > + struct mipi_dsi_device *device)
> > +{
> > + struct imx_nwl_dsi *dsi =
> > + container_of(dsi_host, struct imx_nwl_dsi, dsi_host);
> > +
> > + drm_of_panel_bridge_remove(dsi->dev->of_node, 1, 0);
> > + drm_bridge_remove(&dsi->bridge);
> > +
> > + return 0;
> > +}
> > +
> > +static bool nwl_dsi_read_packet(struct imx_nwl_dsi *dsi, u32 status)
> > +{
> > + struct device *dev = dsi->dev;
> > + struct mipi_dsi_transfer *xfer = dsi->xfer;
> > + u8 *payload = xfer->msg->rx_buf;
> > + u32 val;
> > + u16 word_count;
> > + u8 channel;
> > + u8 data_type;
> > +
> > + xfer->status = 0;
> > +
> > + if (xfer->rx_word_count == 0) {
> > + if (!(status & RX_PKT_HDR_RCVD))
> > + return false;
> > + /* Get the RX header and parse it */
> > + val = nwl_dsi_read(dsi, RX_PKT_HEADER);
> > + word_count = WC(val);
> > + channel = RX_VC(val);
> > + data_type = RX_DT(val);
> > +
> > + if (channel != xfer->msg->channel) {
> > + DRM_DEV_ERROR(dev,
> > + "[%02X] Channel mismatch (%u != %u)\n",
> > + xfer->cmd, channel, xfer->msg->channel);
> > + return true;
> > + }
> > +
> > + switch (data_type) {
> > + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
> > + /* Fall through */
> > + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
> > + if (xfer->msg->rx_len > 1) {
> > + /* read second byte */
> > + payload[1] = word_count >> 8;
> > + ++xfer->rx_len;
> > + }
> > + /* Fall through */
> > + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
> > + /* Fall through */
> > + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
> > + if (xfer->msg->rx_len > 0) {
> > + /* read first byte */
> > + payload[0] = word_count & 0xff;
> > + ++xfer->rx_len;
> > + }
> > + xfer->status = xfer->rx_len;
> > + return true;
> > + case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
> > + word_count &= 0xff;
> > + DRM_DEV_ERROR(dev, "[%02X] DSI error report: 0x%02x\n",
> > + xfer->cmd, word_count);
> > + xfer->status = -EPROTO;
> > + return true;
> > + }
> > +
> > + if (word_count > xfer->msg->rx_len) {
> > + DRM_DEV_ERROR(
> > + dev,
> > + "[%02X] Receive buffer too small: %lu (< %u)\n",
> > + xfer->cmd, xfer->msg->rx_len, word_count);
> > + return true;
> > + }
> > +
> > + xfer->rx_word_count = word_count;
> > + } else {
> > + /* Set word_count from previous header read */
> > + word_count = xfer->rx_word_count;
> > + }
> > +
> > + /* If RX payload is not yet received, wait for it */
> > + if (!(status & RX_PKT_PAYLOAD_DATA_RCVD))
> > + return false;
> > +
> > + /* Read the RX payload */
> > + while (word_count >= 4) {
> > + val = nwl_dsi_read(dsi, RX_PAYLOAD);
> > + payload[0] = (val >> 0) & 0xff;
> > + payload[1] = (val >> 8) & 0xff;
> > + payload[2] = (val >> 16) & 0xff;
> > + payload[3] = (val >> 24) & 0xff;
> > + payload += 4;
> > + xfer->rx_len += 4;
> > + word_count -= 4;
> > + }
> > +
> > + if (word_count > 0) {
> > + val = nwl_dsi_read(dsi, RX_PAYLOAD);
> > + switch (word_count) {
> > + case 3:
> > + payload[2] = (val >> 16) & 0xff;
> > + ++xfer->rx_len;
> > + /* Fall through */
> > + case 2:
> > + payload[1] = (val >> 8) & 0xff;
> > + ++xfer->rx_len;
> > + /* Fall through */
> > + case 1:
> > + payload[0] = (val >> 0) & 0xff;
> > + ++xfer->rx_len;
> > + break;
> > + }
> > + }
> > +
> > + xfer->status = xfer->rx_len;
> > +
> > + return true;
> > +}
> > +
> > +static void nwl_dsi_finish_transmission(struct imx_nwl_dsi *dsi, u32 status)
> > +{
> > + struct mipi_dsi_transfer *xfer = dsi->xfer;
> > + bool end_packet = false;
> > +
> > + if (!xfer)
> > + return;
> > +
> > + if (status & TX_FIFO_OVFLW) {
> > + DRM_DEV_ERROR_RATELIMITED(dsi->dev, "tx fifo overflow\n");
> > + return;
> > + }
> > +
> > + if (status & HS_TX_TIMEOUT) {
> > + DRM_DEV_ERROR_RATELIMITED(dsi->dev, "HS tx timeout\n");
> > + return;
> > + }
> > +
> > + if (xfer->direction == DSI_PACKET_SEND && status & TX_PKT_DONE) {
> > + xfer->status = xfer->tx_len;
> > + end_packet = true;
> > + } else if (status & DPHY_DIRECTION &&
> > + ((status & (RX_PKT_HDR_RCVD | RX_PKT_PAYLOAD_DATA_RCVD)))) {
> > + end_packet = nwl_dsi_read_packet(dsi, status);
> > + }
> > +
> > + if (end_packet)
> > + complete(&xfer->completed);
> > +}
> > +
> > +static void nwl_dsi_begin_transmission(struct imx_nwl_dsi *dsi)
> > +{
> > + struct mipi_dsi_transfer *xfer = dsi->xfer;
> > + struct mipi_dsi_packet *pkt = &xfer->packet;
> > + const u8 *payload;
> > + size_t length;
> > + u16 word_count;
> > + u8 hs_mode;
> > + u32 val;
> > + u32 hs_workaround = 0;
> > +
> > + /* Send the payload, if any */
> > + length = pkt->payload_length;
> > + payload = pkt->payload;
> > +
> > + while (length >= 4) {
> > + val = get_unaligned_le32(payload);
>
> The framework doesn't guarantee the payload to be aligned on a multiple
> of 4 bytes ?
It does as far as i can tell, dropped.
>
> > + hs_workaround |= !(val & 0xFFFF00);
> > + nwl_dsi_write(dsi, TX_PAYLOAD, val);
> > + payload += 4;
> > + length -= 4;
> > + }
> > + /* Send the rest of the payload */
> > + val = 0;
> > + switch (length) {
> > + case 3:
> > + val |= payload[2] << 16;
> > + /* Fall through */
> > + case 2:
> > + val |= payload[1] << 8;
> > + hs_workaround |= !(val & 0xFFFF00);
> > + /* Fall through */
> > + case 1:
> > + val |= payload[0];
> > + nwl_dsi_write(dsi, TX_PAYLOAD, val);
> > + break;
> > + }
> > + xfer->tx_len = pkt->payload_length;
> > +
> > + /*
> > + * Send the header
> > + * header[0] = Virtual Channel + Data Type
> > + * header[1] = Word Count LSB (LP) or first param (SP)
> > + * header[2] = Word Count MSB (LP) or second param (SP)
> > + */
> > + word_count = pkt->header[1] | (pkt->header[2] << 8);
> > + if ((hs_workaround && USE_E11418_HS_MODE_QUIRK(dsi->quirks))) {
> > + DRM_DEV_DEBUG_DRIVER(dsi->dev,
> > + "Using hs mode workaround for cmd 0x%x\n",
> > + xfer->cmd);
> > + hs_mode = 1;
> > + } else {
> > + hs_mode = (xfer->msg->flags & MIPI_DSI_MSG_USE_LPM) ? 0 : 1;
> > + }
> > + val = WC(word_count) |
> > + TX_VC(xfer->msg->channel) |
> > + TX_DT(xfer->msg->type) |
> > + HS_SEL(hs_mode) |
> > + BTA_TX(xfer->need_bta);
> > + nwl_dsi_write(dsi, PKT_CONTROL, val);
> > +
> > + /* Send packet command */
> > + nwl_dsi_write(dsi, SEND_PACKET, 0x1);
> > +}
> > +
> > +static ssize_t nwl_dsi_host_transfer(struct mipi_dsi_host *dsi_host,
> > + const struct mipi_dsi_msg *msg)
> > +{
> > + struct imx_nwl_dsi *dsi =
> > + container_of(dsi_host, struct imx_nwl_dsi, dsi_host);
> > + struct mipi_dsi_transfer xfer;
> > + ssize_t ret = 0;
> > +
> > + /* Create packet to be sent */
> > + dsi->xfer = &xfer;
> > + ret = mipi_dsi_create_packet(&xfer.packet, msg);
> > + if (ret < 0) {
> > + dsi->xfer = NULL;
> > + return ret;
> > + }
> > +
> > + if ((msg->type & MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM ||
> > + msg->type & MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM ||
> > + msg->type & MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM ||
> > + msg->type & MIPI_DSI_DCS_READ) &&
> > + msg->rx_len > 0 && msg->rx_buf != NULL)
> > + xfer.direction = DSI_PACKET_RECEIVE;
> > + else
> > + xfer.direction = DSI_PACKET_SEND;
> > +
> > + xfer.need_bta = (xfer.direction == DSI_PACKET_RECEIVE);
> > + xfer.need_bta |= (msg->flags & MIPI_DSI_MSG_REQ_ACK) ? 1 : 0;
> > + xfer.msg = msg;
> > + xfer.status = -ETIMEDOUT;
> > + xfer.rx_word_count = 0;
> > + xfer.rx_len = 0;
> > + xfer.cmd = 0x00;
> > + if (msg->tx_len > 0)
> > + xfer.cmd = ((u8 *)(msg->tx_buf))[0];
> > + init_completion(&xfer.completed);
> > +
> > + nwl_dsi_enable_rx_clock(dsi);
> > +
> > + /* Initiate the DSI packet transmision */
> > + nwl_dsi_begin_transmission(dsi);
> > +
> > + if (!wait_for_completion_timeout(&xfer.completed, MIPI_FIFO_TIMEOUT)) {
> > + DRM_DEV_ERROR(dsi_host->dev, "[%02X] DSI transfer timed out\n",
> > + xfer.cmd);
> > + ret = -ETIMEDOUT;
> > + } else {
> > + ret = xfer.status;
> > + }
> > +
> > + clk_disable_unprepare(dsi->rx_esc_clk);
> > +
> > + return ret;
> > +}
> > +
> > +const struct mipi_dsi_host_ops nwl_dsi_host_ops = {
> > + .attach = nwl_dsi_host_attach,
> > + .detach = nwl_dsi_host_detach,
> > + .transfer = nwl_dsi_host_transfer,
> > +};
> > +
> > +irqreturn_t nwl_dsi_irq_handler(int irq, void *data)
> > +{
> > + u32 irq_status;
> > + struct imx_nwl_dsi *dsi = data;
> > +
> > + irq_status = nwl_dsi_read(dsi, IRQ_STATUS);
> > +
> > + if (irq_status & TX_PKT_DONE || irq_status & RX_PKT_HDR_RCVD ||
> > + irq_status & RX_PKT_PAYLOAD_DATA_RCVD)
> > + nwl_dsi_finish_transmission(dsi, irq_status);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +EXPORT_SYMBOL_GPL(nwl_dsi_irq_handler);
> > +
> > +int nwl_dsi_enable(struct imx_nwl_dsi *dsi)
> > +{
> > + struct device *dev = dsi->dev;
> > + union phy_configure_opts *phy_cfg = &dsi->phy_cfg;
> > + int ret;
> > +
> > + if (!dsi->lanes) {
> > + DRM_DEV_ERROR(dev, "Need DSI lanes: %d\n", dsi->lanes);
> > + return -EINVAL;
> > + }
> > +
> > + ret = phy_init(dsi->phy);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to init DSI phy: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = phy_configure(dsi->phy, phy_cfg);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to configure DSI phy: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = nwl_dsi_enable_tx_clock(dsi);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to enable tx clock: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = nwl_dsi_config_host(dsi);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to set up DSI: %d", ret);
> > + return ret;
> > + }
> > +
> > + ret = nwl_dsi_config_dpi(dsi);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to set up DPI: %d", ret);
> > + return ret;
> > + }
> > +
> > + ret = phy_power_on(dsi->phy);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(dev, "Failed to power on DPHY (%d)\n", ret);
> > + return ret;
> > + }
> > +
> > + nwl_dsi_init_interrupts(dsi);
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(nwl_dsi_enable);
> > +
> > +int nwl_dsi_disable(struct imx_nwl_dsi *dsi)
> > +{
> > + struct device *dev = dsi->dev;
> > +
> > + DRM_DEV_DEBUG_DRIVER(dev, "Disabling clocks and phy\n");
> > +
> > + phy_power_off(dsi->phy);
> > + phy_exit(dsi->phy);
> > +
> > + /* Disabling the clock before the phy breaks enabling dsi again */
> > + clk_disable_unprepare(dsi->tx_esc_clk);
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(nwl_dsi_disable);
> > diff --git a/drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.h b/drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.h
> > new file mode 100644
> > index 000000000000..7bcf804843e2
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.h
> > @@ -0,0 +1,111 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * i.MX8 NWL MIPI DSI host driver
> > + *
> > + * Copyright (C) 2017 NXP
> > + * Copyright (C) 2019 Purism SPC
> > + */
> > +#ifndef __NWL_DSI_H__
> > +#define __NWL_DSI_H__
> > +
> > +#include <drm/drm_mipi_dsi.h>
> > +
> > +/* DSI HOST registers */
> > +#define CFG_NUM_LANES 0x0
>
> Some of the register names are quite prone to namespace clashes. I
> recommend prefixing them all with NWL_DSI_.
Done, also the defines in nwl-dsi.c.
>
> > +#define CFG_NONCONTINUOUS_CLK 0x4
> > +#define CFG_T_PRE 0x8
> > +#define CFG_T_POST 0xc
> > +#define CFG_TX_GAP 0x10
> > +#define CFG_AUTOINSERT_EOTP 0x14
> > +#define CFG_EXTRA_CMDS_AFTER_EOTP 0x18
> > +#define CFG_HTX_TO_COUNT 0x1c
> > +#define CFG_LRX_H_TO_COUNT 0x20
> > +#define CFG_BTA_H_TO_COUNT 0x24
> > +#define CFG_TWAKEUP 0x28
> > +#define CFG_STATUS_OUT 0x2c
> > +#define RX_ERROR_STATUS 0x30
> > +
> > +/* DSI DPI registers */
> > +#define PIXEL_PAYLOAD_SIZE 0x200
> > +#define PIXEL_FIFO_SEND_LEVEL 0x204
> > +#define INTERFACE_COLOR_CODING 0x208
> > +#define PIXEL_FORMAT 0x20c
> > +#define VSYNC_POLARITY 0x210
> > +#define VSYNC_POLARITY_ACTIVE_LOW 0
> > +#define VSYNC_POLARITY_ACTIVE_HIGH BIT(1)
> > +
> > +#define HSYNC_POLARITY 0x214
> > +#define HSYNC_POLARITY_ACTIVE_LOW 0
> > +#define HSYNC_POLARITY_ACTIVE_HIGH BIT(1)
> > +
> > +#define VIDEO_MODE 0x218
> > +#define HFP 0x21c
> > +#define HBP 0x220
> > +#define HSA 0x224
> > +#define ENABLE_MULT_PKTS 0x228
> > +#define VBP 0x22c
> > +#define VFP 0x230
> > +#define BLLP_MODE 0x234
> > +#define USE_NULL_PKT_BLLP 0x238
> > +#define VACTIVE 0x23c
> > +#define VC 0x240
> > +
> > +/* DSI APB PKT control */
> > +#define TX_PAYLOAD 0x280
> > +#define PKT_CONTROL 0x284
> > +#define SEND_PACKET 0x288
> > +#define PKT_STATUS 0x28c
> > +#define PKT_FIFO_WR_LEVEL 0x290
> > +#define PKT_FIFO_RD_LEVEL 0x294
> > +#define RX_PAYLOAD 0x298
> > +#define RX_PKT_HEADER 0x29c
> > +
> > +/* DSI IRQ handling */
> > +#define IRQ_STATUS 0x2a0
> > +#define SM_NOT_IDLE BIT(0)
> > +#define TX_PKT_DONE BIT(1)
> > +#define DPHY_DIRECTION BIT(2)
> > +#define TX_FIFO_OVFLW BIT(3)
> > +#define TX_FIFO_UDFLW BIT(4)
> > +#define RX_FIFO_OVFLW BIT(5)
> > +#define RX_FIFO_UDFLW BIT(6)
> > +#define RX_PKT_HDR_RCVD BIT(7)
> > +#define RX_PKT_PAYLOAD_DATA_RCVD BIT(8)
> > +#define BTA_TIMEOUT BIT(29)
> > +#define LP_RX_TIMEOUT BIT(30)
> > +#define HS_TX_TIMEOUT BIT(31)
> > +
> > +#define IRQ_STATUS2 0x2a4
> > +#define SINGLE_BIT_ECC_ERR BIT(0)
> > +#define MULTI_BIT_ECC_ERR BIT(1)
> > +#define CRC_ERR BIT(2)
> > +
> > +#define IRQ_MASK 0x2a8
> > +#define SM_NOT_IDLE_MASK BIT(0)
> > +#define TX_PKT_DONE_MASK BIT(1)
> > +#define DPHY_DIRECTION_MASK BIT(2)
> > +#define TX_FIFO_OVFLW_MASK BIT(3)
> > +#define TX_FIFO_UDFLW_MASK BIT(4)
> > +#define RX_FIFO_OVFLW_MASK BIT(5)
> > +#define RX_FIFO_UDFLW_MASK BIT(6)
> > +#define RX_PKT_HDR_RCVD_MASK BIT(7)
> > +#define RX_PKT_PAYLOAD_DATA_RCVD_MASK BIT(8)
> > +#define BTA_TIMEOUT_MASK BIT(29)
> > +#define LP_RX_TIMEOUT_MASK BIT(30)
> > +#define HS_TX_TIMEOUT_MASK BIT(31)
> > +
> > +#define IRQ_MASK2 0x2ac
> > +#define SINGLE_BIT_ECC_ERR_MASK BIT(0)
> > +#define MULTI_BIT_ECC_ERR_MASK BIT(1)
> > +#define CRC_ERR_MASK BIT(2)
> > +
> > +extern const struct mipi_dsi_host_ops nwl_dsi_host_ops;
> > +
> > +irqreturn_t nwl_dsi_irq_handler(int irq, void *data);
> > +int nwl_dsi_enable(struct imx_nwl_dsi *dsi);
> > +int nwl_dsi_disable(struct imx_nwl_dsi *dsi);
> > +int nwl_dsi_get_dphy_params(struct imx_nwl_dsi *dsi,
> > + const struct drm_display_mode *mode,
> > + union phy_configure_opts *phy_opts);
> > +
> > +#endif /* __NWL_DSI_H__ */
>
> --
> Regards,
>
> Laurent Pinchart
>
Cheers and thanks for having a look!
-- Guido
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 1/2] samples/rpmsg: Replace print_hex_dump() with print_hex_dump_debug()
From: Suman Anna @ 2019-08-09 16:27 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen
Cc: linux-remoteproc, linux-kernel, linux-arm-kernel
In-Reply-To: <20190809162710.823-1-s-anna@ti.com>
Replace the raw print_hex_dump() call in the rpmsg_sample_cb() function
with the equivalent print_hex_dump_debug() better suited for dynamic
debug. This switch allows flexibility of controlling this trace through
dynamic debug when enabled.
Signed-off-by: Suman Anna <s-anna@ti.com>
---
samples/rpmsg/rpmsg_client_sample.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
index 2a0695573b47..b9a99e621a5c 100644
--- a/samples/rpmsg/rpmsg_client_sample.c
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -29,8 +29,8 @@ static int rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
dev_info(&rpdev->dev, "incoming msg %d (src: 0x%x)\n",
++idata->rx_count, src);
- print_hex_dump(KERN_DEBUG, __func__, DUMP_PREFIX_NONE, 16, 1,
- data, len, true);
+ print_hex_dump_debug(__func__, DUMP_PREFIX_NONE, 16, 1, data, len,
+ true);
/* samples should not live forever */
if (idata->rx_count >= MSG_LIMIT) {
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 2/2] samples/rpmsg: Introduce a module parameter for message count
From: Suman Anna @ 2019-08-09 16:27 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen
Cc: linux-remoteproc, linux-kernel, linux-arm-kernel
In-Reply-To: <20190809162710.823-1-s-anna@ti.com>
The current rpmsg_client_sample uses a fixed number of messages to
be sent to each instance. This is currently set at 100. Introduce
an optional module parameter 'count' so that the number of messages
to be exchanged can be made flexible.
Signed-off-by: Suman Anna <s-anna@ti.com>
---
samples/rpmsg/rpmsg_client_sample.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
index b9a99e621a5c..ae5081662283 100644
--- a/samples/rpmsg/rpmsg_client_sample.c
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -14,7 +14,9 @@
#include <linux/rpmsg.h>
#define MSG "hello world!"
-#define MSG_LIMIT 100
+
+static int count = 100;
+module_param(count, int, 0644);
struct instance_data {
int rx_count;
@@ -33,7 +35,7 @@ static int rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
true);
/* samples should not live forever */
- if (idata->rx_count >= MSG_LIMIT) {
+ if (idata->rx_count >= count) {
dev_info(&rpdev->dev, "goodbye!\n");
return 0;
}
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 0/2] Minor cleanups/improvements in rpmsg-client-sample
From: Suman Anna @ 2019-08-09 16:27 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen
Cc: linux-remoteproc, linux-kernel, linux-arm-kernel
Hi Bjorn,
The following are minor cleanup/improvement patches to the rpmsg_client_sample.
The first patch is new, and the second patch is a repost. Appreciate it if you
can pick these up for 5.4 merge window.
regards
Suman
Suman Anna (2):
samples/rpmsg: Replace print_hex_dump() with print_hex_dump_debug()
samples/rpmsg: Introduce a module parameter for message count
samples/rpmsg/rpmsg_client_sample.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 0/7] ARM: preparation for multiplatform iop32x
From: Arnd Bergmann @ 2019-08-09 16:29 UTC (permalink / raw)
To: soc
Cc: Dave Jiang, Arnd Bergmann, Linus Walleij, Russell King,
linux-arm-kernel, Dan Williams, Imre Kaloz, Martin Michlmayr,
Lennert Buytenhek
I'm looking into converting some of the remaining ARMv5
platforms in arch/arm/ to work together in a single kernel
binary.
IOP32x seems to be a fairly easy target for multiplatform
by itself, but the way the plat-iop code interacts with
three generations of the code, and how the dma-adma driver
is configured at compile-time for each version gets in the
way.
I considered adding more indirection layers for those two,
but removing iop33x and iop13xx is much easier in comparison,
so this is the first approach I'm posting.
If we conclude that iop33x and iop13xx are indeed not used
any more, the remaining patches in this series are
straightforward. The actual multiplatform conversion also
requires changes to the irqchip driver that are not completely
mechanic, and we can discuss those after deciding what to do
with the first set.
Adding a few people to Cc that historically worked on IOP.
Arnd
Arnd Bergmann (7):
[RFC] ARM: remove Intel iop33x and iop13xx support
dma: iop-adma: include prefetch.h
dma: iop-adma: use correct printk format strings
dma: iop-adma: allow building without platform headers
ARM: xscale: fix multi-cpu compilation
ARM: iop32x: make mach/uncompress.h independent of mach/hardware.h
ARM: iop32x: merge everything into mach-iop32x/
arch/arm/Kconfig | 30 -
arch/arm/Kconfig.debug | 8 +-
arch/arm/Makefile | 3 -
arch/arm/configs/iop13xx_defconfig | 118 --
arch/arm/configs/iop33x_defconfig | 85 --
arch/arm/mach-iop13xx/Kconfig | 21 -
arch/arm/mach-iop13xx/Makefile | 9 -
arch/arm/mach-iop13xx/Makefile.boot | 4 -
arch/arm/mach-iop13xx/include/mach/adma.h | 608 ---------
.../mach-iop13xx/include/mach/entry-macro.S | 29 -
arch/arm/mach-iop13xx/include/mach/hardware.h | 22 -
arch/arm/mach-iop13xx/include/mach/iop13xx.h | 508 --------
arch/arm/mach-iop13xx/include/mach/iq81340.h | 29 -
arch/arm/mach-iop13xx/include/mach/irqs.h | 195 ---
arch/arm/mach-iop13xx/include/mach/time.h | 127 --
.../mach-iop13xx/include/mach/uncompress.h | 23 -
arch/arm/mach-iop13xx/io.c | 77 --
arch/arm/mach-iop13xx/iq81340mc.c | 84 --
arch/arm/mach-iop13xx/iq81340sc.c | 86 --
arch/arm/mach-iop13xx/irq.c | 227 ----
arch/arm/mach-iop13xx/msi.c | 152 ---
arch/arm/mach-iop13xx/msi.h | 12 -
arch/arm/mach-iop13xx/pci.c | 1115 -----------------
arch/arm/mach-iop13xx/pci.h | 66 -
arch/arm/mach-iop13xx/setup.c | 595 ---------
arch/arm/mach-iop13xx/tpmi.c | 244 ----
arch/arm/mach-iop32x/Makefile | 10 +-
arch/arm/{plat-iop => mach-iop32x}/adma.c | 39 +-
arch/arm/{plat-iop => mach-iop32x}/cp6.c | 0
arch/arm/mach-iop32x/em7210.c | 5 +-
arch/arm/mach-iop32x/glantank.c | 5 +-
.../mach-iop32x/{include/mach => }/glantank.h | 2 -
.../mach-iop32x/{include/mach => }/hardware.h | 6 +-
arch/arm/{plat-iop => mach-iop32x}/i2c.c | 21 +-
arch/arm/mach-iop32x/include/mach/adma.h | 6 -
.../mach-iop32x/include/mach/entry-macro.S | 2 -
arch/arm/mach-iop32x/include/mach/iop32x.h | 31 -
arch/arm/mach-iop32x/include/mach/irqs.h | 33 -
arch/arm/mach-iop32x/include/mach/time.h | 5 -
.../arm/mach-iop32x/include/mach/uncompress.h | 18 +-
.../asm/hardware => mach-iop32x}/iop3xx.h | 18 +-
arch/arm/mach-iop32x/iq31244.c | 5 +-
.../mach-iop32x/{include/mach => }/iq31244.h | 2 -
arch/arm/mach-iop32x/iq80321.c | 5 +-
.../mach-iop32x/{include/mach => }/iq80321.h | 2 -
arch/arm/mach-iop32x/irq.c | 3 +-
arch/arm/mach-iop32x/irqs.h | 42 +
arch/arm/mach-iop32x/n2100.c | 5 +-
.../mach-iop32x/{include/mach => }/n2100.h | 2 -
arch/arm/{plat-iop => mach-iop32x}/pci.c | 4 +-
arch/arm/{plat-iop => mach-iop32x}/pmu.c | 8 +-
arch/arm/{plat-iop => mach-iop32x}/restart.c | 4 +-
arch/arm/{plat-iop => mach-iop32x}/setup.c | 2 +-
arch/arm/{plat-iop => mach-iop32x}/time.c | 7 +-
arch/arm/mach-iop33x/Kconfig | 22 -
arch/arm/mach-iop33x/Makefile | 9 -
arch/arm/mach-iop33x/Makefile.boot | 4 -
arch/arm/mach-iop33x/include/mach/adma.h | 6 -
.../mach-iop33x/include/mach/entry-macro.S | 34 -
arch/arm/mach-iop33x/include/mach/hardware.h | 44 -
arch/arm/mach-iop33x/include/mach/iop33x.h | 37 -
arch/arm/mach-iop33x/include/mach/iq80331.h | 17 -
arch/arm/mach-iop33x/include/mach/iq80332.h | 17 -
arch/arm/mach-iop33x/include/mach/irqs.h | 57 -
arch/arm/mach-iop33x/include/mach/time.h | 5 -
.../arm/mach-iop33x/include/mach/uncompress.h | 37 -
arch/arm/mach-iop33x/iq80331.c | 148 ---
arch/arm/mach-iop33x/iq80332.c | 148 ---
arch/arm/mach-iop33x/irq.c | 115 --
arch/arm/mach-iop33x/uart.c | 100 --
arch/arm/mm/copypage-xscale.c | 6 +-
arch/arm/plat-iop/Makefile | 28 -
drivers/dma/Kconfig | 4 +-
drivers/dma/iop-adma.c | 22 +-
.../iop3xx-adma.h => drivers/dma/iop-adma.h | 7 +-
drivers/gpio/Kconfig | 2 +-
drivers/i2c/busses/Kconfig | 2 +-
.../linux/platform_data/dma-iop32x.h | 4 +
78 files changed, 134 insertions(+), 5510 deletions(-)
delete mode 100644 arch/arm/configs/iop13xx_defconfig
delete mode 100644 arch/arm/configs/iop33x_defconfig
delete mode 100644 arch/arm/mach-iop13xx/Kconfig
delete mode 100644 arch/arm/mach-iop13xx/Makefile
delete mode 100644 arch/arm/mach-iop13xx/Makefile.boot
delete mode 100644 arch/arm/mach-iop13xx/include/mach/adma.h
delete mode 100644 arch/arm/mach-iop13xx/include/mach/entry-macro.S
delete mode 100644 arch/arm/mach-iop13xx/include/mach/hardware.h
delete mode 100644 arch/arm/mach-iop13xx/include/mach/iop13xx.h
delete mode 100644 arch/arm/mach-iop13xx/include/mach/iq81340.h
delete mode 100644 arch/arm/mach-iop13xx/include/mach/irqs.h
delete mode 100644 arch/arm/mach-iop13xx/include/mach/time.h
delete mode 100644 arch/arm/mach-iop13xx/include/mach/uncompress.h
delete mode 100644 arch/arm/mach-iop13xx/io.c
delete mode 100644 arch/arm/mach-iop13xx/iq81340mc.c
delete mode 100644 arch/arm/mach-iop13xx/iq81340sc.c
delete mode 100644 arch/arm/mach-iop13xx/irq.c
delete mode 100644 arch/arm/mach-iop13xx/msi.c
delete mode 100644 arch/arm/mach-iop13xx/msi.h
delete mode 100644 arch/arm/mach-iop13xx/pci.c
delete mode 100644 arch/arm/mach-iop13xx/pci.h
delete mode 100644 arch/arm/mach-iop13xx/setup.c
delete mode 100644 arch/arm/mach-iop13xx/tpmi.c
rename arch/arm/{plat-iop => mach-iop32x}/adma.c (75%)
rename arch/arm/{plat-iop => mach-iop32x}/cp6.c (100%)
rename arch/arm/mach-iop32x/{include/mach => }/glantank.h (78%)
rename arch/arm/mach-iop32x/{include/mach => }/hardware.h (90%)
rename arch/arm/{plat-iop => mach-iop32x}/i2c.c (81%)
delete mode 100644 arch/arm/mach-iop32x/include/mach/adma.h
delete mode 100644 arch/arm/mach-iop32x/include/mach/iop32x.h
delete mode 100644 arch/arm/mach-iop32x/include/mach/time.h
rename arch/arm/{include/asm/hardware => mach-iop32x}/iop3xx.h (96%)
rename arch/arm/mach-iop32x/{include/mach => }/iq31244.h (89%)
rename arch/arm/mach-iop32x/{include/mach => }/iq80321.h (89%)
create mode 100644 arch/arm/mach-iop32x/irqs.h
rename arch/arm/mach-iop32x/{include/mach => }/n2100.h (89%)
rename arch/arm/{plat-iop => mach-iop32x}/pci.c (99%)
rename arch/arm/{plat-iop => mach-iop32x}/pmu.c (79%)
rename arch/arm/{plat-iop => mach-iop32x}/restart.c (82%)
rename arch/arm/{plat-iop => mach-iop32x}/setup.c (95%)
rename arch/arm/{plat-iop => mach-iop32x}/time.c (97%)
delete mode 100644 arch/arm/mach-iop33x/Kconfig
delete mode 100644 arch/arm/mach-iop33x/Makefile
delete mode 100644 arch/arm/mach-iop33x/Makefile.boot
delete mode 100644 arch/arm/mach-iop33x/include/mach/adma.h
delete mode 100644 arch/arm/mach-iop33x/include/mach/entry-macro.S
delete mode 100644 arch/arm/mach-iop33x/include/mach/hardware.h
delete mode 100644 arch/arm/mach-iop33x/include/mach/iop33x.h
delete mode 100644 arch/arm/mach-iop33x/include/mach/iq80331.h
delete mode 100644 arch/arm/mach-iop33x/include/mach/iq80332.h
delete mode 100644 arch/arm/mach-iop33x/include/mach/irqs.h
delete mode 100644 arch/arm/mach-iop33x/include/mach/time.h
delete mode 100644 arch/arm/mach-iop33x/include/mach/uncompress.h
delete mode 100644 arch/arm/mach-iop33x/iq80331.c
delete mode 100644 arch/arm/mach-iop33x/iq80332.c
delete mode 100644 arch/arm/mach-iop33x/irq.c
delete mode 100644 arch/arm/mach-iop33x/uart.c
delete mode 100644 arch/arm/plat-iop/Makefile
rename arch/arm/include/asm/hardware/iop3xx-adma.h => drivers/dma/iop-adma.h (99%)
rename arch/arm/include/asm/hardware/iop_adma.h => include/linux/platform_data/dma-iop32x.h (98%)
--
2.20.0
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Martin Michlmayr <tbm@cyrius.com>
Cc: Imre Kaloz <kaloz@openwrt.org>
Cc: linux-arm-kernel@lists.infradead.org
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 09/13] net: lpc-enet: fix printk format strings
From: Joe Perches @ 2019-08-09 16:30 UTC (permalink / raw)
To: Arnd Bergmann, soc
Cc: kbuild test robot, netdev, linux-kernel, Vladimir Zapolskiy,
Sylvain Lemieux, David S. Miller, linux-arm-kernel
In-Reply-To: <20190809144043.476786-10-arnd@arndb.de>
On Fri, 2019-08-09 at 16:40 +0200, Arnd Bergmann wrote:
> compile-testing this driver on other architectures showed
> multiple warnings:
>
> drivers/net/ethernet/nxp/lpc_eth.c: In function 'lpc_eth_drv_probe':
> drivers/net/ethernet/nxp/lpc_eth.c:1337:19: warning: format '%d' expects argument of type 'int', but argument 4 has type 'resource_size_t {aka long long unsigned int}' [-Wformat=]
>
> drivers/net/ethernet/nxp/lpc_eth.c:1342:19: warning: format '%x' expects argument of type 'unsigned int', but argument 4 has type 'dma_addr_t {aka long long unsigned int}' [-Wformat=]
>
> Use format strings that work on all architectures.
[]
> diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
[]
> @@ -1333,13 +1333,14 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
> pldat->dma_buff_base_p = dma_handle;
>
> netdev_dbg(ndev, "IO address space :%pR\n", res);
> - netdev_dbg(ndev, "IO address size :%d\n", resource_size(res));
> + netdev_dbg(ndev, "IO address size :%zd\n",
> + (size_t)resource_size(res));
Ideally all these would use %zu not %zd
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 2/7] dma: iop-adma: include prefetch.h
From: Arnd Bergmann @ 2019-08-09 16:33 UTC (permalink / raw)
To: soc
Cc: kbuild test robot, Arnd Bergmann, linux-gpio, Linus Walleij,
Russell King, linux-kernel, Bartosz Golaszewski, Vinod Koul,
linux-i2c, dmaengine, Dan Williams, linux-arm-kernel
In-Reply-To: <20190809163334.489360-1-arnd@arndb.de>
Compile-testing this driver fails on m68k without the
extra header inclusion.
Reported-by: kbuild test robot <lkp@intel.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/dma/iop-adma.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index c6c0143670d9..7857b54770d1 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -16,6 +16,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/prefetch.h>
#include <linux/memory.h>
#include <linux/ioport.h>
#include <linux/raid/pq.h>
--
2.20.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 3/7] dma: iop-adma: use correct printk format strings
From: Arnd Bergmann @ 2019-08-09 16:33 UTC (permalink / raw)
To: soc
Cc: Arnd Bergmann, linux-gpio, Linus Walleij, Russell King,
linux-kernel, Bartosz Golaszewski, Vinod Koul, linux-i2c,
dmaengine, Dan Williams, linux-arm-kernel
In-Reply-To: <20190809163334.489360-1-arnd@arndb.de>
When compile-testing on other architectures, we get lots of warnings
about incorrect format strings, like:
drivers/dma/iop-adma.c: In function 'iop_adma_alloc_slots':
drivers/dma/iop-adma.c:307:6: warning: format '%x' expects argument of type 'unsigned int', but argument 6 has type 'dma_addr_t {aka long long unsigned int}' [-Wformat=]
drivers/dma/iop-adma.c: In function 'iop_adma_prep_dma_memcpy':
>> drivers/dma/iop-adma.c:518:40: warning: format '%u' expects argument of type 'unsigned int', but argument 5 has type 'size_t {aka long unsigned int}' [-Wformat=]
Use %zu for printing size_t as required, and cast the dma_addr_t
arguments to 'u64' for printing with %llx. Ideally this should use
the %pad format string, but that requires an lvalue argument that
doesn't work here.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/dma/iop-adma.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 7857b54770d1..aebdd671651a 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -117,9 +117,9 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
chain_node) {
pr_debug("\tcookie: %d slot: %d busy: %d "
- "this_desc: %#x next_desc: %#x ack: %d\n",
+ "this_desc: %#x next_desc: %#llx ack: %d\n",
iter->async_tx.cookie, iter->idx, busy,
- iter->async_tx.phys, iop_desc_get_next_desc(iter),
+ iter->async_tx.phys, (u64)iop_desc_get_next_desc(iter),
async_tx_test_ack(&iter->async_tx));
prefetch(_iter);
prefetch(&_iter->async_tx);
@@ -307,9 +307,9 @@ iop_adma_alloc_slots(struct iop_adma_chan *iop_chan, int num_slots,
int i;
dev_dbg(iop_chan->device->common.dev,
"allocated slot: %d "
- "(desc %p phys: %#x) slots_per_op %d\n",
+ "(desc %p phys: %#llx) slots_per_op %d\n",
iter->idx, iter->hw_desc,
- iter->async_tx.phys, slots_per_op);
+ (u64)iter->async_tx.phys, slots_per_op);
/* pre-ack all but the last descriptor */
if (num_slots != slots_per_op)
@@ -517,7 +517,7 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
return NULL;
BUG_ON(len > IOP_ADMA_MAX_BYTE_COUNT);
- dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+ dev_dbg(iop_chan->device->common.dev, "%s len: %zu\n",
__func__, len);
spin_lock_bh(&iop_chan->lock);
@@ -550,7 +550,7 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,
BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT);
dev_dbg(iop_chan->device->common.dev,
- "%s src_cnt: %d len: %u flags: %lx\n",
+ "%s src_cnt: %d len: %zu flags: %lx\n",
__func__, src_cnt, len, flags);
spin_lock_bh(&iop_chan->lock);
@@ -583,7 +583,7 @@ iop_adma_prep_dma_xor_val(struct dma_chan *chan, dma_addr_t *dma_src,
if (unlikely(!len))
return NULL;
- dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
+ dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %zu\n",
__func__, src_cnt, len);
spin_lock_bh(&iop_chan->lock);
@@ -621,7 +621,7 @@ iop_adma_prep_dma_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT);
dev_dbg(iop_chan->device->common.dev,
- "%s src_cnt: %d len: %u flags: %lx\n",
+ "%s src_cnt: %d len: %zu flags: %lx\n",
__func__, src_cnt, len, flags);
if (dmaf_p_disabled_continue(flags))
@@ -684,7 +684,7 @@ iop_adma_prep_dma_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
return NULL;
BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT);
- dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
+ dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %zu\n",
__func__, src_cnt, len);
spin_lock_bh(&iop_chan->lock);
--
2.20.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 5/7] ARM: xscale: fix multi-cpu compilation
From: Arnd Bergmann @ 2019-08-09 16:33 UTC (permalink / raw)
To: soc
Cc: Arnd Bergmann, linux-gpio, Linus Walleij, Russell King,
linux-kernel, Bartosz Golaszewski, Vinod Koul, linux-i2c,
dmaengine, Dan Williams, linux-arm-kernel
In-Reply-To: <20190809163334.489360-1-arnd@arndb.de>
Building a combined ARMv4+XScale kernel produces these
and other build failures:
/tmp/copypage-xscale-3aa821.s: Assembler messages:
/tmp/copypage-xscale-3aa821.s:167: Error: selected processor does not support `pld [r7,#0]' in ARM mode
/tmp/copypage-xscale-3aa821.s:168: Error: selected processor does not support `pld [r7,#32]' in ARM mode
/tmp/copypage-xscale-3aa821.s:169: Error: selected processor does not support `pld [r1,#0]' in ARM mode
/tmp/copypage-xscale-3aa821.s:170: Error: selected processor does not support `pld [r1,#32]' in ARM mode
/tmp/copypage-xscale-3aa821.s:171: Error: selected processor does not support `pld [r7,#64]' in ARM mode
/tmp/copypage-xscale-3aa821.s:176: Error: selected processor does not support `ldrd r4,r5,[r7],#8' in ARM mode
/tmp/copypage-xscale-3aa821.s:180: Error: selected processor does not support `strd r4,r5,[r1],#8' in ARM mode
Add an explict .arch armv5 in the inline assembly to allow the ARMv5
specific instructions regardless of the compiler -march= target.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arm/mm/copypage-xscale.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 61d834157bc0..382e1c2855e8 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -42,6 +42,7 @@ static void mc_copy_user_page(void *from, void *to)
* when prefetching destination as well. (NP)
*/
asm volatile ("\
+.arch xscale \n\
pld [%0, #0] \n\
pld [%0, #32] \n\
pld [%1, #0] \n\
@@ -106,8 +107,9 @@ void
xscale_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
{
void *ptr, *kaddr = kmap_atomic(page);
- asm volatile(
- "mov r1, %2 \n\
+ asm volatile("\
+.arch xscale \n\
+ mov r1, %2 \n\
mov r2, #0 \n\
mov r3, #0 \n\
1: mov ip, %0 \n\
--
2.20.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 4/7] dma: iop-adma: allow building without platform headers
From: Arnd Bergmann @ 2019-08-09 16:33 UTC (permalink / raw)
To: soc
Cc: Arnd Bergmann, linux-gpio, Linus Walleij, Russell King,
linux-kernel, Bartosz Golaszewski, Vinod Koul, linux-i2c,
dmaengine, Dan Williams, linux-arm-kernel
In-Reply-To: <20190809163334.489360-1-arnd@arndb.de>
Now that iop3xx and iop13xx are gone, the iop-adma driver no
longer needs to deal with incompatible register layout defined
in machine specific header files.
Move the iop32x specific definitions into drivers/dma/iop-adma.h
and the platform_data into include/linux/platform_data/dma-iop32x.h,
and change the machine code to no longer reference those.
The DMA0_ID/DMA1_ID/AAU_ID macros are required as part of the
platform data interface and still need to be visible, so move
those from one header to the other.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arm/mach-iop32x/include/mach/adma.h | 6 ------
arch/arm/plat-iop/adma.c | 3 +--
drivers/dma/Kconfig | 4 ++--
drivers/dma/iop-adma.c | 3 +--
.../asm/hardware/iop3xx-adma.h => drivers/dma/iop-adma.h | 7 +------
.../iop_adma.h => include/linux/platform_data/dma-iop32x.h | 4 ++++
6 files changed, 9 insertions(+), 18 deletions(-)
delete mode 100644 arch/arm/mach-iop32x/include/mach/adma.h
rename arch/arm/include/asm/hardware/iop3xx-adma.h => drivers/dma/iop-adma.h (99%)
rename arch/arm/include/asm/hardware/iop_adma.h => include/linux/platform_data/dma-iop32x.h (98%)
diff --git a/arch/arm/mach-iop32x/include/mach/adma.h b/arch/arm/mach-iop32x/include/mach/adma.h
deleted file mode 100644
index 2b20063123ad..000000000000
--- a/arch/arm/mach-iop32x/include/mach/adma.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef IOP32X_ADMA_H
-#define IOP32X_ADMA_H
-#include <asm/hardware/iop3xx-adma.h>
-#endif
-
diff --git a/arch/arm/plat-iop/adma.c b/arch/arm/plat-iop/adma.c
index 368496471e60..601cc9c11b07 100644
--- a/arch/arm/plat-iop/adma.c
+++ b/arch/arm/plat-iop/adma.c
@@ -6,8 +6,7 @@
#include <linux/platform_device.h>
#include <asm/hardware/iop3xx.h>
#include <linux/dma-mapping.h>
-#include <mach/adma.h>
-#include <asm/hardware/iop_adma.h>
+#include <linux/platform_data/dma-iop32x.h>
#define IRQ_DMA0_EOT IRQ_IOP32X_DMA0_EOT
#define IRQ_DMA0_EOC IRQ_IOP32X_DMA0_EOC
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index cc84863bc52b..7c511e3db4c8 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -294,8 +294,8 @@ config INTEL_IOATDMA
If unsure, say N.
config INTEL_IOP_ADMA
- tristate "Intel IOP ADMA support"
- depends on ARCH_IOP32X
+ tristate "Intel IOP32x ADMA support"
+ depends on ARCH_IOP32X || COMPILE_TEST
select DMA_ENGINE
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
help
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index aebdd671651a..03f4a588cf7f 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -22,8 +22,7 @@
#include <linux/raid/pq.h>
#include <linux/slab.h>
-#include <mach/adma.h>
-
+#include "iop-adma.h"
#include "dmaengine.h"
#define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
diff --git a/arch/arm/include/asm/hardware/iop3xx-adma.h b/drivers/dma/iop-adma.h
similarity index 99%
rename from arch/arm/include/asm/hardware/iop3xx-adma.h
rename to drivers/dma/iop-adma.h
index 6d998df17efd..c499c9578f00 100644
--- a/arch/arm/include/asm/hardware/iop3xx-adma.h
+++ b/drivers/dma/iop-adma.h
@@ -6,8 +6,7 @@
#define _ADMA_H
#include <linux/types.h>
#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/hardware/iop_adma.h>
+#include <linux/platform_data/dma-iop32x.h>
/* Memory copy units */
#define DMA_CCR(chan) (chan->mmr_base + 0x0)
@@ -34,10 +33,6 @@
#define AAU_EDCR1_IDX 17
#define AAU_EDCR2_IDX 26
-#define DMA0_ID 0
-#define DMA1_ID 1
-#define AAU_ID 2
-
struct iop3xx_aau_desc_ctrl {
unsigned int int_en:1;
unsigned int blk1_cmd_ctrl:3;
diff --git a/arch/arm/include/asm/hardware/iop_adma.h b/include/linux/platform_data/dma-iop32x.h
similarity index 98%
rename from arch/arm/include/asm/hardware/iop_adma.h
rename to include/linux/platform_data/dma-iop32x.h
index bcedbab90ac0..ac83cff89549 100644
--- a/arch/arm/include/asm/hardware/iop_adma.h
+++ b/include/linux/platform_data/dma-iop32x.h
@@ -17,6 +17,10 @@
#endif
#define iop_paranoia(x) BUG_ON(IOP_PARANOIA && (x))
+#define DMA0_ID 0
+#define DMA1_ID 1
+#define AAU_ID 2
+
/**
* struct iop_adma_device - internal representation of an ADMA device
* @pdev: Platform device
--
2.20.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 6/7] ARM: iop32x: make mach/uncompress.h independent of mach/hardware.h
From: Arnd Bergmann @ 2019-08-09 16:33 UTC (permalink / raw)
To: soc
Cc: Arnd Bergmann, linux-gpio, Linus Walleij, Russell King,
linux-kernel, Bartosz Golaszewski, Vinod Koul, linux-i2c,
dmaengine, Dan Williams, linux-arm-kernel
In-Reply-To: <20190809163334.489360-1-arnd@arndb.de>
All supported uarts use the same address: IQ80321_UART and IQ31244_UART
are both defined to the default value of 0xfe800000. By using that as
the address unconditionally, all dependencies on other machine headers
can be avoided.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arm/mach-iop32x/include/mach/uncompress.h | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-iop32x/include/mach/uncompress.h b/arch/arm/mach-iop32x/include/mach/uncompress.h
index ed4ac3e28fa1..c8548875d942 100644
--- a/arch/arm/mach-iop32x/include/mach/uncompress.h
+++ b/arch/arm/mach-iop32x/include/mach/uncompress.h
@@ -6,9 +6,8 @@
#include <asm/types.h>
#include <asm/mach-types.h>
#include <linux/serial_reg.h>
-#include <mach/hardware.h>
-volatile u8 *uart_base;
+#define uart_base ((volatile u8 *)0xfe800000)
#define TX_DONE (UART_LSR_TEMT | UART_LSR_THRE)
@@ -23,17 +22,4 @@ static inline void flush(void)
{
}
-static __inline__ void __arch_decomp_setup(unsigned long arch_id)
-{
- if (machine_is_iq80321())
- uart_base = (volatile u8 *)IQ80321_UART;
- else if (machine_is_iq31244() || machine_is_em7210())
- uart_base = (volatile u8 *)IQ31244_UART;
- else
- uart_base = (volatile u8 *)0xfe800000;
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup() __arch_decomp_setup(arch_id)
+#define arch_decomp_setup() do { } while (0)
--
2.20.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 7/7] ARM: iop32x: merge everything into mach-iop32x/
From: Arnd Bergmann @ 2019-08-09 16:33 UTC (permalink / raw)
To: soc
Cc: Arnd Bergmann, linux-gpio, Linus Walleij, Russell King,
linux-kernel, Bartosz Golaszewski, Vinod Koul, linux-i2c,
dmaengine, Dan Williams, linux-arm-kernel
In-Reply-To: <20190809163334.489360-1-arnd@arndb.de>
Various bits of iop32x are now in their traditional locations in plat-iop,
mach-iop/include/mach/ and in include/asm/mach/hardware. As nothing
outside of the iop32x mach code references these any more, this can all
be moved into one place now.
The only remaining things in the include/mach/ directory are now the
NR_IRQS definition, the entry-macros.S file and the the decompressor
uart access. After the irqchip code has been converted to SPARSE_IRQ
and GENERIC_IRQ_MULTI_HANDLER, it can be moved to ARCH_MULTIPLATFORM.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arm/Makefile | 1 -
arch/arm/mach-iop32x/Makefile | 10 ++++-
arch/arm/{plat-iop => mach-iop32x}/adma.c | 4 +-
arch/arm/{plat-iop => mach-iop32x}/cp6.c | 0
arch/arm/mach-iop32x/em7210.c | 5 ++-
arch/arm/mach-iop32x/glantank.c | 5 ++-
.../mach-iop32x/{include/mach => }/glantank.h | 2 -
.../mach-iop32x/{include/mach => }/hardware.h | 6 +--
arch/arm/{plat-iop => mach-iop32x}/i2c.c | 6 ++-
.../mach-iop32x/include/mach/entry-macro.S | 2 -
arch/arm/mach-iop32x/include/mach/iop32x.h | 31 --------------
arch/arm/mach-iop32x/include/mach/irqs.h | 33 ---------------
arch/arm/mach-iop32x/include/mach/time.h | 5 ---
.../asm/hardware => mach-iop32x}/iop3xx.h | 18 +++++++-
arch/arm/mach-iop32x/iq31244.c | 5 ++-
.../mach-iop32x/{include/mach => }/iq31244.h | 2 -
arch/arm/mach-iop32x/iq80321.c | 5 ++-
.../mach-iop32x/{include/mach => }/iq80321.h | 2 -
arch/arm/mach-iop32x/irq.c | 3 +-
arch/arm/mach-iop32x/irqs.h | 42 +++++++++++++++++++
arch/arm/mach-iop32x/n2100.c | 5 ++-
.../mach-iop32x/{include/mach => }/n2100.h | 2 -
arch/arm/{plat-iop => mach-iop32x}/pci.c | 4 +-
arch/arm/{plat-iop => mach-iop32x}/pmu.c | 2 +-
arch/arm/{plat-iop => mach-iop32x}/restart.c | 4 +-
arch/arm/{plat-iop => mach-iop32x}/setup.c | 2 +-
arch/arm/{plat-iop => mach-iop32x}/time.c | 7 ++--
arch/arm/plat-iop/Makefile | 14 -------
28 files changed, 102 insertions(+), 125 deletions(-)
rename arch/arm/{plat-iop => mach-iop32x}/adma.c (98%)
rename arch/arm/{plat-iop => mach-iop32x}/cp6.c (100%)
rename arch/arm/mach-iop32x/{include/mach => }/glantank.h (78%)
rename arch/arm/mach-iop32x/{include/mach => }/hardware.h (90%)
rename arch/arm/{plat-iop => mach-iop32x}/i2c.c (96%)
delete mode 100644 arch/arm/mach-iop32x/include/mach/iop32x.h
delete mode 100644 arch/arm/mach-iop32x/include/mach/time.h
rename arch/arm/{include/asm/hardware => mach-iop32x}/iop3xx.h (96%)
rename arch/arm/mach-iop32x/{include/mach => }/iq31244.h (89%)
rename arch/arm/mach-iop32x/{include/mach => }/iq80321.h (89%)
create mode 100644 arch/arm/mach-iop32x/irqs.h
rename arch/arm/mach-iop32x/{include/mach => }/n2100.h (89%)
rename arch/arm/{plat-iop => mach-iop32x}/pci.c (99%)
rename arch/arm/{plat-iop => mach-iop32x}/pmu.c (96%)
rename arch/arm/{plat-iop => mach-iop32x}/restart.c (82%)
rename arch/arm/{plat-iop => mach-iop32x}/setup.c (95%)
rename arch/arm/{plat-iop => mach-iop32x}/time.c (97%)
delete mode 100644 arch/arm/plat-iop/Makefile
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index d92bc5328df7..075dd2f06d78 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -231,7 +231,6 @@ plat-$(CONFIG_ARCH_EXYNOS) += samsung
plat-$(CONFIG_ARCH_OMAP) += omap
plat-$(CONFIG_ARCH_S3C64XX) += samsung
plat-$(CONFIG_ARCH_S5PV210) += samsung
-plat-$(CONFIG_PLAT_IOP) += iop
plat-$(CONFIG_PLAT_ORION) += orion
plat-$(CONFIG_PLAT_PXA) += pxa
plat-$(CONFIG_PLAT_S3C24XX) += samsung
diff --git a/arch/arm/mach-iop32x/Makefile b/arch/arm/mach-iop32x/Makefile
index 71d62447d4d5..c8018ef5c6a9 100644
--- a/arch/arm/mach-iop32x/Makefile
+++ b/arch/arm/mach-iop32x/Makefile
@@ -3,7 +3,15 @@
# Makefile for the linux kernel.
#
-obj-y := irq.o
+obj-$(CONFIG_ARCH_IOP32X) += irq.o
+obj-$(CONFIG_ARCH_IOP32X) += i2c.o
+obj-$(CONFIG_ARCH_IOP32X) += pci.o
+obj-$(CONFIG_ARCH_IOP32X) += setup.o
+obj-$(CONFIG_ARCH_IOP32X) += time.o
+obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+obj-$(CONFIG_ARCH_IOP32X) += adma.o
+obj-$(CONFIG_ARCH_IOP32X) += pmu.o
+obj-$(CONFIG_ARCH_IOP32X) += restart.o
obj-$(CONFIG_MACH_GLANTANK) += glantank.o
obj-$(CONFIG_ARCH_IQ80321) += iq80321.o
diff --git a/arch/arm/plat-iop/adma.c b/arch/arm/mach-iop32x/adma.c
similarity index 98%
rename from arch/arm/plat-iop/adma.c
rename to arch/arm/mach-iop32x/adma.c
index 601cc9c11b07..764bcbff98df 100644
--- a/arch/arm/plat-iop/adma.c
+++ b/arch/arm/mach-iop32x/adma.c
@@ -4,10 +4,12 @@
* Copyright © 2006, Intel Corporation.
*/
#include <linux/platform_device.h>
-#include <asm/hardware/iop3xx.h>
#include <linux/dma-mapping.h>
#include <linux/platform_data/dma-iop32x.h>
+#include "iop3xx.h"
+#include "irqs.h"
+
#define IRQ_DMA0_EOT IRQ_IOP32X_DMA0_EOT
#define IRQ_DMA0_EOC IRQ_IOP32X_DMA0_EOC
#define IRQ_DMA0_ERR IRQ_IOP32X_DMA0_ERR
diff --git a/arch/arm/plat-iop/cp6.c b/arch/arm/mach-iop32x/cp6.c
similarity index 100%
rename from arch/arm/plat-iop/cp6.c
rename to arch/arm/mach-iop32x/cp6.c
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 61a1e593f9ec..d43ced3cd4e7 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -21,7 +21,6 @@
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <asm/mach/arch.h>
@@ -29,8 +28,10 @@
#include <asm/mach/pci.h>
#include <asm/mach/time.h>
#include <asm/mach-types.h>
-#include <mach/time.h>
+
+#include "hardware.h"
#include "gpio-iop32x.h"
+#include "irqs.h"
static void __init em7210_timer_init(void)
{
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index 5a45d616d9ac..2fe0f77d1f1d 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -22,7 +22,6 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -30,8 +29,10 @@
#include <asm/mach/time.h>
#include <asm/mach-types.h>
#include <asm/page.h>
-#include <mach/time.h>
+
+#include "hardware.h"
#include "gpio-iop32x.h"
+#include "irqs.h"
/*
* GLAN Tank timer tick configuration.
diff --git a/arch/arm/mach-iop32x/include/mach/glantank.h b/arch/arm/mach-iop32x/glantank.h
similarity index 78%
rename from arch/arm/mach-iop32x/include/mach/glantank.h
rename to arch/arm/mach-iop32x/glantank.h
index b9df2e4614cf..f38e86b82c3d 100644
--- a/arch/arm/mach-iop32x/include/mach/glantank.h
+++ b/arch/arm/mach-iop32x/glantank.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * arch/arm/mach-iop32x/include/mach/glantank.h
- *
* IO-Data GLAN Tank board registers
*/
diff --git a/arch/arm/mach-iop32x/include/mach/hardware.h b/arch/arm/mach-iop32x/hardware.h
similarity index 90%
rename from arch/arm/mach-iop32x/include/mach/hardware.h
rename to arch/arm/mach-iop32x/hardware.h
index 6e5303e60226..43ab4fb8f9b0 100644
--- a/arch/arm/mach-iop32x/include/mach/hardware.h
+++ b/arch/arm/mach-iop32x/hardware.h
@@ -1,8 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/arm/mach-iop32x/include/mach/hardware.h
- */
-
#ifndef __HARDWARE_H
#define __HARDWARE_H
@@ -28,7 +24,7 @@ void iop32x_init_irq(void);
/*
* Generic chipset bits
*/
-#include "iop32x.h"
+#include "iop3xx.h"
/*
* Board specific bits
diff --git a/arch/arm/plat-iop/i2c.c b/arch/arm/mach-iop32x/i2c.c
similarity index 96%
rename from arch/arm/plat-iop/i2c.c
rename to arch/arm/mach-iop32x/i2c.c
index 8d5fe349c7cd..dc9f6a14ab1b 100644
--- a/arch/arm/plat-iop/i2c.c
+++ b/arch/arm/mach-iop32x/i2c.c
@@ -22,10 +22,12 @@
#include <asm/mach/map.h>
#include <asm/setup.h>
#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/hardware/iop3xx.h>
#include <asm/mach/arch.h>
+#include "hardware.h"
+#include "iop3xx.h"
+#include "irqs.h"
+
/*
* Each of the I2C busses have corresponding GPIO lines, and the driver
* need to access these directly to drive the bus low at times.
diff --git a/arch/arm/mach-iop32x/include/mach/entry-macro.S b/arch/arm/mach-iop32x/include/mach/entry-macro.S
index ea13ae02d9b1..8e6766d4621e 100644
--- a/arch/arm/mach-iop32x/include/mach/entry-macro.S
+++ b/arch/arm/mach-iop32x/include/mach/entry-macro.S
@@ -7,8 +7,6 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-#include <mach/iop32x.h>
-
.macro get_irqnr_preamble, base, tmp
mrc p15, 0, \tmp, c15, c1, 0
orr \tmp, \tmp, #(1 << 6)
diff --git a/arch/arm/mach-iop32x/include/mach/iop32x.h b/arch/arm/mach-iop32x/include/mach/iop32x.h
deleted file mode 100644
index 84223f86552f..000000000000
--- a/arch/arm/mach-iop32x/include/mach/iop32x.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-iop32x/include/mach/iop32x.h
- *
- * Intel IOP32X Chip definitions
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- * Copyright (C) 2004 Intel Corp.
- */
-
-#ifndef __IOP32X_H
-#define __IOP32X_H
-
-/*
- * Peripherals that are shared between the iop32x and iop33x but
- * located at different addresses.
- */
-#define IOP3XX_TIMER_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07e0 + (reg))
-
-#include <asm/hardware/iop3xx.h>
-
-/* ATU Parameters
- * set up a 1:1 bus to physical ram relationship
- * w/ physical ram on top of pci in the memory map
- */
-#define IOP32X_MAX_RAM_SIZE 0x40000000UL
-#define IOP3XX_MAX_RAM_SIZE IOP32X_MAX_RAM_SIZE
-#define IOP3XX_PCI_LOWER_MEM_BA 0x80000000
-
-#endif
diff --git a/arch/arm/mach-iop32x/include/mach/irqs.h b/arch/arm/mach-iop32x/include/mach/irqs.h
index 82b11743e91c..c4e78df428e8 100644
--- a/arch/arm/mach-iop32x/include/mach/irqs.h
+++ b/arch/arm/mach-iop32x/include/mach/irqs.h
@@ -9,39 +9,6 @@
#ifndef __IRQS_H
#define __IRQS_H
-/*
- * IOP80321 chipset interrupts
- */
-#define IRQ_IOP32X_DMA0_EOT 0
-#define IRQ_IOP32X_DMA0_EOC 1
-#define IRQ_IOP32X_DMA1_EOT 2
-#define IRQ_IOP32X_DMA1_EOC 3
-#define IRQ_IOP32X_AA_EOT 6
-#define IRQ_IOP32X_AA_EOC 7
-#define IRQ_IOP32X_CORE_PMON 8
-#define IRQ_IOP32X_TIMER0 9
-#define IRQ_IOP32X_TIMER1 10
-#define IRQ_IOP32X_I2C_0 11
-#define IRQ_IOP32X_I2C_1 12
-#define IRQ_IOP32X_MESSAGING 13
-#define IRQ_IOP32X_ATU_BIST 14
-#define IRQ_IOP32X_PERFMON 15
-#define IRQ_IOP32X_CORE_PMU 16
-#define IRQ_IOP32X_BIU_ERR 17
-#define IRQ_IOP32X_ATU_ERR 18
-#define IRQ_IOP32X_MCU_ERR 19
-#define IRQ_IOP32X_DMA0_ERR 20
-#define IRQ_IOP32X_DMA1_ERR 21
-#define IRQ_IOP32X_AA_ERR 23
-#define IRQ_IOP32X_MSG_ERR 24
-#define IRQ_IOP32X_SSP 25
-#define IRQ_IOP32X_XINT0 27
-#define IRQ_IOP32X_XINT1 28
-#define IRQ_IOP32X_XINT2 29
-#define IRQ_IOP32X_XINT3 30
-#define IRQ_IOP32X_HPI 31
-
#define NR_IRQS 32
-
#endif
diff --git a/arch/arm/mach-iop32x/include/mach/time.h b/arch/arm/mach-iop32x/include/mach/time.h
deleted file mode 100644
index d08950ccebc4..000000000000
--- a/arch/arm/mach-iop32x/include/mach/time.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IOP32X_TIME_H_
-#define _IOP32X_TIME_H_
-#define IRQ_IOP_TIMER0 IRQ_IOP32X_TIMER0
-#endif
diff --git a/arch/arm/include/asm/hardware/iop3xx.h b/arch/arm/mach-iop32x/iop3xx.h
similarity index 96%
rename from arch/arm/include/asm/hardware/iop3xx.h
rename to arch/arm/mach-iop32x/iop3xx.h
index 3cb6f22f510b..46b4b34a4ad2 100644
--- a/arch/arm/include/asm/hardware/iop3xx.h
+++ b/arch/arm/mach-iop32x/iop3xx.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * arch/arm/include/asm/hardware/iop3xx.h
- *
* Intel IOP32X and IOP33X register definitions
*
* Author: Rory Bolt <rorybolt@pacbell.net>
@@ -12,6 +10,22 @@
#ifndef __IOP3XX_H
#define __IOP3XX_H
+/*
+ * Peripherals that are shared between the iop32x and iop33x but
+ * located at different addresses.
+ */
+#define IOP3XX_TIMER_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07e0 + (reg))
+
+#include "iop3xx.h"
+
+/* ATU Parameters
+ * set up a 1:1 bus to physical ram relationship
+ * w/ physical ram on top of pci in the memory map
+ */
+#define IOP32X_MAX_RAM_SIZE 0x40000000UL
+#define IOP3XX_MAX_RAM_SIZE IOP32X_MAX_RAM_SIZE
+#define IOP3XX_PCI_LOWER_MEM_BA 0x80000000
+
/*
* IOP3XX GPIO handling
*/
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index 8755aa87e591..04a7d389d365 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -23,7 +23,6 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <asm/cputype.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
@@ -33,7 +32,9 @@
#include <asm/mach-types.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <mach/time.h>
+
+#include "hardware.h"
+#include "irqs.h"
#include "gpio-iop32x.h"
/*
diff --git a/arch/arm/mach-iop32x/include/mach/iq31244.h b/arch/arm/mach-iop32x/iq31244.h
similarity index 89%
rename from arch/arm/mach-iop32x/include/mach/iq31244.h
rename to arch/arm/mach-iop32x/iq31244.h
index e62da5da6ed4..a7ac691e48d3 100644
--- a/arch/arm/mach-iop32x/include/mach/iq31244.h
+++ b/arch/arm/mach-iop32x/iq31244.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * arch/arm/mach-iop32x/include/mach/iq31244.h
- *
* Intel IQ31244 evaluation board registers
*/
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index e12699d1c540..4bd596d6c9c1 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -20,7 +20,6 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -29,7 +28,9 @@
#include <asm/mach-types.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <mach/time.h>
+
+#include "hardware.h"
+#include "irqs.h"
#include "gpio-iop32x.h"
/*
diff --git a/arch/arm/mach-iop32x/include/mach/iq80321.h b/arch/arm/mach-iop32x/iq80321.h
similarity index 89%
rename from arch/arm/mach-iop32x/include/mach/iq80321.h
rename to arch/arm/mach-iop32x/iq80321.h
index faf62c26f6f8..3a5d10626ea6 100644
--- a/arch/arm/mach-iop32x/include/mach/iq80321.h
+++ b/arch/arm/mach-iop32x/iq80321.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * arch/arm/mach-iop32x/include/mach/iq80321.h
- *
* Intel IQ80321 evaluation board registers
*/
diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c
index 2f5d4ec94f9c..2d48bf1398c1 100644
--- a/arch/arm/mach-iop32x/irq.c
+++ b/arch/arm/mach-iop32x/irq.c
@@ -13,9 +13,10 @@
#include <linux/list.h>
#include <asm/mach/irq.h>
#include <asm/irq.h>
-#include <mach/hardware.h>
#include <asm/mach-types.h>
+#include "hardware.h"
+
static u32 iop32x_mask;
static void intctl_write(u32 val)
diff --git a/arch/arm/mach-iop32x/irqs.h b/arch/arm/mach-iop32x/irqs.h
new file mode 100644
index 000000000000..69858e4e905d
--- /dev/null
+++ b/arch/arm/mach-iop32x/irqs.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright: (C) 2002 Rory Bolt
+ */
+
+#ifndef __IOP32X_IRQS_H
+#define __IOP32X_IRQS_H
+
+/*
+ * IOP80321 chipset interrupts
+ */
+#define IRQ_IOP32X_DMA0_EOT 0
+#define IRQ_IOP32X_DMA0_EOC 1
+#define IRQ_IOP32X_DMA1_EOT 2
+#define IRQ_IOP32X_DMA1_EOC 3
+#define IRQ_IOP32X_AA_EOT 6
+#define IRQ_IOP32X_AA_EOC 7
+#define IRQ_IOP32X_CORE_PMON 8
+#define IRQ_IOP32X_TIMER0 9
+#define IRQ_IOP32X_TIMER1 10
+#define IRQ_IOP32X_I2C_0 11
+#define IRQ_IOP32X_I2C_1 12
+#define IRQ_IOP32X_MESSAGING 13
+#define IRQ_IOP32X_ATU_BIST 14
+#define IRQ_IOP32X_PERFMON 15
+#define IRQ_IOP32X_CORE_PMU 16
+#define IRQ_IOP32X_BIU_ERR 17
+#define IRQ_IOP32X_ATU_ERR 18
+#define IRQ_IOP32X_MCU_ERR 19
+#define IRQ_IOP32X_DMA0_ERR 20
+#define IRQ_IOP32X_DMA1_ERR 21
+#define IRQ_IOP32X_AA_ERR 23
+#define IRQ_IOP32X_MSG_ERR 24
+#define IRQ_IOP32X_SSP 25
+#define IRQ_IOP32X_XINT0 27
+#define IRQ_IOP32X_XINT1 28
+#define IRQ_IOP32X_XINT2 29
+#define IRQ_IOP32X_XINT3 30
+#define IRQ_IOP32X_HPI 31
+
+#endif
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 26d76b377e79..5382a93ad0f8 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -28,7 +28,6 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -37,7 +36,9 @@
#include <asm/mach-types.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <mach/time.h>
+
+#include "hardware.h"
+#include "irqs.h"
#include "gpio-iop32x.h"
/*
diff --git a/arch/arm/mach-iop32x/include/mach/n2100.h b/arch/arm/mach-iop32x/n2100.h
similarity index 89%
rename from arch/arm/mach-iop32x/include/mach/n2100.h
rename to arch/arm/mach-iop32x/n2100.h
index 70bb660b643a..0b97b940d3e7 100644
--- a/arch/arm/mach-iop32x/include/mach/n2100.h
+++ b/arch/arm/mach-iop32x/n2100.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * arch/arm/mach-iop32x/include/mach/n2100.h
- *
* Thecus N2100 board registers
*/
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/mach-iop32x/pci.c
similarity index 99%
rename from arch/arm/plat-iop/pci.c
rename to arch/arm/mach-iop32x/pci.c
index 4c42c95e4bf5..ab0010dc3145 100644
--- a/arch/arm/plat-iop/pci.c
+++ b/arch/arm/mach-iop32x/pci.c
@@ -17,9 +17,9 @@
#include <linux/io.h>
#include <asm/irq.h>
#include <asm/signal.h>
-#include <mach/hardware.h>
#include <asm/mach/pci.h>
-#include <asm/hardware/iop3xx.h>
+#include "hardware.h"
+#include "iop3xx.h"
// #define DEBUG
diff --git a/arch/arm/plat-iop/pmu.c b/arch/arm/mach-iop32x/pmu.c
similarity index 96%
rename from arch/arm/plat-iop/pmu.c
rename to arch/arm/mach-iop32x/pmu.c
index 3834142c17f4..bdbc7a3cb8a3 100644
--- a/arch/arm/plat-iop/pmu.c
+++ b/arch/arm/mach-iop32x/pmu.c
@@ -5,7 +5,7 @@
*/
#include <linux/platform_device.h>
-#include <mach/irqs.h>
+#include "irqs.h"
static struct resource pmu_resource = {
.start = IRQ_IOP32X_CORE_PMU,
diff --git a/arch/arm/plat-iop/restart.c b/arch/arm/mach-iop32x/restart.c
similarity index 82%
rename from arch/arm/plat-iop/restart.c
rename to arch/arm/mach-iop32x/restart.c
index cf6d3d9a2112..3dfa54d3a7a8 100644
--- a/arch/arm/plat-iop/restart.c
+++ b/arch/arm/mach-iop32x/restart.c
@@ -4,9 +4,9 @@
*
* Copyright (C) 2001 MontaVista Software, Inc.
*/
-#include <asm/hardware/iop3xx.h>
#include <asm/system_misc.h>
-#include <mach/hardware.h>
+#include "hardware.h"
+#include "iop3xx.h"
void iop3xx_restart(enum reboot_mode mode, const char *cmd)
{
diff --git a/arch/arm/plat-iop/setup.c b/arch/arm/mach-iop32x/setup.c
similarity index 95%
rename from arch/arm/plat-iop/setup.c
rename to arch/arm/mach-iop32x/setup.c
index d10e0102d82c..a0a81c28a632 100644
--- a/arch/arm/plat-iop/setup.c
+++ b/arch/arm/mach-iop32x/setup.c
@@ -10,7 +10,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <asm/mach/map.h>
-#include <asm/hardware/iop3xx.h>
+#include "iop3xx.h"
/*
* Standard IO mapping for all IOP3xx based systems. Note that
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/mach-iop32x/time.c
similarity index 97%
rename from arch/arm/plat-iop/time.c
rename to arch/arm/mach-iop32x/time.c
index f9dd1f50cfe5..18a4df5c1baa 100644
--- a/arch/arm/plat-iop/time.c
+++ b/arch/arm/mach-iop32x/time.c
@@ -19,12 +19,13 @@
#include <linux/clockchips.h>
#include <linux/export.h>
#include <linux/sched_clock.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <linux/uaccess.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
-#include <mach/time.h>
+
+#include "hardware.h"
+#include "irqs.h"
/*
* Minimum clocksource/clockevent timer range in seconds
@@ -167,7 +168,7 @@ void __init iop_init_time(unsigned long tick_rate)
*/
write_tmr0(timer_ctl & ~IOP_TMR_EN);
write_tisr(1);
- setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq);
+ setup_irq(IRQ_IOP32X_TIMER0, &iop_timer_irq);
iop_clockevent.cpumask = cpumask_of(0);
clockevents_config_and_register(&iop_clockevent, tick_rate,
0xf, 0xfffffffe);
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
deleted file mode 100644
index 86e354b9065d..000000000000
--- a/arch/arm/plat-iop/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the linux kernel.
-#
-
-# IOP32X
-obj-$(CONFIG_ARCH_IOP32X) += i2c.o
-obj-$(CONFIG_ARCH_IOP32X) += pci.o
-obj-$(CONFIG_ARCH_IOP32X) += setup.o
-obj-$(CONFIG_ARCH_IOP32X) += time.o
-obj-$(CONFIG_ARCH_IOP32X) += cp6.o
-obj-$(CONFIG_ARCH_IOP32X) += adma.o
-obj-$(CONFIG_ARCH_IOP32X) += pmu.o
-obj-$(CONFIG_ARCH_IOP32X) += restart.o
--
2.20.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [GIT PULL] arm64 fixes for 5.3-rc4
From: pr-tracker-bot @ 2019-08-09 16:35 UTC (permalink / raw)
To: Catalin Marinas
Cc: Will Deacon, Linus Torvalds, linux-kernel, linux-arm-kernel
In-Reply-To: <20190809161513.GA42536@arrakis.emea.arm.com>
The pull request you sent on Fri, 9 Aug 2019 17:15:14 +0100:
> git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux tags/arm64-fixes
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/15a555a4b8be26683d77df8d5dbe8ac83f5ec3a6
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 0/7] ARM: preparation for multiplatform iop32x
From: Lennert Buytenhek @ 2019-08-09 16:38 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Dave Jiang, Linus Walleij, Russell King, soc, Dan Williams,
Imre Kaloz, Martin Michlmayr, linux-arm-kernel
In-Reply-To: <20190809162956.488941-1-arnd@arndb.de>
On Fri, Aug 09, 2019 at 06:29:41PM +0200, Arnd Bergmann wrote:
> I'm looking into converting some of the remaining ARMv5
> platforms in arch/arm/ to work together in a single kernel
> binary.
>
> IOP32x seems to be a fairly easy target for multiplatform
> by itself, but the way the plat-iop code interacts with
> three generations of the code, and how the dma-adma driver
> is configured at compile-time for each version gets in the
> way.
>
> I considered adding more indirection layers for those two,
> but removing iop33x and iop13xx is much easier in comparison,
> so this is the first approach I'm posting.
>
> If we conclude that iop33x and iop13xx are indeed not used
> any more, the remaining patches in this series are
> straightforward. The actual multiplatform conversion also
> requires changes to the irqchip driver that are not completely
> mechanic, and we can discuss those after deciding what to do
> with the first set.
>
> Adding a few people to Cc that historically worked on IOP.
I haven't worked with any of these platforms for many years now,
and I can't really say much about their current use.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/4] dt-bindings: watchdog: Add i.MX7ULP bindings
From: Guenter Roeck @ 2019-08-09 16:42 UTC (permalink / raw)
To: Anson Huang
Cc: mark.rutland, devicetree, leonard.crestez, schnitzeltony,
linux-watchdog, otavio, festevam, s.hauer, jan.tuerk, linux,
linux-kernel, robh+dt, Linux-imx, kernel, u.kleine-koenig, wim,
shawnguo, linux-arm-kernel
In-Reply-To: <1565334842-28161-1-git-send-email-Anson.Huang@nxp.com>
On Fri, Aug 09, 2019 at 03:13:59PM +0800, Anson Huang wrote:
> Add the watchdog bindings for Freescale i.MX7ULP.
>
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
> ---
> .../bindings/watchdog/fsl-imx7ulp-wdt.txt | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.txt
>
> diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.txt b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.txt
> new file mode 100644
> index 0000000..d83fc5c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.txt
> @@ -0,0 +1,22 @@
> +* Freescale i.MX7ULP Watchdog Timer (WDT) Controller
> +
> +Required properties:
> +- compatible : Should be "fsl,imx7ulp-wdt"
> +- reg : Should contain WDT registers location and length
> +- interrupts : Should contain WDT interrupt
> +- clocks: Should contain a phandle pointing to the gated peripheral clock.
The driver as submitted does not include clock or interrupt handling.
Why are those properties listed as mandatory if they are not really
needed (nor used) ?
> +
> +Optional properties:
> +- timeout-sec : Contains the watchdog timeout in seconds
> +
> +Examples:
> +
> +wdog1: wdog@403d0000 {
> + compatible = "fsl,imx7ulp-wdt";
> + reg = <0x403d0000 0x10000>;
> + interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&pcc2 IMX7ULP_CLK_WDG1>;
> + assigned-clocks = <&pcc2 IMX7ULP_CLK_WDG1>;
> + assigned-clocks-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
> + timeout-sec = <40>;
> +};
> --
> 2.7.4
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] mxsfb: allow attachment of display bridges
From: Guido Günther @ 2019-08-09 16:45 UTC (permalink / raw)
To: Ville Baillie
Cc: marex, kernel, dri-devel, airlied, festevam, s.hauer,
linux-kernel, stefan, linux-imx, daniel, Robert Chiras, shawnguo,
linux-arm-kernel
In-Reply-To: <20190801111853.GA24574@villeb-dev>
Hi,
On Thu, Aug 01, 2019 at 11:18:53AM +0000, Ville Baillie wrote:
> ---
> drivers/gpu/drm/mxsfb/mxsfb_drv.c | 20 ++++++++++++++++----
> drivers/gpu/drm/mxsfb/mxsfb_drv.h | 1 +
> drivers/gpu/drm/mxsfb/mxsfb_out.c | 14 +++++++++++---
> 3 files changed, 28 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 6fafc90da4ec..c19a7b7aa3a6 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -229,10 +229,22 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
> goto err_vblank;
> }
>
> - ret = drm_panel_attach(mxsfb->panel, &mxsfb->connector);
> - if (ret) {
> - dev_err(drm->dev, "Cannot connect panel\n");
> - goto err_vblank;
> + if (mxsfb->panel) {
> + ret = drm_panel_attach(mxsfb->panel, &mxsfb->connector);
> + if (ret) {
> + dev_err(drm->dev, "Cannot connect panel\n");
> + goto err_vblank;
> + }
> + } else if (mxsfb->bridge) {
> + ret = drm_bridge_attach(&mxsfb->pipe.encoder, mxsfb->bridge,
> + NULL);
> + if (ret) {
> + dev_err(drm->dev, "Cannot connect bridge\n");
> + goto err_vblank;
> + }
> + } else {
> + dev_err(drm->dev, "No panel or bridge\n");
> + return -EINVAL;
> }
>
> drm->mode_config.min_width = MXSFB_MIN_XRES;
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> index d975300dca05..436fe4bbb47a 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> @@ -29,6 +29,7 @@ struct mxsfb_drm_private {
> struct drm_simple_display_pipe pipe;
> struct drm_connector connector;
> struct drm_panel *panel;
> + struct drm_bridge *bridge;
> };
>
> int mxsfb_setup_crtc(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> index 91e76f9cead6..77e03eb0fca6 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> @@ -78,9 +78,11 @@ int mxsfb_create_output(struct drm_device *drm)
> {
> struct mxsfb_drm_private *mxsfb = drm->dev_private;
> struct drm_panel *panel;
> + struct drm_bridge *bridge;
> int ret;
>
> - ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, NULL);
> + ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
> + &bridge);
> if (ret)
> return ret;
>
> @@ -91,8 +93,14 @@ int mxsfb_create_output(struct drm_device *drm)
> ret = drm_connector_init(drm, &mxsfb->connector,
> &mxsfb_panel_connector_funcs,
> DRM_MODE_CONNECTOR_Unknown);
> - if (!ret)
> - mxsfb->panel = panel;
> + if (!ret) {
> + if (panel)
> + mxsfb->panel = panel;
> + else if (bridge)
> + mxsfb->bridge = bridge;
> + else
> + return -EINVAL;
> + }
>
> return ret;
> }
> --
> 2.17.1
Robert Chiras posted bridge support for mxsfb back in June:
https://patchwork.freedesktop.org/patch/314430/?series=62822&rev=1
Cheers,
-- Guido
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH V5 00/12] 52-bit kernel + user VAs
From: Will Deacon @ 2019-08-09 16:47 UTC (permalink / raw)
To: Steve Capper
Cc: crecklin, ard.biesheuvel, catalin.marinas, bhsharma, maz,
linux-arm-kernel
In-Reply-To: <20190807155524.5112-1-steve.capper@arm.com>
On Wed, Aug 07, 2019 at 04:55:12PM +0100, Steve Capper wrote:
> This patch series adds support for 52-bit kernel VAs using some of the
> machinery already introduced by the 52-bit userspace VA code in 5.0.
Cheers, I've pushed this out on a for-next/52-bit-kva branch with one
small patch on top and Catalin's tags added.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 7/8] arm64: defconfig: Enable the PSCI CPUidle driver
From: Will Deacon @ 2019-08-09 16:53 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Mark Rutland, Ulf Hansson, linux-pm, Catalin Marinas,
Daniel Lezcano, Rafael J. Wysocki, LKML, Sudeep Holla, Shawn Guo,
LAKML
In-Reply-To: <58d9677db3510ed106fe23118090c84f78a44102.1565348376.git.lorenzo.pieralisi@arm.com>
On Fri, Aug 09, 2019 at 12:03:13PM +0100, Lorenzo Pieralisi wrote:
> Enable the PSCI CPUidle driver to replace the functionality
> previously provided by the generic ARM CPUidle driver through
> CPU operations.
>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Sudeep Holla <sudeep.holla@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> ---
> arch/arm64/configs/defconfig | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index 0e58ef02880c..c0a7cfe3aebd 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -72,6 +72,7 @@ CONFIG_RANDOMIZE_BASE=y
> CONFIG_HIBERNATION=y
> CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
> CONFIG_ARM_CPUIDLE=y
> +CONFIG_ARM_PSCI_CPUIDLE=y
> CONFIG_CPU_FREQ=y
> CONFIG_CPU_FREQ_STAT=y
> CONFIG_CPU_FREQ_GOV_POWERSAVE=m
I'll queue the first 6 patches in this series, but please route this one
via arm-soc to avoid conflicts:
Acked-by: Will Deacon <will@kernel.org>
Failing that, I'm happy to take it at -rc1.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/7] [RFC] ARM: remove Intel iop33x and iop13xx support
From: Wolfram Sang @ 2019-08-09 16:57 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-gpio, linux-kernel, Linus Walleij, soc, Russell King,
Bartosz Golaszewski, Vinod Koul, linux-i2c, dmaengine,
Dan Williams, linux-arm-kernel
In-Reply-To: <20190809163334.489360-1-arnd@arndb.de>
[-- Attachment #1.1: Type: text/plain, Size: 918 bytes --]
On Fri, Aug 09, 2019 at 06:33:15PM +0200, Arnd Bergmann wrote:
> There are three families of IOP machines we support in Linux: iop32x
> (which includes EP80219), iop33x and iop13xx (aka IOP34x aka WP8134x).
>
> All products we support in the kernel are based on the first of these,
> iop32x, the other families only ever supported the Intel reference
> boards but no actual machine anyone could ever buy.
>
> While one could clearly make them all three work in a single kernel
> with some work, this takes the easy way out, removing the later two
> platforms entirely, under the assumption that there are no remaining
> users.
>
> Earlier versions of OpenWRT and Debian both had support for iop32x
> but not the others, and they both dropped iop32x as well in their 2015
> releases.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Wolfram Sang <wsa@the-dreams.de> # for I2C parts
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 00/15] Arm SMMU refactoring
From: Robin Murphy @ 2019-08-09 17:07 UTC (permalink / raw)
To: will
Cc: robdclark, joro, bjorn.andersson, iommu, vivek.gautam,
gregory.clement, linux-arm-kernel
Hi all,
This is a big refactoring of arm-smmu in order to help cope with the
various divergent implementation details currently flying around. So
far we've been accruing various quirks and errata workarounds within
the main flow of the driver, but given that it's written to an
architecture rather than any particular hardware implementation, after
a point these start to become increasingly invasive and potentially
conflict with each other.
These patches clean up the existing quirks handled by the driver to
lay a foundation on which we can continue to add more in a maintainable
fashion. The idea is that major vendor customisations can then be kept
in arm-smmu-<vendor>.c implementation files out of each others' way.
A branch is available at:
git://linux-arm.org/linux-rm iommu/smmu-impl
which I'll probably keep tweaking until I'm happy with the names of
things; I just didn't want to delay this initial posting any lomnger.
Robin.
Robin Murphy (15):
iommu/arm-smmu: Convert GR0 registers to bitfields
iommu/arm-smmu: Convert GR1 registers to bitfields
iommu/arm-smmu: Convert context bank registers to bitfields
iommu/arm-smmu: Rework cb_base handling
iommu/arm-smmu: Split arm_smmu_tlb_inv_range_nosync()
iommu/arm-smmu: Get rid of weird "atomic" write
iommu/arm-smmu: Abstract GR1 accesses
iommu/arm-smmu: Abstract context bank accesses
iommu/arm-smmu: Abstract GR0 accesses
iommu/arm-smmu: Rename arm-smmu-regs.h
iommu/arm-smmu: Add implementation infrastructure
iommu/arm-smmu: Move Secure access quirk to implementation
iommu/arm-smmu: Add configuration implementation hook
iommu/arm-smmu: Add reset implementation hook
iommu/arm-smmu: Add context init implementation hook
MAINTAINERS | 3 +-
drivers/iommu/Makefile | 2 +-
drivers/iommu/arm-smmu-impl.c | 165 ++++++++++
drivers/iommu/arm-smmu-regs.h | 210 -------------
drivers/iommu/arm-smmu.c | 570 +++++++++++-----------------------
drivers/iommu/arm-smmu.h | 386 +++++++++++++++++++++++
drivers/iommu/qcom_iommu.c | 15 +-
7 files changed, 743 insertions(+), 608 deletions(-)
create mode 100644 drivers/iommu/arm-smmu-impl.c
delete mode 100644 drivers/iommu/arm-smmu-regs.h
create mode 100644 drivers/iommu/arm-smmu.h
--
2.21.0.dirty
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 01/15] iommu/arm-smmu: Convert GR0 registers to bitfields
From: Robin Murphy @ 2019-08-09 17:07 UTC (permalink / raw)
To: will
Cc: robdclark, joro, bjorn.andersson, iommu, vivek.gautam,
gregory.clement, linux-arm-kernel
In-Reply-To: <cover.1565369764.git.robin.murphy@arm.com>
FIELD_PREP remains a terrible name, but the overall simplification will
make further work on this stuff that much more manageable. This also
serves as an audit of the header, wherein we can impose a consistent
grouping and ordering of the offset and field definitions
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu-regs.h | 126 ++++++++++++++++------------------
drivers/iommu/arm-smmu.c | 51 +++++++-------
2 files changed, 84 insertions(+), 93 deletions(-)
diff --git a/drivers/iommu/arm-smmu-regs.h b/drivers/iommu/arm-smmu-regs.h
index 1c278f7ae888..d189f025537a 100644
--- a/drivers/iommu/arm-smmu-regs.h
+++ b/drivers/iommu/arm-smmu-regs.h
@@ -10,111 +10,101 @@
#ifndef _ARM_SMMU_REGS_H
#define _ARM_SMMU_REGS_H
+#include <linux/bits.h>
+
/* Configuration registers */
#define ARM_SMMU_GR0_sCR0 0x0
-#define sCR0_CLIENTPD (1 << 0)
-#define sCR0_GFRE (1 << 1)
-#define sCR0_GFIE (1 << 2)
-#define sCR0_EXIDENABLE (1 << 3)
-#define sCR0_GCFGFRE (1 << 4)
-#define sCR0_GCFGFIE (1 << 5)
-#define sCR0_USFCFG (1 << 10)
-#define sCR0_VMIDPNE (1 << 11)
-#define sCR0_PTM (1 << 12)
-#define sCR0_FB (1 << 13)
-#define sCR0_VMID16EN (1 << 31)
-#define sCR0_BSU_SHIFT 14
-#define sCR0_BSU_MASK 0x3
+#define sCR0_VMID16EN BIT(31)
+#define sCR0_BSU GENMASK(15, 14)
+#define sCR0_FB BIT(13)
+#define sCR0_PTM BIT(12)
+#define sCR0_VMIDPNE BIT(11)
+#define sCR0_USFCFG BIT(10)
+#define sCR0_GCFGFIE BIT(5)
+#define sCR0_GCFGFRE BIT(4)
+#define sCR0_EXIDENABLE BIT(3)
+#define sCR0_GFIE BIT(2)
+#define sCR0_GFRE BIT(1)
+#define sCR0_CLIENTPD BIT(0)
/* Auxiliary Configuration register */
#define ARM_SMMU_GR0_sACR 0x10
/* Identification registers */
#define ARM_SMMU_GR0_ID0 0x20
+#define ID0_S1TS BIT(30)
+#define ID0_S2TS BIT(29)
+#define ID0_NTS BIT(28)
+#define ID0_SMS BIT(27)
+#define ID0_ATOSNS BIT(26)
+#define ID0_PTFS_NO_AARCH32 BIT(25)
+#define ID0_PTFS_NO_AARCH32S BIT(24)
+#define ID0_CTTW BIT(14)
+#define ID0_NUMIRPT GENMASK(23, 16)
+#define ID0_NUMSIDB GENMASK(12, 9)
+#define ID0_EXIDS BIT(8)
+#define ID0_NUMSMRG GENMASK(7, 0)
+
#define ARM_SMMU_GR0_ID1 0x24
+#define ID1_PAGESIZE BIT(31)
+#define ID1_NUMPAGENDXB GENMASK(30, 28)
+#define ID1_NUMS2CB GENMASK(23, 16)
+#define ID1_NUMCB GENMASK(7, 0)
+
#define ARM_SMMU_GR0_ID2 0x28
+#define ID2_VMID16 BIT(15)
+#define ID2_PTFS_64K BIT(14)
+#define ID2_PTFS_16K BIT(13)
+#define ID2_PTFS_4K BIT(12)
+#define ID2_UBS GENMASK(11, 8)
+#define ID2_OAS GENMASK(7, 4)
+#define ID2_IAS GENMASK(3, 0)
+
#define ARM_SMMU_GR0_ID3 0x2c
#define ARM_SMMU_GR0_ID4 0x30
#define ARM_SMMU_GR0_ID5 0x34
#define ARM_SMMU_GR0_ID6 0x38
+
#define ARM_SMMU_GR0_ID7 0x3c
+#define ID7_MAJOR GENMASK(7, 4)
+#define ID7_MINOR GENMASK(3, 0)
+
#define ARM_SMMU_GR0_sGFSR 0x48
#define ARM_SMMU_GR0_sGFSYNR0 0x50
#define ARM_SMMU_GR0_sGFSYNR1 0x54
#define ARM_SMMU_GR0_sGFSYNR2 0x58
-#define ID0_S1TS (1 << 30)
-#define ID0_S2TS (1 << 29)
-#define ID0_NTS (1 << 28)
-#define ID0_SMS (1 << 27)
-#define ID0_ATOSNS (1 << 26)
-#define ID0_PTFS_NO_AARCH32 (1 << 25)
-#define ID0_PTFS_NO_AARCH32S (1 << 24)
-#define ID0_CTTW (1 << 14)
-#define ID0_NUMIRPT_SHIFT 16
-#define ID0_NUMIRPT_MASK 0xff
-#define ID0_NUMSIDB_SHIFT 9
-#define ID0_NUMSIDB_MASK 0xf
-#define ID0_EXIDS (1 << 8)
-#define ID0_NUMSMRG_SHIFT 0
-#define ID0_NUMSMRG_MASK 0xff
-
-#define ID1_PAGESIZE (1 << 31)
-#define ID1_NUMPAGENDXB_SHIFT 28
-#define ID1_NUMPAGENDXB_MASK 7
-#define ID1_NUMS2CB_SHIFT 16
-#define ID1_NUMS2CB_MASK 0xff
-#define ID1_NUMCB_SHIFT 0
-#define ID1_NUMCB_MASK 0xff
-
-#define ID2_OAS_SHIFT 4
-#define ID2_OAS_MASK 0xf
-#define ID2_IAS_SHIFT 0
-#define ID2_IAS_MASK 0xf
-#define ID2_UBS_SHIFT 8
-#define ID2_UBS_MASK 0xf
-#define ID2_PTFS_4K (1 << 12)
-#define ID2_PTFS_16K (1 << 13)
-#define ID2_PTFS_64K (1 << 14)
-#define ID2_VMID16 (1 << 15)
-
-#define ID7_MAJOR_SHIFT 4
-#define ID7_MAJOR_MASK 0xf
-
/* Global TLB invalidation */
#define ARM_SMMU_GR0_TLBIVMID 0x64
#define ARM_SMMU_GR0_TLBIALLNSNH 0x68
#define ARM_SMMU_GR0_TLBIALLH 0x6c
#define ARM_SMMU_GR0_sTLBGSYNC 0x70
+
#define ARM_SMMU_GR0_sTLBGSTATUS 0x74
-#define sTLBGSTATUS_GSACTIVE (1 << 0)
+#define sTLBGSTATUS_GSACTIVE BIT(0)
/* Stream mapping registers */
#define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2))
-#define SMR_VALID (1 << 31)
-#define SMR_MASK_SHIFT 16
-#define SMR_ID_SHIFT 0
+#define SMR_VALID BIT(31)
+#define SMR_MASK GENMASK(31, 16)
+#define SMR_ID GENMASK(15, 0)
#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2))
-#define S2CR_CBNDX_SHIFT 0
-#define S2CR_CBNDX_MASK 0xff
-#define S2CR_EXIDVALID (1 << 10)
-#define S2CR_TYPE_SHIFT 16
-#define S2CR_TYPE_MASK 0x3
-enum arm_smmu_s2cr_type {
- S2CR_TYPE_TRANS,
- S2CR_TYPE_BYPASS,
- S2CR_TYPE_FAULT,
-};
-
-#define S2CR_PRIVCFG_SHIFT 24
-#define S2CR_PRIVCFG_MASK 0x3
+#define S2CR_PRIVCFG GENMASK(25, 24)
enum arm_smmu_s2cr_privcfg {
S2CR_PRIVCFG_DEFAULT,
S2CR_PRIVCFG_DIPAN,
S2CR_PRIVCFG_UNPRIV,
S2CR_PRIVCFG_PRIV,
};
+#define S2CR_TYPE GENMASK(17, 16)
+enum arm_smmu_s2cr_type {
+ S2CR_TYPE_TRANS,
+ S2CR_TYPE_BYPASS,
+ S2CR_TYPE_FAULT,
+};
+#define S2CR_EXIDVALID BIT(10)
+#define S2CR_CBNDX GENMASK(7, 0)
/* Context bank attribute registers */
#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 64977c131ee6..89eddc54e41c 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -20,6 +20,7 @@
#include <linux/acpi.h>
#include <linux/acpi_iort.h>
#include <linux/atomic.h>
+#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
@@ -1019,7 +1020,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
{
struct arm_smmu_smr *smr = smmu->smrs + idx;
- u32 reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
+ u32 reg = FIELD_PREP(SMR_ID, smr->id) | FIELD_PREP(SMR_MASK, smr->mask);
if (!(smmu->features & ARM_SMMU_FEAT_EXIDS) && smr->valid)
reg |= SMR_VALID;
@@ -1029,9 +1030,9 @@ static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
static void arm_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
{
struct arm_smmu_s2cr *s2cr = smmu->s2crs + idx;
- u32 reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT |
- (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
- (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
+ u32 reg = FIELD_PREP(S2CR_TYPE, s2cr->type) |
+ FIELD_PREP(S2CR_CBNDX, s2cr->cbndx) |
+ FIELD_PREP(S2CR_PRIVCFG, s2cr->privcfg);
if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs &&
smmu->smrs[idx].valid)
@@ -1063,15 +1064,15 @@ static void arm_smmu_test_smr_masks(struct arm_smmu_device *smmu)
* bits are set, so check each one separately. We can reject
* masters later if they try to claim IDs outside these masks.
*/
- smr = smmu->streamid_mask << SMR_ID_SHIFT;
+ smr = FIELD_PREP(SMR_ID, smmu->streamid_mask);
writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
- smmu->streamid_mask = smr >> SMR_ID_SHIFT;
+ smmu->streamid_mask = FIELD_GET(SMR_ID, smr);
- smr = smmu->streamid_mask << SMR_MASK_SHIFT;
+ smr = FIELD_PREP(SMR_MASK, smmu->streamid_mask);
writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
- smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT;
+ smmu->smr_mask_mask = FIELD_GET(SMR_MASK, smr);
}
static int arm_smmu_find_sme(struct arm_smmu_device *smmu, u16 id, u16 mask)
@@ -1140,8 +1141,8 @@ static int arm_smmu_master_alloc_smes(struct device *dev)
mutex_lock(&smmu->stream_map_mutex);
/* Figure out a viable stream map entry allocation */
for_each_cfg_sme(fwspec, i, idx) {
- u16 sid = fwspec->ids[i];
- u16 mask = fwspec->ids[i] >> SMR_MASK_SHIFT;
+ u16 sid = FIELD_GET(SMR_ID, fwspec->ids[i]);
+ u16 mask = FIELD_GET(SMR_MASK, fwspec->ids[i]);
if (idx != INVALID_SMENDX) {
ret = -EEXIST;
@@ -1466,8 +1467,8 @@ static int arm_smmu_add_device(struct device *dev)
ret = -EINVAL;
for (i = 0; i < fwspec->num_ids; i++) {
- u16 sid = fwspec->ids[i];
- u16 mask = fwspec->ids[i] >> SMR_MASK_SHIFT;
+ u16 sid = FIELD_GET(SMR_ID, fwspec->ids[i]);
+ u16 mask = FIELD_GET(SMR_MASK, fwspec->ids[i]);
if (sid & ~smmu->streamid_mask) {
dev_err(dev, "stream ID 0x%x out of range for SMMU (0x%x)\n",
@@ -1648,12 +1649,12 @@ static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
u32 mask, fwid = 0;
if (args->args_count > 0)
- fwid |= (u16)args->args[0];
+ fwid |= FIELD_PREP(SMR_ID, args->args[0]);
if (args->args_count > 1)
- fwid |= (u16)args->args[1] << SMR_MASK_SHIFT;
+ fwid |= FIELD_PREP(SMR_MASK, args->args[1]);
else if (!of_property_read_u32(args->np, "stream-match-mask", &mask))
- fwid |= (u16)mask << SMR_MASK_SHIFT;
+ fwid |= FIELD_PREP(SMR_MASK, mask);
return iommu_fwspec_add_ids(dev, &fwid, 1);
}
@@ -1728,7 +1729,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
* bit is only present in MMU-500r2 onwards.
*/
reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);
- major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;
+ major = FIELD_GET(ID7_MAJOR, reg);
reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
if (major >= 2)
reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
@@ -1780,7 +1781,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
reg &= ~sCR0_FB;
/* Don't upgrade barriers */
- reg &= ~(sCR0_BSU_MASK << sCR0_BSU_SHIFT);
+ reg &= ~(sCR0_BSU);
if (smmu->features & ARM_SMMU_FEAT_VMID16)
reg |= sCR0_VMID16EN;
@@ -1879,12 +1880,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
smmu->features |= ARM_SMMU_FEAT_EXIDS;
size = 1 << 16;
} else {
- size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
+ size = 1 << FIELD_GET(ID0_NUMSIDB, id);
}
smmu->streamid_mask = size - 1;
if (id & ID0_SMS) {
smmu->features |= ARM_SMMU_FEAT_STREAM_MATCH;
- size = (id >> ID0_NUMSMRG_SHIFT) & ID0_NUMSMRG_MASK;
+ size = FIELD_GET(ID0_NUMSMRG, id);
if (size == 0) {
dev_err(smmu->dev,
"stream-matching supported, but no SMRs present!\n");
@@ -1923,15 +1924,15 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
smmu->pgshift = (id & ID1_PAGESIZE) ? 16 : 12;
/* Check for size mismatch of SMMU address space from mapped region */
- size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1);
+ size = 1 << (FIELD_GET(ID1_NUMPAGENDXB, id) + 1);
size <<= smmu->pgshift;
if (smmu->cb_base != gr0_base + size)
dev_warn(smmu->dev,
"SMMU address space size (0x%lx) differs from mapped region size (0x%tx)!\n",
size * 2, (smmu->cb_base - gr0_base) * 2);
- smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) & ID1_NUMS2CB_MASK;
- smmu->num_context_banks = (id >> ID1_NUMCB_SHIFT) & ID1_NUMCB_MASK;
+ smmu->num_s2_context_banks = FIELD_GET(ID1_NUMS2CB, id);
+ smmu->num_context_banks = FIELD_GET(ID1_NUMCB, id);
if (smmu->num_s2_context_banks > smmu->num_context_banks) {
dev_err(smmu->dev, "impossible number of S2 context banks!\n");
return -ENODEV;
@@ -1957,11 +1958,11 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
/* ID2 */
id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID2);
- size = arm_smmu_id_size_to_bits((id >> ID2_IAS_SHIFT) & ID2_IAS_MASK);
+ size = arm_smmu_id_size_to_bits(FIELD_GET(ID2_IAS, id));
smmu->ipa_size = size;
/* The output mask is also applied for bypass */
- size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);
+ size = arm_smmu_id_size_to_bits(FIELD_GET(ID2_OAS, id));
smmu->pa_size = size;
if (id & ID2_VMID16)
@@ -1981,7 +1982,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
if (smmu->version == ARM_SMMU_V1_64K)
smmu->features |= ARM_SMMU_FEAT_FMT_AARCH64_64K;
} else {
- size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK;
+ size = FIELD_GET(ID2_UBS, id);
smmu->va_size = arm_smmu_id_size_to_bits(size);
if (id & ID2_PTFS_4K)
smmu->features |= ARM_SMMU_FEAT_FMT_AARCH64_4K;
--
2.21.0.dirty
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 02/15] iommu/arm-smmu: Convert GR1 registers to bitfields
From: Robin Murphy @ 2019-08-09 17:07 UTC (permalink / raw)
To: will
Cc: robdclark, joro, bjorn.andersson, iommu, vivek.gautam,
gregory.clement, linux-arm-kernel
In-Reply-To: <cover.1565369764.git.robin.murphy@arm.com>
As for GR0, use the bitfield helpers to make GR1 usage a little cleaner,
and use it as an opportunity to audit and tidy the definitions. This
tweaks the handling of CBAR types to match what we did for S2CR a while
back, and fixes a couple of names which didn't quite match the latest
architecture spec (IHI0062D.c).
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu-regs.h | 33 ++++++++++++++-------------------
drivers/iommu/arm-smmu.c | 18 +++++++++---------
2 files changed, 23 insertions(+), 28 deletions(-)
diff --git a/drivers/iommu/arm-smmu-regs.h b/drivers/iommu/arm-smmu-regs.h
index d189f025537a..671c2d98c9da 100644
--- a/drivers/iommu/arm-smmu-regs.h
+++ b/drivers/iommu/arm-smmu-regs.h
@@ -108,30 +108,25 @@ enum arm_smmu_s2cr_type {
/* Context bank attribute registers */
#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
-#define CBAR_VMID_SHIFT 0
-#define CBAR_VMID_MASK 0xff
-#define CBAR_S1_BPSHCFG_SHIFT 8
-#define CBAR_S1_BPSHCFG_MASK 3
-#define CBAR_S1_BPSHCFG_NSH 3
-#define CBAR_S1_MEMATTR_SHIFT 12
-#define CBAR_S1_MEMATTR_MASK 0xf
+#define CBAR_IRPTNDX GENMASK(31, 24)
+#define CBAR_TYPE GENMASK(17, 16)
+enum arm_smmu_cbar_type {
+ CBAR_TYPE_S2_TRANS,
+ CBAR_TYPE_S1_TRANS_S2_BYPASS,
+ CBAR_TYPE_S1_TRANS_S2_FAULT,
+ CBAR_TYPE_S1_TRANS_S2_TRANS,
+};
+#define CBAR_S1_MEMATTR GENMASK(15, 12)
#define CBAR_S1_MEMATTR_WB 0xf
-#define CBAR_TYPE_SHIFT 16
-#define CBAR_TYPE_MASK 0x3
-#define CBAR_TYPE_S2_TRANS (0 << CBAR_TYPE_SHIFT)
-#define CBAR_TYPE_S1_TRANS_S2_BYPASS (1 << CBAR_TYPE_SHIFT)
-#define CBAR_TYPE_S1_TRANS_S2_FAULT (2 << CBAR_TYPE_SHIFT)
-#define CBAR_TYPE_S1_TRANS_S2_TRANS (3 << CBAR_TYPE_SHIFT)
-#define CBAR_IRPTNDX_SHIFT 24
-#define CBAR_IRPTNDX_MASK 0xff
+#define CBAR_S1_BPSHCFG GENMASK(9, 8)
+#define CBAR_S1_BPSHCFG_NSH 3
+#define CBAR_VMID GENMASK(7, 0)
#define ARM_SMMU_GR1_CBFRSYNRA(n) (0x400 + ((n) << 2))
#define ARM_SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2))
-#define CBA2R_RW64_32BIT (0 << 0)
-#define CBA2R_RW64_64BIT (1 << 0)
-#define CBA2R_VMID_SHIFT 16
-#define CBA2R_VMID_MASK 0xffff
+#define CBA2R_VMID16 GENMASK(31, 16)
+#define CBA2R_VA64 BIT(0)
#define ARM_SMMU_CB_SCTLR 0x0
#define ARM_SMMU_CB_ACTLR 0x4
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 89eddc54e41c..515fb1ce39ed 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -237,7 +237,7 @@ struct arm_smmu_cfg {
u16 asid;
u16 vmid;
};
- u32 cbar;
+ enum arm_smmu_cbar_type cbar;
enum arm_smmu_context_fmt fmt;
};
#define INVALID_IRPTNDX 0xff
@@ -692,31 +692,31 @@ static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx)
/* CBA2R */
if (smmu->version > ARM_SMMU_V1) {
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
- reg = CBA2R_RW64_64BIT;
+ reg = CBA2R_VA64;
else
- reg = CBA2R_RW64_32BIT;
+ reg = 0;
/* 16-bit VMIDs live in CBA2R */
if (smmu->features & ARM_SMMU_FEAT_VMID16)
- reg |= cfg->vmid << CBA2R_VMID_SHIFT;
+ reg |= FIELD_PREP(CBA2R_VMID16, cfg->vmid);
writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBA2R(idx));
}
/* CBAR */
- reg = cfg->cbar;
+ reg = FIELD_PREP(CBAR_TYPE, cfg->cbar);
if (smmu->version < ARM_SMMU_V2)
- reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT;
+ reg |= FIELD_PREP(CBAR_IRPTNDX, cfg->irptndx);
/*
* Use the weakest shareability/memory types, so they are
* overridden by the ttbcr/pte.
*/
if (stage1) {
- reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
- (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
+ reg |= FIELD_PREP(CBAR_S1_BPSHCFG, CBAR_S1_BPSHCFG_NSH) |
+ FIELD_PREP(CBAR_S1_MEMATTR, CBAR_S1_MEMATTR_WB);
} else if (!(smmu->features & ARM_SMMU_FEAT_VMID16)) {
/* 8-bit VMIDs live in CBAR */
- reg |= cfg->vmid << CBAR_VMID_SHIFT;
+ reg |= FIELD_PREP(CBAR_VMID, cfg->vmid);
}
writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(idx));
--
2.21.0.dirty
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 03/15] iommu/arm-smmu: Convert context bank registers to bitfields
From: Robin Murphy @ 2019-08-09 17:07 UTC (permalink / raw)
To: will
Cc: robdclark, joro, bjorn.andersson, iommu, vivek.gautam,
gregory.clement, linux-arm-kernel
In-Reply-To: <cover.1565369764.git.robin.murphy@arm.com>
Finish the final part of the job, once again updating some names to
match the current spec.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu-regs.h | 86 ++++++++++++++++++-----------------
drivers/iommu/arm-smmu.c | 16 +++----
drivers/iommu/qcom_iommu.c | 13 +++---
3 files changed, 59 insertions(+), 56 deletions(-)
diff --git a/drivers/iommu/arm-smmu-regs.h b/drivers/iommu/arm-smmu-regs.h
index 671c2d98c9da..75056edad31d 100644
--- a/drivers/iommu/arm-smmu-regs.h
+++ b/drivers/iommu/arm-smmu-regs.h
@@ -129,19 +129,59 @@ enum arm_smmu_cbar_type {
#define CBA2R_VA64 BIT(0)
#define ARM_SMMU_CB_SCTLR 0x0
+#define SCTLR_S1_ASIDPNE BIT(12)
+#define SCTLR_CFCFG BIT(7)
+#define SCTLR_CFIE BIT(6)
+#define SCTLR_CFRE BIT(5)
+#define SCTLR_E BIT(4)
+#define SCTLR_AFE BIT(2)
+#define SCTLR_TRE BIT(1)
+#define SCTLR_M BIT(0)
+
#define ARM_SMMU_CB_ACTLR 0x4
+
#define ARM_SMMU_CB_RESUME 0x8
-#define ARM_SMMU_CB_TTBCR2 0x10
+#define RESUME_TERMINATE BIT(0)
+
+#define ARM_SMMU_CB_TCR2 0x10
+#define TCR2_SEP GENMASK(17, 15)
+#define TCR2_SEP_UPSTREAM 0x7
+#define TCR2_AS BIT(4)
+
#define ARM_SMMU_CB_TTBR0 0x20
#define ARM_SMMU_CB_TTBR1 0x28
-#define ARM_SMMU_CB_TTBCR 0x30
+#define TTBRn_ASID GENMASK_ULL(63, 48)
+
+#define ARM_SMMU_CB_TCR 0x30
#define ARM_SMMU_CB_CONTEXTIDR 0x34
#define ARM_SMMU_CB_S1_MAIR0 0x38
#define ARM_SMMU_CB_S1_MAIR1 0x3c
+
#define ARM_SMMU_CB_PAR 0x50
+#define CB_PAR_F BIT(0)
+
#define ARM_SMMU_CB_FSR 0x58
+#define FSR_MULTI BIT(31)
+#define FSR_SS BIT(30)
+#define FSR_UUT BIT(8)
+#define FSR_ASF BIT(7)
+#define FSR_TLBLKF BIT(6)
+#define FSR_TLBMCF BIT(5)
+#define FSR_EF BIT(4)
+#define FSR_PF BIT(3)
+#define FSR_AFF BIT(2)
+#define FSR_TF BIT(1)
+
+#define FSR_IGN (FSR_AFF | FSR_ASF | \
+ FSR_TLBMCF | FSR_TLBLKF)
+#define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \
+ FSR_EF | FSR_PF | FSR_TF | FSR_IGN)
+
#define ARM_SMMU_CB_FAR 0x60
+
#define ARM_SMMU_CB_FSYNR0 0x68
+#define FSYNR0_WNR BIT(4)
+
#define ARM_SMMU_CB_S1_TLBIVA 0x600
#define ARM_SMMU_CB_S1_TLBIASID 0x610
#define ARM_SMMU_CB_S1_TLBIVAL 0x620
@@ -150,46 +190,8 @@ enum arm_smmu_cbar_type {
#define ARM_SMMU_CB_TLBSYNC 0x7f0
#define ARM_SMMU_CB_TLBSTATUS 0x7f4
#define ARM_SMMU_CB_ATS1PR 0x800
+
#define ARM_SMMU_CB_ATSR 0x8f0
-
-#define SCTLR_S1_ASIDPNE (1 << 12)
-#define SCTLR_CFCFG (1 << 7)
-#define SCTLR_CFIE (1 << 6)
-#define SCTLR_CFRE (1 << 5)
-#define SCTLR_E (1 << 4)
-#define SCTLR_AFE (1 << 2)
-#define SCTLR_TRE (1 << 1)
-#define SCTLR_M (1 << 0)
-
-#define CB_PAR_F (1 << 0)
-
-#define ATSR_ACTIVE (1 << 0)
-
-#define RESUME_RETRY (0 << 0)
-#define RESUME_TERMINATE (1 << 0)
-
-#define TTBCR2_SEP_SHIFT 15
-#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT)
-#define TTBCR2_AS (1 << 4)
-
-#define TTBRn_ASID_SHIFT 48
-
-#define FSR_MULTI (1 << 31)
-#define FSR_SS (1 << 30)
-#define FSR_UUT (1 << 8)
-#define FSR_ASF (1 << 7)
-#define FSR_TLBLKF (1 << 6)
-#define FSR_TLBMCF (1 << 5)
-#define FSR_EF (1 << 4)
-#define FSR_PF (1 << 3)
-#define FSR_AFF (1 << 2)
-#define FSR_TF (1 << 1)
-
-#define FSR_IGN (FSR_AFF | FSR_ASF | \
- FSR_TLBMCF | FSR_TLBLKF)
-#define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \
- FSR_EF | FSR_PF | FSR_TF | FSR_IGN)
-
-#define FSYNR0_WNR (1 << 4)
+#define ATSR_ACTIVE BIT(0)
#endif /* _ARM_SMMU_REGS_H */
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 515fb1ce39ed..d9a93e5f422f 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -628,16 +628,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
cb->cfg = cfg;
- /* TTBCR */
+ /* TCR */
if (stage1) {
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
cb->tcr[0] = pgtbl_cfg->arm_v7s_cfg.tcr;
} else {
cb->tcr[0] = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
cb->tcr[1] = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
- cb->tcr[1] |= TTBCR2_SEP_UPSTREAM;
+ cb->tcr[1] |= FIELD_PREP(TCR2_SEP, TCR2_SEP_UPSTREAM);
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
- cb->tcr[1] |= TTBCR2_AS;
+ cb->tcr[1] |= TCR2_AS;
}
} else {
cb->tcr[0] = pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
@@ -650,9 +650,9 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
cb->ttbr[1] = pgtbl_cfg->arm_v7s_cfg.ttbr[1];
} else {
cb->ttbr[0] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
- cb->ttbr[0] |= (u64)cfg->asid << TTBRn_ASID_SHIFT;
+ cb->ttbr[0] |= FIELD_PREP(TTBRn_ASID, cfg->asid);
cb->ttbr[1] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1];
- cb->ttbr[1] |= (u64)cfg->asid << TTBRn_ASID_SHIFT;
+ cb->ttbr[1] |= FIELD_PREP(TTBRn_ASID, cfg->asid);
}
} else {
cb->ttbr[0] = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
@@ -721,13 +721,13 @@ static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx)
writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(idx));
/*
- * TTBCR
+ * TCR
* We must write this before the TTBRs, since it determines the
* access behaviour of some fields (in particular, ASID[15:8]).
*/
if (stage1 && smmu->version > ARM_SMMU_V1)
- writel_relaxed(cb->tcr[1], cb_base + ARM_SMMU_CB_TTBCR2);
- writel_relaxed(cb->tcr[0], cb_base + ARM_SMMU_CB_TTBCR);
+ writel_relaxed(cb->tcr[1], cb_base + ARM_SMMU_CB_TCR2);
+ writel_relaxed(cb->tcr[0], cb_base + ARM_SMMU_CB_TCR);
/* TTBRs */
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c
index 34d0b9783b3e..746bf2a7df05 100644
--- a/drivers/iommu/qcom_iommu.c
+++ b/drivers/iommu/qcom_iommu.c
@@ -7,6 +7,7 @@
*/
#include <linux/atomic.h>
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-iommu.h>
@@ -247,16 +248,16 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
/* TTBRs */
iommu_writeq(ctx, ARM_SMMU_CB_TTBR0,
pgtbl_cfg.arm_lpae_s1_cfg.ttbr[0] |
- ((u64)ctx->asid << TTBRn_ASID_SHIFT));
+ FIELD_PREP(TTBRn_ASID, ctx->asid));
iommu_writeq(ctx, ARM_SMMU_CB_TTBR1,
pgtbl_cfg.arm_lpae_s1_cfg.ttbr[1] |
- ((u64)ctx->asid << TTBRn_ASID_SHIFT));
+ FIELD_PREP(TTBRn_ASID, ctx->asid));
- /* TTBCR */
- iommu_writel(ctx, ARM_SMMU_CB_TTBCR2,
+ /* TCR */
+ iommu_writel(ctx, ARM_SMMU_CB_TCR2,
(pgtbl_cfg.arm_lpae_s1_cfg.tcr >> 32) |
- TTBCR2_SEP_UPSTREAM);
- iommu_writel(ctx, ARM_SMMU_CB_TTBCR,
+ FIELD_PREP(TCR2_SEP, TCR2_SEP_UPSTREAM));
+ iommu_writel(ctx, ARM_SMMU_CB_TCR,
pgtbl_cfg.arm_lpae_s1_cfg.tcr);
/* MAIRs (stage-1 only) */
--
2.21.0.dirty
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 05/15] iommu/arm-smmu: Split arm_smmu_tlb_inv_range_nosync()
From: Robin Murphy @ 2019-08-09 17:07 UTC (permalink / raw)
To: will
Cc: robdclark, joro, bjorn.andersson, iommu, vivek.gautam,
gregory.clement, linux-arm-kernel
In-Reply-To: <cover.1565369764.git.robin.murphy@arm.com>
Since we now use separate iommu_gather_ops for stage 1 and stage 2
contexts, we may as well divide up the monolithic callback into its
respective stage 1 and stage 2 parts.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu.c | 66 ++++++++++++++++++++++------------------
1 file changed, 37 insertions(+), 29 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 463bc8d98adb..a681e000e704 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -490,46 +490,54 @@ static void arm_smmu_tlb_inv_context_s2(void *cookie)
arm_smmu_tlb_sync_global(smmu);
}
-static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
- size_t granule, bool leaf, void *cookie)
+static void arm_smmu_tlb_inv_range_s1(unsigned long iova, size_t size,
+ size_t granule, bool leaf, void *cookie)
{
struct arm_smmu_domain *smmu_domain = cookie;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
- bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
- void __iomem *reg = ARM_SMMU_CB(smmu_domain->smmu, cfg->cbndx);
+ void __iomem *reg = ARM_SMMU_CB(smmu, cfg->cbndx);
- if (smmu_domain->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
+ if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
wmb();
- if (stage1) {
- reg += leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA;
+ reg += leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA;
- if (cfg->fmt != ARM_SMMU_CTX_FMT_AARCH64) {
- iova &= ~12UL;
- iova |= cfg->asid;
- do {
- writel_relaxed(iova, reg);
- iova += granule;
- } while (size -= granule);
- } else {
- iova >>= 12;
- iova |= (u64)cfg->asid << 48;
- do {
- writeq_relaxed(iova, reg);
- iova += granule >> 12;
- } while (size -= granule);
- }
- } else {
- reg += leaf ? ARM_SMMU_CB_S2_TLBIIPAS2L :
- ARM_SMMU_CB_S2_TLBIIPAS2;
- iova >>= 12;
+ if (cfg->fmt != ARM_SMMU_CTX_FMT_AARCH64) {
+ iova &= ~12UL;
+ iova |= cfg->asid;
do {
- smmu_write_atomic_lq(iova, reg);
+ writel_relaxed(iova, reg);
+ iova += granule;
+ } while (size -= granule);
+ } else {
+ iova >>= 12;
+ iova |= (u64)cfg->asid << 48;
+ do {
+ writeq_relaxed(iova, reg);
iova += granule >> 12;
} while (size -= granule);
}
}
+static void arm_smmu_tlb_inv_range_s2(unsigned long iova, size_t size,
+ size_t granule, bool leaf, void *cookie)
+{
+ struct arm_smmu_domain *smmu_domain = cookie;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
+ void __iomem *reg = ARM_SMMU_CB(smmu, smmu_domain->cfg.cbndx);
+
+ if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
+ wmb();
+
+ reg += leaf ? ARM_SMMU_CB_S2_TLBIIPAS2L : ARM_SMMU_CB_S2_TLBIIPAS2;
+ iova >>= 12;
+ do {
+ smmu_write_atomic_lq(iova, reg);
+ iova += granule >> 12;
+ } while (size -= granule);
+}
+
/*
* On MMU-401 at least, the cost of firing off multiple TLBIVMIDs appears
* almost negligible, but the benefit of getting the first one in as far ahead
@@ -550,13 +558,13 @@ static void arm_smmu_tlb_inv_vmid_nosync(unsigned long iova, size_t size,
static const struct iommu_gather_ops arm_smmu_s1_tlb_ops = {
.tlb_flush_all = arm_smmu_tlb_inv_context_s1,
- .tlb_add_flush = arm_smmu_tlb_inv_range_nosync,
+ .tlb_add_flush = arm_smmu_tlb_inv_range_s1,
.tlb_sync = arm_smmu_tlb_sync_context,
};
static const struct iommu_gather_ops arm_smmu_s2_tlb_ops_v2 = {
.tlb_flush_all = arm_smmu_tlb_inv_context_s2,
- .tlb_add_flush = arm_smmu_tlb_inv_range_nosync,
+ .tlb_add_flush = arm_smmu_tlb_inv_range_s2,
.tlb_sync = arm_smmu_tlb_sync_context,
};
--
2.21.0.dirty
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 04/15] iommu/arm-smmu: Rework cb_base handling
From: Robin Murphy @ 2019-08-09 17:07 UTC (permalink / raw)
To: will
Cc: robdclark, joro, bjorn.andersson, iommu, vivek.gautam,
gregory.clement, linux-arm-kernel
In-Reply-To: <cover.1565369764.git.robin.murphy@arm.com>
To keep register-access quirks manageable, we want to structure things
to avoid needing too many individual overrides. It seems fairly clean to
have a single interface which handles both global and context registers
in terms of the architectural pages, so the first preparatory step is to
rework cb_base into a page number rather than an absolute address.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index d9a93e5f422f..463bc8d98adb 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -95,7 +95,7 @@
#endif
/* Translation context bank */
-#define ARM_SMMU_CB(smmu, n) ((smmu)->cb_base + ((n) << (smmu)->pgshift))
+#define ARM_SMMU_CB(smmu, n) ((smmu)->base + (((smmu)->cb_base + (n)) << (smmu)->pgshift))
#define MSI_IOVA_BASE 0x8000000
#define MSI_IOVA_LENGTH 0x100000
@@ -168,8 +168,8 @@ struct arm_smmu_device {
struct device *dev;
void __iomem *base;
- void __iomem *cb_base;
- unsigned long pgshift;
+ unsigned int cb_base;
+ unsigned int pgshift;
#define ARM_SMMU_FEAT_COHERENT_WALK (1 << 0)
#define ARM_SMMU_FEAT_STREAM_MATCH (1 << 1)
@@ -1815,7 +1815,7 @@ static int arm_smmu_id_size_to_bits(int size)
static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
{
- unsigned long size;
+ unsigned int size;
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
u32 id;
bool cttw_reg, cttw_fw = smmu->features & ARM_SMMU_FEAT_COHERENT_WALK;
@@ -1899,7 +1899,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
return -ENOMEM;
dev_notice(smmu->dev,
- "\tstream matching with %lu register groups", size);
+ "\tstream matching with %u register groups", size);
}
/* s2cr->type == 0 means translation, so initialise explicitly */
smmu->s2crs = devm_kmalloc_array(smmu->dev, size, sizeof(*smmu->s2crs),
@@ -1925,11 +1925,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
/* Check for size mismatch of SMMU address space from mapped region */
size = 1 << (FIELD_GET(ID1_NUMPAGENDXB, id) + 1);
- size <<= smmu->pgshift;
- if (smmu->cb_base != gr0_base + size)
+ if (smmu->cb_base != 2 * size << smmu->pgshift)
dev_warn(smmu->dev,
- "SMMU address space size (0x%lx) differs from mapped region size (0x%tx)!\n",
- size * 2, (smmu->cb_base - gr0_base) * 2);
+ "SMMU address space size (0x%x) differs from mapped region size (0x%x)!\n",
+ 2 * size << smmu->pgshift, smmu->cb_base);
+ /* Now cb_base can reach its final form: a page number */
+ smmu->cb_base = size;
smmu->num_s2_context_banks = FIELD_GET(ID1_NUMS2CB, id);
smmu->num_context_banks = FIELD_GET(ID1_NUMCB, id);
@@ -2200,7 +2201,8 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);
- smmu->cb_base = smmu->base + resource_size(res) / 2;
+ /* We'll finish calculating this later once we know the page size */
+ smmu->cb_base = resource_size(res);
num_irqs = 0;
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) {
--
2.21.0.dirty
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox