* Re: [PATCH v6 3/4] drm/panel: Add support for S6E3HA2 panel driver on TM2 board
From: Andrzej Hajda @ 2017-01-05 7:05 UTC (permalink / raw)
To: Hoegeun Kwon, robh, thierry.reding, airlied, kgene, krzk,
inki.dae
Cc: devicetree, linux-samsung-soc, Donghwa Lee, linux-kernel,
dri-devel, jh80.chung, cw00.choi, Hyungwon Hwang
In-Reply-To: <1483598750-15062-4-git-send-email-hoegeun.kwon@samsung.com>
On 05.01.2017 07:45, Hoegeun Kwon wrote:
> This patch add support for MIPI-DSI based S6E3HA2 AMOLED panel
> driver. This panel has 1440x2560 resolution in 5.7-inch physical
> panel in the TM2 device.
>
> Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
> Signed-off-by: Hyungwon Hwang <human.hwang@samsung.com>
> Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
> Tested-by: Chanwoo Choi <cw00.choi@samsung.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Regards
Andrzej
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v6 5/5] soc: zte: pm_domains: Add support for zx296718
From: Shawn Guo @ 2017-01-05 7:38 UTC (permalink / raw)
To: Baoyou Xie
Cc: mark.rutland, amitdanielk, ulf.hansson, geert+renesas, arnd,
devicetree, pankaj.dubey, xie.baoyou, linux-kernel, krzk,
claudiu.manoil, robh+dt, chen.chaokai, laurent.pinchart,
yangbo.lu, wang.qiang01, jun.nie, linux-arm-kernel
In-Reply-To: <1483530494-14177-5-git-send-email-baoyou.xie@linaro.org>
On Wed, Jan 04, 2017 at 07:48:14PM +0800, Baoyou Xie wrote:
> This patch introduces the power domain driver of zx296718
> which belongs to zte's zx2967 family.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> Reviewed-by: Jun Nie <jun.nie@linaro.org>
> ---
> drivers/soc/zte/Makefile | 1 +
> drivers/soc/zte/zx296718_pm_domains.c | 181 ++++++++++++++++++++++++++++++++++
> 2 files changed, 182 insertions(+)
> create mode 100644 drivers/soc/zte/zx296718_pm_domains.c
>
> diff --git a/drivers/soc/zte/Makefile b/drivers/soc/zte/Makefile
> index 8a37f2f..96b7cd4 100644
> --- a/drivers/soc/zte/Makefile
> +++ b/drivers/soc/zte/Makefile
> @@ -2,3 +2,4 @@
> # ZTE SOC drivers
> #
> obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx2967_pm_domains.o
> +obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx296718_pm_domains.o
> diff --git a/drivers/soc/zte/zx296718_pm_domains.c b/drivers/soc/zte/zx296718_pm_domains.c
> new file mode 100644
> index 0000000..52003ee
> --- /dev/null
> +++ b/drivers/soc/zte/zx296718_pm_domains.c
> @@ -0,0 +1,181 @@
> +/*
> + * Copyright (C) 2017 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + * License terms: GNU General Public License (GPL) version 2
> + */
Please have a newline between licence declaration and headers to improve
the readability. Same for zx2967_pm_domains.c.
> +#include <dt-bindings/soc/zte,pm_domains.h>
> +#include "zx2967_pm_domains.h"
> +
> +static u16 zx296718_offsets[REG_ARRAY_SIZE] = {
> + [REG_CLKEN] = 0x18,
> + [REG_ISOEN] = 0x1c,
> + [REG_RSTEN] = 0x20,
> + [REG_PWREN] = 0x24,
> + [REG_ACK_SYNC] = 0x28,
> +};
> +
> +enum {
> + PCU_DM_VOU = 0,
> + PCU_DM_SAPPU,
> + PCU_DM_VDE,
> + PCU_DM_VCE,
> + PCU_DM_HDE,
> + PCU_DM_VIU,
> + PCU_DM_USB20,
> + PCU_DM_USB21,
> + PCU_DM_USB30,
> + PCU_DM_HSIC,
> + PCU_DM_GMAC,
> + PCU_DM_TS,
> +};
I think we can save this enum completely by defining those
DM_ZX296718_xxx constants in zte,pm_domains.h in the same order of this
enum (hardware bit position order), so that DM_ZX296718_xxx can directly
be used as .bit field of struct zx2967_pm_domain.
#define DM_ZX296718_VOU 0
#define DM_ZX296718_SAPPU 1
#define DM_ZX296718_VDE 2 /* g1v6 */
#define DM_ZX296718_VCE 3 /* h1v6 */
#define DM_ZX296718_HDE 4 /* g2v2 */
#define DM_ZX296718_VIU 5
#define DM_ZX296718_USB20 6
#define DM_ZX296718_USB21 7
#define DM_ZX296718_USB30 8
#define DM_ZX296718_HSIC 9
#define DM_ZX296718_GMAC 10
#define DM_ZX296718_TS 11
> +
> +static struct zx2967_pm_domain vou_domain = {
> + .dm = {
> + .name = "vou_domain",
> + },
> + .bit = PCU_DM_VOU,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain sappu_domain = {
> + .dm = {
> + .name = "sappu_domain",
> + },
> + .bit = PCU_DM_SAPPU,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain vde_domain = {
> + .dm = {
> + .name = "vde_domain",
> + },
> + .bit = PCU_DM_VDE,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain vce_domain = {
> + .dm = {
> + .name = "vce_domain",
> + },
> + .bit = PCU_DM_VCE,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain hde_domain = {
> + .dm = {
> + .name = "hde_domain",
> + },
> + .bit = PCU_DM_HDE,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain viu_domain = {
> + .dm = {
> + .name = "viu_domain",
> + },
> + .bit = PCU_DM_VIU,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain usb20_domain = {
> + .dm = {
> + .name = "usb20_domain",
> + },
> + .bit = PCU_DM_USB20,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain usb21_domain = {
> + .dm = {
> + .name = "usb21_domain",
> + },
> + .bit = PCU_DM_USB21,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain usb30_domain = {
> + .dm = {
> + .name = "usb30_domain",
> + },
> + .bit = PCU_DM_USB30,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain hsic_domain = {
> + .dm = {
> + .name = "hsic_domain",
> + },
> + .bit = PCU_DM_HSIC,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain gmac_domain = {
> + .dm = {
> + .name = "gmac_domain",
> + },
> + .bit = PCU_DM_GMAC,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain ts_domain = {
> + .dm = {
> + .name = "ts_domain",
> + },
> + .bit = PCU_DM_TS,
> + .polarity = PWREN,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct generic_pm_domain *zx296718_pm_domains[] = {
> + [DM_ZX296718_SAPPU] = &sappu_domain.dm,
> + [DM_ZX296718_VDE] = &vde_domain.dm,
> + [DM_ZX296718_VCE] = &vce_domain.dm,
> + [DM_ZX296718_HDE] = &hde_domain.dm,
> + [DM_ZX296718_VIU] = &viu_domain.dm,
> + [DM_ZX296718_USB20] = &usb20_domain.dm,
> + [DM_ZX296718_USB21] = &usb21_domain.dm,
> + [DM_ZX296718_USB30] = &usb30_domain.dm,
> + [DM_ZX296718_HSIC] = &hsic_domain.dm,
> + [DM_ZX296718_GMAC] = &gmac_domain.dm,
> + [DM_ZX296718_TS] = &ts_domain.dm,
> + [DM_ZX296718_VOU] = &vou_domain.dm,
If you update the order of DM_ZX296718_xxx in zte,pm_domains.h, it would
be nice to update this list accordingly as well.
> +};
> +
> +static int zx296718_pd_probe(struct platform_device *pdev)
> +{
> + return zx2967_pd_probe(pdev,
> + zx296718_pm_domains,
> + ARRAY_SIZE(zx296718_pm_domains));
> +}
> +
> +static const struct of_device_id zx296718_pm_domain_matches[] = {
> + { .compatible = "zte,zx296718-pcu", },
> + { },
> +};
> +
> +static struct platform_driver zx296718_pd_driver = {
> + .driver = {
> + .name = "zx-powerdomain",
This is a zx296718 specific driver. So zx296718-powerdomain should
be a better name?
Shawn
> + .owner = THIS_MODULE,
> + .of_match_table = zx296718_pm_domain_matches,
> + },
> + .probe = zx296718_pd_probe,
> +};
> +
> +static int __init zx296718_pd_init(void)
> +{
> + return platform_driver_register(&zx296718_pd_driver);
> +}
> +subsys_initcall(zx296718_pd_init);
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH V7 3/4] drm/bridge: Add driver for GE B850v3 LVDS/DP++ Bridge
From: Archit Taneja @ 2017-01-05 7:48 UTC (permalink / raw)
To: Peter Senna Tschudin, airlied-cv59FeDIM0c,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b, daniel.vetter-/w4YWyX8dFk,
davem-fT/PcQaiUtIeIZ0/mPfg9Q, devicetree-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
enric.balletbo-ZGY8ohtN/8qB+jHODAdFcQ,
eballetbo-Re5JQEeQqe8AvxtiuMwx3w, galak-sgV2jX0FEOL9JmXXK+q4OQ,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
heiko-4mtYJXux2i+zQB+pC5nmwQ,
ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
javier-0uQlZySMnqxg9hUCZPvPmw, jslaby-AlSwsSmVLrQ,
kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-0h96xk9xTtrk1uMJSBkQmQ, mark.rutland-5wv7dgnIgG8,
martin.donnelly-JJi787mZWgc, martyn.welch-ZGY8ohtN/8pPYcu2f3hruQ,
mchehab-JPH+aEBZ4P+UEJcrhfAQsw, pawel.moll-5wv7dgnIgG8,
peter.senna-Re5JQEeQqe8AvxtiuMwx3w,
p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
rmk+kernel-I+IVW8TIWO2tmTQ+vhA3Yw, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
shawnguo-DgEjT+Ai2ygdnm+yROfE0A, tiwai
Cc: Rob Herring, Fabio Estevam
In-Reply-To: <4232c88a99f44a24287d04d74b891e2eb139864c.1483301745.git.peter.senna-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
Hi,
Some comments below.
On 01/02/2017 01:54 AM, Peter Senna Tschudin wrote:
> Add a driver that create a drm_bridge and a drm_connector for the LVDS
> to DP++ display bridge of the GE B850v3.
>
> There are two physical bridges on the video signal pipeline: a
> STDP4028(LVDS to DP) and a STDP2690(DP to DP++). The hardware and
> firmware made it complicated for this binding to comprise two device
> tree nodes, as the design goal is to configure both bridges based on
> the LVDS signal, which leave the driver powerless to control the video
> processing pipeline. The two bridges behaves as a single bridge, and
> the driver is only needed for telling the host about EDID / HPD, and
> for giving the host powers to ack interrupts. The video signal pipeline
> is as follows:
>
> Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
>
> Cc: Martyn Welch <martyn.welch-ZGY8ohtN/8pPYcu2f3hruQ@public.gmane.org>
> Cc: Martin Donnelly <martin.donnelly-JJi787mZWgc@public.gmane.org>
> Cc: Daniel Vetter <daniel.vetter-/w4YWyX8dFk@public.gmane.org>
> Cc: Enric Balletbo i Serra <enric.balletbo-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
> Cc: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
> CC: David Airlie <airlied-cv59FeDIM0c@public.gmane.org>
> CC: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> CC: Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> CC: Archit Taneja <architt-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Reviewed-by: Enric Balletbo <enric.balletbo-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
> Signed-off-by: Peter Senna Tschudin <peter.senna-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
> ---
> drivers/gpu/drm/bridge/Kconfig | 11 +
> drivers/gpu/drm/bridge/Makefile | 1 +
> drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c | 384 +++++++++++++++++++++++++++++
> 3 files changed, 396 insertions(+)
> create mode 100644 drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
>
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index eb8688e..e3e1f3b 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -48,6 +48,17 @@ config DRM_DW_HDMI_I2S_AUDIO
> Support the I2S Audio interface which is part of the Synopsis
> Designware HDMI block.
>
> +config DRM_GE_B850V3_LVDS_DP
> + tristate "GE B850v3 LVDS to DP++ display bridge"
> + depends on OF
> + select DRM_KMS_HELPER
> + select DRM_PANEL
> + ---help---
> + This is a driver for the display bridge of
> + GE B850v3 that convert dual channel LVDS
> + to DP++. This is used with the i.MX6 imx-ldb
> + driver.
> +
> config DRM_NXP_PTN3460
> tristate "NXP PTN3460 DP/LVDS bridge"
> depends on OF
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> index 2e83a785..886d0fd 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -5,6 +5,7 @@ obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
> obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
> obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
> obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
> +obj-$(CONFIG_DRM_GE_B850V3_LVDS_DP) += ge_b850v3_lvds_dp.o
> obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
> obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
> obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
> diff --git a/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c b/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
> new file mode 100644
> index 0000000..4574f6e
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
> @@ -0,0 +1,384 @@
> +/*
> + * Driver for GE B850v3 DP display bridge
Mentioning LVDS to DP++ here would be nice.
> +
> + * Copyright (c) 2016, Collabora Ltd.
> + * Copyright (c) 2016, General Electric Company
> +
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> +
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> +
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> + * This driver creates a drm_bridge and a drm_connector for the LVDS to DP++
> + * display bridge of the GE B850v3. There are two physical bridges on the video
> + * signal pipeline: a STDP4028(LVDS to DP) and a STDP2690(DP to DP++). However
> + * the physical bridges are automatically configured by the input video signal,
> + * and the driver has no access to the video processing pipeline. The driver is
> + * only needed to read EDID from the STDP2690 and to handle HPD events from the
> + * STDP4028. The driver communicates with both bridges over i2c. The video
> + * signal pipeline is as follows:
> + *
> + * Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
> + *
> + */
> +
> +#include <linux/gpio.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_edid.h>
> +#include <drm/drmP.h>
> +
> +#define DEFAULT_EDID_REG 0x72
> +#define DEFAULT_EDID_REG_NAME "edid"
> +
> +#define EDID_EXT_BLOCK_CNT 0x7E
> +
> +#define STDP4028_IRQ_OUT_CONF_REG 0x02
> +#define STDP4028_DPTX_IRQ_EN_REG 0x3C
> +#define STDP4028_DPTX_IRQ_STS_REG 0x3D
> +#define STDP4028_DPTX_STS_REG 0x3E
> +
> +#define STDP4028_DPTX_DP_IRQ_EN 0x1000
> +
> +#define STDP4028_DPTX_HOTPLUG_IRQ_EN 0x0400
> +#define STDP4028_DPTX_LINK_CH_IRQ_EN 0x2000
> +#define STDP4028_DPTX_IRQ_CONFIG \
> + (STDP4028_DPTX_LINK_CH_IRQ_EN | STDP4028_DPTX_HOTPLUG_IRQ_EN)
> +
> +#define STDP4028_DPTX_HOTPLUG_STS 0x0200
> +#define STDP4028_DPTX_LINK_STS 0x1000
> +#define STDP4028_CON_STATE_CONNECTED \
> + (STDP4028_DPTX_HOTPLUG_STS | STDP4028_DPTX_LINK_STS)
> +
> +#define STDP4028_DPTX_HOTPLUG_CH_STS 0x0400
> +#define STDP4028_DPTX_LINK_CH_STS 0x2000
> +#define STDP4028_DPTX_IRQ_CLEAR \
> + (STDP4028_DPTX_LINK_CH_STS | STDP4028_DPTX_HOTPLUG_CH_STS)
> +
> +struct ge_b850v3_lvds_dp {
> + struct drm_connector connector;
> + struct drm_bridge bridge;
> + struct i2c_client *ge_b850v3_lvds_dp_i2c;
> + struct i2c_client *edid_i2c;
> + struct edid *edid;
> + struct mutex edid_mutex;
> + struct mutex irq_reg_mutex;
> +};
> +
> +static inline struct ge_b850v3_lvds_dp *
> + bridge_to_ge_b850v3_lvds_dp(struct drm_bridge *bridge)
> +{
> + return container_of(bridge, struct ge_b850v3_lvds_dp, bridge);
> +}
> +
> +static inline struct ge_b850v3_lvds_dp *
> + connector_to_ge_b850v3_lvds_dp(struct drm_connector *connector)
> +{
> + return container_of(connector, struct ge_b850v3_lvds_dp, connector);
> +}
> +
> +u8 *stdp2690_get_edid(struct i2c_client *client)
> +{
> + struct i2c_adapter *adapter = client->adapter;
> + unsigned char start = 0x00;
> + unsigned int total_size;
> + u8 *block = kmalloc(EDID_LENGTH, GFP_KERNEL);
> +
> + struct i2c_msg msgs[] = {
> + {
> + .addr = client->addr,
> + .flags = 0,
> + .len = 1,
> + .buf = &start,
> + }, {
> + .addr = client->addr,
> + .flags = I2C_M_RD,
> + .len = EDID_LENGTH,
> + .buf = block,
> + }
> + };
> +
> + if (!block)
> + return NULL;
> +
> + if (i2c_transfer(adapter, msgs, 2) != 2) {
> + DRM_ERROR("Unable to read EDID.\n");
> + goto err;
> + }
> +
> + if (!drm_edid_block_valid(block, 0, false, NULL)) {
> + DRM_ERROR("Invalid EDID block\n");
> + goto err;
> + }
> +
> + total_size = (block[EDID_EXT_BLOCK_CNT] + 1) * EDID_LENGTH;
> + if (total_size > EDID_LENGTH) {
> + kfree(block);
> + block = kmalloc(total_size, GFP_KERNEL);
> + if (!block)
> + return NULL;
> +
> + /* Yes, read the entire buffer, and do not skip the first
> + * EDID_LENGTH bytes.
> + */
Is this the reason why you aren't using drm_do_get_edid()?
> + start = 0x00;
> + msgs[1].len = total_size;
> + msgs[1].buf = block;
> +
> + if (i2c_transfer(adapter, msgs, 2) != 2) {
> + DRM_ERROR("Unable to read EDID extension blocks.\n");
> + goto err;
> + }
We should ideally check if the extension blocks are valid too.
> + }
> +
> + return block;
> +
> +err:
> + kfree(block);
> + return NULL;
> +}
> +
> +static int ge_b850v3_lvds_dp_get_modes(struct drm_connector *connector)
> +{
> + struct ge_b850v3_lvds_dp *ptn_bridge;
Why are the bridge pointers named ptn_bridge? I'm guessing it's because you
used nxp-ptn3460 bridge driver as reference. You should use something relevant
to your device.
> + struct i2c_client *client;
> + int num_modes = 0;
> +
> + ptn_bridge = connector_to_ge_b850v3_lvds_dp(connector);
> + client = ptn_bridge->edid_i2c;
> +
> + mutex_lock(&ptn_bridge->edid_mutex);
Do we really need this mutex? All the paths that call a connector's get_modes
hold the drm device's dev->mode_config.mutex lock anyway.
> +
> + kfree(ptn_bridge->edid);
> + ptn_bridge->edid = (struct edid *) stdp2690_get_edid(client);
> +
> + if (ptn_bridge->edid) {
> + drm_mode_connector_update_edid_property(connector,
> + ptn_bridge->edid);
> + num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
> + }
> +
> + mutex_unlock(&ptn_bridge->edid_mutex);
> +
> + return num_modes;
> +}
> +
> +
> +static enum drm_mode_status ge_b850v3_lvds_dp_mode_valid(
> + struct drm_connector *connector, struct drm_display_mode *mode)
> +{
> + return MODE_OK;
> +}
> +
> +static const struct
> +drm_connector_helper_funcs ge_b850v3_lvds_dp_connector_helper_funcs = {
> + .get_modes = ge_b850v3_lvds_dp_get_modes,
> + .mode_valid = ge_b850v3_lvds_dp_mode_valid,
> +};
> +
> +static enum drm_connector_status ge_b850v3_lvds_dp_detect(
> + struct drm_connector *connector, bool force)
> +{
> + struct ge_b850v3_lvds_dp *ptn_bridge =
> + connector_to_ge_b850v3_lvds_dp(connector);
> + struct i2c_client *ge_b850v3_lvds_dp_i2c =
> + ptn_bridge->ge_b850v3_lvds_dp_i2c;
> + s32 link_state;
> +
> + link_state = i2c_smbus_read_word_data(ge_b850v3_lvds_dp_i2c,
> + STDP4028_DPTX_STS_REG);
> +
> + if (link_state == STDP4028_CON_STATE_CONNECTED)
> + return connector_status_connected;
> +
> + if (link_state == 0)
> + return connector_status_disconnected;
> +
> + return connector_status_unknown;
> +}
> +
> +static const struct drm_connector_funcs ge_b850v3_lvds_dp_connector_funcs = {
> + .dpms = drm_atomic_helper_connector_dpms,
> + .fill_modes = drm_helper_probe_single_connector_modes,
> + .detect = ge_b850v3_lvds_dp_detect,
> + .destroy = drm_connector_cleanup,
> + .reset = drm_atomic_helper_connector_reset,
> + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static irqreturn_t ge_b850v3_lvds_dp_irq_handler(int irq, void *dev_id)
> +{
> + struct ge_b850v3_lvds_dp *ptn_bridge = dev_id;
> + struct i2c_client *ge_b850v3_lvds_dp_i2c
> + = ptn_bridge->ge_b850v3_lvds_dp_i2c;
> +
> + mutex_lock(&ptn_bridge->irq_reg_mutex);
Do we need this mutex? The handler is registered with the IRQF_ONESHOT
flag, so we won't get another interrupt until this handler returns.
> +
> + i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> + STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR);
> +
> + mutex_unlock(&ptn_bridge->irq_reg_mutex);
> +
> + if (ptn_bridge->connector.dev)
> + drm_kms_helper_hotplug_event(ptn_bridge->connector.dev);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int ge_b850v3_lvds_dp_attach(struct drm_bridge *bridge)
> +{
> + struct ge_b850v3_lvds_dp *ptn_bridge
> + = bridge_to_ge_b850v3_lvds_dp(bridge);
> + struct drm_connector *connector = &ptn_bridge->connector;
> + struct i2c_client *ge_b850v3_lvds_dp_i2c
> + = ptn_bridge->ge_b850v3_lvds_dp_i2c;
> + int ret;
> +
> + if (!bridge->encoder) {
> + DRM_ERROR("Parent encoder object not found");
> + return -ENODEV;
> + }
> +
> + connector->polled = DRM_CONNECTOR_POLL_HPD;
> +
> + drm_connector_helper_add(connector,
> + &ge_b850v3_lvds_dp_connector_helper_funcs);
> +
> + ret = drm_connector_init(bridge->dev, connector,
> + &ge_b850v3_lvds_dp_connector_funcs,
> + DRM_MODE_CONNECTOR_DisplayPort);
> + if (ret) {
> + DRM_ERROR("Failed to initialize connector with drm\n");
> + return ret;
> + }
> +
> + ret = drm_mode_connector_attach_encoder(connector, bridge->encoder);
> + if (ret)
> + return ret;
> +
> + drm_helper_hpd_irq_event(connector->dev);
This call doesn't serve any purpose for a connector until it is registered.
You can drop this.
> +
> + /* Configures the bridge to re-enable interrupts after each ack. */
> + i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> + STDP4028_IRQ_OUT_CONF_REG, STDP4028_DPTX_DP_IRQ_EN);
> +
> + /* Enable interrupts */
> + i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> + STDP4028_DPTX_IRQ_EN_REG, STDP4028_DPTX_IRQ_CONFIG);
> +
> + return 0;
> +}
> +
> +static void ge_b850v3_lvds_dp_detach(struct drm_bridge *bridge)
> +{
> + struct ge_b850v3_lvds_dp *ptn_bridge
> + = bridge_to_ge_b850v3_lvds_dp(bridge);
> + struct i2c_client *ge_b850v3_lvds_dp_i2c
> + = ptn_bridge->ge_b850v3_lvds_dp_i2c;
> +
> + /* Disable interrupts */
> + i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> + STDP4028_DPTX_IRQ_EN_REG, ~STDP4028_DPTX_IRQ_CONFIG);
> +}
> +
> +static const struct drm_bridge_funcs ge_b850v3_lvds_dp_funcs = {
> + .attach = ge_b850v3_lvds_dp_attach,
> + .detach = ge_b850v3_lvds_dp_detach,
> +};
> +
> +static int ge_b850v3_lvds_dp_probe(struct i2c_client *ge_b850v3_lvds_dp_i2c,
> + const struct i2c_device_id *id)
> +{
> + struct device *dev = &ge_b850v3_lvds_dp_i2c->dev;
> + struct ge_b850v3_lvds_dp *ptn_bridge;
> +
> + ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
> + if (!ptn_bridge)
> + return -ENOMEM;
> +
> + mutex_init(&ptn_bridge->edid_mutex);
> + mutex_init(&ptn_bridge->irq_reg_mutex);
> +
> + ptn_bridge->ge_b850v3_lvds_dp_i2c = ge_b850v3_lvds_dp_i2c;
> + ptn_bridge->bridge.driver_private = ptn_bridge;
bridge->driver_private isn't used by the driver anywhere. It's probably
better to drop it until it is used.
> + i2c_set_clientdata(ge_b850v3_lvds_dp_i2c, ptn_bridge);
> +
> + ptn_bridge->edid_i2c = i2c_new_secondary_device(ge_b850v3_lvds_dp_i2c,
> + DEFAULT_EDID_REG_NAME, DEFAULT_EDID_REG);
> +
> + if (!ptn_bridge->edid_i2c) {
> + dev_err(dev, "Error registering edid i2c_client, aborting...\n");
> + return -ENODEV;
> + }
> +
> + ptn_bridge->bridge.funcs = &ge_b850v3_lvds_dp_funcs;
> + ptn_bridge->bridge.of_node = dev->of_node;
> + drm_bridge_add(&ptn_bridge->bridge);
> +
> + /* Clear pending interrupts since power up. */
> + i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> + STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR);
> +
> + if (!ge_b850v3_lvds_dp_i2c->irq)
> + return 0;
> +
> + return devm_request_threaded_irq(&ge_b850v3_lvds_dp_i2c->dev,
> + ge_b850v3_lvds_dp_i2c->irq, NULL,
> + ge_b850v3_lvds_dp_irq_handler,
> + IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
> + "ge-b850v3-lvds-dp", ptn_bridge);
> +}
> +
> +static int ge_b850v3_lvds_dp_remove(struct i2c_client *ge_b850v3_lvds_dp_i2c)
> +{
> + struct ge_b850v3_lvds_dp *ptn_bridge =
> + i2c_get_clientdata(ge_b850v3_lvds_dp_i2c);
> +
> + i2c_unregister_device(ptn_bridge->edid_i2c);
> +
> + drm_bridge_remove(&ptn_bridge->bridge);
> +
> + kfree(ptn_bridge->edid);
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id ge_b850v3_lvds_dp_i2c_table[] = {
> + {"b850v3-lvds-dp", 0},
> + {},
> +};
> +MODULE_DEVICE_TABLE(i2c, ge_b850v3_lvds_dp_i2c_table);
> +
> +static const struct of_device_id ge_b850v3_lvds_dp_match[] = {
> + { .compatible = "ge,b850v3-lvds-dp" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, ge_b850v3_lvds_dp_match);
> +
> +static struct i2c_driver ge_b850v3_lvds_dp_driver = {
> + .id_table = ge_b850v3_lvds_dp_i2c_table,
> + .probe = ge_b850v3_lvds_dp_probe,
> + .remove = ge_b850v3_lvds_dp_remove,
> + .driver = {
> + .name = "b850v3-lvds-dp",
> + .of_match_table = ge_b850v3_lvds_dp_match,
> + },
> +};
> +module_i2c_driver(ge_b850v3_lvds_dp_driver);
> +
> +MODULE_AUTHOR("Peter Senna Tschudin <peter.senna-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>");
> +MODULE_AUTHOR("Martyn Welch <martyn.welch-ZGY8ohtN/8pPYcu2f3hruQ@public.gmane.org>");
> +MODULE_DESCRIPTION("GE LVDS to DP++ display bridge)");
> +MODULE_LICENSE("GPL v2");
>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v4 2/5] mfd: lm3533: Support initialization from Device Tree
From: Lee Jones @ 2017-01-05 7:49 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Rob Herring, Mark Rutland, Jonathan Cameron, Hartmut Knaack,
Lars-Peter Clausen, Peter Meerwald-Stadler, Richard Purdie,
Jacek Anaszewski, Pavel Machek, Jingoo Han, devicetree,
linux-kernel, linux-iio, linux-leds, Bjorn Andersson
In-Reply-To: <20170104192608.GN10531@minitux>
On Wed, 04 Jan 2017, Bjorn Andersson wrote:
> On Wed 04 Jan 03:54 PST 2017, Lee Jones wrote:
>
> > On Mon, 26 Dec 2016, Bjorn Andersson wrote:
> >
> > > From: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> > >
> > > Implement support for initialization of the lm3533 driver core and
> > > probing child devices from Device Tree.
> > >
>
> [..]
>
> > > @@ -512,6 +514,11 @@ static int lm3533_device_init(struct lm3533 *lm3533)
> > > lm3533_device_bl_init(lm3533);
> > > lm3533_device_led_init(lm3533);
> > >
> > > + if (lm3533->dev->of_node) {
> > > + of_platform_populate(lm3533->dev->of_node, NULL, NULL,
> > > + lm3533->dev);
> > > + }
> >
> > I think it's save to call of_platform_populate(), even if !of_node.
> > It will just fail and return an error code, which you are ignoring
> > anyway.
> >
>
> I thought so too, but that's apparently how you trigger probing children
> of the root node. So we're stuck with a conditional.
Ah, so this is to protect against the case where DT is present, but a
node for this device is not (or is disabled), so is left unprobed.
Then the bind is initiated via I2C? Or something else?
> > > static int lm3533_i2c_probe(struct i2c_client *i2c,
> > > const struct i2c_device_id *id)
> > > {
>
> [..]
>
> > >
> > > + if (i2c->dev.of_node) {
> >
> > I'd prefer this check to be placed in lm3533_pdata_from_of_node().
> >
> > Just return silently if !dev->of_node.
> >
>
> I agree, will update this.
>
> > > + ret = lm3533_pdata_from_of_node(lm3533->dev);
> > > + if (ret < 0)
> > > + return ret;
> > > + }
> > > +
> > > return lm3533_device_init(lm3533);
> > > }
> > >
>
> Regards,
> Bjorn
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [PATCH v5 2/3] drm/panel: Add support for S6E3HA2 panel driver on TM2 board
From: Inki Dae @ 2017-01-05 7:52 UTC (permalink / raw)
To: Andrzej Hajda, Rob Herring, Hoegeun Kwon
Cc: devicetree, krzk, cw00.choi, Donghwa Lee, linux-kernel, dri-devel,
jh80.chung, linux-samsung-soc, kgene, Hyungwon Hwang
In-Reply-To: <412a0238-dd8e-6c74-46a7-876e112189f1@samsung.com>
2017년 01월 05일 15:55에 Andrzej Hajda 이(가) 쓴 글:
> On 04.01.2017 15:44, Rob Herring wrote:
>> On Wed, Jan 04, 2017 at 05:15:10PM +0900, Hoegeun Kwon wrote:
>>> This patch add support for MIPI-DSI based S6E3HA2 AMOLED panel
>>> driver. This panel has 1440x2560 resolution in 5.7-inch physical
>>> panel in the TM2 device.
>>>
>>> Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
>>> Signed-off-by: Hyungwon Hwang <human.hwang@samsung.com>
>>> Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
>>> ---
>>> .../bindings/display/panel/samsung,s6e3ha2.txt | 40 ++
>>> drivers/gpu/drm/panel/Kconfig | 6 +
>>> drivers/gpu/drm/panel/Makefile | 1 +
>>> drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 741 +++++++++++++++++++++
>>> 4 files changed, 788 insertions(+)
>>> create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt
>>> create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
>>>
>>> diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt
>>> new file mode 100644
>>> index 0000000..6879f51
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt
>>> @@ -0,0 +1,40 @@
>>> +Samsung S6E3HA2 5.7" 1440x2560 AMOLED panel
>>> +
>>> +Required properties:
>>> + - compatible: "samsung,s6e3ha2"
>>> + - reg: the virtual channel number of a DSI peripheral
>>> + - vdd3-supply: I/O voltage supply
>>> + - vci-supply: voltage supply for analog circuits
>>> + - reset-gpios: a GPIO spec for the reset pin (active low)
>>> + - enable-gpios: a GPIO spec for the panel enable pin (active high)
>>> + - te-gpios: a GPIO spec for the tearing effect synchronization signal
>>> + gpio pin (active high)
>>> +
>>> +The device node can contain one 'port' child node with one child
>>> +'endpoint' node, according to the bindings defined in [1]. This
>>> +node should describe panel's video bus.
>>> +
>>> +[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
>>> +
>>> +Example:
>>> +
>>> +&dsi {
>>> + ...
>>> +
>>> + panel@0 {
>>> + compatible = "samsung,s6e3ha2";
>>> + reg = <0>;
>>> + vdd3-supply = <&ldo27_reg>;
>>> + vci-supply = <&ldo28_reg>;
>>> + reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
>>> + enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
>>> + te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>;
>>> +
>>> + port {
>>> + panel_in: endpoint {
>>> + remote-endpoint = <&dsi_out>;
>> As I said previously, it makes no sense to have a graph to dsi_out it is
>> simply the parent node.
>
> The problem is that exynos_dsi requires presence of endpoint node, when
> it was written the policy was that graphs must be always present.
> DSI reads from this node samsung,burst-clock-frequency and
> samsung,esc-clock-frequency. For example in exynos4412-trats2.dts:
>
>> dsi_0: dsi@11C80000 {
>> ...
>> ports {
>> #address-cells = <1>;
>> #size-cells = <0>;
>>
>> port@1 {
>> reg = <1>;
>>
>> dsi_out: endpoint {
>> remote-endpoint = <&dsi_in>;
>> samsung,burst-clock-frequency
>> = <500000000>;
>> samsung,esc-clock-frequency =
>> <20000000>;
>> };
>> };
>> };
>>
>> panel@0 {
>> ...
>> port {
>> dsi_in: endpoint {
>> remote-endpoint = <&dsi_out>;
>> };
>> };
>> };
>> };
>
> However, DSI driver does not use remote-endpoint property, it is here
> only to fulfill of_graph policy.
> So if something like below is acceptable, we can get rid of port node in
> panel:
>
>> dsi_0: dsi@11C80000 {
>> ...
>> ports {
>> #address-cells = <1>;
>> #size-cells = <0>;
>>
>> port@1 {
>> reg = <1>;
>>
>> dsi_out: endpoint {
>> samsung,burst-clock-frequency
>> = <500000000>;
>> samsung,esc-clock-frequency =
>> <20000000>;
>> };
>> };
>> };
>>
>> panel@0 {
>> ...
>> };
>> };
>
> What do you think?
>
> Other solution is to move problematic properties somewhere else, but
> this require change of bindings.
> Anyway I would be glad to remove port nodes in other samsung panels:
> s6e8aa0, ld9040.
In addition,
Now dsi and mic device nodes of exynos5433.dtsi include remote nodes which define Display pipeline. This is wrong.
Display pipeline is specific to board, not SoC so these things should be moved to exynos5433-tm2.dts file.
Hoegeun, you can do this with other patch also.
Thanks.
>
> Regards
> Andrzej
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* RE: [PATCH 6/9] arm64: dts: ls1046a: add MSI dts node
From: M.H. Lian @ 2017-01-05 8:05 UTC (permalink / raw)
To: Rob Herring
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Marc Zyngier,
Jason Cooper, Roy Zang, Mingkai Hu, Stuart Yoder, Leo Li,
Scott Wood
In-Reply-To: <20170103171258.h5djzsarokjjldjx@rob-hp-laptop>
Hi Rob,
Thanks for your comment.
I will change whitespace.
Thanks,
Minghuan
> -----Original Message-----
> From: Rob Herring [mailto:robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org]
> Sent: Wednesday, January 04, 2017 1:13 AM
> To: M.H. Lian <minghuan.lian-3arQi8VN3Tc@public.gmane.org>
> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>; Jason
> Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>; Roy Zang <roy.zang-3arQi8VN3Tc@public.gmane.org>; Mingkai
> Hu <mingkai.hu-3arQi8VN3Tc@public.gmane.org>; Stuart Yoder <stuart.yoder-3arQi8VN3Tc@public.gmane.org>; Leo Li
> <leoyang.li-3arQi8VN3Tc@public.gmane.org>; Scott Wood <scott.wood-3arQi8VN3Tc@public.gmane.org>
> Subject: Re: [PATCH 6/9] arm64: dts: ls1046a: add MSI dts node
>
> On Tue, Dec 27, 2016 at 05:13:02PM +0800, Minghuan Lian wrote:
> > LS1046a includes 3 MSI controllers.
> > Each controller supports 128 interrupts.
> >
> > Signed-off-by: Minghuan Lian <Minghuan.Lian-3arQi8VN3Tc@public.gmane.org>
> > ---
> > .../interrupt-controller/fsl,ls-scfg-msi.txt | 1 +
> > arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 31
> ++++++++++++++++++++++
> > 2 files changed, 32 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-
> scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-
> controller/fsl,ls-scfg-msi.txt
> > index 2755cd1..54597b0 100644
> > --- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-
> msi.txt
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-
> msi.txt
> > @@ -6,6 +6,7 @@ Required properties:
> > Layerscape PCIe MSI controller block such as:
> > "fsl,ls1021a-msi"
> > "fsl,ls1043a-msi"
> > + "fsl,ls1046a-msi"
>
> Differing whitespace.
>
> Otherwise,
>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 03/22] iio: adc: add support for X-Powers AXP20X and AXP22X PMICs ADCs
From: Quentin Schulz @ 2017-01-05 8:06 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Mark Rutland, devicetree, Lars-Peter Clausen, open list:THERMAL,
linux-iio, linux-kernel, Sebastian Reichel, Russell King,
Bruno Prémont, Rob Herring, linux-arm-kernel,
Peter Meerwald-Stadler, knaack.h, Maxime Ripard, Lee Jones,
Thomas Petazzoni, Jonathan Cameron, Icenowy Zheng
In-Reply-To: <CAGb2v67S==AG=jZA=mO-bB4u1F2TOwhmBXg385W1xhUa3RAFbA@mail.gmail.com>
Hi Chen-Yu,
On 05/01/2017 06:42, Chen-Yu Tsai wrote:
> On Tue, Jan 3, 2017 at 12:37 AM, Quentin Schulz
> <quentin.schulz@free-electrons.com> wrote:
[...]
>> +
>> +#define AXP20X_ADC_RATE_MASK (3 << 6)
>> +#define AXP20X_ADC_RATE_25HZ (0 << 6)
>> +#define AXP20X_ADC_RATE_50HZ BIT(6)
>
> Please be consistent with the format.
>
>> +#define AXP20X_ADC_RATE_100HZ (2 << 6)
>> +#define AXP20X_ADC_RATE_200HZ (3 << 6)
>> +
>> +#define AXP22X_ADC_RATE_100HZ (0 << 6)
>> +#define AXP22X_ADC_RATE_200HZ BIT(6)
>> +#define AXP22X_ADC_RATE_400HZ (2 << 6)
>> +#define AXP22X_ADC_RATE_800HZ (3 << 6)
>
> These are power-of-2 multiples of some base rate. May I suggest
> a formula macro instead. Either way, you seem to be using only
> one value. Will this be made configurable in the future?
>
Yes, I could use a formula macro instead. No plan to make it
configurable, should I make it configurable?
>> +
>> +#define AXP20X_ADC_CHANNEL(_channel, _name, _type, _reg) \
>> + { \
>> + .type = _type, \
>> + .indexed = 1, \
>> + .channel = _channel, \
>> + .address = _reg, \
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
>> + BIT(IIO_CHAN_INFO_SCALE), \
>> + .datasheet_name = _name, \
>> + }
>> +
>> +#define AXP20X_ADC_CHANNEL_OFFSET(_channel, _name, _type, _reg) \
>> + { \
>> + .type = _type, \
>> + .indexed = 1, \
>> + .channel = _channel, \
>> + .address = _reg, \
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
>> + BIT(IIO_CHAN_INFO_SCALE) |\
>> + BIT(IIO_CHAN_INFO_OFFSET),\
>> + .datasheet_name = _name, \
>> + }
>> +
>> +struct axp20x_adc_iio {
>> + struct iio_dev *indio_dev;
>> + struct regmap *regmap;
>> +};
>> +
>> +enum axp20x_adc_channel {
>> + AXP20X_ACIN_V = 0,
>> + AXP20X_ACIN_I,
>> + AXP20X_VBUS_V,
>> + AXP20X_VBUS_I,
>> + AXP20X_TEMP_ADC,
>
> PMIC_TEMP would be better. And please save a slot for TS input.
>
ACK.
Hum.. I'm wondering what should be the IIO type of the TS input channel
then? The TS Pin can be used in two modes: either to monitor the
temperature of the battery or as an external ADC, at least that's what I
understand from the datasheet.
>> + AXP20X_GPIO0_V,
>> + AXP20X_GPIO1_V,
>
> Please skip a slot for "battery instantaneous power".
>
>> + AXP20X_BATT_V,
>> + AXP20X_BATT_CHRG_I,
>> + AXP20X_BATT_DISCHRG_I,
>> + AXP20X_IPSOUT_V,
>> +};
>> +
>> +enum axp22x_adc_channel {
>> + AXP22X_TEMP_ADC = 0,
>
> Same comments as AXP20X_TEMP_ADC.
>
>> + AXP22X_BATT_V,
>> + AXP22X_BATT_CHRG_I,
>> + AXP22X_BATT_DISCHRG_I,
>> +};
>
> Shouldn't these channel numbers be exported as part of the device tree
> bindings? At the very least, they shouldn't be changed.
>
I don't understand what you mean by that. Do you mean you want a
consistent numbering between the AXP20X and the AXP22X, so that
AXP22X_BATT_V would have the same channel number than AXP20X_BATT_V?
Could you explain a bit more your thoughts on the channel numbers being
exported as part of the device tree bindings?
> Also please add a comment saying that the channels are numbered
> in the order of their respective registers, and not the table
> describing the ADCs in the datasheet (9.7 Signal Capture for AXP209
> and 9.5 E-Gauge for AXP221).
>
Yes I can.
What about Rob wanting channel numbers to start at zero for each
different IIO type (i.e., today we have AXP22X_BATT_CHRG_I being
exported as in_current1_raw whereas he wants in_current0_raw).
[...]
>> +static int axp22x_adc_read_raw(struct iio_dev *indio_dev,
>> + struct iio_chan_spec const *channel, int *val,
>> + int *val2)
>> +{
>> + struct axp20x_adc_iio *info = iio_priv(indio_dev);
>> + int size = 12, ret;
>> +
>> + switch (channel->channel) {
>> + case AXP22X_BATT_DISCHRG_I:
>> + size = 13;
>> + case AXP22X_TEMP_ADC:
>> + case AXP22X_BATT_V:
>> + case AXP22X_BATT_CHRG_I:
>
> According to the datasheet, AXP22X_BATT_CHRG_I is also 13 bits wide.
>
Where did you get that?
Also, the datasheet is inconsistent:
- 9.5 E-Gauge Fuel Gauge system => the min value is at 0x0 and the max
value at 0xfff for all channels, that's 12 bits.
- 10.1.4 ADC Data => all channels except battery discharge current are
on 12 bits (8 high, 4 low).
[...]
>> +static int axp22x_read_raw(struct iio_dev *indio_dev,
>> + struct iio_chan_spec const *chan, int *val,
>> + int *val2, long mask)
>> +{
>> + switch (mask) {
>> + case IIO_CHAN_INFO_OFFSET:
>> + *val = -2667;
>
> Datasheet says -267.7 C, or -2677 here.
>
The formula in the datasheet is (in milli Celsius):
processed = raw * 100 - 266700;
while the IIO framework asks for a scale and an offset which are then
applied as:
processed = (raw + offset) * scale;
Thus by factorizing, we get:
processed = (raw - 2667) * 100;
[...]
>> +static int axp20x_remove(struct platform_device *pdev)
>> +{
>> + struct axp20x_adc_iio *info;
>> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>> +
>> + info = iio_priv(indio_dev);
>
> Nit: you could just reverse the 2 declarations above and join this
> line after struct axp20x_adc_iio *info;
>
>> + regmap_write(info->regmap, AXP20X_ADC_EN1, 0);
>> + regmap_write(info->regmap, AXP20X_ADC_EN2, 0);
>
> The existing VBUS power supply driver enables the VBUS ADC bits itself,
> and does not check them later on. This means if one were to remove this
> axp20x-adc module, the voltage/current readings in the VBUS power supply
> would be invalid. Some sort of workaround would be needed here in this
> driver of the VBUS driver.
>
That would be one reason to migrate the VBUS driver to use the IIO
channels, wouldn't it?
But ACK, I'll think about something to work around this issue.
>> +
>> + return 0;
>> +}
>> +
>> +static struct platform_driver axp20x_adc_driver = {
>> + .driver = {
>> + .name = "axp20x-adc",
>> + .of_match_table = axp20x_adc_of_match,
>> + },
>> + .probe = axp20x_probe,
>> + .remove = axp20x_remove,
>> +};
>> +
>> +module_platform_driver(axp20x_adc_driver);
>> +
>> +MODULE_DESCRIPTION("ADC driver for AXP20X and AXP22X PMICs");
>> +MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
>> +MODULE_LICENSE("GPL");
>> diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
>> index a4860bc..650c6f6 100644
>> --- a/include/linux/mfd/axp20x.h
>> +++ b/include/linux/mfd/axp20x.h
>> @@ -150,6 +150,10 @@ enum {
>> #define AXP20X_VBUS_I_ADC_L 0x5d
>> #define AXP20X_TEMP_ADC_H 0x5e
>> #define AXP20X_TEMP_ADC_L 0x5f
>> +
>> +#define AXP22X_TEMP_ADC_H 0x56
>> +#define AXP22X_TEMP_ADC_L 0x57
>> +
>
> This is in the wrong patch. Also we already have
>
> /* AXP22X specific registers */
> #define AXP22X_PMIC_ADC_H 0x56
> #define AXP22X_PMIC_ADC_L 0x57
> #define AXP22X_TS_ADC_H 0x58
> #define AXP22X_TS_ADC_L 0x59
>
> If you want, you could just rename them to be consistent.
>
ACK.
Thanks,
Quentin
--
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH 05/22] ARM: dtsi: axp209: add AXP209 ADC subnode
From: Quentin Schulz @ 2017-01-05 8:08 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Mark Rutland, devicetree, Lars-Peter Clausen, open list:THERMAL,
linux-iio, linux-kernel, Sebastian Reichel, Russell King,
Bruno Prémont, Rob Herring, linux-arm-kernel,
Peter Meerwald-Stadler, knaack.h, Maxime Ripard, Lee Jones,
Thomas Petazzoni, Jonathan Cameron, Icenowy Zheng
In-Reply-To: <CAGb2v66dw=DECuHpLDzHnMP-O4UwZ+RkPsH0RofOGdBa7z7OHw@mail.gmail.com>
On 05/01/2017 06:51, Chen-Yu Tsai wrote:
> On Tue, Jan 3, 2017 at 12:37 AM, Quentin Schulz
> <quentin.schulz@free-electrons.com> wrote:
>> X-Powers AXP209 PMIC has multiple ADCs, each one exposing data from the
>> different power supplies connected to the PMIC.
>>
>> This adds the ADC subnode for AXP20X PMIC.
>>
>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>> ---
>> arch/arm/boot/dts/axp209.dtsi | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/axp209.dtsi b/arch/arm/boot/dts/axp209.dtsi
>> index 675bb0f..2a4e8ee 100644
>> --- a/arch/arm/boot/dts/axp209.dtsi
>> +++ b/arch/arm/boot/dts/axp209.dtsi
>> @@ -53,6 +53,11 @@
>> interrupt-controller;
>> #interrupt-cells = <1>;
>>
>> + axp209_adc: axp209_adc {
>
> Node name should be generic. Please change it to "adc".
>
OK, do I keep the label as is?
axp209_adc: adc {
Thanks,
Quentin
--
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH RESEND] dmaengine: stm32-dma: Add error messages if xlate fails
From: M'boumba Cedric Madianga @ 2017-01-05 8:09 UTC (permalink / raw)
To: vinod.koul-ral2JQCrhuEAvxtiuMwx3w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w,
alexandre.torgue-qxv4g6HH51o,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: M'boumba Cedric Madianga
This patch adds some error messages when a slave device fails to request a
channel.
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Reviewed-by: Ludovic BARRE <ludovic.barre-qxv4g6HH51o@public.gmane.org>
---
Resolve conflicts issue
---
drivers/dma/stm32-dma.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index fc9738e..4eacd9d 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -987,30 +987,36 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
struct stm32_dma_device *dmadev = ofdma->of_dma_data;
+ struct device *dev = dmadev->ddev.dev;
struct stm32_dma_cfg cfg;
struct stm32_dma_chan *chan;
struct dma_chan *c;
- if (dma_spec->args_count < 3)
+ if (dma_spec->args_count < 4) {
+ dev_err(dev, "Bad number of cells\n");
return NULL;
+ }
cfg.channel_id = dma_spec->args[0];
cfg.request_line = dma_spec->args[1];
cfg.stream_config = dma_spec->args[2];
- cfg.threshold = 0;
+ cfg.threshold = dma_spec->args[3];
- if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >=
- STM32_DMA_MAX_REQUEST_ID))
+ if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) ||
+ (cfg.request_line >= STM32_DMA_MAX_REQUEST_ID)) {
+ dev_err(dev, "Bad channel and/or request id\n");
return NULL;
-
- if (dma_spec->args_count > 3)
- cfg.threshold = dma_spec->args[3];
+ }
chan = &dmadev->chan[cfg.channel_id];
c = dma_get_slave_channel(&chan->vchan.chan);
- if (c)
- stm32_dma_set_config(chan, &cfg);
+ if (!c) {
+ dev_err(dev, "No more channel avalaible\n");
+ return NULL;
+ }
+
+ stm32_dma_set_config(chan, &cfg);
return c;
}
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2, 1/9] irqchip/ls-scfg-msi: fix typo of MSI compatible strings
From: Minghuan Lian @ 2017-01-05 8:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, devicetree
Cc: Rob Herring, Jason Cooper, Roy Zang, Marc Zyngier, Stuart Yoder,
Yang-Leo Li, Minghuan Lian, Scott Wood, Mingkai Hu
The patch is to fix typo of the Layerscape SCFG MSI dts compatible
strings. "1" is replaced by "l".
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
Acked-by: Rob Herring <robh@kernel.org>
---
v2-v1:
- None
.../devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt | 6 +++---
drivers/irqchip/irq-ls-scfg-msi.c | 6 ++++--
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 9e38949..2755cd1 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -4,8 +4,8 @@ Required properties:
- compatible: should be "fsl,<soc-name>-msi" to identify
Layerscape PCIe MSI controller block such as:
- "fsl,1s1021a-msi"
- "fsl,1s1043a-msi"
+ "fsl,ls1021a-msi"
+ "fsl,ls1043a-msi"
- msi-controller: indicates that this is a PCIe MSI controller node
- reg: physical base address of the controller and length of memory mapped.
- interrupts: an interrupt to the parent interrupt controller.
@@ -23,7 +23,7 @@ MSI controller node
Examples:
msi1: msi-controller@1571000 {
- compatible = "fsl,1s1043a-msi";
+ compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1571000 0x0 0x8>,
msi-controller;
interrupts = <0 116 0x4>;
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 02cca74c..cef67cc 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -219,8 +219,10 @@ static int ls_scfg_msi_remove(struct platform_device *pdev)
}
static const struct of_device_id ls_scfg_msi_id[] = {
- { .compatible = "fsl,1s1021a-msi", },
- { .compatible = "fsl,1s1043a-msi", },
+ { .compatible = "fsl,1s1021a-msi", }, /* a typo */
+ { .compatible = "fsl,1s1043a-msi", }, /* a typo */
+ { .compatible = "fsl,ls1021a-msi", },
+ { .compatible = "fsl,ls1043a-msi", },
{},
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2,2/9] arm: dts: ls1021a: fix typo of MSI compatible string
From: Minghuan Lian @ 2017-01-05 8:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, devicetree
Cc: Rob Herring, Jason Cooper, Roy Zang, Marc Zyngier, Stuart Yoder,
Yang-Leo Li, Minghuan Lian, Scott Wood, Mingkai Hu
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>
"1" should be replaced by "l". This is a typo.
The patch is to fix it.
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v2-v1:
- None
arch/arm/boot/dts/ls1021a.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 282d854..6651938 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -122,14 +122,14 @@
};
msi1: msi-controller@1570e00 {
- compatible = "fsl,1s1021a-msi";
+ compatible = "fsl,ls1021a-msi";
reg = <0x0 0x1570e00 0x0 0x8>;
msi-controller;
interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
};
msi2: msi-controller@1570e08 {
- compatible = "fsl,1s1021a-msi";
+ compatible = "fsl,ls1021a-msi";
reg = <0x0 0x1570e08 0x0 0x8>;
msi-controller;
interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
--
1.9.1
^ permalink raw reply related
* [PATCH v2, 3/9] arm64: dts: ls1043a: fix typo of MSI compatible string
From: Minghuan Lian @ 2017-01-05 8:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, devicetree
Cc: Rob Herring, Jason Cooper, Roy Zang, Marc Zyngier, Stuart Yoder,
Yang-Leo Li, Minghuan Lian, Scott Wood, Mingkai Hu
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>
"1" should be replaced by "l". This is a typo.
The patch is to fix it.
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v2-v1:
- None
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index ec13a6e..692fc35 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -589,21 +589,21 @@
};
msi1: msi-controller1@1571000 {
- compatible = "fsl,1s1043a-msi";
+ compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1571000 0x0 0x8>;
msi-controller;
interrupts = <0 116 0x4>;
};
msi2: msi-controller2@1572000 {
- compatible = "fsl,1s1043a-msi";
+ compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1572000 0x0 0x8>;
msi-controller;
interrupts = <0 126 0x4>;
};
msi3: msi-controller3@1573000 {
- compatible = "fsl,1s1043a-msi";
+ compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1573000 0x0 0x8>;
msi-controller;
interrupts = <0 160 0x4>;
--
1.9.1
^ permalink raw reply related
* [PATCH v2,4/9] arm: dts: ls1021a: share all MSIs
From: Minghuan Lian @ 2017-01-05 8:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, devicetree
Cc: Rob Herring, Jason Cooper, Roy Zang, Marc Zyngier, Stuart Yoder,
Yang-Leo Li, Minghuan Lian, Scott Wood, Mingkai Hu
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>
In order to maximize the use of MSI, a PCIe controller will share
all MSI controllers. The patch changes msi-parent to refer to all
MSI controller dts nodes.
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v2-v1:
- None
arch/arm/boot/dts/ls1021a.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 6651938..1c82024 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -723,7 +723,7 @@
bus-range = <0x0 0xff>;
ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000 /* downstream I/O */
0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&msi1>;
+ msi-parent = <&msi1>, <&msi2>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0000 0 0 1 &gic GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
@@ -746,7 +746,7 @@
bus-range = <0x0 0xff>;
ranges = <0x81000000 0x0 0x00000000 0x48 0x00010000 0x0 0x00010000 /* downstream I/O */
0x82000000 0x0 0x40000000 0x48 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&msi2>;
+ msi-parent = <&msi1>, <&msi2>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0000 0 0 1 &gic GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>,
--
1.9.1
^ permalink raw reply related
* [PATCH v2,5/9] arm64: dts: ls1043a: share all MSIs
From: Minghuan Lian @ 2017-01-05 8:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, devicetree
Cc: Rob Herring, Jason Cooper, Roy Zang, Marc Zyngier, Stuart Yoder,
Yang-Leo Li, Minghuan Lian, Scott Wood, Mingkai Hu
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>
In order to maximize the use of MSI, a PCIe controller will share
all MSI controllers. The patch changes "msi-parent" to refer to all
MSI controller dts nodes.
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v2-v1:
- None
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 692fc35..3947220 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -625,7 +625,7 @@
bus-range = <0x0 0xff>;
ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000 /* downstream I/O */
0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&msi1>;
+ msi-parent = <&msi1>, <&msi2>, <&msi3>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0000 0 0 1 &gic 0 110 0x4>,
@@ -650,7 +650,7 @@
bus-range = <0x0 0xff>;
ranges = <0x81000000 0x0 0x00000000 0x48 0x00010000 0x0 0x00010000 /* downstream I/O */
0x82000000 0x0 0x40000000 0x48 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&msi2>;
+ msi-parent = <&msi1>, <&msi2>, <&msi3>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0000 0 0 1 &gic 0 120 0x4>,
@@ -675,7 +675,7 @@
bus-range = <0x0 0xff>;
ranges = <0x81000000 0x0 0x00000000 0x50 0x00010000 0x0 0x00010000 /* downstream I/O */
0x82000000 0x0 0x40000000 0x50 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&msi3>;
+ msi-parent = <&msi1>, <&msi2>, <&msi3>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0000 0 0 1 &gic 0 154 0x4>,
--
1.9.1
^ permalink raw reply related
* [PATCH v2,6/9] arm64: dts: ls1046a: add MSI dts node
From: Minghuan Lian @ 2017-01-05 8:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, devicetree
Cc: Rob Herring, Jason Cooper, Roy Zang, Marc Zyngier, Stuart Yoder,
Yang-Leo Li, Minghuan Lian, Scott Wood, Mingkai Hu
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>
LS1046a includes 3 MSI controllers.
Each controller supports 128 interrupts.
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
Acked-by: Rob Herring <robh@kernel.org>
---
v2-v1:
- change whitespace number
.../interrupt-controller/fsl,ls-scfg-msi.txt | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 31 ++++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 2755cd1..dde4552 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -6,6 +6,7 @@ Required properties:
Layerscape PCIe MSI controller block such as:
"fsl,ls1021a-msi"
"fsl,ls1043a-msi"
+ "fsl,ls1046a-msi"
- msi-controller: indicates that this is a PCIe MSI controller node
- reg: physical base address of the controller and length of memory mapped.
- interrupts: an interrupt to the parent interrupt controller.
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 38806ca..49dbafc 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -511,5 +511,36 @@
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen 4 1>;
};
+
+ msi1: msi-controller@1580000 {
+ compatible = "fsl,ls1046a-msi";
+ msi-controller;
+ reg = <0x0 0x1580000 0x0 0x10000>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ msi2: msi-controller@1590000 {
+ compatible = "fsl,ls1046a-msi";
+ msi-controller;
+ reg = <0x0 0x1590000 0x0 0x10000>;
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ msi3: msi-controller@15a0000 {
+ compatible = "fsl,ls1046a-msi";
+ msi-controller;
+ reg = <0x0 0x15a0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
};
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2,7/9] irqchip/ls-scfg-msi: add LS1046a MSI support
From: Minghuan Lian @ 2017-01-05 8:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, devicetree
Cc: Rob Herring, Jason Cooper, Roy Zang, Marc Zyngier, Stuart Yoder,
Yang-Leo Li, Minghuan Lian, Scott Wood, Mingkai Hu
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>
LS1046a includes 4 MSIRs, each MSIR is assigned a dedicate GIC
SPI interrupt and provides 32 MSI interrupts. Compared to previous
MSI, LS1046a's IBS(interrupt bit select) shift is changed to 2 and
total MSI interrupt number is changed to 128.
The patch adds structure 'ls_scfg_msir' to describe MSIR setting and
'ibs_shift' to store the different value between the SoCs.
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v2-v1:
- MSI dts node change has been merged into the patch 6/9
drivers/irqchip/irq-ls-scfg-msi.c | 161 +++++++++++++++++++++++++++++---------
1 file changed, 126 insertions(+), 35 deletions(-)
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index cef67cc..67547bd 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -17,13 +17,24 @@
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/spinlock.h>
-#define MSI_MAX_IRQS 32
-#define MSI_IBS_SHIFT 3
-#define MSIR 4
+#define MSI_IRQS_PER_MSIR 32
+#define MSI_MSIR_OFFSET 4
+
+struct ls_scfg_msi_cfg {
+ u32 ibs_shift; /* Shift of interrupt bit select */
+};
+
+struct ls_scfg_msir {
+ struct ls_scfg_msi *msi_data;
+ unsigned int index;
+ unsigned int gic_irq;
+ void __iomem *reg;
+};
struct ls_scfg_msi {
spinlock_t lock;
@@ -32,8 +43,11 @@ struct ls_scfg_msi {
struct irq_domain *msi_domain;
void __iomem *regs;
phys_addr_t msiir_addr;
- int irq;
- DECLARE_BITMAP(used, MSI_MAX_IRQS);
+ struct ls_scfg_msi_cfg *cfg;
+ u32 msir_num;
+ struct ls_scfg_msir *msir;
+ u32 irqs_num;
+ unsigned long *used;
};
static struct irq_chip ls_scfg_msi_irq_chip = {
@@ -55,7 +69,7 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
msg->address_hi = upper_32_bits(msi_data->msiir_addr);
msg->address_lo = lower_32_bits(msi_data->msiir_addr);
- msg->data = data->hwirq << MSI_IBS_SHIFT;
+ msg->data = data->hwirq;
}
static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
@@ -81,8 +95,8 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain,
WARN_ON(nr_irqs != 1);
spin_lock(&msi_data->lock);
- pos = find_first_zero_bit(msi_data->used, MSI_MAX_IRQS);
- if (pos < MSI_MAX_IRQS)
+ pos = find_first_zero_bit(msi_data->used, msi_data->irqs_num);
+ if (pos < msi_data->irqs_num)
__set_bit(pos, msi_data->used);
else
err = -ENOSPC;
@@ -106,7 +120,7 @@ static void ls_scfg_msi_domain_irq_free(struct irq_domain *domain,
int pos;
pos = d->hwirq;
- if (pos < 0 || pos >= MSI_MAX_IRQS) {
+ if (pos < 0 || pos >= msi_data->irqs_num) {
pr_err("failed to teardown msi. Invalid hwirq %d\n", pos);
return;
}
@@ -123,15 +137,17 @@ static void ls_scfg_msi_domain_irq_free(struct irq_domain *domain,
static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
{
- struct ls_scfg_msi *msi_data = irq_desc_get_handler_data(desc);
+ struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
+ struct ls_scfg_msi *msi_data = msir->msi_data;
unsigned long val;
- int pos, virq;
+ int pos, virq, hwirq;
chained_irq_enter(irq_desc_get_chip(desc), desc);
- val = ioread32be(msi_data->regs + MSIR);
- for_each_set_bit(pos, &val, MSI_MAX_IRQS) {
- virq = irq_find_mapping(msi_data->parent, (31 - pos));
+ val = ioread32be(msir->reg);
+ for_each_set_bit(pos, &val, MSI_IRQS_PER_MSIR) {
+ hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
+ virq = irq_find_mapping(msi_data->parent, hwirq);
if (virq)
generic_handle_irq(virq);
}
@@ -143,7 +159,7 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data)
{
/* Initialize MSI domain parent */
msi_data->parent = irq_domain_add_linear(NULL,
- MSI_MAX_IRQS,
+ msi_data->irqs_num,
&ls_scfg_msi_domain_ops,
msi_data);
if (!msi_data->parent) {
@@ -164,16 +180,83 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data)
return 0;
}
+static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
+{
+ struct ls_scfg_msir *msir;
+ int virq, i, hwirq;
+
+ virq = platform_get_irq(msi_data->pdev, index);
+ if (virq <= 0)
+ return -ENODEV;
+
+ msir = &msi_data->msir[index];
+ msir->index = index;
+ msir->msi_data = msi_data;
+ msir->gic_irq = virq;
+ msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index;
+
+ irq_set_chained_handler_and_data(msir->gic_irq,
+ ls_scfg_msi_irq_handler,
+ msir);
+
+ /* Release the hwirqs corresponding to this MSIR */
+ for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+ hwirq = i << msi_data->cfg->ibs_shift | msir->index;
+ bitmap_clear(msi_data->used, hwirq, 1);
+ }
+
+ return 0;
+}
+
+static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
+{
+ struct ls_scfg_msi *msi_data = msir->msi_data;
+ int i, hwirq;
+
+ if (msir->gic_irq > 0)
+ irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL);
+
+ for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+ hwirq = i << msi_data->cfg->ibs_shift | msir->index;
+ bitmap_set(msi_data->used, hwirq, 1);
+ }
+
+ return 0;
+}
+
+static struct ls_scfg_msi_cfg ls1021_msi_cfg = {
+ .ibs_shift = 3,
+};
+
+static struct ls_scfg_msi_cfg ls1046_msi_cfg = {
+ .ibs_shift = 2,
+};
+
+static const struct of_device_id ls_scfg_msi_id[] = {
+ { .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg },
+ { .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg },
+ { .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ls_scfg_msi_id);
+
static int ls_scfg_msi_probe(struct platform_device *pdev)
{
+ const struct of_device_id *match;
struct ls_scfg_msi *msi_data;
struct resource *res;
- int ret;
+ int i, ret;
+
+ match = of_match_device(ls_scfg_msi_id, &pdev->dev);
+ if (!match)
+ return -ENODEV;
msi_data = devm_kzalloc(&pdev->dev, sizeof(*msi_data), GFP_KERNEL);
if (!msi_data)
return -ENOMEM;
+ msi_data->cfg = (struct ls_scfg_msi_cfg *) match->data;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
msi_data->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(msi_data->regs)) {
@@ -182,23 +265,37 @@ static int ls_scfg_msi_probe(struct platform_device *pdev)
}
msi_data->msiir_addr = res->start;
- msi_data->irq = platform_get_irq(pdev, 0);
- if (msi_data->irq <= 0) {
- dev_err(&pdev->dev, "failed to get MSI irq\n");
- return -ENODEV;
- }
-
msi_data->pdev = pdev;
spin_lock_init(&msi_data->lock);
+ msi_data->irqs_num = MSI_IRQS_PER_MSIR *
+ (1 << msi_data->cfg->ibs_shift);
+ msi_data->used = devm_kcalloc(&pdev->dev,
+ BITS_TO_LONGS(msi_data->irqs_num),
+ sizeof(*msi_data->used),
+ GFP_KERNEL);
+ if (!msi_data->used)
+ return -ENOMEM;
+ /*
+ * Reserve all the hwirqs
+ * The available hwirqs will be released in ls1_msi_setup_hwirq()
+ */
+ bitmap_set(msi_data->used, 0, msi_data->irqs_num);
+
+ msi_data->msir_num = of_irq_count(pdev->dev.of_node);
+ msi_data->msir = devm_kcalloc(&pdev->dev, msi_data->msir_num,
+ sizeof(*msi_data->msir),
+ GFP_KERNEL);
+ if (!msi_data->msir)
+ return -ENOMEM;
+
+ for (i = 0; i < msi_data->msir_num; i++)
+ ls_scfg_msi_setup_hwirq(msi_data, i);
+
ret = ls_scfg_msi_domains_init(msi_data);
if (ret)
return ret;
- irq_set_chained_handler_and_data(msi_data->irq,
- ls_scfg_msi_irq_handler,
- msi_data);
-
platform_set_drvdata(pdev, msi_data);
return 0;
@@ -207,8 +304,10 @@ static int ls_scfg_msi_probe(struct platform_device *pdev)
static int ls_scfg_msi_remove(struct platform_device *pdev)
{
struct ls_scfg_msi *msi_data = platform_get_drvdata(pdev);
+ int i;
- irq_set_chained_handler_and_data(msi_data->irq, NULL, NULL);
+ for (i = 0; i < msi_data->msir_num; i++)
+ ls_scfg_msi_teardown_hwirq(&msi_data->msir[i]);
irq_domain_remove(msi_data->msi_domain);
irq_domain_remove(msi_data->parent);
@@ -218,14 +317,6 @@ static int ls_scfg_msi_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id ls_scfg_msi_id[] = {
- { .compatible = "fsl,1s1021a-msi", }, /* a typo */
- { .compatible = "fsl,1s1043a-msi", }, /* a typo */
- { .compatible = "fsl,ls1021a-msi", },
- { .compatible = "fsl,ls1043a-msi", },
- {},
-};
-
static struct platform_driver ls_scfg_msi_driver = {
.driver = {
.name = "ls-scfg-msi",
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 15/22] mfd: axp20x: add CHRG_CTRL1 to writeable regs for AXP20X/AXP22X
From: Quentin Schulz @ 2017-01-05 8:10 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Mark Rutland, devicetree, Lars-Peter Clausen, open list:THERMAL,
linux-iio, linux-kernel, Sebastian Reichel, Russell King,
Bruno Prémont, Rob Herring, linux-arm-kernel,
Peter Meerwald-Stadler, knaack.h, Maxime Ripard, Lee Jones,
Thomas Petazzoni, Jonathan Cameron, Icenowy Zheng
In-Reply-To: <CAGb2v67KmaECfFO+QBxKbtKscD0O=KNVHO1TS4FspYEdaLWUCA@mail.gmail.com>
On 05/01/2017 07:10, Chen-Yu Tsai wrote:
> On Tue, Jan 3, 2017 at 12:37 AM, Quentin Schulz
> <quentin.schulz@free-electrons.com> wrote:
>> The CHR_CTRL1 register is made of 7 read-write bits with one being used
>> to set the target voltage for battery charging.
>
> The description is incorrect.
>
> All 8 bits are read-write:
>
> - The highest bit enables the charger module
> - Bits [6:5] set the target voltage
> - Bits [4:3] set when the charge cycle ends, based on percentage
> of charge current
> - Bits [2:0] set the charge current
>
> Feel free to use the above in the commit message.
>
Thanks for the correction.
>>
>> This adds the CHRG_CTRL1 register to the list of writeable registers for
>> AXP20X and AXP22X PMICs.
>
> You might want to add up to CHRG_CTRL3 for the AXP22x and CHRG_CTRL2
> for the AXP20x. These control additional aspects of the charger.
>
ACK.
> AXP20X_CHRG_BAK_CTRL controls the charger for the RTC battery. You
> could add this now, or let the person doing the RTC battery driver
> add it.
I'll let the person adding the RTC battery driver add it.
Thanks,
Quentin
--
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH v2,8/9] irqchip/ls-scfg-msi: add LS1043a v1.1 MSI support
From: Minghuan Lian @ 2017-01-05 8:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, devicetree
Cc: Rob Herring, Jason Cooper, Roy Zang, Marc Zyngier, Stuart Yoder,
Yang-Leo Li, Minghuan Lian, Scott Wood, Mingkai Hu
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>
A MSI controller of LS1043a v1.0 only includes one MSIR and
is assigned one GIC interrupt. In order to support affinity,
LS1043a v1.1 MSI is assigned 4 MSIRs and 4 GIC interrupts.
But the MSIR has the different offset and only supports 8 MSIs.
The bits between variable bit_start and bit_end in structure
ls_scfg_msir are used to show 8 MSI interrupts. msir_irqs and
msir_base are added to describe the difference of MSI between
LS1043a v1.1 and other SoCs.
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
Acked-by: Rob Herring <robh@kernel.org>
---
v2-v1:
- None
.../interrupt-controller/fsl,ls-scfg-msi.txt | 1 +
drivers/irqchip/irq-ls-scfg-msi.c | 45 +++++++++++++++++++---
2 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index dde4552..49ccabb 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -7,6 +7,7 @@ Required properties:
"fsl,ls1021a-msi"
"fsl,ls1043a-msi"
"fsl,ls1046a-msi"
+ "fsl,ls1043a-v1.1-msi"
- msi-controller: indicates that this is a PCIe MSI controller node
- reg: physical base address of the controller and length of memory mapped.
- interrupts: an interrupt to the parent interrupt controller.
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 67547bd..dc19569 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -25,14 +25,21 @@
#define MSI_IRQS_PER_MSIR 32
#define MSI_MSIR_OFFSET 4
+#define MSI_LS1043V1_1_IRQS_PER_MSIR 8
+#define MSI_LS1043V1_1_MSIR_OFFSET 0x10
+
struct ls_scfg_msi_cfg {
u32 ibs_shift; /* Shift of interrupt bit select */
+ u32 msir_irqs; /* The irq number per MSIR */
+ u32 msir_base; /* The base address of MSIR */
};
struct ls_scfg_msir {
struct ls_scfg_msi *msi_data;
unsigned int index;
unsigned int gic_irq;
+ unsigned int bit_start;
+ unsigned int bit_end;
void __iomem *reg;
};
@@ -140,13 +147,18 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
struct ls_scfg_msi *msi_data = msir->msi_data;
unsigned long val;
- int pos, virq, hwirq;
+ int pos, size, virq, hwirq;
chained_irq_enter(irq_desc_get_chip(desc), desc);
val = ioread32be(msir->reg);
- for_each_set_bit(pos, &val, MSI_IRQS_PER_MSIR) {
- hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
+
+ pos = msir->bit_start;
+ size = msir->bit_end + 1;
+
+ for_each_set_bit_from(pos, &val, size) {
+ hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
+ msir->index;
virq = irq_find_mapping(msi_data->parent, hwirq);
if (virq)
generic_handle_irq(virq);
@@ -193,14 +205,24 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
msir->index = index;
msir->msi_data = msi_data;
msir->gic_irq = virq;
- msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index;
+ msir->reg = msi_data->regs + msi_data->cfg->msir_base + 4 * index;
+
+ if (msi_data->cfg->msir_irqs == MSI_LS1043V1_1_IRQS_PER_MSIR) {
+ msir->bit_start = 32 - ((msir->index + 1) *
+ MSI_LS1043V1_1_IRQS_PER_MSIR);
+ msir->bit_end = msir->bit_start +
+ MSI_LS1043V1_1_IRQS_PER_MSIR - 1;
+ } else {
+ msir->bit_start = 0;
+ msir->bit_end = msi_data->cfg->msir_irqs - 1;
+ }
irq_set_chained_handler_and_data(msir->gic_irq,
ls_scfg_msi_irq_handler,
msir);
/* Release the hwirqs corresponding to this MSIR */
- for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+ for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
hwirq = i << msi_data->cfg->ibs_shift | msir->index;
bitmap_clear(msi_data->used, hwirq, 1);
}
@@ -216,7 +238,7 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
if (msir->gic_irq > 0)
irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL);
- for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+ for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
hwirq = i << msi_data->cfg->ibs_shift | msir->index;
bitmap_set(msi_data->used, hwirq, 1);
}
@@ -226,15 +248,26 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
static struct ls_scfg_msi_cfg ls1021_msi_cfg = {
.ibs_shift = 3,
+ .msir_irqs = MSI_IRQS_PER_MSIR,
+ .msir_base = MSI_MSIR_OFFSET,
};
static struct ls_scfg_msi_cfg ls1046_msi_cfg = {
.ibs_shift = 2,
+ .msir_irqs = MSI_IRQS_PER_MSIR,
+ .msir_base = MSI_MSIR_OFFSET,
+};
+
+static struct ls_scfg_msi_cfg ls1043_v1_1_msi_cfg = {
+ .ibs_shift = 2,
+ .msir_irqs = MSI_LS1043V1_1_IRQS_PER_MSIR,
+ .msir_base = MSI_LS1043V1_1_MSIR_OFFSET,
};
static const struct of_device_id ls_scfg_msi_id[] = {
{ .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg },
{ .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg },
+ { .compatible = "fsl,ls1043a-v1.1-msi", .data = &ls1043_v1_1_msi_cfg },
{ .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg },
{},
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2,9/9] irqchip/ls-scfg-msi: add MSI affinity support
From: Minghuan Lian @ 2017-01-05 8:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, devicetree
Cc: Rob Herring, Jason Cooper, Roy Zang, Marc Zyngier, Stuart Yoder,
Yang-Leo Li, Minghuan Lian, Scott Wood, Mingkai Hu
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>
For LS1046a and LS1043a v1.1, the MSI controller has 4 MSIRs and 4
CPUs. A GIC SPI interrupt of MSIR can be associated with a CPU.
When changing MSI interrupt affinity, this MSI will be moved to the
corresponding MSIR and MSI message data will be changed according to
MSIR. when requesting a MSI, the bits of all 4 MSIR will be reserved.
The parameter 'msi_affinity_flag' is provide to change this mode.
"lsmsi=no-affinity" will disable affinity, all MSI can only be
associated with CPU 0.
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v2-v1:
- None
drivers/irqchip/irq-ls-scfg-msi.c | 75 ++++++++++++++++++++++++++++++++++++---
1 file changed, 70 insertions(+), 5 deletions(-)
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index dc19569..753fe39 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -40,6 +40,7 @@ struct ls_scfg_msir {
unsigned int gic_irq;
unsigned int bit_start;
unsigned int bit_end;
+ unsigned int srs; /* Shared interrupt register select */
void __iomem *reg;
};
@@ -70,6 +71,19 @@ struct ls_scfg_msi {
.chip = &ls_scfg_msi_irq_chip,
};
+static int msi_affinity_flag = 1;
+
+static int __init early_parse_ls_scfg_msi(char *p)
+{
+ if (p && strncmp(p, "no-affinity", 11) == 0)
+ msi_affinity_flag = 0;
+ else
+ msi_affinity_flag = 1;
+
+ return 0;
+}
+early_param("lsmsi", early_parse_ls_scfg_msi);
+
static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
{
struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(data);
@@ -77,12 +91,43 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
msg->address_hi = upper_32_bits(msi_data->msiir_addr);
msg->address_lo = lower_32_bits(msi_data->msiir_addr);
msg->data = data->hwirq;
+
+ if (msi_affinity_flag) {
+ u32 msir_index;
+
+ msir_index = cpumask_first(data->common->affinity);
+ if (msir_index >= msi_data->msir_num)
+ msir_index = 0;
+
+ msg->data |= msir_index;
+ }
}
static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
const struct cpumask *mask, bool force)
{
- return -EINVAL;
+ struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(irq_data);
+ u32 cpu;
+
+ if (!msi_affinity_flag)
+ return -EINVAL;
+
+ if (!force)
+ cpu = cpumask_any_and(mask, cpu_online_mask);
+ else
+ cpu = cpumask_first(mask);
+
+ if (cpu >= msi_data->msir_num)
+ return -EINVAL;
+
+ if (msi_data->msir[cpu].gic_irq <= 0) {
+ pr_warn("cannot bind the irq to cpu%d\n", cpu);
+ return -EINVAL;
+ }
+
+ cpumask_copy(irq_data->common->affinity, mask);
+
+ return IRQ_SET_MASK_OK;
}
static struct irq_chip ls_scfg_msi_parent_chip = {
@@ -158,7 +203,7 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
for_each_set_bit_from(pos, &val, size) {
hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
- msir->index;
+ msir->srs;
virq = irq_find_mapping(msi_data->parent, hwirq);
if (virq)
generic_handle_irq(virq);
@@ -221,10 +266,19 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
ls_scfg_msi_irq_handler,
msir);
+ if (msi_affinity_flag) {
+ /* Associate MSIR interrupt to the cpu */
+ irq_set_affinity(msir->gic_irq, get_cpu_mask(index));
+ msir->srs = 0; /* This value is determined by the CPU */
+ } else
+ msir->srs = index;
+
/* Release the hwirqs corresponding to this MSIR */
- for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
- hwirq = i << msi_data->cfg->ibs_shift | msir->index;
- bitmap_clear(msi_data->used, hwirq, 1);
+ if (!msi_affinity_flag || msir->index == 0) {
+ for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
+ hwirq = i << msi_data->cfg->ibs_shift | msir->index;
+ bitmap_clear(msi_data->used, hwirq, 1);
+ }
}
return 0;
@@ -316,6 +370,17 @@ static int ls_scfg_msi_probe(struct platform_device *pdev)
bitmap_set(msi_data->used, 0, msi_data->irqs_num);
msi_data->msir_num = of_irq_count(pdev->dev.of_node);
+
+ if (msi_affinity_flag) {
+ u32 cpu_num;
+
+ cpu_num = num_possible_cpus();
+ if (msi_data->msir_num >= cpu_num)
+ msi_data->msir_num = cpu_num;
+ else
+ msi_affinity_flag = 0;
+ }
+
msi_data->msir = devm_kcalloc(&pdev->dev, msi_data->msir_num,
sizeof(*msi_data->msir),
GFP_KERNEL);
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 05/22] ARM: dtsi: axp209: add AXP209 ADC subnode
From: Chen-Yu Tsai @ 2017-01-05 8:16 UTC (permalink / raw)
To: Quentin Schulz
Cc: Mark Rutland, devicetree, Lars-Peter Clausen, open list:THERMAL,
linux-iio, linux-kernel, Sebastian Reichel, Russell King,
Chen-Yu Tsai, Rob Herring, linux-arm-kernel,
Peter Meerwald-Stadler, knaack.h, Maxime Ripard,
Bruno Prémont, Lee Jones, Thomas Petazzoni, Jonathan Cameron,
Icenowy Zheng
In-Reply-To: <1ddf7012-3336-84c2-6392-353b01beea93@free-electrons.com>
On Thu, Jan 5, 2017 at 4:08 PM, Quentin Schulz
<quentin.schulz@free-electrons.com> wrote:
> On 05/01/2017 06:51, Chen-Yu Tsai wrote:
>> On Tue, Jan 3, 2017 at 12:37 AM, Quentin Schulz
>> <quentin.schulz@free-electrons.com> wrote:
>>> X-Powers AXP209 PMIC has multiple ADCs, each one exposing data from the
>>> different power supplies connected to the PMIC.
>>>
>>> This adds the ADC subnode for AXP20X PMIC.
>>>
>>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>>> ---
>>> arch/arm/boot/dts/axp209.dtsi | 5 +++++
>>> 1 file changed, 5 insertions(+)
>>>
>>> diff --git a/arch/arm/boot/dts/axp209.dtsi b/arch/arm/boot/dts/axp209.dtsi
>>> index 675bb0f..2a4e8ee 100644
>>> --- a/arch/arm/boot/dts/axp209.dtsi
>>> +++ b/arch/arm/boot/dts/axp209.dtsi
>>> @@ -53,6 +53,11 @@
>>> interrupt-controller;
>>> #interrupt-cells = <1>;
>>>
>>> + axp209_adc: axp209_adc {
>>
>> Node name should be generic. Please change it to "adc".
>>
>
> OK, do I keep the label as is?
>
> axp209_adc: adc {
Yup. The label is for dereferencing and stuff, and exists in a global scope.
You wouldn't want 2 label names clashing.
ChenYu
>
> Thanks,
> Quentin
>
> --
> Quentin Schulz, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
^ permalink raw reply
* Re: [PATCH v2 2/4] serial: 8250: Add new port type for TI DA8xx/OMAPL13x/AM17xx/AM18xx/C66x
From: Sekhar Nori @ 2017-01-05 8:21 UTC (permalink / raw)
To: David Lechner, Greg Kroah-Hartman, Santosh Shilimkar
Cc: Mark Rutland, devicetree, Axel Haslam, Kevin Hilman, linux-kernel,
Bartosz Golaszewski, Rob Herring, Alexandre Bailon, linux-serial,
Jiri Slaby, Franklin S Cooper Jr, linux-arm-kernel
In-Reply-To: <1483561814-21953-3-git-send-email-david@lechnology.com>
On Thursday 05 January 2017 02:00 AM, David Lechner wrote:
> This adds a new UART port type for TI DA8xx/OMAPL13x/AM17xx/AM18xx/C66x.
The Keystone2 processors do include the C66x DSP. But the SoCs being
targeted with this patch are the ARM + DSP variants. Using 66AK2x is
more appropriate.
http://www.ti.com/lsds/ti/processors/dsp/c6000_dsp-arm/66ak2x/overview.page
Also, DA8xx includes DA830 which is pin-compatible with AM17x. So you
can shorten the list of supported processors to DA8xx/66AK2x.
> These SoCs have standard 8250 registers plus some extra non-standard
> registers.
>
> The UART will not function unless the non-standard Power and Emulation
> Management Register (PWREMU_MGMT) is configured correctly. This is
> currently handled in arch/arm/mach-davinci/serial.c for non-device-tree
> boards. Making this part of the UART driver will allow UART to work on
> device-tree boards as well and the mach code can eventually be removed.
>
> Signed-off-by: David Lechner <david@lechnology.com>
Looks good to me, apart from the minor change above.
Acked-by: Sekhar Nori <nsekhar@ti.com>
Thanks,
Sekhar
^ permalink raw reply
* [RFC 0/1] Platform driver support for 'amd5536udc' driver
From: Raviteja Garimella @ 2017-01-05 8:23 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Greg Kroah-Hartman, Felipe Balbi
Cc: devicetree, linux-kernel, bcm-kernel-feedback-list, linux-usb
This patch adds platform device support to the existing 'amd5536udc'
driver.
The UDC is based on Synopsys Designware core USB (2.0) Device controller
IP.
The driver so far supports UDCs that are a part of AMD southbridge
and is connected through PCI bus.
The same driver can be used with UDCs that are integrated into SoCs
like Broadcom's Northstar2/Cygnus platforms by adding platform device
suooprt.
This patch contains all the changes that were required to get the driver
functional on Broadcom's Northstar2 platform.
This is a request for comments from maintainers/others regarding approach
on whether to have 2 different drivers (one each for AMD and Broadcom)
with a common library (3 files in total), or have a single driver like
it's done in this patch and have the driver filename changed to some
common name based on ther underlying IP, like snps_udc.c.
Below are the main changes done:
1. Added OF based platform device registration -- so that the driver gets
probed based on the device tree entry. Like wise, remove routine and
platform PM ops are supported.
2. Modified debug prints to be compatible with both pci and platform
devices.
3. Added members to 'struct udc' in header file for extcon and phy support.
This is required if the UDC is connected to a Dual Role Device Phy
where the Phy can be configured to be in Device mode or Host mode based
on the type of external cable that is connected to the port.
4. Added checks in udc connect/disconnect routines so as to return if the
routine is already called.
5. Modified the arguments passed to dma_pool_create routine -- which
expects struct device, whereas NULL is passed in the existing version.
6. Kconfig changes are done so that the driver now depends on either of
CONFIG_OF or CONFIG_PCI. More description about the Synopsys IP is
provided.
Raviteja Garimella (1):
Changes to support the driver for platform device registration
drivers/usb/gadget/udc/Kconfig | 6 +-
drivers/usb/gadget/udc/amd5536udc.c | 397 +++++++++++++++++++++++++++++++++---
drivers/usb/gadget/udc/amd5536udc.h | 17 +-
3 files changed, 387 insertions(+), 33 deletions(-)
--
2.1.0
^ permalink raw reply
* [RFC 1/1] Changes to support the driver for platform device registration
From: Raviteja Garimella @ 2017-01-05 8:23 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Greg Kroah-Hartman, Felipe Balbi
Cc: devicetree, linux-kernel, bcm-kernel-feedback-list, linux-usb
In-Reply-To: <1483604597-26160-1-git-send-email-raviteja.garimella@broadcom.com>
-- Add OF based platform device registration
-- Modify debug prints to be compatible with both pci and platform devices
-- Add members to 'struct udc' for extcon and phy support
-- Add checks to not process repeated calls to udc connect and
disconnect routines
-- Kconfig changes
Signed-off-by: Raviteja Garimella <raviteja.garimella@broadcom.com>
---
drivers/usb/gadget/udc/Kconfig | 6 +-
drivers/usb/gadget/udc/amd5536udc.c | 397 +++++++++++++++++++++++++++++++++---
drivers/usb/gadget/udc/amd5536udc.h | 17 +-
3 files changed, 387 insertions(+), 33 deletions(-)
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index 658b8da..7728fec 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -263,7 +263,7 @@ source "drivers/usb/gadget/udc/bdc/Kconfig"
config USB_AMD5536UDC
tristate "AMD5536 UDC"
- depends on PCI
+ depends on PCI || OF
help
The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
It is a USB Highspeed DMA capable USB device controller. Beside ep0
@@ -271,6 +271,10 @@ config USB_AMD5536UDC
The UDC port supports OTG operation, and may be used as a host port
if it's not being used to implement peripheral or OTG roles.
+ This UDC is based on Synopsis Designware core USB Device controller
+ IP. The driver also supports UDCs integrated to ARM based SoC's like
+ Broadcom's Northstar2 and Cygnus platforms.
+
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "amd5536udc" and force all
gadget drivers to also be dynamically linked.
diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c
index ea03ca7..b086cf1 100644
--- a/drivers/usb/gadget/udc/amd5536udc.c
+++ b/drivers/usb/gadget/udc/amd5536udc.c
@@ -22,16 +22,25 @@
* UDC DMA requires 32-bit aligned buffers so DMA with gadget ether does not
* work without updating NET_IP_ALIGN. Or PIO mode (module param "use_dma=0")
* can be used with gadget ether.
+ *
+ * This driver is compatible for Broadcom's UDC for Northstar2 and Cygnus
+ * SOCs. The UDC is based on Synopsys designware core USB device controller IP.
*/
/* debug control */
/* #define UDC_VERBOSE */
/* Driver strings */
-#define UDC_MOD_DESCRIPTION "AMD 5536 UDC - USB Device Controller"
+#define UDC_MOD_DESCRIPTION "AMD 5536 UDC - Synopsys USB Device Controller"
#define UDC_DRIVER_VERSION_STRING "01.00.0206"
/* system */
+#include <linux/extcon.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
@@ -251,18 +260,18 @@ static void print_regs(struct udc *dev)
if (use_dma && use_dma_ppb && !use_dma_ppb_du) {
DBG(dev, "DMA mode = PPBNDU (packet per buffer "
"WITHOUT desc. update)\n");
- dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU");
+ dev_info(dev->dev, "DMA mode (%s)\n", "PPBNDU");
} else if (use_dma && use_dma_ppb && use_dma_ppb_du) {
DBG(dev, "DMA mode = PPBDU (packet per buffer "
"WITH desc. update)\n");
- dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU");
+ dev_info(dev->dev, "DMA mode (%s)\n", "PPBDU");
}
if (use_dma && use_dma_bufferfill_mode) {
DBG(dev, "DMA mode = BF (buffer fill mode)\n");
- dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF");
+ dev_info(dev->dev, "DMA mode (%s)\n", "BF");
}
if (!use_dma)
- dev_info(&dev->pdev->dev, "FIFO mode\n");
+ dev_info(dev->dev, "FIFO mode\n");
DBG(dev, "-------------------------------------------------------\n");
}
@@ -1666,8 +1675,11 @@ static void udc_setup_endpoints(struct udc *dev)
/* Bringup after Connect event, initial bringup to be ready for ep0 events */
static void usb_connect(struct udc *dev)
{
+ /* Return if already connected */
+ if (dev->connected)
+ return;
- dev_info(&dev->pdev->dev, "USB Connect\n");
+ dev_info(dev->dev, "USB Connect\n");
dev->connected = 1;
@@ -1684,8 +1696,11 @@ static void usb_connect(struct udc *dev)
*/
static void usb_disconnect(struct udc *dev)
{
+ /* Return if already disconnected */
+ if (!dev->connected)
+ return;
- dev_info(&dev->pdev->dev, "USB Disconnect\n");
+ dev_info(dev->dev, "USB Disconnect\n");
dev->connected = 0;
@@ -1758,11 +1773,15 @@ static void udc_soft_reset(struct udc *dev)
/* device int. status reset */
writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts);
- spin_lock_irqsave(&udc_irq_spinlock, flags);
- writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
- readl(&dev->regs->cfg);
- spin_unlock_irqrestore(&udc_irq_spinlock, flags);
-
+ /* Don't do this for Broadcom UDC since this is a reserved
+ * bit.
+ */
+ if (dev->chiprev != UDC_BCM_REV) {
+ spin_lock_irqsave(&udc_irq_spinlock, flags);
+ writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
+ readl(&dev->regs->cfg);
+ spin_unlock_irqrestore(&udc_irq_spinlock, flags);
+ }
}
/* RDE timer callback to set RDE bit */
@@ -2149,7 +2168,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
}
/* HE event ? */
if (tmp & AMD_BIT(UDC_EPSTS_HE)) {
- dev_err(&dev->pdev->dev, "HE ep%dout occurred\n", ep->num);
+ dev_err(dev->dev, "HE ep%dout occurred\n", ep->num);
/* clear HE */
writel(tmp | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts);
@@ -2348,7 +2367,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
if (use_dma) {
/* BNA ? */
if (epsts & AMD_BIT(UDC_EPSTS_BNA)) {
- dev_err(&dev->pdev->dev,
+ dev_err(dev->dev,
"BNA ep%din occurred - DESPTR = %08lx\n",
ep->num,
(unsigned long) readl(&ep->regs->desptr));
@@ -2361,7 +2380,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
}
/* HE event ? */
if (epsts & AMD_BIT(UDC_EPSTS_HE)) {
- dev_err(&dev->pdev->dev,
+ dev_err(dev->dev,
"HE ep%dn occurred - DESPTR = %08lx\n",
ep->num, (unsigned long) readl(&ep->regs->desptr));
@@ -2999,7 +3018,7 @@ __acquires(dev->lock)
/* link up all endpoints */
udc_setup_endpoints(dev);
- dev_info(&dev->pdev->dev, "Connect: %s\n",
+ dev_info(dev->dev, "Connect: %s\n",
usb_speed_string(dev->gadget.speed));
/* init ep 0 */
@@ -3162,7 +3181,7 @@ static int init_dma_pools(struct udc *dev)
}
/* DMA setup */
- dev->data_requests = dma_pool_create("data_requests", NULL,
+ dev->data_requests = dma_pool_create("data_requests", dev->dev,
sizeof(struct udc_data_dma), 0, 0);
if (!dev->data_requests) {
DBG(dev, "can't get request data pool\n");
@@ -3173,7 +3192,7 @@ static int init_dma_pools(struct udc *dev)
dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl;
/* dma desc for setup data */
- dev->stp_requests = dma_pool_create("setup requests", NULL,
+ dev->stp_requests = dma_pool_create("setup requests", dev->dev,
sizeof(struct udc_stp_dma), 0, 0);
if (!dev->stp_requests) {
DBG(dev, "can't get stp request pool\n");
@@ -3232,24 +3251,29 @@ static int udc_probe(struct udc *dev)
/* init registers, interrupts, ... */
startup_registers(dev);
- dev_info(&dev->pdev->dev, "%s\n", mod_desc);
+ dev_info(dev->dev, "%s\n", mod_desc);
snprintf(tmp, sizeof(tmp), "%d", dev->irq);
- dev_info(&dev->pdev->dev,
- "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
- tmp, dev->phys_addr, dev->chiprev,
- (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
- strcpy(tmp, UDC_DRIVER_VERSION_STRING);
- if (dev->chiprev == UDC_HSA0_REV) {
- dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
- retval = -ENODEV;
- goto finished;
+
+ /* Print this device info for AMD chips only */
+ if (dev->chiprev == UDC_HSA0_REV ||
+ dev->chiprev == UDC_HSB1_REV) {
+ dev_info(dev->dev, "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
+ tmp, dev->phys_addr, dev->chiprev,
+ (dev->chiprev == UDC_HSA0_REV) ?
+ "A0" : "B1");
+ strcpy(tmp, UDC_DRIVER_VERSION_STRING);
+ if (dev->chiprev == UDC_HSA0_REV) {
+ dev_err(dev->dev, "chip revision is A0; too old\n");
+ retval = -ENODEV;
+ goto finished;
+ }
+ dev_info(dev->dev,
+ "driver version: %s(for Geode5536 B1)\n", tmp);
}
- dev_info(&dev->pdev->dev,
- "driver version: %s(for Geode5536 B1)\n", tmp);
udc = dev;
- retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+ retval = usb_add_gadget_udc_release(udc->dev, &dev->gadget,
gadget_release);
if (retval)
goto finished;
@@ -3363,6 +3387,7 @@ static int udc_pci_probe(
dev->phys_addr = resource;
dev->irq = pdev->irq;
dev->pdev = pdev;
+ dev->dev = &pdev->dev;
/* general probing */
if (udc_probe(dev)) {
@@ -3408,6 +3433,316 @@ static struct pci_driver udc_pci_driver = {
module_pci_driver(udc_pci_driver);
+void start_udc(struct udc *udc)
+{
+ if (udc->driver) {
+ dev_info(udc->dev, "Connecting...\n");
+ udc_enable_dev_setup_interrupts(udc);
+ udc_basic_init(udc);
+ udc->connected = 1;
+ }
+}
+
+void stop_udc(struct udc *udc)
+{
+ int num;
+ u32 reg;
+
+ spin_lock(&udc->lock);
+
+ /* Flush the receieve fifo */
+ reg = readl(&udc->regs->ctl);
+ reg |= AMD_BIT(UDC_DEVCTL_SRX_FLUSH);
+ writel(reg, &udc->regs->ctl);
+
+ reg = readl(&udc->regs->ctl);
+ reg &= ~(AMD_BIT(UDC_DEVCTL_SRX_FLUSH));
+ writel(reg, &udc->regs->ctl);
+ dev_dbg(udc->dev, "ep rx queue flushed\n");
+
+ /* Mask interrupts. Required more so when the
+ * UDC is connected to a DRD phy.
+ */
+ udc_mask_unused_interrupts(udc);
+
+ /* Disconnect gadget driver */
+ if (udc->driver) {
+ spin_unlock(&udc->lock);
+ udc->driver->disconnect(&udc->gadget);
+ spin_lock(&udc->lock);
+
+ /* empty queues */
+ for (num = 0; num < UDC_EP_NUM; num++)
+ empty_req_queue(&udc->ep[num]);
+ }
+ udc->connected = 0;
+
+ spin_unlock(&udc->lock);
+ dev_info(udc->dev, "Device disconnected\n");
+}
+
+void udc_drd_work(struct work_struct *work)
+{
+ struct udc *udc;
+
+ udc = container_of(to_delayed_work(work),
+ struct udc, drd_work);
+
+ if (udc->conn_type) {
+ dev_dbg(udc->dev, "idle -> device\n");
+ start_udc(udc);
+ } else {
+ dev_dbg(udc->dev, "device -> idle\n");
+ stop_udc(udc);
+ }
+}
+
+static int usbd_connect_notify(struct notifier_block *self,
+ unsigned long event, void *ptr)
+{
+ struct udc *udc = container_of(self, struct udc, nb);
+
+ dev_dbg(udc->dev, "%s: event: %lu\n", __func__, event);
+
+ udc->conn_type = event;
+
+ schedule_delayed_work(&udc->drd_work, 0);
+
+ return NOTIFY_OK;
+}
+
+static int udc_plat_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct udc *udc;
+ int ret;
+
+ udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL);
+ if (!udc)
+ return -ENOMEM;
+
+ spin_lock_init(&udc->lock);
+ udc->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ udc->virt_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(udc->regs))
+ return PTR_ERR(udc->regs);
+
+ /* udc csr registers base */
+ udc->csr = udc->virt_addr + UDC_CSR_ADDR;
+
+ /* dev registers base */
+ udc->regs = udc->virt_addr + UDC_DEVCFG_ADDR;
+
+ /* ep registers base */
+ udc->ep_regs = udc->virt_addr + UDC_EPREGS_ADDR;
+
+ /* fifo's base */
+ udc->rxfifo = (u32 __iomem *)(udc->virt_addr + UDC_RXFIFO_ADDR);
+ udc->txfifo = (u32 __iomem *)(udc->virt_addr + UDC_TXFIFO_ADDR);
+
+ udc->phys_addr = (unsigned long)res->start;
+
+ udc->irq = irq_of_parse_and_map(dev->of_node, 0);
+ if (udc->irq <= 0) {
+ dev_err(dev, "Can't parse and map interrupt\n");
+ return -EINVAL;
+ }
+
+ udc->udc_phy = devm_of_phy_get_by_index(dev, dev->of_node, 0);
+ if (IS_ERR(udc->udc_phy)) {
+ dev_err(dev, "Failed to obtain phy from device tree\n");
+ return PTR_ERR(udc->udc_phy);
+ }
+
+ ret = phy_init(udc->udc_phy);
+ if (ret) {
+ dev_err(dev, "UDC phy init failed");
+ return ret;
+ }
+
+ ret = phy_power_on(udc->udc_phy);
+ if (ret) {
+ dev_err(dev, "UDC phy power on failed");
+ phy_exit(udc->udc_phy);
+ return ret;
+ }
+
+ /* Register for extcon if supported */
+ if (of_get_property(dev->of_node, "extcon", NULL)) {
+ udc->edev = extcon_get_edev_by_phandle(dev, 0);
+ if (IS_ERR(udc->edev)) {
+ if (PTR_ERR(udc->edev) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_err(dev, "Invalid or missing extcon\n");
+ ret = PTR_ERR(udc->edev);
+ goto exit_phy;
+ }
+
+ udc->nb.notifier_call = usbd_connect_notify;
+ ret = extcon_register_notifier(udc->edev, EXTCON_USB,
+ &udc->nb);
+ if (ret < 0) {
+ dev_err(dev, "Can't register extcon device\n");
+ goto exit_phy;
+ }
+
+ ret = extcon_get_cable_state_(udc->edev, EXTCON_USB);
+ if (ret < 0) {
+ dev_err(dev, "Can't get cable state\n");
+ goto exit_extcon;
+ } else if (ret) {
+ udc->conn_type = ret;
+ }
+ INIT_DELAYED_WORK(&udc->drd_work, udc_drd_work);
+ }
+
+ /* init dma pools */
+ if (use_dma) {
+ ret = init_dma_pools(udc);
+ if (ret != 0)
+ goto exit_extcon;
+ }
+
+ ret = devm_request_irq(dev, udc->irq, udc_irq, IRQF_SHARED,
+ "snps-udc", udc);
+ if (ret < 0) {
+ dev_err(dev, "Request irq %d failed for UDC\n", udc->irq);
+ goto exit_dma;
+ }
+
+ platform_set_drvdata(pdev, udc);
+ udc->chiprev = UDC_BCM_REV;
+
+ if (udc_probe(udc)) {
+ ret = -ENODEV;
+ goto exit_dma;
+ }
+ dev_info(dev, "Synopsys UDC platform driver probe successful\n");
+
+ return 0;
+
+exit_dma:
+ if (use_dma)
+ free_dma_pools(udc);
+exit_extcon:
+ if (udc->edev)
+ extcon_unregister_notifier(udc->edev, EXTCON_USB, &udc->nb);
+exit_phy:
+ if (udc->udc_phy) {
+ phy_power_off(udc->udc_phy);
+ phy_exit(udc->udc_phy);
+ }
+ return ret;
+}
+
+static int udc_plat_remove(struct platform_device *pdev)
+{
+ struct udc *dev;
+
+ dev = platform_get_drvdata(pdev);
+
+ usb_del_gadget_udc(&udc->gadget);
+ /* gadget driver must not be registered */
+ if (WARN_ON(dev->driver))
+ return 0;
+
+ /* dma pool cleanup */
+ free_dma_pools(dev);
+
+ udc_remove(dev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (udc->drd_wq) {
+ flush_workqueue(udc->drd_wq);
+ destroy_workqueue(udc->drd_wq);
+ }
+
+ /* free_udc_dma(pdev, udc); */
+ phy_power_off(udc->udc_phy);
+ phy_exit(udc->udc_phy);
+ extcon_unregister_notifier(udc->edev, EXTCON_USB, &udc->nb);
+
+ dev_info(&pdev->dev, "Synopsys UDC driver removed\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int udc_plat_suspend(struct device *dev)
+{
+ struct udc *udc;
+
+ udc = dev_get_drvdata(dev);
+ usb_disconnect(udc);
+
+ if (extcon_get_cable_state_(udc->edev, EXTCON_USB) > 0) {
+ dev_dbg(udc->dev, "device -> idle\n");
+ stop_udc(udc);
+ }
+ phy_power_off(udc->udc_phy);
+ phy_exit(udc->udc_phy);
+
+ return 0;
+}
+
+static int udc_plat_resume(struct device *dev)
+{
+ struct udc *udc;
+ int ret;
+
+ udc = dev_get_drvdata(dev);
+
+ ret = phy_init(udc->udc_phy);
+ if (ret) {
+ dev_err(udc->dev, "UDC phy init failure");
+ return ret;
+ }
+
+ ret = phy_power_on(udc->udc_phy);
+ if (ret) {
+ dev_err(udc->dev, "UDC phy power on failure");
+ phy_exit(udc->udc_phy);
+ return ret;
+ }
+
+ if (extcon_get_cable_state_(udc->edev, EXTCON_USB) > 0) {
+ dev_dbg(udc->dev, "idle -> device\n");
+ start_udc(udc);
+ }
+
+ return 0;
+}
+static const struct dev_pm_ops udc_plat_pm_ops = {
+ .suspend = udc_plat_suspend,
+ .resume = udc_plat_resume,
+};
+#endif
+
+#if defined(CONFIG_OF)
+static const struct of_device_id of_udc_match[] = {
+ { .compatible = "snps,bcm-ahb-udc", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, of_udc_match);
+#endif
+
+static struct platform_driver udc_plat_driver = {
+ .probe = udc_plat_probe,
+ .remove = udc_plat_remove,
+ .driver = {
+ .name = "snps-udc",
+ .of_match_table = of_match_ptr(of_udc_match),
+#ifdef CONFIG_PM_SLEEP
+ .pm = &udc_plat_pm_ops,
+#endif
+ },
+};
+module_platform_driver(udc_plat_driver);
+
MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
MODULE_AUTHOR("Thomas Dahlmann");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/amd5536udc.h b/drivers/usb/gadget/udc/amd5536udc.h
index 4638d70..88e1b75 100644
--- a/drivers/usb/gadget/udc/amd5536udc.h
+++ b/drivers/usb/gadget/udc/amd5536udc.h
@@ -22,6 +22,9 @@
#define UDC_HSA0_REV 1
#define UDC_HSB1_REV 2
+/* Broadcom chip rev. */
+#define UDC_BCM_REV 10
+
/*
* SETUP usb commands
* needed, because some SETUP's are handled in hw, but must be passed to
@@ -106,6 +109,7 @@
#define UDC_DEVCTL_BRLEN_MASK 0x00ff0000
#define UDC_DEVCTL_BRLEN_OFS 16
+#define UDC_DEVCTL_SRX_FLUSH 14
#define UDC_DEVCTL_CSR_DONE 13
#define UDC_DEVCTL_DEVNAK 12
#define UDC_DEVCTL_SD 10
@@ -518,6 +522,7 @@ struct udc_ep {
in : 1;
};
+#define USBD_WQ_DELAY_MS msecs_to_jiffies(100)
/* device struct */
struct udc {
struct usb_gadget gadget;
@@ -557,6 +562,16 @@ struct udc {
u16 cur_config;
u16 cur_intf;
u16 cur_alt;
+
+ /* for platform device and extcon support */
+ struct device *dev;
+ struct phy *udc_phy;
+ struct extcon_dev *edev;
+ struct extcon_specific_cable_nb extcon_nb;
+ struct notifier_block nb;
+ struct delayed_work drd_work;
+ struct workqueue_struct *drd_wq;
+ u32 conn_type;
};
#define to_amd5536_udc(g) (container_of((g), struct udc, gadget))
@@ -603,7 +618,7 @@ union udc_setup_data {
/* debug macros ------------------------------------------------------------*/
-#define DBG(udc , args...) dev_dbg(&(udc)->pdev->dev, args)
+#define DBG(udc , args...) dev_dbg(udc->dev, args)
#ifdef UDC_VERBOSE
#define VDBG DBG
--
2.1.0
^ permalink raw reply related
* Re: [PATCH v3 2/2] dt-bindings: Add DT bindings info for FlexRM ring manager
From: Anup Patel @ 2017-01-05 8:26 UTC (permalink / raw)
To: Rob Herring
Cc: Mark Rutland, Device Tree, Scott Branden, Ray Jui, Jassi Brar,
Linux Kernel, Pramod KUMAR, BCM Kernel Feedback, Rob Rice,
Linux ARM Kernel
In-Reply-To: <20170104143752.bl47gdfczbnfy6b3@rob-hp-laptop>
On Wed, Jan 4, 2017 at 8:07 PM, Rob Herring <robh@kernel.org> wrote:
> On Wed, Jan 04, 2017 at 11:04:42AM +0530, Anup Patel wrote:
>> This patch adds device tree bindings document for the FlexRM
>> ring manager found on Broadcom iProc SoCs.
>>
>> Reviewed-by: Ray Jui <ray.jui@broadcom.com>
>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
>> Signed-off-by: Anup Patel <anup.patel@broadcom.com>
>> ---
>> .../bindings/mailbox/brcm,iproc-flexrm-mbox.txt | 60 ++++++++++++++++++++++
>> 1 file changed, 60 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/mailbox/brcm,iproc-flexrm-mbox.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mailbox/brcm,iproc-flexrm-mbox.txt b/Documentation/devicetree/bindings/mailbox/brcm,iproc-flexrm-mbox.txt
>> new file mode 100644
>> index 0000000..ca51a39
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mailbox/brcm,iproc-flexrm-mbox.txt
>> @@ -0,0 +1,60 @@
>> +Broadcom FlexRM Ring Manager
>> +============================
>> +The Broadcom FlexRM ring manager provides a set of rings which can be
>> +used to submit work to offload engines. An SoC may have multiple FlexRM
>> +hardware blocks. There is one device tree entry per FlexRM block. The
>> +FlexRM driver will create a mailbox-controller instance for given FlexRM
>> +hardware block where each mailbox channel is a separate FlexRM ring.
>> +
>> +Required properties:
>> +--------------------
>> +- compatible: Should be "brcm,iproc-flexrm-mbox"
>> +- reg: Specifies base physical address and size of the FlexRM
>> + ring registers
>> +- msi-parent: Phandles (and potential Device IDs) to MSI controllers
>> + The FlexRM engine will send MSIs (instead of wired
>> + interrupts) to CPU. There is one MSI for each FlexRM ring.
>> + Refer devicetree/bindings/interrupt-controller/msi.txt
>> +- #mbox-cells: Specifies the number of cells needed to encode a mailbox
>> + channel. This should be 3.
>> +
>> + The 1st cell is the mailbox channel number.
>> +
>> + The 2nd cell contains MSI completion threshold. This is the
>> + number of completion messages for which FlexRM will inject
>> + one MSI interrupt to CPU.
>> +
>> + The 3nd cell contains MSI timer value representing time for
>> + which FlexRM will wait to accumulate N completion messages
>> + where N is the value specified by 2nd cell above. If FlexRM
>> + does not get required number of completion messages in time
>> + specified by this cell then it will inject one MSI interrupt
>> + to CPU provided atleast one completion message is available.
>> +
>> +Optional properties:
>> +--------------------
>> +- dma-coherent: Present if DMA operations made by the FlexRM engine (such
>> + as DMA descriptor access, access to buffers pointed by DMA
>> + descriptors and read/write pointer updates to DDR) are
>> + cache coherent with the CPU.
>> +
>> +Example:
>> +--------
>> +crypto_mbox: mbox@67000000 {
>> + compatible = "brcm,iproc-flexrm-mbox";
>> + reg = <0x67000000 0x200000>;
>> + msi-parent = <&gic_its 0x7f00>;
>> + #mbox-cells = <3>;
>> +};
>> +
>> +crypto_client {
>
> crypto@<addr>
>
>> + ...
>> + mboxes = <&crypto_mbox 0 0x1 0xffff>,
>> + <&crypto_mbox 1 0x1 0xffff>,
>> + <&crypto_mbox 16 0x1 0xffff>,
>> + <&crypto_mbox 17 0x1 0xffff>,
>> + <&crypto_mbox 30 0x1 0xffff>,
>> + <&crypto_mbox 31 0x1 0xffff>;
>> + };
>> + ...
>
> Please somewhat fully list the contents for node.
>
Sure, I will add more complete example DT node for
mailbox client.
Regards,
Anup
^ permalink raw reply
* [PATCH v2 0/4] Add touch key driver support for TM2
From: Jaechul Lee @ 2017-01-05 8:27 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Mark Rutland, Catalin Marinas,
Will Deacon, Kukjin Kim, Krzysztof Kozlowski,
Javier Martinez Canillas
Cc: Jaechul Lee, Andi Shyti, Chanwoo Choi,
beomho.seo-Sze3O3UU22JBDgjK7y7TUQ,
galaxyra-Re5JQEeQqe8AvxtiuMwx3w,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-input-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CGME20170105082715epcas1p10e0820a792ba9d89cd165299d6602654@epcas1p1.samsung.com>
Hi,
This patchset adds support for the tm2 touchkey device.
The driver has been ported from Tizen Kernel, originally written
by Beomho. I ported it to the latest mainline Kernel.
The patchset applies on next-20170105.
Changes in v2:
- fixed reviews from Javier, Dmitry
- refactored power enable/disable functions.
- reordered signed-offs in patch 2, while patch 4 is left as it
was as Andi copy pasted the node to the new tm2.dts file
- added Jarvier's (patch 1,2,4) and Krzysztof's (patch 4) reviews
and Rob's Ack
- patch 3 diff has been generated with -B50%
Best Regards,
Jaechul
Andi Shyti (1):
arm64: dts: exynos: make tm2 and tm2e independent from each other
Jaechul Lee (3):
input: Add support for the tm2 touchkey device driver
input: tm2-touchkey: Add touchkey driver support for TM2
arm64: dts: exynos: Add tm2 touchkey node
.../bindings/input/samsung,tm2-touchkey.txt | 27 +
.../boot/dts/exynos/exynos5433-tm2-common.dtsi | 1116 ++++++++++++++++++++
arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 1105 +------------------
arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts | 2 +-
drivers/input/keyboard/Kconfig | 11 +
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/tm2-touchkey.c | 280 +++++
7 files changed, 1445 insertions(+), 1097 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/samsung,tm2-touchkey.txt
create mode 100644 arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
create mode 100644 drivers/input/keyboard/tm2-touchkey.c
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox