* Re: [PATCH 2/3] drm/bridge: Add ti-ftp410 HDMI transmitter driver
From: Laurent Pinchart @ 2016-11-03 17:46 UTC (permalink / raw)
To: Jyri Sarha
Cc: devicetree, bcousson, khilman, dri-devel, bgolaszewski,
tomi.valkeinen
In-Reply-To: <9b6a6a4405de344cb9fbea735fea37adee1d726e.1478103726.git.jsarha@ti.com>
Hi Jyri,
Thank you for the patch.
On Wednesday 02 Nov 2016 18:32:16 Jyri Sarha wrote:
> Add very basic ti-ftp410 HDMI transmitter driver. The only feature
> separating this from a completely dummy bridge is the DDC i2c
> support. However, other HW specific features may be added later when
> needed. For instance there is a set of registers behind i2c if it is
> connected. The implementations is tested against my new tilcdc bridge
> support and works with BeagleBone DVI-D Cape Rev A3. A DT binding
> document is also added.
>
> Signed-off-by: Jyri Sarha <jsarha@ti.com>
> ---
> .../bindings/display/bridge/ti,tfp410.txt | 30 ++++
> drivers/gpu/drm/bridge/Kconfig | 7 +
> drivers/gpu/drm/bridge/Makefile | 1 +
> drivers/gpu/drm/bridge/ti-tfp410.c | 199 ++++++++++++++++++
> 4 files changed, 237 insertions(+)
> create mode 100644
> Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt create mode
> 100644 drivers/gpu/drm/bridge/ti-tfp410.c
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt
> b/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt new file
> mode 100644
> index 0000000..dc93713
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt
> @@ -0,0 +1,30 @@
> +TFP410 HDMI/DVI bridge bindings
I'd name the document "TI TFP410 DVI Transmitter". DVI bridge doesn't tell
whether the device is a receiver or transmitter.
> +Required properties:
> + - compatible: "ti,tfp410"
The device is an I2C slave, it should have a reg property. Given that the chip
can be used without being controlled through I2C, the reg property should be
optional. You should document this clearly, and explain how the DT node can be
instantiated as a child of an I2C controller when the I2C interface is used,
or in other parts of the device tree otherwise.
> +Optional properties:
> + - ddc-i2c: phandle of an I2C controller used for DDC EDID probing
The TFP410 doesn't handle DDC, this property should be part of the connector
node.
> +Optional subnodes:
> + - video input: this subnode can contain a video input port node
> + to connect the bridge to a display controller output (See this
> + documentation [1]).
You also need an output port for the DVI output. Those two ports should be
required, not optional.
> +[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
> +
> +Example:
> + hdmi-bridge {
> + compatible = "ti,tfp410";
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + bridge_in: endpoint {
> + remote-endpoint = <&dc_out>;
> + };
> + };
> + };
> + };
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index bd6acc8..a424e03 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -81,6 +81,13 @@ config DRM_TOSHIBA_TC358767
> ---help---
> Toshiba TC358767 eDP bridge chip driver.
>
> +config DRM_TI_TFP410
> + tristate "TI TFP410 DVI/HDMI bridge"
> + depends on OF
> + select DRM_KMS_HELPER
> + ---help---
> + Texas Instruments TFP410 DVI/HDMI Transmitter driver
> +
> source "drivers/gpu/drm/bridge/analogix/Kconfig"
>
> source "drivers/gpu/drm/bridge/adv7511/Kconfig"
> diff --git a/drivers/gpu/drm/bridge/Makefile
> b/drivers/gpu/drm/bridge/Makefile index 97ed1a5..8b065d9 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -11,3 +11,4 @@ obj-$(CONFIG_DRM_SII902X) += sii902x.o
> obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
> obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
> obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
> +obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
> diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c
> b/drivers/gpu/drm/bridge/ti-tfp410.c new file mode 100644
> index 0000000..b0753d2
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/ti-tfp410.c
> @@ -0,0 +1,199 @@
> +/*
> + * Copyright (C) 2016 Texas Instruments
> + * Author: Jyri Sarha <jsarha@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> by + * the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/of_graph.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +
> +struct tfp410 {
> + struct drm_bridge bridge;
> + struct drm_connector connector;
> +
> + struct i2c_adapter *ddc;
> +
> + struct device *dev;
> +};
> +
> +static inline struct tfp410 *
> +drm_bridge_to_tfp410(struct drm_bridge *bridge)
> +{
> + return container_of(bridge, struct tfp410, bridge);
> +}
> +
> +static inline struct tfp410 *
> +drm_connector_to_tfp410(struct drm_connector *connector)
> +{
> + return container_of(connector, struct tfp410, connector);
> +}
> +
> +static int tfp410_get_modes(struct drm_connector *connector)
> +{
> + struct tfp410 *hdmi = drm_connector_to_tfp410(connector);
> + struct edid *edid;
> + int ret;
> +
> + if (!hdmi->ddc)
> + goto fallback;
> +
> + edid = drm_get_edid(connector, hdmi->ddc);
> + if (!edid) {
> + DRM_INFO("EDID read failed. Fallback to standard modes\n");
> + goto fallback;
> + }
> +
> + drm_mode_connector_update_edid_property(connector, edid);
> +
> + return drm_add_edid_modes(connector, edid);
> +fallback:
> + /* No EDID, fallback on the XGA standard modes */
> + ret = drm_add_modes_noedid(connector, 1920, 1200);
> +
> + /* And prefer a mode pretty much anything can handle */
> + drm_set_preferred_mode(connector, 1024, 768);
> +
> + return ret;
> +}
> +
> +static const struct drm_connector_helper_funcs tfp410_con_helper_funcs = {
> + .get_modes = tfp410_get_modes,
> +};
> +
> +static enum drm_connector_status
> +tfp410_connector_detect(struct drm_connector *connector, bool force)
> +{
> + struct tfp410 *hdmi = drm_connector_to_tfp410(connector);
> +
> + if (hdmi->ddc) {
> + if (drm_probe_ddc(hdmi->ddc))
> + return connector_status_connected;
> + else
> + return connector_status_disconnected;
> + }
> +
> + return connector_status_unknown;
> +}
> +
> +static const struct drm_connector_funcs tfp410_con_funcs = {
> + .dpms = drm_atomic_helper_connector_dpms,
> + .detect = tfp410_connector_detect,
> + .fill_modes = drm_helper_probe_single_connector_modes,
> + .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 int tfp410_attach(struct drm_bridge *bridge)
> +{
> + struct tfp410 *hdmi = drm_bridge_to_tfp410(bridge);
> + int ret;
> +
> + if (!bridge->encoder) {
> + dev_err(hdmi->dev, "Missing encoder\n");
> + return -ENODEV;
> + }
> +
> + drm_connector_helper_add(&hdmi->connector,
> + &tfp410_con_helper_funcs);
> + ret = drm_connector_init(bridge->dev, &hdmi->connector,
> + &tfp410_con_funcs, DRM_MODE_CONNECTOR_HDMIA);
> + if (ret) {
> + dev_err(hdmi->dev, "drm_connector_init() failed: %d\n", ret);
> + return ret;
> + }
> +
> + drm_mode_connector_attach_encoder(&hdmi->connector,
> + bridge->encoder);
> +
> + return 0;
> +}
> +
> +static const struct drm_bridge_funcs tfp410_bridge_funcs = {
> + .attach = tfp410_attach,
> +};
> +
> +static int tfp410_probe(struct platform_device *pdev)
> +{
> + struct device_node *ddc_phandle;
> + struct tfp410 *hdmi;
> + int ret;
> +
> + if (!pdev->dev.of_node) {
> + dev_err(&pdev->dev, "device-tree data is missing\n");
> + return -ENXIO;
> + }
> +
> + hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
> + if (!hdmi)
> + return -ENOMEM;
> + platform_set_drvdata(pdev, hdmi);
> +
> + ddc_phandle = of_parse_phandle(pdev->dev.of_node, "ddc-i2c", 0);
> + if (ddc_phandle) {
> + hdmi->ddc = of_get_i2c_adapter_by_node(ddc_phandle);
> + of_node_put(ddc_phandle);
> + if (!hdmi->ddc)
> + return -EPROBE_DEFER;
> + } else {
> + dev_info(&pdev->dev,
> + "No ddc i2c bus, disabling EDID readout\n");
> + }
> +
> + hdmi->bridge.funcs = &tfp410_bridge_funcs;
> + hdmi->bridge.of_node = pdev->dev.of_node;
> + hdmi->dev = &pdev->dev;
> +
> + ret = drm_bridge_add(&hdmi->bridge);
> + if (ret) {
> + dev_err(&pdev->dev, "drm_bridge_add() failed: %d\n", ret);
> + goto fail;
> + }
> +
> + return 0;
> +fail:
> + i2c_put_adapter(hdmi->ddc);
> + return ret;
> +}
> +
> +static int tfp410_remove(struct platform_device *pdev)
> +{
> + struct tfp410 *hdmi = platform_get_drvdata(pdev);
> +
> + drm_bridge_remove(&hdmi->bridge);
> +
> + if (hdmi->ddc)
> + i2c_put_adapter(hdmi->ddc);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id tfp410_match[] = {
> + { .compatible = "ti,tfp410" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, tfp410_match);
> +
> +struct platform_driver tfp410_driver = {
> + .probe = tfp410_probe,
> + .remove = tfp410_remove,
> + .driver = {
> + .name = "tfp410-bridge",
> + .of_match_table = tfp410_match,
> + },
> +};
> +module_platform_driver(tfp410_driver);
> +
> +MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
> +MODULE_DESCRIPTION("TI TFP410 HDMI bridge driver");
> +MODULE_LICENSE("GPL");
--
Regards,
Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v2 06/14] ASoC: sun4i-codec: Add support for A31 playback through headphone output
From: Maxime Ripard @ 2016-11-03 17:36 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Rob Herring, Mark Rutland, alsa-devel, linux-arm-kernel,
linux-kernel, devicetree, linux-sunxi
In-Reply-To: <20161103075556.29018-7-wens@csie.org>
[-- Attachment #1: Type: text/plain, Size: 752 bytes --]
Hi,
On Thu, Nov 03, 2016 at 03:55:48PM +0800, Chen-Yu Tsai wrote:
> +/* headphone controls */
> +static const char * const sun6i_codec_hp_src_enum_text[] = {
> + "DAC", "Mixer",
> +};
> +
> +static SOC_ENUM_DOUBLE_DECL(sun6i_codec_hp_src_enum,
> + SUN6I_CODEC_OM_DACA_CTRL,
> + SUN6I_CODEC_OM_DACA_CTRL_LHPIS,
> + SUN6I_CODEC_OM_DACA_CTRL_RHPIS,
> + sun6i_codec_hp_src_enum_text);
> +
> +static const struct snd_kcontrol_new sun6i_codec_hp_src[] = {
> + SOC_DAPM_ENUM("Headphone Source Playback Route",
> + sun6i_codec_hp_src_enum),
> +};
What is that route exactly? A muxer?
Thanks,
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v2 02/14] ASoC: sun4i-codec: Expand quirks to handle register offsets and card creation
From: Maxime Ripard @ 2016-11-03 17:34 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Rob Herring, Mark Rutland, alsa-devel, linux-arm-kernel,
linux-kernel, devicetree, linux-sunxi
In-Reply-To: <20161103075556.29018-3-wens@csie.org>
[-- Attachment #1: Type: text/plain, Size: 1151 bytes --]
On Thu, Nov 03, 2016 at 03:55:44PM +0800, Chen-Yu Tsai wrote:
> The A31 has a similar codec to the A10/A20. The PCM parts are very
> similar, with just different register offsets. The analog paths are
> very different. There are more inputs and outputs.
>
> The A31s, A23, and H3 have a similar PCM interface, again with register
> offsets slightly rearranged. The analog path controls, while very
> similar between them and the A31, have been moved a separate bus which
> is accessed through a message box like interface in the PRCM address
> range. This would be handled by a separate auxiliary device tied in
> through the device tree in its supporting create_card function.
>
> The quirks structure is expanded to include different register offsets
> and separate callbacks for creating the ASoC card. The regmap_config,
> quirks, and of_device_match tables have been moved to facilitate this.
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Applied "ASoC: sun4i-codec: Move data structures to add create_card call to quirks" to the asoc tree
From: Mark Brown @ 2016-11-03 17:26 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: Maxime Ripard, Mark Brown, Liam Girdwood
In-Reply-To: <20161103075556.29018-2-wens-jdAy2FN1RRM@public.gmane.org>
The patch
ASoC: sun4i-codec: Move data structures to add create_card call to quirks
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 2f2a3462bc15e9613412ca186bf8a6611afa66c7 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
Date: Thu, 3 Nov 2016 15:55:43 +0800
Subject: [PATCH] ASoC: sun4i-codec: Move data structures to add create_card
call to quirks
The audio codec on later Allwinner SoCs have a different layout and
audio path compared to the A10/A20. However the PCM parts are still
the same.
The different layout and audio paths mean we need a different
create_card function for different families, so they can create
DAPM endpoint widgets and routes.
This patch moves the regmap configs, quirks and of_device_id
structures to just before the probe function, so we can, among other
things, include a pointer for the create_card function. None of the
lines of code were changed.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
Acked-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
sound/soc/sunxi/sun4i-codec.c | 78 +++++++++++++++++++++----------------------
1 file changed, 39 insertions(+), 39 deletions(-)
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index a60707761abf..7b78f4045d38 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -678,45 +678,6 @@ static struct snd_soc_dai_driver dummy_cpu_dai = {
},
};
-static const struct regmap_config sun4i_codec_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .max_register = SUN4I_CODEC_ADC_RXCNT,
-};
-
-static const struct regmap_config sun7i_codec_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL,
-};
-
-struct sun4i_codec_quirks {
- const struct regmap_config *regmap_config;
-};
-
-static const struct sun4i_codec_quirks sun4i_codec_quirks = {
- .regmap_config = &sun4i_codec_regmap_config,
-};
-
-static const struct sun4i_codec_quirks sun7i_codec_quirks = {
- .regmap_config = &sun7i_codec_regmap_config,
-};
-
-static const struct of_device_id sun4i_codec_of_match[] = {
- {
- .compatible = "allwinner,sun4i-a10-codec",
- .data = &sun4i_codec_quirks,
- },
- {
- .compatible = "allwinner,sun7i-a20-codec",
- .data = &sun7i_codec_quirks,
- },
- {}
-};
-MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
-
static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
int *num_links)
{
@@ -781,6 +742,45 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
return card;
};
+static const struct regmap_config sun4i_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN4I_CODEC_ADC_RXCNT,
+};
+
+static const struct regmap_config sun7i_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL,
+};
+
+struct sun4i_codec_quirks {
+ const struct regmap_config *regmap_config;
+};
+
+static const struct sun4i_codec_quirks sun4i_codec_quirks = {
+ .regmap_config = &sun4i_codec_regmap_config,
+};
+
+static const struct sun4i_codec_quirks sun7i_codec_quirks = {
+ .regmap_config = &sun7i_codec_regmap_config,
+};
+
+static const struct of_device_id sun4i_codec_of_match[] = {
+ {
+ .compatible = "allwinner,sun4i-a10-codec",
+ .data = &sun4i_codec_quirks,
+ },
+ {
+ .compatible = "allwinner,sun7i-a20-codec",
+ .data = &sun7i_codec_quirks,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
+
static int sun4i_codec_probe(struct platform_device *pdev)
{
struct snd_soc_card *card;
--
2.10.1
^ permalink raw reply related
* Re: [PATCH v2 1/2] phy: rockchip-inno-usb2: support otg-port for rk3399
From: Kishon Vijay Abraham I @ 2016-11-03 17:17 UTC (permalink / raw)
To: William Wu, heiko-4mtYJXux2i+zQB+pC5nmwQ
Cc: huangtao-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA, groeck-hpIqsD4AKlfQT0dZR+AlfA,
frank.wang-TNX95d0MmH7DzftRWevZcw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dianders-hpIqsD4AKlfQT0dZR+AlfA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
briannorris-hpIqsD4AKlfQT0dZR+AlfA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1478138774-3254-2-git-send-email-wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
On Thursday 03 November 2016 07:36 AM, William Wu wrote:
> The rk3399 SoC USB2 PHY is comprised of one Host port and
> one OTG port. And OTG port is for USB2.0 part of USB3.0 OTG
> controller, as a part to construct a fully feature Type-C
> subsystem.
>
> With this patch, we can support OTG port with the following
> functions:
> - Support BC1.2 charger detect, and use extcon notifier to
> send USB charger types to power driver.
> - Support PHY suspend for power management.
> - Support OTG Host only mode.
>
> Also, correct 480MHz output clock stable time. We found that
> the system crashed due to 480MHz output clock of USB2 PHY was
> unstable after clock had been enabled by gpu module.
Can you split the clock fix into a separate patch?
Thanks
Kishon
>
> Theoretically, 1 millisecond is a critical value for 480 output
> clock stable time, so we try changing the delay time to 1.2
> millisecond to avoid this issue.
>
> Signed-off-by: William Wu <wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---
> Changes in v2:
> - remove wakelock
>
> drivers/phy/phy-rockchip-inno-usb2.c | 593 +++++++++++++++++++++++++++++++++--
> 1 file changed, 562 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/phy-rockchip-inno-usb2.c
> index ac20310..8f2d2b6 100644
> --- a/drivers/phy/phy-rockchip-inno-usb2.c
> +++ b/drivers/phy/phy-rockchip-inno-usb2.c
> @@ -17,6 +17,7 @@
> #include <linux/clk.h>
> #include <linux/clk-provider.h>
> #include <linux/delay.h>
> +#include <linux/extcon.h>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> #include <linux/gpio/consumer.h>
> @@ -30,11 +31,15 @@
> #include <linux/of_platform.h>
> #include <linux/phy/phy.h>
> #include <linux/platform_device.h>
> +#include <linux/power_supply.h>
> #include <linux/regmap.h>
> #include <linux/mfd/syscon.h>
> +#include <linux/usb/of.h>
> +#include <linux/usb/otg.h>
>
> #define BIT_WRITEABLE_SHIFT 16
> -#define SCHEDULE_DELAY (60 * HZ)
> +#define SCHEDULE_DELAY (60 * HZ)
> +#define OTG_SCHEDULE_DELAY (2 * HZ)
>
> enum rockchip_usb2phy_port_id {
> USB2PHY_PORT_OTG,
> @@ -49,6 +54,37 @@ enum rockchip_usb2phy_host_state {
> PHY_STATE_FS_LS_ONLINE = 4,
> };
>
> +/**
> + * Different states involved in USB charger detection.
> + * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
> + * process is not yet started.
> + * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
> + * USB_CHG_STATE_DCD_DONE Data pin contact is detected.
> + * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
> + * between SDP and DCP/CDP).
> + * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
> + * between DCP and CDP).
> + * USB_CHG_STATE_DETECTED USB charger type is determined.
> + */
> +enum usb_chg_state {
> + USB_CHG_STATE_UNDEFINED = 0,
> + USB_CHG_STATE_WAIT_FOR_DCD,
> + USB_CHG_STATE_DCD_DONE,
> + USB_CHG_STATE_PRIMARY_DONE,
> + USB_CHG_STATE_SECONDARY_DONE,
> + USB_CHG_STATE_DETECTED,
> +};
> +
> +static const unsigned int rockchip_usb2phy_extcon_cable[] = {
> + EXTCON_USB,
> + EXTCON_USB_HOST,
> + EXTCON_CHG_USB_SDP,
> + EXTCON_CHG_USB_CDP,
> + EXTCON_CHG_USB_DCP,
> + EXTCON_CHG_USB_SLOW,
> + EXTCON_NONE,
> +};
> +
> struct usb2phy_reg {
> unsigned int offset;
> unsigned int bitend;
> @@ -58,19 +94,55 @@ struct usb2phy_reg {
> };
>
> /**
> + * struct rockchip_chg_det_reg: usb charger detect registers
> + * @cp_det: charging port detected successfully.
> + * @dcp_det: dedicated charging port detected successfully.
> + * @dp_det: assert data pin connect successfully.
> + * @idm_sink_en: open dm sink curren.
> + * @idp_sink_en: open dp sink current.
> + * @idp_src_en: open dm source current.
> + * @rdm_pdwn_en: open dm pull down resistor.
> + * @vdm_src_en: open dm voltage source.
> + * @vdp_src_en: open dp voltage source.
> + * @opmode: utmi operational mode.
> + */
> +struct rockchip_chg_det_reg {
> + struct usb2phy_reg cp_det;
> + struct usb2phy_reg dcp_det;
> + struct usb2phy_reg dp_det;
> + struct usb2phy_reg idm_sink_en;
> + struct usb2phy_reg idp_sink_en;
> + struct usb2phy_reg idp_src_en;
> + struct usb2phy_reg rdm_pdwn_en;
> + struct usb2phy_reg vdm_src_en;
> + struct usb2phy_reg vdp_src_en;
> + struct usb2phy_reg opmode;
> +};
> +
> +/**
> * struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
> * @phy_sus: phy suspend register.
> + * @bvalid_det_en: vbus valid rise detection enable register.
> + * @bvalid_det_st: vbus valid rise detection status register.
> + * @bvalid_det_clr: vbus valid rise detection clear register.
> * @ls_det_en: linestate detection enable register.
> * @ls_det_st: linestate detection state register.
> * @ls_det_clr: linestate detection clear register.
> + * @utmi_avalid: utmi vbus avalid status register.
> + * @utmi_bvalid: utmi vbus bvalid status register.
> * @utmi_ls: utmi linestate state register.
> * @utmi_hstdet: utmi host disconnect register.
> */
> struct rockchip_usb2phy_port_cfg {
> struct usb2phy_reg phy_sus;
> + struct usb2phy_reg bvalid_det_en;
> + struct usb2phy_reg bvalid_det_st;
> + struct usb2phy_reg bvalid_det_clr;
> struct usb2phy_reg ls_det_en;
> struct usb2phy_reg ls_det_st;
> struct usb2phy_reg ls_det_clr;
> + struct usb2phy_reg utmi_avalid;
> + struct usb2phy_reg utmi_bvalid;
> struct usb2phy_reg utmi_ls;
> struct usb2phy_reg utmi_hstdet;
> };
> @@ -80,31 +152,51 @@ struct rockchip_usb2phy_port_cfg {
> * @reg: the address offset of grf for usb-phy config.
> * @num_ports: specify how many ports that the phy has.
> * @clkout_ctl: keep on/turn off output clk of phy.
> + * @chg_det: charger detection registers.
> */
> struct rockchip_usb2phy_cfg {
> unsigned int reg;
> unsigned int num_ports;
> struct usb2phy_reg clkout_ctl;
> const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS];
> + const struct rockchip_chg_det_reg chg_det;
> };
>
> /**
> * struct rockchip_usb2phy_port: usb-phy port data.
> * @port_id: flag for otg port or host port.
> * @suspended: phy suspended flag.
> + * @utmi_avalid: utmi avalid status usage flag.
> + * true - use avalid to get vbus status
> + * flase - use bvalid to get vbus status
> + * @vbus_attached: otg device vbus status.
> + * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
> * @ls_irq: IRQ number assigned for linestate detection.
> * @mutex: for register updating in sm_work.
> - * @sm_work: OTG state machine work.
> + * @chg_work: charge detect work.
> + * @otg_sm_work: OTG state machine work.
> + * @sm_work: HOST state machine work.
> * @phy_cfg: port register configuration, assigned by driver data.
> + * @event_nb: hold event notification callback.
> + * @state: define OTG enumeration states before device reset.
> + * @mode: the dr_mode of the controller.
> */
> struct rockchip_usb2phy_port {
> struct phy *phy;
> unsigned int port_id;
> bool suspended;
> + bool utmi_avalid;
> + bool vbus_attached;
> + int bvalid_irq;
> int ls_irq;
> struct mutex mutex;
> + struct delayed_work chg_work;
> + struct delayed_work otg_sm_work;
> struct delayed_work sm_work;
> const struct rockchip_usb2phy_port_cfg *port_cfg;
> + struct notifier_block event_nb;
> + enum usb_otg_state state;
> + enum usb_dr_mode mode;
> };
>
> /**
> @@ -113,6 +205,11 @@ struct rockchip_usb2phy_port {
> * @clk: clock struct of phy input clk.
> * @clk480m: clock struct of phy output clk.
> * @clk_hw: clock struct of phy output clk management.
> + * @chg_state: states involved in USB charger detection.
> + * @chg_type: USB charger types.
> + * @dcd_retries: The retry count used to track Data contact
> + * detection process.
> + * @edev: extcon device for notification registration
> * @phy_cfg: phy register configuration, assigned by driver data.
> * @ports: phy port instance.
> */
> @@ -122,6 +219,10 @@ struct rockchip_usb2phy {
> struct clk *clk;
> struct clk *clk480m;
> struct clk_hw clk480m_hw;
> + enum usb_chg_state chg_state;
> + enum power_supply_type chg_type;
> + u8 dcd_retries;
> + struct extcon_dev *edev;
> const struct rockchip_usb2phy_cfg *phy_cfg;
> struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS];
> };
> @@ -166,7 +267,7 @@ static int rockchip_usb2phy_clk480m_enable(struct clk_hw *hw)
> return ret;
>
> /* waitting for the clk become stable */
> - mdelay(1);
> + udelay(1200);
> }
>
> return 0;
> @@ -263,33 +364,84 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
> return ret;
> }
>
> -static int rockchip_usb2phy_init(struct phy *phy)
> +static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
> {
> - struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
> - struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
> int ret;
> + struct device_node *node = rphy->dev->of_node;
> + struct extcon_dev *edev;
> +
> + if (of_property_read_bool(node, "extcon")) {
> + edev = extcon_get_edev_by_phandle(rphy->dev, 0);
> + if (IS_ERR(edev)) {
> + if (PTR_ERR(edev) != -EPROBE_DEFER)
> + dev_err(rphy->dev, "Invalid or missing extcon\n");
> + return PTR_ERR(edev);
> + }
> + } else {
> + /* Initialize extcon device */
> + edev = devm_extcon_dev_allocate(rphy->dev,
> + rockchip_usb2phy_extcon_cable);
>
> - if (rport->port_id == USB2PHY_PORT_HOST) {
> - /* clear linestate and enable linestate detect irq */
> - mutex_lock(&rport->mutex);
> + if (IS_ERR(edev))
> + return -ENOMEM;
>
> - ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
> + ret = devm_extcon_dev_register(rphy->dev, edev);
> if (ret) {
> - mutex_unlock(&rport->mutex);
> + dev_err(rphy->dev, "failed to register extcon device\n");
> return ret;
> }
> + }
>
> - ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
> - if (ret) {
> - mutex_unlock(&rport->mutex);
> - return ret;
> + rphy->edev = edev;
> +
> + return 0;
> +}
> +
> +static int rockchip_usb2phy_init(struct phy *phy)
> +{
> + struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
> + struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
> + int ret = 0;
> +
> + mutex_lock(&rport->mutex);
> +
> + if (rport->port_id == USB2PHY_PORT_OTG) {
> + if (rport->mode != USB_DR_MODE_HOST) {
> + /* clear bvalid status and enable bvalid detect irq */
> + ret = property_enable(rphy,
> + &rport->port_cfg->bvalid_det_clr,
> + true);
> + if (ret)
> + goto out;
> +
> + ret = property_enable(rphy,
> + &rport->port_cfg->bvalid_det_en,
> + true);
> + if (ret)
> + goto out;
> +
> + schedule_delayed_work(&rport->otg_sm_work,
> + OTG_SCHEDULE_DELAY);
> + } else {
> + /* If OTG works in host only mode, do nothing. */
> + dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
> }
> + } else if (rport->port_id == USB2PHY_PORT_HOST) {
> + /* clear linestate and enable linestate detect irq */
> + ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
> + if (ret)
> + goto out;
> +
> + ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
> + if (ret)
> + goto out;
>
> - mutex_unlock(&rport->mutex);
> schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
> }
>
> - return 0;
> +out:
> + mutex_unlock(&rport->mutex);
> + return ret;
> }
>
> static int rockchip_usb2phy_power_on(struct phy *phy)
> @@ -340,7 +492,11 @@ static int rockchip_usb2phy_exit(struct phy *phy)
> {
> struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>
> - if (rport->port_id == USB2PHY_PORT_HOST)
> + if (rport->port_id == USB2PHY_PORT_OTG &&
> + rport->mode != USB_DR_MODE_HOST) {
> + cancel_delayed_work_sync(&rport->otg_sm_work);
> + cancel_delayed_work_sync(&rport->chg_work);
> + } else if (rport->port_id == USB2PHY_PORT_HOST)
> cancel_delayed_work_sync(&rport->sm_work);
>
> return 0;
> @@ -354,6 +510,249 @@ static const struct phy_ops rockchip_usb2phy_ops = {
> .owner = THIS_MODULE,
> };
>
> +static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
> +{
> + struct rockchip_usb2phy_port *rport =
> + container_of(work, struct rockchip_usb2phy_port,
> + otg_sm_work.work);
> + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> + static unsigned int cable;
> + unsigned long delay;
> + bool vbus_attach, sch_work, notify_charger;
> +
> + if (rport->utmi_avalid)
> + vbus_attach =
> + property_enabled(rphy, &rport->port_cfg->utmi_avalid);
> + else
> + vbus_attach =
> + property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
> +
> + sch_work = false;
> + notify_charger = false;
> + delay = OTG_SCHEDULE_DELAY;
> + dev_dbg(&rport->phy->dev, "%s otg sm work\n",
> + usb_otg_state_string(rport->state));
> +
> + switch (rport->state) {
> + case OTG_STATE_UNDEFINED:
> + rport->state = OTG_STATE_B_IDLE;
> + if (!vbus_attach)
> + rockchip_usb2phy_power_off(rport->phy);
> + /* fall through */
> + case OTG_STATE_B_IDLE:
> + if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) > 0) {
> + dev_dbg(&rport->phy->dev, "usb otg host connect\n");
> + rport->state = OTG_STATE_A_HOST;
> + rockchip_usb2phy_power_on(rport->phy);
> + return;
> + } else if (vbus_attach) {
> + dev_dbg(&rport->phy->dev, "vbus_attach\n");
> + switch (rphy->chg_state) {
> + case USB_CHG_STATE_UNDEFINED:
> + schedule_delayed_work(&rport->chg_work, 0);
> + return;
> + case USB_CHG_STATE_DETECTED:
> + switch (rphy->chg_type) {
> + case POWER_SUPPLY_TYPE_USB:
> + dev_dbg(&rport->phy->dev,
> + "sdp cable is connecetd\n");
> + rockchip_usb2phy_power_on(rport->phy);
> + rport->state = OTG_STATE_B_PERIPHERAL;
> + notify_charger = true;
> + sch_work = true;
> + cable = EXTCON_CHG_USB_SDP;
> + break;
> + case POWER_SUPPLY_TYPE_USB_DCP:
> + dev_dbg(&rport->phy->dev,
> + "dcp cable is connecetd\n");
> + rockchip_usb2phy_power_off(rport->phy);
> + notify_charger = true;
> + sch_work = true;
> + cable = EXTCON_CHG_USB_DCP;
> + break;
> + case POWER_SUPPLY_TYPE_USB_CDP:
> + dev_dbg(&rport->phy->dev,
> + "cdp cable is connecetd\n");
> + rockchip_usb2phy_power_on(rport->phy);
> + rport->state = OTG_STATE_B_PERIPHERAL;
> + notify_charger = true;
> + sch_work = true;
> + cable = EXTCON_CHG_USB_CDP;
> + break;
> + default:
> + break;
> + }
> + break;
> + default:
> + break;
> + }
> + } else {
> + notify_charger = true;
> + rphy->chg_state = USB_CHG_STATE_UNDEFINED;
> + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
> + }
> +
> + if (rport->vbus_attached != vbus_attach) {
> + rport->vbus_attached = vbus_attach;
> +
> + if (notify_charger && rphy->edev)
> + extcon_set_cable_state_(rphy->edev,
> + cable, vbus_attach);
> + }
> + break;
> + case OTG_STATE_B_PERIPHERAL:
> + if (!vbus_attach) {
> + dev_dbg(&rport->phy->dev, "usb disconnect\n");
> + rphy->chg_state = USB_CHG_STATE_UNDEFINED;
> + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
> + rport->state = OTG_STATE_B_IDLE;
> + delay = 0;
> + rockchip_usb2phy_power_off(rport->phy);
> + }
> + sch_work = true;
> + break;
> + case OTG_STATE_A_HOST:
> + if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) == 0) {
> + dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
> + rport->state = OTG_STATE_B_IDLE;
> + rockchip_usb2phy_power_off(rport->phy);
> + }
> + break;
> + default:
> + break;
> + }
> +
> + if (sch_work)
> + schedule_delayed_work(&rport->otg_sm_work, delay);
> +}
> +
> +static const char *chg_to_string(enum power_supply_type chg_type)
> +{
> + switch (chg_type) {
> + case POWER_SUPPLY_TYPE_USB:
> + return "USB_SDP_CHARGER";
> + case POWER_SUPPLY_TYPE_USB_DCP:
> + return "USB_DCP_CHARGER";
> + case POWER_SUPPLY_TYPE_USB_CDP:
> + return "USB_CDP_CHARGER";
> + default:
> + return "INVALID_CHARGER";
> + }
> +}
> +
> +static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
> + bool en)
> +{
> + property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
> + property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
> +}
> +
> +static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
> + bool en)
> +{
> + property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
> + property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
> +}
> +
> +static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
> + bool en)
> +{
> + property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
> + property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
> +}
> +
> +#define CHG_DCD_POLL_TIME (100 * HZ / 1000)
> +#define CHG_DCD_MAX_RETRIES 6
> +#define CHG_PRIMARY_DET_TIME (40 * HZ / 1000)
> +#define CHG_SECONDARY_DET_TIME (40 * HZ / 1000)
> +static void rockchip_chg_detect_work(struct work_struct *work)
> +{
> + struct rockchip_usb2phy_port *rport =
> + container_of(work, struct rockchip_usb2phy_port, chg_work.work);
> + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> + bool is_dcd, tmout, vout;
> + unsigned long delay;
> +
> + dev_dbg(&rport->phy->dev, "chg detection work state = %d\n",
> + rphy->chg_state);
> + switch (rphy->chg_state) {
> + case USB_CHG_STATE_UNDEFINED:
> + if (!rport->suspended)
> + rockchip_usb2phy_power_off(rport->phy);
> + /* put the controller in non-driving mode */
> + property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false);
> + /* Start DCD processing stage 1 */
> + rockchip_chg_enable_dcd(rphy, true);
> + rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
> + rphy->dcd_retries = 0;
> + delay = CHG_DCD_POLL_TIME;
> + break;
> + case USB_CHG_STATE_WAIT_FOR_DCD:
> + /* get data contact detection status */
> + is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det);
> + tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
> + /* stage 2 */
> + if (is_dcd || tmout) {
> + /* stage 4 */
> + /* Turn off DCD circuitry */
> + rockchip_chg_enable_dcd(rphy, false);
> + /* Voltage Source on DP, Probe on DM */
> + rockchip_chg_enable_primary_det(rphy, true);
> + delay = CHG_PRIMARY_DET_TIME;
> + rphy->chg_state = USB_CHG_STATE_DCD_DONE;
> + } else {
> + /* stage 3 */
> + delay = CHG_DCD_POLL_TIME;
> + }
> + break;
> + case USB_CHG_STATE_DCD_DONE:
> + vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det);
> + rockchip_chg_enable_primary_det(rphy, false);
> + if (vout) {
> + /* Voltage Source on DM, Probe on DP */
> + rockchip_chg_enable_secondary_det(rphy, true);
> + delay = CHG_SECONDARY_DET_TIME;
> + rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE;
> + } else {
> + if (tmout) {
> + /* floating charger found */
> + rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
> + rphy->chg_state = USB_CHG_STATE_DETECTED;
> + delay = 0;
> + } else {
> + rphy->chg_type = POWER_SUPPLY_TYPE_USB;
> + rphy->chg_state = USB_CHG_STATE_DETECTED;
> + delay = 0;
> + }
> + }
> + break;
> + case USB_CHG_STATE_PRIMARY_DONE:
> + vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det);
> + /* Turn off voltage source */
> + rockchip_chg_enable_secondary_det(rphy, false);
> + if (vout)
> + rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
> + else
> + rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP;
> + /* fall through */
> + case USB_CHG_STATE_SECONDARY_DONE:
> + rphy->chg_state = USB_CHG_STATE_DETECTED;
> + delay = 0;
> + /* fall through */
> + case USB_CHG_STATE_DETECTED:
> + /* put the controller in normal mode */
> + property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true);
> + rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
> + dev_info(&rport->phy->dev, "charger = %s\n",
> + chg_to_string(rphy->chg_type));
> + return;
> + default:
> + return;
> + }
> +
> + schedule_delayed_work(&rport->chg_work, delay);
> +}
> +
> /*
> * The function manage host-phy port state and suspend/resume phy port
> * to save power.
> @@ -485,6 +884,26 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
> return IRQ_HANDLED;
> }
>
> +static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
> +{
> + struct rockchip_usb2phy_port *rport = data;
> + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> +
> + if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st))
> + return IRQ_NONE;
> +
> + mutex_lock(&rport->mutex);
> +
> + /* clear bvalid detect irq pending status */
> + property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true);
> +
> + mutex_unlock(&rport->mutex);
> +
> + rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
> +
> + return IRQ_HANDLED;
> +}
> +
> static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
> struct rockchip_usb2phy_port *rport,
> struct device_node *child_np)
> @@ -509,13 +928,86 @@ static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
> IRQF_ONESHOT,
> "rockchip_usb2phy", rport);
> if (ret) {
> - dev_err(rphy->dev, "failed to request irq handle\n");
> + dev_err(rphy->dev, "failed to request linestate irq handle\n");
> return ret;
> }
>
> return 0;
> }
>
> +static int rockchip_otg_event(struct notifier_block *nb,
> + unsigned long event, void *ptr)
> +{
> + struct rockchip_usb2phy_port *rport =
> + container_of(nb, struct rockchip_usb2phy_port, event_nb);
> +
> + schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
> +
> + return NOTIFY_DONE;
> +}
> +
> +static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
> + struct rockchip_usb2phy_port *rport,
> + struct device_node *child_np)
> +{
> + int ret;
> +
> + rport->port_id = USB2PHY_PORT_OTG;
> + rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
> + rport->state = OTG_STATE_UNDEFINED;
> +
> + /*
> + * set suspended flag to true, but actually don't
> + * put phy in suspend mode, it aims to enable usb
> + * phy and clock in power_on() called by usb controller
> + * driver during probe.
> + */
> + rport->suspended = true;
> + rport->vbus_attached = false;
> +
> + mutex_init(&rport->mutex);
> +
> + rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
> + if (rport->mode == USB_DR_MODE_HOST) {
> + ret = 0;
> + goto out;
> + }
> +
> + INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
> + INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
> +
> + rport->utmi_avalid =
> + of_property_read_bool(child_np, "rockchip,utmi-avalid");
> +
> + rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
> + if (rport->bvalid_irq < 0) {
> + dev_err(rphy->dev, "no vbus valid irq provided\n");
> + ret = rport->bvalid_irq;
> + goto out;
> + }
> +
> + ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL,
> + rockchip_usb2phy_bvalid_irq,
> + IRQF_ONESHOT,
> + "rockchip_usb2phy_bvalid", rport);
> + if (ret) {
> + dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n");
> + goto out;
> + }
> +
> + if (!IS_ERR(rphy->edev)) {
> + rport->event_nb.notifier_call = rockchip_otg_event;
> +
> + ret = extcon_register_notifier(rphy->edev, EXTCON_USB_HOST,
> + &rport->event_nb);
> + if (ret)
> + dev_err(rphy->dev, "register USB HOST notifier failed\n");
> + }
> +
> +out:
> + return ret;
> +}
> +
> static int rockchip_usb2phy_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -553,8 +1045,14 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>
> rphy->dev = dev;
> phy_cfgs = match->data;
> + rphy->chg_state = USB_CHG_STATE_UNDEFINED;
> + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
> platform_set_drvdata(pdev, rphy);
>
> + ret = rockchip_usb2phy_extcon_register(rphy);
> + if (ret)
> + return ret;
> +
> /* find out a proper config which can be matched with dt. */
> index = 0;
> while (phy_cfgs[index].reg) {
> @@ -591,13 +1089,9 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
> struct rockchip_usb2phy_port *rport = &rphy->ports[index];
> struct phy *phy;
>
> - /*
> - * This driver aim to support both otg-port and host-port,
> - * but unfortunately, the otg part is not ready in current,
> - * so this comments and below codes are interim, which should
> - * be changed after otg-port is supplied soon.
> - */
> - if (of_node_cmp(child_np->name, "host-port"))
> + /* This driver aims to support both otg-port and host-port */
> + if (of_node_cmp(child_np->name, "host-port") &&
> + of_node_cmp(child_np->name, "otg-port"))
> goto next_child;
>
> phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
> @@ -610,9 +1104,18 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
> rport->phy = phy;
> phy_set_drvdata(rport->phy, rport);
>
> - ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np);
> - if (ret)
> - goto put_child;
> + /* initialize otg/host port separately */
> + if (!of_node_cmp(child_np->name, "host-port")) {
> + ret = rockchip_usb2phy_host_port_init(rphy, rport,
> + child_np);
> + if (ret)
> + goto put_child;
> + } else {
> + ret = rockchip_usb2phy_otg_port_init(rphy, rport,
> + child_np);
> + if (ret)
> + goto put_child;
> + }
>
> next_child:
> /* to prevent out of boundary */
> @@ -654,10 +1157,18 @@ static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = {
>
> static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
> {
> - .reg = 0xe450,
> + .reg = 0xe450,
> .num_ports = 2,
> .clkout_ctl = { 0xe450, 4, 4, 1, 0 },
> .port_cfgs = {
> + [USB2PHY_PORT_OTG] = {
> + .phy_sus = { 0xe454, 1, 0, 2, 1 },
> + .bvalid_det_en = { 0xe3c0, 3, 3, 0, 1 },
> + .bvalid_det_st = { 0xe3e0, 3, 3, 0, 1 },
> + .bvalid_det_clr = { 0xe3d0, 3, 3, 0, 1 },
> + .utmi_avalid = { 0xe2ac, 7, 7, 0, 1 },
> + .utmi_bvalid = { 0xe2ac, 12, 12, 0, 1 },
> + },
> [USB2PHY_PORT_HOST] = {
> .phy_sus = { 0xe458, 1, 0, 0x2, 0x1 },
> .ls_det_en = { 0xe3c0, 6, 6, 0, 1 },
> @@ -667,12 +1178,32 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
> .utmi_hstdet = { 0xe2ac, 23, 23, 0, 1 }
> }
> },
> + .chg_det = {
> + .opmode = { 0xe454, 3, 0, 5, 1 },
> + .cp_det = { 0xe2ac, 2, 2, 0, 1 },
> + .dcp_det = { 0xe2ac, 1, 1, 0, 1 },
> + .dp_det = { 0xe2ac, 0, 0, 0, 1 },
> + .idm_sink_en = { 0xe450, 8, 8, 0, 1 },
> + .idp_sink_en = { 0xe450, 7, 7, 0, 1 },
> + .idp_src_en = { 0xe450, 9, 9, 0, 1 },
> + .rdm_pdwn_en = { 0xe450, 10, 10, 0, 1 },
> + .vdm_src_en = { 0xe450, 12, 12, 0, 1 },
> + .vdp_src_en = { 0xe450, 11, 11, 0, 1 },
> + },
> },
> {
> - .reg = 0xe460,
> + .reg = 0xe460,
> .num_ports = 2,
> .clkout_ctl = { 0xe460, 4, 4, 1, 0 },
> .port_cfgs = {
> + [USB2PHY_PORT_OTG] = {
> + .phy_sus = { 0xe464, 1, 0, 2, 1 },
> + .bvalid_det_en = { 0xe3c0, 8, 8, 0, 1 },
> + .bvalid_det_st = { 0xe3e0, 8, 8, 0, 1 },
> + .bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
> + .utmi_avalid = { 0xe2ac, 10, 10, 0, 1 },
> + .utmi_bvalid = { 0xe2ac, 16, 16, 0, 1 },
> + },
> [USB2PHY_PORT_HOST] = {
> .phy_sus = { 0xe468, 1, 0, 0x2, 0x1 },
> .ls_det_en = { 0xe3c0, 11, 11, 0, 1 },
>
^ permalink raw reply
* Re: [PATCH] ARM: DTS: r8a7794: alt: Fix PCF names for DU
From: Sergei Shtylyov @ 2016-11-03 16:57 UTC (permalink / raw)
To: Jacopo Mondi, horms-/R6kz+dDXgpPR4JQBCEnsQ,
magnus.damm-Re5JQEeQqe8AvxtiuMwx3w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw
Cc: linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1478180574-15464-1-git-send-email-jacopo-AW8dsiIh9cEdnm+yROfE0A@public.gmane.org>
Hello.
On 11/03/2016 04:42 PM, Jacopo Mondi wrote:
> Update the PCF pin groups and function names of DU interface for
PFC maybe?
> r8a7794 ALT board.
>
> The currently specified pin groups and function names prevented PCF and
> DU interfaces from being correctly configured:
>
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> rcar-du: probe of feb00000.display failed with error -22
>
> Signed-off-by: Jacopo Mondi <jacopo-AW8dsiIh9cEdnm+yROfE0A@public.gmane.org>
> ---
>
> Patch applied against Simon Horman's renesas/master branch.
> The PCF pin groups and function renaming was introduced by commit 56ed4bb9 and
> DTS for ALT board has never been update accordingly.
We didn't care about Alt at the time, the patch was done in the interests
of the SILK board. I didn't realize the DU pin groups were used for Alt before
the actual support was added for them. Thank you for finally fixing this!
> Tested displaying frames on VGA interface: the rcar-du driver loads correctly.
MBR, Sergei
--
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 v5 5/7] net: ethernet: bgmac: device tree phy enablement
From: Jon Mason @ 2016-11-03 16:45 UTC (permalink / raw)
To: rafal-g1n6cQUeyibVItvQsEIGlw
Cc: David Miller, Rob Herring, Mark Rutland, Florian Fainelli,
bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w,
netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <35b16640-8600-8c48-2f04-886dc925229d-g1n6cQUeyibVItvQsEIGlw@public.gmane.org>
On Thu, Nov 03, 2016 at 09:31:21AM +0100, Rafal Milecki wrote:
> On 11/02/2016 06:08 PM, Jon Mason wrote:
> >Change the bgmac driver to allow for phy's defined by the device tree
>
> This is a late review, I know, sorry... :(
>
>
> >+static int bcma_phy_direct_connect(struct bgmac *bgmac)
> >+{
> >+ struct fixed_phy_status fphy_status = {
> >+ .link = 1,
> >+ .speed = SPEED_1000,
> >+ .duplex = DUPLEX_FULL,
> >+ };
> >+ struct phy_device *phy_dev;
> >+ int err;
> >+
> >+ phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
> >+ if (!phy_dev || IS_ERR(phy_dev)) {
> >+ dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
> >+ return -ENODEV;
> >+ }
> >+
> >+ err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
> >+ PHY_INTERFACE_MODE_MII);
> >+ if (err) {
> >+ dev_err(bgmac->dev, "Connecting PHY failed\n");
> >+ return err;
> >+ }
> >+
> >+ return err;
> >+}
>
> This bcma specific function looks exactly the same as...
>
>
> >+static int platform_phy_direct_connect(struct bgmac *bgmac)
> >+{
> >+ struct fixed_phy_status fphy_status = {
> >+ .link = 1,
> >+ .speed = SPEED_1000,
> >+ .duplex = DUPLEX_FULL,
> >+ };
> >+ struct phy_device *phy_dev;
> >+ int err;
> >+
> >+ phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
> >+ if (!phy_dev || IS_ERR(phy_dev)) {
> >+ dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
> >+ return -ENODEV;
> >+ }
> >+
> >+ err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
> >+ PHY_INTERFACE_MODE_MII);
> >+ if (err) {
> >+ dev_err(bgmac->dev, "Connecting PHY failed\n");
> >+ return err;
> >+ }
> >+
> >+ return err;
> >+}
>
> This one.
>
> Would that make sense to keep bgmac_phy_connect_direct and just use it in
> bcma/platform code?
Yes, I was having the same internal debate. I hate the duplication of
code, but I really wanted to keep the PHY logic out of the bgmac.c
file. Do you think it is acceptable to make this an inline function
in bgmac.h?
Thanks,
Jon
--
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 v2 6/6] ARM: dts: stm32f429: Add QSPI clock
From: Alexandre Torgue @ 2016-11-03 16:45 UTC (permalink / raw)
To: gabriel.fernandez, Rob Herring, Mark Rutland, Russell King,
Maxime Coquelin, Michael Turquette, Stephen Boyd, Nicolas Pitre,
Arnd Bergmann, daniel.thompson
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-clk,
ludovic.barre, olivier.bideau, amelie.delaunay
In-Reply-To: <1476436699-21879-7-git-send-email-gabriel.fernandez@st.com>
Hi Gabriel,
On 10/14/2016 11:18 AM, gabriel.fernandez@st.com wrote:
> From: Gabriel Fernandez <gabriel.fernandez@st.com>
>
> This patch adds the QSPI clock for stm32f469 discovery board.
>
> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
> ---
> arch/arm/boot/dts/stm32f469-disco.dts | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
> index e911af8..4052023 100644
> --- a/arch/arm/boot/dts/stm32f469-disco.dts
> +++ b/arch/arm/boot/dts/stm32f469-disco.dts
> @@ -66,6 +66,10 @@
> };
> };
>
> +&rcc {
> + compatible = "st,stm32f469-rcc", "st,stm32-rcc";
> +};
> +
With this patch, stm32f469-disco doesn't boot if clk drivers patch are
not applied.
Can you please send a new version to keep compatibility with older clk
driver.
&rcc {
> + compatible = "st,stm32f469-rcc", "st,stm32-rcc";
-> compatible = "st,stm32f469-rcc", "st,stm32f42xx-rcc", "st,stm32-rcc";
> +};
> +
I will take it in next pull request round.
Regards
Alex
> &clk_hse {
> clock-frequency = <8000000>;
> };
>
^ permalink raw reply
* [PATCH 4/4] ARM: dts: Add #pinctrl-cells for pinctrl-single instances
From: Tony Lindgren @ 2016-11-03 16:35 UTC (permalink / raw)
To: Linus Walleij
Cc: Jon Hunter, Mark Rutland, Rob Herring, Grygorii Strashko,
Nishanth Menon, linux-gpio, devicetree, linux-kernel, linux-omap
In-Reply-To: <20161103163550.27330-1-tony@atomide.com>
Drivers using pinctrl-single,pins have #pinctrl-cells = <1>, while
pinctrl-single,bits need #pinctrl-cells = <2>.
Note that this patch can be optionally applied separately from the
driver changes as the driver supports also the legacy binding without
#pinctrl-cells.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt | 3 +++
arch/arm/boot/dts/am33xx.dtsi | 2 ++
arch/arm/boot/dts/am3517.dtsi | 1 +
arch/arm/boot/dts/am4372.dtsi | 1 +
arch/arm/boot/dts/da850.dtsi | 1 +
arch/arm/boot/dts/dm814x.dtsi | 1 +
arch/arm/boot/dts/dm816x.dtsi | 2 ++
arch/arm/boot/dts/dra7.dtsi | 1 +
arch/arm/boot/dts/hi3620.dtsi | 2 ++
arch/arm/boot/dts/keystone-k2g.dtsi | 1 +
arch/arm/boot/dts/keystone-k2l.dtsi | 1 +
arch/arm/boot/dts/omap2420.dtsi | 2 ++
arch/arm/boot/dts/omap2430.dtsi | 2 ++
arch/arm/boot/dts/omap3.dtsi | 2 ++
arch/arm/boot/dts/omap34xx.dtsi | 1 +
arch/arm/boot/dts/omap36xx.dtsi | 1 +
arch/arm/boot/dts/omap4.dtsi | 2 ++
arch/arm/boot/dts/omap5.dtsi | 2 ++
arch/arm/boot/dts/pxa3xx.dtsi | 1 +
arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 3 +++
20 files changed, 32 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -7,6 +7,9 @@ Required properties:
- reg : offset and length of the register set for the mux registers
+- #pinctrl-cells : number of cells in addition to the index, set to 1
+ for pinctrl-single,pins and 2 for pinctrl-single,bits
+
- pinctrl-single,register-width : pinmux register access width in bits
- pinctrl-single,function-mask : mask of allowed pinmux function bits
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -130,6 +130,7 @@
reg = <0x210000 0x2000>;
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
ranges = <0 0x210000 0x2000>;
am33xx_pinmux: pinmux@800 {
@@ -137,6 +138,7 @@
reg = <0x800 0x238>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0x7f>;
};
diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/am3517.dtsi
--- a/arch/arm/boot/dts/am3517.dtsi
+++ b/arch/arm/boot/dts/am3517.dtsi
@@ -66,6 +66,7 @@
reg = <0x480025d8 0x24>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <16>;
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -189,6 +189,7 @@
reg = <0x800 0x31c>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <32>;
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -36,6 +36,7 @@
reg = <0x14120 0x50>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <2>;
pinctrl-single,bit-per-mux;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0xf>;
diff --git a/arch/arm/boot/dts/dm814x.dtsi b/arch/arm/boot/dts/dm814x.dtsi
--- a/arch/arm/boot/dts/dm814x.dtsi
+++ b/arch/arm/boot/dts/dm814x.dtsi
@@ -374,6 +374,7 @@
reg = <0x800 0x438>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0x307ff>;
};
diff --git a/arch/arm/boot/dts/dm816x.dtsi b/arch/arm/boot/dts/dm816x.dtsi
--- a/arch/arm/boot/dts/dm816x.dtsi
+++ b/arch/arm/boot/dts/dm816x.dtsi
@@ -83,6 +83,7 @@
reg = <0x48140000 0x21000>;
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
ranges = <0 0x48140000 0x21000>;
dm816x_pinmux: pinmux@800 {
@@ -90,6 +91,7 @@
reg = <0x800 0x50a>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
pinctrl-single,register-width = <16>;
pinctrl-single,function-mask = <0xf>;
};
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -171,6 +171,7 @@
reg = <0x1400 0x0468>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <32>;
diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
--- a/arch/arm/boot/dts/hi3620.dtsi
+++ b/arch/arm/boot/dts/hi3620.dtsi
@@ -537,6 +537,7 @@
reg = <0x803000 0x188>;
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
#gpio-range-cells = <3>;
ranges;
@@ -558,6 +559,7 @@
reg = <0x803800 0x2dc>;
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
ranges;
pinctrl-single,register-width = <32>;
diff --git a/arch/arm/boot/dts/keystone-k2g.dtsi b/arch/arm/boot/dts/keystone-k2g.dtsi
--- a/arch/arm/boot/dts/keystone-k2g.dtsi
+++ b/arch/arm/boot/dts/keystone-k2g.dtsi
@@ -72,6 +72,7 @@
soc {
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
compatible = "ti,keystone","simple-bus";
ranges = <0x0 0x0 0x0 0xc0000000>;
dma-ranges = <0x80000000 0x8 0x00000000 0x80000000>;
diff --git a/arch/arm/boot/dts/keystone-k2l.dtsi b/arch/arm/boot/dts/keystone-k2l.dtsi
--- a/arch/arm/boot/dts/keystone-k2l.dtsi
+++ b/arch/arm/boot/dts/keystone-k2l.dtsi
@@ -59,6 +59,7 @@
reg = <0x02620690 0xc>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <2>;
pinctrl-single,bit-per-mux;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0x1>;
diff --git a/arch/arm/boot/dts/omap2420.dtsi b/arch/arm/boot/dts/omap2420.dtsi
--- a/arch/arm/boot/dts/omap2420.dtsi
+++ b/arch/arm/boot/dts/omap2420.dtsi
@@ -38,6 +38,7 @@
reg = <0x0 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
ranges = <0 0x0 0x1000>;
omap2420_pmx: pinmux@30 {
@@ -46,6 +47,7 @@
reg = <0x30 0x0113>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
pinctrl-single,register-width = <8>;
pinctrl-single,function-mask = <0x3f>;
};
diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi
--- a/arch/arm/boot/dts/omap2430.dtsi
+++ b/arch/arm/boot/dts/omap2430.dtsi
@@ -38,6 +38,7 @@
reg = <0x2000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
ranges = <0 0x2000 0x1000>;
omap2430_pmx: pinmux@30 {
@@ -46,6 +47,7 @@
reg = <0x30 0x0154>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
pinctrl-single,register-width = <8>;
pinctrl-single,function-mask = <0x3f>;
};
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -106,6 +106,7 @@
reg = <0x30 0x238>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <16>;
@@ -145,6 +146,7 @@
reg = <0xa00 0x5c>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <16>;
diff --git a/arch/arm/boot/dts/omap34xx.dtsi b/arch/arm/boot/dts/omap34xx.dtsi
--- a/arch/arm/boot/dts/omap34xx.dtsi
+++ b/arch/arm/boot/dts/omap34xx.dtsi
@@ -34,6 +34,7 @@
reg = <0x480025d8 0x24>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <16>;
diff --git a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/omap36xx.dtsi
--- a/arch/arm/boot/dts/omap36xx.dtsi
+++ b/arch/arm/boot/dts/omap36xx.dtsi
@@ -66,6 +66,7 @@
reg = <0x480025a0 0x5c>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <16>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -184,6 +184,7 @@
reg = <0x40 0x0196>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <16>;
@@ -256,6 +257,7 @@
reg = <0x1e040 0x0038>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <16>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -171,6 +171,7 @@
reg = <0x40 0x01b6>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <16>;
@@ -270,6 +271,7 @@
reg = <0xc840 0x003c>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
pinctrl-single,register-width = <16>;
diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/pxa3xx.dtsi
--- a/arch/arm/boot/dts/pxa3xx.dtsi
+++ b/arch/arm/boot/dts/pxa3xx.dtsi
@@ -138,6 +138,7 @@
reg = <0x40e10000 0xffff>;
#address-cells = <1>;
#size-cells = <0>;
+ #pinctrl-cells = <1>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0x7>;
};
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
--- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
@@ -364,6 +364,7 @@
reg = <0x0 0xf7010000 0x0 0x27c>;
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
#gpio-range-cells = <3>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <7>;
@@ -402,6 +403,7 @@
reg = <0x0 0xf7010800 0x0 0x28c>;
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
pinctrl-single,register-width = <32>;
};
@@ -410,6 +412,7 @@
reg = <0x0 0xf8001800 0x0 0x78>;
#address-cells = <1>;
#size-cells = <1>;
+ #pinctrl-cells = <1>;
pinctrl-single,register-width = <32>;
};
--
2.10.2
^ permalink raw reply
* [PATCH 3/4] pinctrl: single: Use generic parser and #pinctrl-cells for pinctrl-single,bits
From: Tony Lindgren @ 2016-11-03 16:35 UTC (permalink / raw)
To: Linus Walleij
Cc: Jon Hunter, Mark Rutland, Rob Herring, Grygorii Strashko,
Nishanth Menon, linux-gpio, devicetree, linux-kernel, linux-omap
In-Reply-To: <20161103163550.27330-1-tony@atomide.com>
We can now use generic parser and keep things compatible with the
old binding.
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/pinctrl/pinctrl-single.c | 48 ++++++++++++++++++++--------------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -35,7 +35,6 @@
#include "pinconf.h"
#define DRIVER_NAME "pinctrl-single"
-#define PCS_MUX_BITS_NAME "pinctrl-single,bits"
#define PCS_OFF_DISABLED ~0U
/**
@@ -1219,36 +1218,22 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
return res;
}
-#define PARAMS_FOR_BITS_PER_MUX 3
-
static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
struct device_node *np,
struct pinctrl_map **map,
unsigned *num_maps,
const char **pgnames)
{
+ const char *name = "pinctrl-single,pins";
struct pcs_func_vals *vals;
- const __be32 *mux;
- int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
+ int rows, *pins, found = 0, res = -ENOMEM, i;
int npins_in_row;
struct pcs_function *function;
- mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
-
- if (!mux) {
- dev_err(pcs->dev, "no valid property for %s\n", np->name);
- return -EINVAL;
- }
-
- if (size < (sizeof(*mux) * PARAMS_FOR_BITS_PER_MUX)) {
- dev_err(pcs->dev, "bad data for %s\n", np->name);
- return -EINVAL;
- }
-
- /* Number of elements in array */
- size /= sizeof(*mux);
+ rows = pinctrl_count_index_with_args(np, name);
+ if (rows == -EINVAL)
+ return rows;
- rows = size / PARAMS_FOR_BITS_PER_MUX;
npins_in_row = pcs->width / pcs->bits_per_pin;
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row,
@@ -1261,15 +1246,30 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
if (!pins)
goto free_vals;
- while (index < size) {
+ for (i = 0; i < rows; i++) {
+ struct of_phandle_args pinctrl_spec;
unsigned offset, val;
unsigned mask, bit_pos, val_pos, mask_pos, submask;
unsigned pin_num_from_lsb;
int pin;
- offset = be32_to_cpup(mux + index++);
- val = be32_to_cpup(mux + index++);
- mask = be32_to_cpup(mux + index++);
+ res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec);
+ if (res)
+ return res;
+
+ if (pinctrl_spec.args_count < 3) {
+ dev_err(pcs->dev, "invalid args_count for spec: %i\n",
+ pinctrl_spec.args_count);
+ break;
+ }
+
+ /* Index plus two value cells */
+ offset = pinctrl_spec.args[0];
+ val = pinctrl_spec.args[1];
+ mask = pinctrl_spec.args[2];
+
+ dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x mask: 0x%x\n",
+ pinctrl_spec.np->name, offset, val, mask);
/* Parse pins in each row from LSB */
while (mask) {
--
2.10.2
^ permalink raw reply
* [PATCH 2/4] pinctrl: single: Use generic parser and #pinctrl-cells for pinctrl-single,pins
From: Tony Lindgren @ 2016-11-03 16:35 UTC (permalink / raw)
To: Linus Walleij
Cc: Jon Hunter, Mark Rutland, Rob Herring, Grygorii Strashko,
Nishanth Menon, linux-gpio, devicetree, linux-kernel, linux-omap
In-Reply-To: <20161103163550.27330-1-tony@atomide.com>
We can now use generic parser. To support the legacy binding without
#pinctrl-cells, add pcs_quirk_missing_pinctrl_cells() and warn about
missing #pinctrl-cells.
Let's also update the documentation for struct pcs_soc_data while at it
as that seems to be out of date.
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/pinctrl/pinctrl-single.c | 111 ++++++++++++++++++++++++++++++++-------
1 file changed, 93 insertions(+), 18 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -31,10 +31,10 @@
#include <linux/platform_data/pinctrl-single.h>
#include "core.h"
+#include "devicetree.h"
#include "pinconf.h"
#define DRIVER_NAME "pinctrl-single"
-#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
#define PCS_MUX_BITS_NAME "pinctrl-single,bits"
#define PCS_OFF_DISABLED ~0U
@@ -162,8 +162,11 @@ struct pcs_soc_data {
* @base: virtual address of the controller
* @size: size of the ioremapped area
* @dev: device entry
+ * @np: device tree node
* @pctl: pin controller device
* @flags: mask of PCS_FEAT_xxx values
+ * @missing_nr_pinctrl_cells: for legacy binding, may go away
+ * @socdata: soc specific data
* @lock: spinlock for register access
* @mutex: mutex protecting the lists
* @width: bits per mux register
@@ -171,7 +174,8 @@ struct pcs_soc_data {
* @fshift: function register shift
* @foff: value to turn mux off
* @fmax: max number of functions in fmask
- * @bits_per_pin:number of bits per pin
+ * @bits_per_mux: number of bits per mux
+ * @bits_per_pin: number of bits per pin
* @pins: physical pins on the SoC
* @pgtree: pingroup index radix tree
* @ftree: function index radix tree
@@ -192,11 +196,13 @@ struct pcs_device {
void __iomem *base;
unsigned size;
struct device *dev;
+ struct device_node *np;
struct pinctrl_dev *pctl;
unsigned flags;
#define PCS_QUIRK_SHARED_IRQ (1 << 2)
#define PCS_FEAT_IRQ (1 << 1)
#define PCS_FEAT_PINCONF (1 << 0)
+ struct property *missing_nr_pinctrl_cells;
struct pcs_soc_data socdata;
raw_spinlock_t lock;
struct mutex mutex;
@@ -1125,20 +1131,14 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
unsigned *num_maps,
const char **pgnames)
{
+ const char *name = "pinctrl-single,pins";
struct pcs_func_vals *vals;
- const __be32 *mux;
- int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
+ int rows, *pins, found = 0, res = -ENOMEM, i;
struct pcs_function *function;
- mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
- if ((!mux) || (size < sizeof(*mux) * 2)) {
- dev_err(pcs->dev, "bad data for mux %s\n",
- np->name);
- return -EINVAL;
- }
-
- size /= sizeof(*mux); /* Number of elements in array */
- rows = size / 2;
+ rows = pinctrl_count_index_with_args(np, name);
+ if (rows == -EINVAL)
+ return rows;
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL);
if (!vals)
@@ -1148,14 +1148,28 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
if (!pins)
goto free_vals;
- while (index < size) {
- unsigned offset, val;
+ for (i = 0; i < rows; i++) {
+ struct of_phandle_args pinctrl_spec;
+ unsigned int offset;
int pin;
- offset = be32_to_cpup(mux + index++);
- val = be32_to_cpup(mux + index++);
+ res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec);
+ if (res)
+ return res;
+
+ if (pinctrl_spec.args_count < 2) {
+ dev_err(pcs->dev, "invalid args_count for spec: %i\n",
+ pinctrl_spec.args_count);
+ break;
+ }
+
+ /* Index plus one value cell */
+ offset = pinctrl_spec.args[0];
vals[found].reg = pcs->base + offset;
- vals[found].val = val;
+ vals[found].val = pinctrl_spec.args[1];
+
+ dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x\n",
+ pinctrl_spec.np->name, offset, pinctrl_spec.args[1]);
pin = pcs_get_pin_by_offset(pcs, offset);
if (pin < 0) {
@@ -1473,6 +1487,10 @@ static void pcs_free_resources(struct pcs_device *pcs)
pinctrl_unregister(pcs->pctl);
pcs_free_funcs(pcs);
pcs_free_pingroups(pcs);
+#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
+ if (pcs->missing_nr_pinctrl_cells)
+ of_remove_property(pcs->np, pcs->missing_nr_pinctrl_cells);
+#endif
}
static const struct of_device_id pcs_of_match[];
@@ -1790,6 +1808,55 @@ static int pinctrl_single_resume(struct platform_device *pdev)
}
#endif
+/**
+ * pcs_quirk_missing_pinctrl_cells - handle legacy binding
+ * @pcs: pinctrl driver instance
+ * @np: device tree node
+ * @cells: number of cells
+ *
+ * Handle legacy binding with no #pinctrl-cells. This should be
+ * always two pinctrl-single,bit-per-mux and one for others.
+ * At some point we may want to consider removing this.
+ */
+static int pcs_quirk_missing_pinctrl_cells(struct pcs_device *pcs,
+ struct device_node *np,
+ int cells)
+{
+ struct property *p;
+ const char *name = "#pinctrl-cells";
+ int error;
+ u32 val;
+
+ error = of_property_read_u32(np, name, &val);
+ if (!error)
+ return 0;
+
+ dev_warn(pcs->dev, "please update dts to use %s = <%i>\n",
+ name, cells);
+
+ p = devm_kzalloc(pcs->dev, sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->length = sizeof(__be32);
+ p->value = devm_kzalloc(pcs->dev, sizeof(__be32), GFP_KERNEL);
+ if (!p->value)
+ return -ENOMEM;
+ *(__be32 *)p->value = cpu_to_be32(cells);
+
+ p->name = devm_kstrdup(pcs->dev, name, GFP_KERNEL);
+ if (!p->name)
+ return -ENOMEM;
+
+ pcs->missing_nr_pinctrl_cells = p;
+
+#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
+ error = of_add_property(np, pcs->missing_nr_pinctrl_cells);
+#endif
+
+ return error;
+}
+
static int pcs_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1810,6 +1877,7 @@ static int pcs_probe(struct platform_device *pdev)
return -ENOMEM;
}
pcs->dev = &pdev->dev;
+ pcs->np = np;
raw_spin_lock_init(&pcs->lock);
mutex_init(&pcs->mutex);
INIT_LIST_HEAD(&pcs->pingroups);
@@ -1846,6 +1914,13 @@ static int pcs_probe(struct platform_device *pdev)
pcs->bits_per_mux = of_property_read_bool(np,
"pinctrl-single,bit-per-mux");
+ ret = pcs_quirk_missing_pinctrl_cells(pcs, np,
+ pcs->bits_per_mux ? 2 : 1);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to patch #pinctrl-cells\n");
+
+ return ret;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
--
2.10.2
^ permalink raw reply
* [PATCH 1/4] pinctrl: Introduce generic #pinctrl-cells and pinctrl_parse_index_with_args
From: Tony Lindgren @ 2016-11-03 16:35 UTC (permalink / raw)
To: Linus Walleij
Cc: Jon Hunter, Mark Rutland, Rob Herring, Grygorii Strashko,
Nishanth Menon, linux-gpio, devicetree, linux-kernel, linux-omap
In-Reply-To: <20161103163550.27330-1-tony@atomide.com>
Introduce #pinctrl-cells helper binding and generic helper functions
pinctrl_count_index_with_args() and pinctrl_parse_index_with_args().
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
.../bindings/pinctrl/pinctrl-bindings.txt | 44 ++++++-
drivers/pinctrl/devicetree.c | 144 +++++++++++++++++++++
drivers/pinctrl/devicetree.h | 21 +++
3 files changed, 208 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -97,6 +97,11 @@ For example:
};
== Pin controller devices ==
+Required properties: See the pin controller driver specific documentation
+
+Optional properties:
+#pinctrl-cells: Number of pin control cells in addition to the index within the
+ pin controller device instance
Pin controller devices should contain the pin configuration nodes that client
devices reference.
@@ -119,7 +124,8 @@ For example:
The contents of each of those pin configuration child nodes is defined
entirely by the binding for the individual pin controller device. There
-exists no common standard for this content.
+exists no common standard for this content. The pinctrl framework only
+provides generic helper bindings that the pin controller driver can use.
The pin configuration nodes need not be direct children of the pin controller
device; they may be grandchildren, for example. Whether this is legal, and
@@ -156,6 +162,42 @@ state_2_node_a {
pins = "mfio29", "mfio30";
};
+Optionally an altenative binding can be used if more suitable depending on the
+pin controller hardware. For hardaware where there is a large number of identical
+pin controller instances, naming each pin and function can easily become
+unmaintainable. This is especially the case if the same controller is used for
+different pins and functions depending on the SoC revision and packaging.
+
+For cases like this, the pin controller driver may use pinctrl-pin-array helper
+binding with a hardware based index and a number of pin configuration values:
+
+pincontroller {
+ ... /* Standard DT properties for the device itself elided */
+ #pinctrl-cells = <2>;
+
+ state_0_node_a {
+ pinctrl-pin-array = <
+ 0 A_DELAY_PS(0) G_DELAY_PS(120)
+ 4 A_DELAY_PS(0) G_DELAY_PS(360)
+ ...
+ >;
+ };
+ ...
+};
+
+Above #pinctrl-cells specifies the number of value cells in addition to the
+index of the registers. This is similar to the interrupts-extended binding with
+one exception. There is no need to specify the phandle for each entry as that
+is already known as the defined pins are always children of the pin controller
+node. Further having the phandle pointing to another pin controller would not
+currently work as the pinctrl framework uses named modes to group pins for each
+pin control device.
+
+The index for pinctrl-pin-array must relate to the hardware for the pinctrl
+registers, and must not be a virtual index of pin instances. The reason for
+this is to avoid mapping of the index in the dts files and the pin controller
+driver as it can change.
+
== Generic pin configuration node content ==
Many data items that are represented in a pin configuration node are common
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -253,3 +253,147 @@ int pinctrl_dt_to_map(struct pinctrl *p)
pinctrl_dt_free_maps(p);
return ret;
}
+
+/*
+ * For pinctrl binding, typically #pinctrl-cells is for the pin controller
+ * device, so either parent or grandparent. See pinctrl-bindings.txt.
+ */
+static int pinctrl_find_cells_size(const struct device_node *np)
+{
+ const char *cells_name = "#pinctrl-cells";
+ int cells_size, error;
+
+ error = of_property_read_u32(np->parent, cells_name, &cells_size);
+ if (error) {
+ error = of_property_read_u32(np->parent->parent,
+ cells_name, &cells_size);
+ if (error)
+ return -ENOENT;
+ }
+
+ return cells_size;
+}
+
+/**
+ * pinctrl_get_list_and_count - Gets the list and it's cell size and number
+ * @np: pointer to device node with the property
+ * @list_name: property that contains the list
+ * @list: pointer for the list found
+ * @cells_size: pointer for the cell size found
+ * @nr_elements: pointer for the number of elements found
+ *
+ * Typically np is a single pinctrl entry containing the list.
+ */
+static int pinctrl_get_list_and_count(const struct device_node *np,
+ const char *list_name,
+ const __be32 **list,
+ int *cells_size,
+ int *nr_elements)
+{
+ int size;
+
+ *cells_size = 0;
+ *nr_elements = 0;
+
+ *list = of_get_property(np, list_name, &size);
+ if (!*list)
+ return -ENOENT;
+
+ *cells_size = pinctrl_find_cells_size(np);
+ if (*cells_size < 0)
+ return -ENOENT;
+
+ /* First element is always the index within the pinctrl device */
+ *nr_elements = (size / sizeof(**list)) / (*cells_size + 1);
+
+ return 0;
+}
+
+/**
+ * pinctrl_count_index_with_args - Count number of elements in a pinctrl entry
+ * @np: pointer to device node with the property
+ * @list_name: property that contains the list
+ *
+ * Counts the number of elements in a pinctrl array consisting of an index
+ * within the controller and a number of u32 entries specified for each
+ * entry. Note that device_node is always for the parent pin controller device.
+ */
+int pinctrl_count_index_with_args(const struct device_node *np,
+ const char *list_name)
+{
+ const __be32 *list;
+ int size, nr_cells, error;
+
+ error = pinctrl_get_list_and_count(np, list_name, &list,
+ &nr_cells, &size);
+ if (error)
+ return error;
+
+ return size;
+}
+EXPORT_SYMBOL_GPL(pinctrl_count_index_with_args);
+
+/**
+ * pinctrl_copy_args - Populates of_phandle_args based on index
+ * @np: pointer to device node with the property
+ * @list: pointer to a list with the elements
+ * @index: entry within the list of elements
+ * @nr_cells: number of cells in the list
+ * @nr_elem: number of elements for each entry in the list
+ * @out_args: returned values
+ *
+ * Populates the of_phandle_args based on the index in the list.
+ */
+static int pinctrl_copy_args(const struct device_node *np,
+ const __be32 *list,
+ int index, int nr_cells, int nr_elem,
+ struct of_phandle_args *out_args)
+{
+ int i;
+
+ memset(out_args, 0, sizeof(*out_args));
+ out_args->np = (struct device_node *)np;
+ out_args->args_count = nr_cells + 1;
+
+ if (index >= nr_elem)
+ return -EINVAL;
+
+ list += index * (nr_cells + 1);
+
+ for (i = 0; i < nr_cells + 1; i++)
+ out_args->args[i] = be32_to_cpup(list++);
+
+ return 0;
+}
+
+/**
+ * pinctrl_parse_index_with_args - Find a node pointed by index in a list
+ * @np: pointer to device node with the property
+ * @list_name: property that contains the list
+ * @index: index within the list
+ * @out_arts: entries in the list pointed by index
+ *
+ * Finds the selected element in a pinctrl array consisting of an index
+ * within the controller and a number of u32 entries specified for each
+ * entry. Note that device_node is always for the parent pin controller device.
+ */
+int pinctrl_parse_index_with_args(const struct device_node *np,
+ const char *list_name, int index,
+ struct of_phandle_args *out_args)
+{
+ const __be32 *list;
+ int nr_elem, nr_cells, error;
+
+ error = pinctrl_get_list_and_count(np, list_name, &list,
+ &nr_cells, &nr_elem);
+ if (error || !nr_cells)
+ return error;
+
+ error = pinctrl_copy_args(np, list, index, nr_cells, nr_elem,
+ out_args);
+ if (error)
+ return error;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pinctrl_parse_index_with_args);
diff --git a/drivers/pinctrl/devicetree.h b/drivers/pinctrl/devicetree.h
--- a/drivers/pinctrl/devicetree.h
+++ b/drivers/pinctrl/devicetree.h
@@ -21,6 +21,13 @@
void pinctrl_dt_free_maps(struct pinctrl *p);
int pinctrl_dt_to_map(struct pinctrl *p);
+int pinctrl_count_index_with_args(const struct device_node *np,
+ const char *list_name);
+
+int pinctrl_parse_index_with_args(const struct device_node *np,
+ const char *list_name, int index,
+ struct of_phandle_args *out_args);
+
#else
static inline int pinctrl_dt_to_map(struct pinctrl *p)
@@ -32,4 +39,18 @@ static inline void pinctrl_dt_free_maps(struct pinctrl *p)
{
}
+static inline int pinctrl_count_index_with_args(const struct device_node *np,
+ const char *list_name)
+{
+ return -ENODEV;
+}
+
+static inline int
+pinctrl_parse_index_with_args(const struct device_node *np,
+ const char *list_name, int index,
+ struct of_phandle_args *out_args)
+{
+ return -ENODEV;
+}
+
#endif
--
2.10.2
^ permalink raw reply
* [PATCHv2 0/4] Generic #pinctrl-cells and and pinctrl_parse_index_with_args
From: Tony Lindgren @ 2016-11-03 16:35 UTC (permalink / raw)
To: Linus Walleij
Cc: Jon Hunter, Mark Rutland, Rob Herring, Grygorii Strashko,
Nishanth Menon, linux-gpio, devicetree, linux-kernel, linux-omap
Hi all,
Here a repost of some pinctrl changes to introduce #pinctrl-cells and
a generic parser pinctrl_parse_index_with_args that the drivers can
optionally use.
Regards,
Tony
Changes from v1:
- Update based on comments from Linus Walleij to not pass
#pinctrl-cells as an argument and improve the binding
documentation
Tony Lindgren (4):
pinctrl: Introduce generic #pinctrl-cells and
pinctrl_parse_index_with_args
pinctrl: single: Use generic parser and #pinctrl-cells for
pinctrl-single,pins
pinctrl: single: Use generic parser and #pinctrl-cells for
pinctrl-single,bits
ARM: dts: Add #pinctrl-cells for pinctrl-single instances
.../bindings/pinctrl/pinctrl-bindings.txt | 44 +++++-
.../devicetree/bindings/pinctrl/pinctrl-single.txt | 3 +
arch/arm/boot/dts/am33xx.dtsi | 2 +
arch/arm/boot/dts/am3517.dtsi | 1 +
arch/arm/boot/dts/am4372.dtsi | 1 +
arch/arm/boot/dts/da850.dtsi | 1 +
arch/arm/boot/dts/dm814x.dtsi | 1 +
arch/arm/boot/dts/dm816x.dtsi | 2 +
arch/arm/boot/dts/dra7.dtsi | 1 +
arch/arm/boot/dts/hi3620.dtsi | 2 +
arch/arm/boot/dts/keystone-k2g.dtsi | 1 +
arch/arm/boot/dts/keystone-k2l.dtsi | 1 +
arch/arm/boot/dts/omap2420.dtsi | 2 +
arch/arm/boot/dts/omap2430.dtsi | 2 +
arch/arm/boot/dts/omap3.dtsi | 2 +
arch/arm/boot/dts/omap34xx.dtsi | 1 +
arch/arm/boot/dts/omap36xx.dtsi | 1 +
arch/arm/boot/dts/omap4.dtsi | 2 +
arch/arm/boot/dts/omap5.dtsi | 2 +
arch/arm/boot/dts/pxa3xx.dtsi | 1 +
arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 3 +
drivers/pinctrl/devicetree.c | 144 +++++++++++++++++++
drivers/pinctrl/devicetree.h | 21 +++
drivers/pinctrl/pinctrl-single.c | 159 +++++++++++++++------
24 files changed, 357 insertions(+), 43 deletions(-)
--
2.10.2
^ permalink raw reply
* [PATCH v4 4/4] ARM: dts: da850: Add the usb otg device node
From: Alexandre Bailon @ 2016-11-03 15:59 UTC (permalink / raw)
To: khilman, robh+dt, b-liu
Cc: linux-kernel, linux-usb, devicetree, linux-arm-kernel, nsekhar,
Alexandre Bailon
In-Reply-To: <1478188752-22447-1-git-send-email-abailon@baylibre.com>
This adds the device tree node for the usb otg
controller present in the da850 family of SoC's.
This also enables the otg usb controller for the lcdk board.
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
---
arch/arm/boot/dts/da850-lcdk.dts | 8 ++++++++
arch/arm/boot/dts/da850.dtsi | 15 +++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
index 7b8ab21..9f5040c 100644
--- a/arch/arm/boot/dts/da850-lcdk.dts
+++ b/arch/arm/boot/dts/da850-lcdk.dts
@@ -158,6 +158,14 @@
rx-num-evt = <32>;
};
+&usb_phy {
+ status = "okay";
+ };
+
+&usb0 {
+ status = "okay";
+};
+
&aemif {
pinctrl-names = "default";
pinctrl-0 = <&nand_pins>;
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index f79e1b9..322a31a 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -372,6 +372,21 @@
>;
status = "disabled";
};
+ usb_phy: usb-phy {
+ compatible = "ti,da830-usb-phy";
+ #phy-cells = <1>;
+ status = "disabled";
+ };
+ usb0: usb@200000 {
+ compatible = "ti,da830-musb";
+ reg = <0x200000 0x10000>;
+ interrupts = <58>;
+ interrupt-names = "mc";
+ dr_mode = "otg";
+ phys = <&usb_phy 0>;
+ phy-names = "usb-phy";
+ status = "disabled";
+ };
gpio: gpio@226000 {
compatible = "ti,dm6441-gpio";
gpio-controller;
--
2.7.3
^ permalink raw reply related
* [PATCH v4 3/4] usb: musb: da8xx: Add DT support for the DA8xx driver
From: Alexandre Bailon @ 2016-11-03 15:59 UTC (permalink / raw)
To: khilman, robh+dt, b-liu
Cc: linux-kernel, linux-usb, devicetree, linux-arm-kernel, nsekhar,
Petr Kulhavy, Alexandre Bailon
In-Reply-To: <1478188752-22447-1-git-send-email-abailon@baylibre.com>
From: Petr Kulhavy <petr@barix.com>
This adds DT support for TI DA8xx/OMAP-L1x/AM17xx/AM18xx MUSB driver
Signed-off-by: Petr Kulhavy <petr@barix.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Tested-by: David Lechner <david@lechnology.com>
---
drivers/usb/musb/da8xx.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 210b7e4..51ae3b6 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -6,6 +6,9 @@
* Based on the DaVinci "glue layer" code.
* Copyright (C) 2005-2006 by Texas Instruments
*
+ * DT support
+ * Copyright (c) 2016 Petr Kulhavy <petr@barix.com>
+ *
* This file is part of the Inventra Controller Driver for Linux.
*
* The Inventra Controller Driver for Linux is free software; you
@@ -433,6 +436,21 @@ static int da8xx_musb_exit(struct musb *musb)
return 0;
}
+static inline u8 get_vbus_power(struct device *dev)
+{
+ struct regulator *vbus_supply;
+ int current_uA;
+
+ vbus_supply = regulator_get_optional(dev, "vbus");
+ if (IS_ERR(vbus_supply))
+ return 255;
+ current_uA = regulator_get_current_limit(vbus_supply);
+ regulator_put(vbus_supply);
+ if (current_uA <= 0 || current_uA > 510000)
+ return 255;
+ return current_uA / 1000 / 2;
+}
+
static const struct musb_platform_ops da8xx_ops = {
.quirks = MUSB_DMA_CPPI | MUSB_INDEXED_EP,
.init = da8xx_musb_init,
@@ -458,6 +476,12 @@ static const struct platform_device_info da8xx_dev_info = {
.dma_mask = DMA_BIT_MASK(32),
};
+static const struct musb_hdrc_config da8xx_config = {
+ .ram_bits = 10,
+ .num_eps = 5,
+ .multipoint = 1,
+};
+
static int da8xx_probe(struct platform_device *pdev)
{
struct resource musb_resources[2];
@@ -465,6 +489,7 @@ static int da8xx_probe(struct platform_device *pdev)
struct da8xx_glue *glue;
struct platform_device_info pinfo;
struct clk *clk;
+ struct device_node *np = pdev->dev.of_node;
int ret;
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
@@ -486,6 +511,16 @@ static int da8xx_probe(struct platform_device *pdev)
glue->dev = &pdev->dev;
glue->clk = clk;
+ if (IS_ENABLED(CONFIG_OF) && np) {
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->config = &da8xx_config;
+ pdata->mode = musb_get_mode(&pdev->dev);
+ pdata->power = get_vbus_power(&pdev->dev);
+ }
+
pdata->platform_ops = &da8xx_ops;
glue->usb_phy = usb_phy_generic_register();
@@ -536,11 +571,22 @@ static int da8xx_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id da8xx_id_table[] = {
+ {
+ .compatible = "ti,da830-musb",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, da8xx_id_table);
+#endif
+
static struct platform_driver da8xx_driver = {
.probe = da8xx_probe,
.remove = da8xx_remove,
.driver = {
.name = "musb-da8xx",
+ .of_match_table = of_match_ptr(da8xx_id_table),
},
};
--
2.7.3
^ permalink raw reply related
* [PATCH v4 2/4] usb: musb: core: added helper function for parsing DT
From: Alexandre Bailon @ 2016-11-03 15:59 UTC (permalink / raw)
To: khilman, robh+dt, b-liu
Cc: linux-kernel, linux-usb, devicetree, linux-arm-kernel, nsekhar,
Petr Kulhavy, Alexandre Bailon
In-Reply-To: <1478188752-22447-1-git-send-email-abailon@baylibre.com>
From: Petr Kulhavy <petr@barix.com>
This adds the function musb_get_mode() to get the DT property "dr_mode"
Signed-off-by: Petr Kulhavy <petr@barix.com>
Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Tested-by: David Lechner <david@lechnology.com>
Reviewed-by: Kevin Hilman <khilman@baylibre.com>
---
drivers/usb/musb/musb_core.c | 19 +++++++++++++++++++
drivers/usb/musb/musb_core.h | 6 ++++++
2 files changed, 25 insertions(+)
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 27dadc0..bba07e7 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -100,6 +100,7 @@
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/usb.h>
+#include <linux/usb/of.h>
#include "musb_core.h"
#include "musb_trace.h"
@@ -130,6 +131,24 @@ static inline struct musb *dev_to_musb(struct device *dev)
return dev_get_drvdata(dev);
}
+enum musb_mode musb_get_mode(struct device *dev)
+{
+ enum usb_dr_mode mode;
+
+ mode = usb_get_dr_mode(dev);
+ switch (mode) {
+ case USB_DR_MODE_HOST:
+ return MUSB_HOST;
+ case USB_DR_MODE_PERIPHERAL:
+ return MUSB_PERIPHERAL;
+ case USB_DR_MODE_OTG:
+ case USB_DR_MODE_UNKNOWN:
+ default:
+ return MUSB_OTG;
+ }
+}
+EXPORT_SYMBOL_GPL(musb_get_mode);
+
/*-------------------------------------------------------------------------*/
#ifndef CONFIG_BLACKFIN
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 2cb88a49..76f00f6 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -617,4 +617,10 @@ static inline void musb_platform_post_root_reset_end(struct musb *musb)
musb->ops->post_root_reset_end(musb);
}
+/*
+ * gets the "dr_mode" property from DT and converts it into musb_mode
+ * if the property is not found or not recognized returns MUSB_OTG
+ */
+extern enum musb_mode musb_get_mode(struct device *dev);
+
#endif /* __MUSB_CORE_H__ */
--
2.7.3
^ permalink raw reply related
* [PATCH v4 1/4] dt/bindings: Add binding for the DA8xx MUSB driver
From: Alexandre Bailon @ 2016-11-03 15:59 UTC (permalink / raw)
To: khilman, robh+dt, b-liu
Cc: linux-kernel, linux-usb, devicetree, linux-arm-kernel, nsekhar,
Petr Kulhavy, Alexandre Bailon
In-Reply-To: <1478188752-22447-1-git-send-email-abailon@baylibre.com>
From: Petr Kulhavy <petr@barix.com>
DT binding for the TI DA8xx/OMAP-L1x/AM17xx/AM18xx MUSB driver.
Signed-off-by: Petr Kulhavy <petr@barix.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Acked-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/usb/da8xx-usb.txt | 43 ++++++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 Documentation/devicetree/bindings/usb/da8xx-usb.txt
diff --git a/Documentation/devicetree/bindings/usb/da8xx-usb.txt b/Documentation/devicetree/bindings/usb/da8xx-usb.txt
new file mode 100644
index 0000000..ccb844a
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/da8xx-usb.txt
@@ -0,0 +1,43 @@
+TI DA8xx MUSB
+~~~~~~~~~~~~~
+For DA8xx/OMAP-L1x/AM17xx/AM18xx platforms.
+
+Required properties:
+~~~~~~~~~~~~~~~~~~~~
+ - compatible : Should be set to "ti,da830-musb".
+
+ - reg: Offset and length of the USB controller register set.
+
+ - interrupts: The USB interrupt number.
+
+ - interrupt-names: Should be set to "mc".
+
+ - dr_mode: The USB operation mode. Should be one of "host", "peripheral" or "otg".
+
+ - phys: Phandle for the PHY device
+
+ - phy-names: Should be "usb-phy"
+
+Optional properties:
+~~~~~~~~~~~~~~~~~~~~
+ - vbus-supply: Phandle to a regulator providing the USB bus power.
+
+Example:
+ usb_phy: usb-phy {
+ compatible = "ti,da830-usb-phy";
+ #phy-cells = <0>;
+ status = "okay";
+ };
+ usb0: usb@200000 {
+ compatible = "ti,da830-musb";
+ reg = <0x00200000 0x10000>;
+ interrupts = <58>;
+ interrupt-names = "mc";
+
+ dr_mode = "host";
+ vbus-supply = <&usb_vbus>;
+ phys = <&usb_phy 0>;
+ phy-names = "usb-phy";
+
+ status = "okay";
+ };
--
2.7.3
^ permalink raw reply related
* [PATCH v4 0/4] Add DT support for DA8xx
From: Alexandre Bailon @ 2016-11-03 15:59 UTC (permalink / raw)
To: khilman, robh+dt, b-liu
Cc: linux-kernel, linux-usb, devicetree, linux-arm-kernel, nsekhar,
Alexandre Bailon
Changes in v2:
* Remove unrelated changes in patch 3
* Rename the device node in patch 4
Changes in v3:
* Fix few mistakes in DT binding sample
* Only build the device table if DT is enabled
Change in v4:
* Fix a nit
Alexandre Bailon (1):
ARM: dts: da850: Add the usb otg device node
Petr Kulhavy (3):
dt/bindings: Add binding for the DA8xx MUSB driver
usb: musb: core: added helper function for parsing DT
usb: musb: da8xx: Add DT support for the DA8xx driver
.../devicetree/bindings/usb/da8xx-usb.txt | 43 ++++++++++++++++++++
arch/arm/boot/dts/da850-lcdk.dts | 8 ++++
arch/arm/boot/dts/da850.dtsi | 15 +++++++
drivers/usb/musb/da8xx.c | 46 ++++++++++++++++++++++
drivers/usb/musb/musb_core.c | 19 +++++++++
drivers/usb/musb/musb_core.h | 6 +++
6 files changed, 137 insertions(+)
create mode 100644 Documentation/devicetree/bindings/usb/da8xx-usb.txt
--
2.7.3
^ permalink raw reply
* Applied "spi: sun6i: Support Allwinner H3 SPI controller" to the spi tree
From: Mark Brown @ 2016-11-03 15:42 UTC (permalink / raw)
To: Milo Kim; +Cc: Maxime Ripard, Mark Brown
In-Reply-To: <20161028065412.23008-5-woogyom.kim@gmail.com>
The patch
spi: sun6i: Support Allwinner H3 SPI controller
has been applied to the spi tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 10565dfd35488c45826201b4ce28597d6b5de3dd Mon Sep 17 00:00:00 2001
From: Milo Kim <woogyom.kim@gmail.com>
Date: Fri, 28 Oct 2016 15:54:12 +0900
Subject: [PATCH] spi: sun6i: Support Allwinner H3 SPI controller
H3 has two SPI controllers. The size of the buffer is 64 * 8.
(8 bit transfer by 64 entry FIFO)
A31 has four controllers. The size of the buffer is 128 * 8.
(8 bit transfer by 128 entry FIFO)
Register maps are sharable, so sun6i SPI driver is reusable with
device configuration.
Use the variable, 'fifo_depth' instead of fixed value to support both SPI
controllers.
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/spi/spi-sun6i.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 9918a57a6a6e..e3114832c485 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
@@ -24,6 +25,7 @@
#include <linux/spi/spi.h>
#define SUN6I_FIFO_DEPTH 128
+#define SUN8I_FIFO_DEPTH 64
#define SUN6I_GBL_CTL_REG 0x04
#define SUN6I_GBL_CTL_BUS_ENABLE BIT(0)
@@ -90,6 +92,7 @@ struct sun6i_spi {
const u8 *tx_buf;
u8 *rx_buf;
int len;
+ unsigned long fifo_depth;
};
static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
@@ -155,7 +158,9 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
{
- return SUN6I_FIFO_DEPTH - 1;
+ struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
+
+ return sspi->fifo_depth - 1;
}
static int sun6i_spi_transfer_one(struct spi_master *master,
@@ -170,7 +175,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
u32 reg;
/* We don't support transfer larger than the FIFO */
- if (tfr->len > SUN6I_FIFO_DEPTH)
+ if (tfr->len > sspi->fifo_depth)
return -EINVAL;
reinit_completion(&sspi->done);
@@ -265,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
SUN6I_BURST_CTL_CNT_STC(tx_len));
/* Fill the TX FIFO */
- sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
+ sun6i_spi_fill_fifo(sspi, sspi->fifo_depth);
/* Enable the interrupts */
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
@@ -288,7 +293,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
goto out;
}
- sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+ sun6i_spi_drain_fifo(sspi, sspi->fifo_depth);
out:
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
@@ -398,6 +403,8 @@ static int sun6i_spi_probe(struct platform_device *pdev)
}
sspi->master = master;
+ sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev);
+
master->max_speed_hz = 100 * 1000 * 1000;
master->min_speed_hz = 3 * 1000;
master->set_cs = sun6i_spi_set_cs;
@@ -470,7 +477,8 @@ static int sun6i_spi_remove(struct platform_device *pdev)
}
static const struct of_device_id sun6i_spi_match[] = {
- { .compatible = "allwinner,sun6i-a31-spi", },
+ { .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH },
+ { .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH },
{}
};
MODULE_DEVICE_TABLE(of, sun6i_spi_match);
--
2.10.1
^ permalink raw reply related
* Re: [PATCH v2] of, numa: Return NUMA_NO_NODE from disable of_node_to_nid() if nid not possible.
From: David Daney @ 2016-11-03 15:11 UTC (permalink / raw)
To: Rob Herring, David Daney
Cc: devicetree@vger.kernel.org, Robert Richter, David Daney,
Catalin Marinas, Will Deacon, linux-kernel@vger.kernel.org,
Gilbert Netzer, Hanjun Guo, Ganapatrao Kulkarni, Frank Rowand,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <CAL_JsqKnXk99SUa1cjC2QFA9rizjn4=JHZh3ua_gvcOtpGx8jg@mail.gmail.com>
On 11/02/2016 08:37 PM, Rob Herring wrote:
> On Fri, Oct 28, 2016 at 4:15 PM, David Daney <ddaney.cavm@gmail.com> wrote:
>> From: David Daney <david.daney@cavium.com>
>>
>> On arm64 NUMA kernels we can pass "numa=off" on the command line to
>> disable NUMA. A side effect of this is that kmalloc_node() calls to
>> non-zero nodes will crash the system with an OOPS:
>>
>> [ 0.000000] ITS@0x0000901000020000: allocated 2097152 Devices @10002000000 (flat, esz 8, psz 64K, shr 1)
>> [ 0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00001680
>> [ 0.000000] pgd = fffffc0009470000
>> [ 0.000000] [00001680] *pgd=0000010ffff90003, *pud=0000010ffff90003, *pmd=0000010ffff90003, *pte=0000000000000000
>> [ 0.000000] Internal error: Oops: 96000006 [#1] SMP
>> .
>> .
>> .
>> [ 0.000000] [<fffffc00081c8950>] __alloc_pages_nodemask+0xa4/0xe68
>> [ 0.000000] [<fffffc000821fa70>] new_slab+0xd0/0x564
>> [ 0.000000] [<fffffc0008221e24>] ___slab_alloc+0x2e4/0x514
>> [ 0.000000] [<fffffc0008239498>] __slab_alloc+0x48/0x58
>> [ 0.000000] [<fffffc0008222c20>] __kmalloc_node+0xd0/0x2dc
>> [ 0.000000] [<fffffc0008115374>] __irq_domain_add+0x7c/0x164
>> [ 0.000000] [<fffffc0008b461dc>] its_probe+0x784/0x81c
>> [ 0.000000] [<fffffc0008b462bc>] its_init+0x48/0x1b0
>> [ 0.000000] [<fffffc0008b4543c>] gic_init_bases+0x228/0x360
>> [ 0.000000] [<fffffc0008b456bc>] gic_of_init+0x148/0x1cc
>> [ 0.000000] [<fffffc0008b5aec8>] of_irq_init+0x184/0x298
>> [ 0.000000] [<fffffc0008b43f9c>] irqchip_init+0x14/0x38
>> [ 0.000000] [<fffffc0008b12d60>] init_IRQ+0xc/0x30
>> [ 0.000000] [<fffffc0008b10a3c>] start_kernel+0x240/0x3b8
>> [ 0.000000] [<fffffc0008b101c4>] __primary_switched+0x30/0x6c
>> [ 0.000000] Code: 912ec2a0 b9403809 0a0902fb 37b007db (f9400300)
>> .
>> .
>> .
>>
>> This is caused by code like this in kernel/irq/irqdomain.c
>>
>> domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
>> GFP_KERNEL, of_node_to_nid(of_node));
>>
>> When NUMA is disabled, the concept of a node is really undefined, so
>> of_node_to_nid() should unconditionally return NUMA_NO_NODE.
>>
>> Fix by returning NUMA_NO_NODE when the nid is not in the set of
>> possible nodes.
>>
>> Reported-by: Gilbert Netzer <noname@pdc.kth.se>
>> Signed-off-by: David Daney <david.daney@cavium.com>
>
> Does this need to go in 4.9?
That would be my preference.
> stable? If so, since what kernel version?
>
v4.7 and later would be nice.
I guess if you merge it, you could add the Cc: stable@ tag
Thanks for looking at this,
David Daney
^ permalink raw reply
* Re: [PATCHv3 1/4] dt-bindings: mfd: Add Altera Arria10 SR Monitor
From: Lee Jones @ 2016-11-03 14:39 UTC (permalink / raw)
To: tthayer
Cc: robh+dt, mark.rutland, dinguyen, linux, arnd, gregkh, davem,
geert, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <1478097178-24341-2-git-send-email-tthayer@opensource.altera.com>
On Wed, 02 Nov 2016, tthayer@opensource.altera.com wrote:
> From: Thor Thayer <tthayer@opensource.altera.com>
>
> Add the Arria10 DevKit System Resource Chip register and state
> monitoring module to the MFD.
>
> Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
> ---
> Note: This needs to be applied to the bindings document that
> was Acked & Applied but didn't reach the for-next branch.
> See https://patchwork.ozlabs.org/patch/629397/
> ---
> v2 Change compatible string -mon to -monitor for clarity
> v3 Replace node name a10sr_monitor with just monitor.
> Replace node name a10sr_gpio with just gpio.
> ---
> Documentation/devicetree/bindings/mfd/altera-a10sr.txt | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
For my own reference:
Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>
> diff --git a/Documentation/devicetree/bindings/mfd/altera-a10sr.txt b/Documentation/devicetree/bindings/mfd/altera-a10sr.txt
> index ea151f2..69243d2 100644
> --- a/Documentation/devicetree/bindings/mfd/altera-a10sr.txt
> +++ b/Documentation/devicetree/bindings/mfd/altera-a10sr.txt
> @@ -17,7 +17,8 @@ The A10SR consists of these sub-devices:
>
> Device Description
> ------ ----------
> -a10sr_gpio GPIO Controller
> +gpio GPIO Controller
> +monitor Register and State Monitoring
>
> Arria10 GPIO
> Required Properties:
> @@ -27,6 +28,10 @@ Required Properties:
> the second cell is used to specify flags.
> See ../gpio/gpio.txt for more information.
>
> +Arria10 Register and State Monitor
> +Required Properties:
> +- compatible : Should be "altr,a10sr-monitor"
> +
> Example:
>
> resource-manager@0 {
> @@ -43,4 +48,8 @@ Example:
> gpio-controller;
> #gpio-cells = <2>;
> };
> +
> + monitor {
> + compatible = "altr,a10sr-monitor";
> + };
> };
--
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] of: base: Export symbol of __of_find_all_nodes()
From: Rob Herring @ 2016-11-03 14:16 UTC (permalink / raw)
To: Laxman Dewangan
Cc: Frank Rowand, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <581ACA0B.3010107-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
On Thu, Nov 3, 2016 at 12:24 AM, Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> wrote:
>
> On Thursday 03 November 2016 09:09 AM, Rob Herring wrote:
>>
>> On Fri, Oct 28, 2016 at 6:28 AM, Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>> wrote:
>>>
>>> The function __of_find_all_nodes() is used in the public header
>>> linux/of.h and if any driver developed using this API then
>>> it reports error as unknown symbol if compiled as module.
>>>
>>> Export this APIs using EXPORT_SYMBOL() so that it can be used
>>> from driver compiled as module.
>>
>> What driver needs this? This isn't really a function I'd expect drivers to
>> use.
>>
>
> I am using the for loop for each node using the macro
> for_each_of_allnodes_from() which is define as
>
> #define for_each_of_allnodes_from(from, dn) \
> for (dn = __of_find_all_nodes(from); dn; dn =
> __of_find_all_nodes(dn))
>
> and this is using the above APIs.
And then what driver is using this define?
Rob
--
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 V3 6/6] bus: Add support for Tegra Generic Memory Interface
From: Jon Hunter @ 2016-11-03 13:50 UTC (permalink / raw)
To: Mirza Krak
Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, pdeschrijver-DDmLM1+adcrQT0dZR+AlfA,
Prashant Gaikwad, Michael Turquette, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA, linux-kernel,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CALw8SCVu+-h_yhOa7uDuyFBPVvhwjD64S+-MDeYN8EZsGHpXyw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On 03/11/16 13:08, Mirza Krak wrote:
> 2016-11-03 11:51 GMT+01:00 Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>:
>>
>> On 27/10/16 15:01, Mirza Krak wrote:
>>>
>>> From: Mirza Krak <mirza.krak-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>>
>>> The Generic Memory Interface bus can be used to connect high-speed
>>> devices such as NOR flash, FPGAs, DSPs...
>>>
>>> Signed-off-by: Mirza Krak <mirza.krak-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>> Tested-by: Marcel Ziswiler <marcel.ziswiler-2KBjVHiyJgBBDgjK7y7TUQ@public.gmane.org>
>>> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
>>> ---
>>>
>>> Changes in v2:
>>> - Fixed some checkpatch errors
>>> - Re-ordered probe to get rid of local variables
>>> - Moved of_platform_default_populate call to the end of probe
>>> - Use the timing and configuration properties from the child device
>>> - Added warning if more then 1 child device exist
>>>
>>> Changes in v3:
>>> - added helper function to disable the controller which is used in remove
>>> and
>>> on error.
>>> - Added logic to parse CS# from "ranges" property with fallback to "reg"
>>> property
>>>
>>> drivers/bus/Kconfig | 8 ++
>>> drivers/bus/Makefile | 1 +
>>> drivers/bus/tegra-gmi.c | 267
>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 276 insertions(+)
>>> create mode 100644 drivers/bus/tegra-gmi.c
>>>
>>> diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
>>> index 4ed7d26..2e75a7f 100644
>>> --- a/drivers/bus/Kconfig
>>> +++ b/drivers/bus/Kconfig
>>> @@ -141,6 +141,14 @@ config TEGRA_ACONNECT
>>> Driver for the Tegra ACONNECT bus which is used to interface
>>> with
>>> the devices inside the Audio Processing Engine (APE) for
>>> Tegra210.
>>>
>>> +config TEGRA_GMI
>>> + tristate "Tegra Generic Memory Interface bus driver"
>>> + depends on ARCH_TEGRA
>>> + help
>>> + Driver for the Tegra Generic Memory Interface bus which can be
>>> used
>>> + to attach devices such as NOR, UART, FPGA and more.
>>> +
>>> +
>>
>>
>> Nit-pick ... only one additional line above is needed to be consistent with
>> the rest of the file.
>
> Will fix that.
>
>>
>>
>>> config UNIPHIER_SYSTEM_BUS
>>> tristate "UniPhier System Bus driver"
>>> depends on ARCH_UNIPHIER && OF
>>> diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
>>> index ac84cc4..34e2bab 100644
>>> --- a/drivers/bus/Makefile
>>> +++ b/drivers/bus/Makefile
>>> @@ -18,5 +18,6 @@ obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
>>> obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
>>> obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
>>> obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
>>> +obj-$(CONFIG_TEGRA_GMI) += tegra-gmi.o
>>> obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
>>> obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
>>> diff --git a/drivers/bus/tegra-gmi.c b/drivers/bus/tegra-gmi.c
>>> new file mode 100644
>>> index 0000000..dd9623e
>>> --- /dev/null
>>> +++ b/drivers/bus/tegra-gmi.c
>>> @@ -0,0 +1,267 @@
>>> +/*
>>> + * Driver for NVIDIA Generic Memory Interface
>>> + *
>>> + * Copyright (C) 2016 Host Mobility AB. All rights reserved.
>>> + *
>>> + * This file is licensed under the terms of the GNU General Public
>>> + * License version 2. This program is licensed "as is" without any
>>> + * warranty of any kind, whether express or implied.
>>> + */
>>> +#include <linux/clk.h>
>>> +#include <linux/delay.h>
>>> +#include <linux/io.h>
>>> +#include <linux/module.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/reset.h>
>>> +
>>> +#define TEGRA_GMI_CONFIG 0x00
>>> +#define TEGRA_GMI_CONFIG_GO BIT(31)
>>> +#define TEGRA_GMI_BUS_WIDTH_32BIT BIT(30)
>>> +#define TEGRA_GMI_MUX_MODE BIT(28)
>>> +#define TEGRA_GMI_RDY_BEFORE_DATA BIT(24)
>>> +#define TEGRA_GMI_RDY_ACTIVE_HIGH BIT(23)
>>> +#define TEGRA_GMI_ADV_ACTIVE_HIGH BIT(22)
>>> +#define TEGRA_GMI_OE_ACTIVE_HIGH BIT(21)
>>> +#define TEGRA_GMI_CS_ACTIVE_HIGH BIT(20)
>>> +#define TEGRA_GMI_CS_SELECT(x) ((x & 0x7) << 4)
>>> +
>>> +#define TEGRA_GMI_TIMING0 0x10
>>> +#define TEGRA_GMI_MUXED_WIDTH(x) ((x & 0xf) << 12)
>>> +#define TEGRA_GMI_HOLD_WIDTH(x) ((x & 0xf) << 8)
>>> +#define TEGRA_GMI_ADV_WIDTH(x) ((x & 0xf) << 4)
>>> +#define TEGRA_GMI_CE_WIDTH(x) (x & 0xf)
>>> +
>>> +#define TEGRA_GMI_TIMING1 0x14
>>> +#define TEGRA_GMI_WE_WIDTH(x) ((x & 0xff) << 16)
>>> +#define TEGRA_GMI_OE_WIDTH(x) ((x & 0xff) << 8)
>>> +#define TEGRA_GMI_WAIT_WIDTH(x) (x & 0xff)
>>> +
>>> +struct tegra_gmi_priv {
>>> + void __iomem *base;
>>> + struct reset_control *rst;
>>> + struct clk *clk;
>>> +
>>> + u32 snor_config;
>>> + u32 snor_timing0;
>>> + u32 snor_timing1;
>>> +};
>>> +
>>> +static void tegra_gmi_disable(struct tegra_gmi_priv *priv)
>>> +{
>>> + u32 config;
>>> +
>>> + /* stop GMI operation */
>>> + config = readl(priv->base + TEGRA_GMI_CONFIG);
>>> + config &= ~TEGRA_GMI_CONFIG_GO;
>>> + writel(config, priv->base + TEGRA_GMI_CONFIG);
>>> +
>>> + reset_control_assert(priv->rst);
>>> + clk_disable_unprepare(priv->clk);
>>> +}
>>> +
>>> +static void tegra_gmi_init(struct device *dev, struct tegra_gmi_priv
>>> *priv)
>>> +{
>>> + writel(priv->snor_timing0, priv->base + TEGRA_GMI_TIMING0);
>>> + writel(priv->snor_timing1, priv->base + TEGRA_GMI_TIMING1);
>>> +
>>> + priv->snor_config |= TEGRA_GMI_CONFIG_GO;
>>> + writel(priv->snor_config, priv->base + TEGRA_GMI_CONFIG);
>>> +}
>>> +
>>> +static int tegra_gmi_parse_dt(struct device *dev, struct tegra_gmi_priv
>>> *priv)
>>> +{
>>> + struct device_node *child =
>>> of_get_next_available_child(dev->of_node,
>>> + NULL);
>>> + u32 property, ranges[4];
>>> + int ret;
>>> +
>>> + if (!child) {
>>> + dev_warn(dev, "no child nodes found\n");
>>> + return 0;
>>
>>
>> Don't we want to return an error here? Otherwise, we will call
>> tegra_gmi_init() with an invalid configuration.
>
> True, we probably want that. My thought was that we might accept a
> tegra-gmi node without any child nodes and just print a warning. But
> since it is the child node that holds the bus configuration it makes
> sense to fail probe due to no child nodes.
I was wondering that too, but given that we then program and enable the
GMI I think it is best to just fail for now.
>>
>>
>>> + }
>>> +
>>> + /*
>>> + * We currently only support one child device due to lack of
>>> + * chip-select address decoding. Which means that we only have one
>>> + * chip-select line from the GMI controller.
>>> + */
>>> + if (of_get_child_count(dev->of_node) > 1)
>>> + dev_warn(dev, "only one child device is supported.");
>>> +
>>> + if (of_property_read_bool(child, "nvidia,snor-data-width-32bit"))
>>> + priv->snor_config |= TEGRA_GMI_BUS_WIDTH_32BIT;
>>> +
>>> + if (of_property_read_bool(child, "nvidia,snor-mux-mode"))
>>> + priv->snor_config |= TEGRA_GMI_MUX_MODE;
>>> +
>>> + if (of_property_read_bool(child,
>>> "nvidia,snor-rdy-active-before-data"))
>>> + priv->snor_config |= TEGRA_GMI_RDY_BEFORE_DATA;
>>> +
>>> + if (of_property_read_bool(child, "nvidia,snor-rdy-inv"))
>>> + priv->snor_config |= TEGRA_GMI_RDY_ACTIVE_HIGH;
>>> +
>>> + if (of_property_read_bool(child, "nvidia,snor-adv-inv"))
>>> + priv->snor_config |= TEGRA_GMI_ADV_ACTIVE_HIGH;
>>> +
>>> + if (of_property_read_bool(child, "nvidia,snor-oe-inv"))
>>> + priv->snor_config |= TEGRA_GMI_OE_ACTIVE_HIGH;
>>> +
>>> + if (of_property_read_bool(child, "nvidia,snor-cs-inv"))
>>> + priv->snor_config |= TEGRA_GMI_CS_ACTIVE_HIGH;
>>> +
>>> + /* Decode the CS# */
>>> + ret = of_property_read_u32_array(child, "ranges", ranges, 4);
>>> + if (ret < 0) {
>>> + /* Invalid binding */
>>> + if (ret == -EOVERFLOW) {
>>> + dev_err(dev, "invalid ranges length\n");
>>> + goto error_cs_decode;
>>> + }
>>> +
>>> + /*
>>> + * If we reach here it means that the child node has an
>>> empty
>>> + * ranges or it does not exist at all. Attempt to decode
>>> the
>>> + * CS# from the reg property instead.
>>> + */
>>> + ret = of_property_read_u32(child, "reg", &property);
>>> + if (ret < 0) {
>>> + dev_err(dev, "no reg property found\n");
>>> + goto error_cs_decode;
>>> + }
>>> + } else {
>>> + property = ranges[1];
>>> + }
>>> +
>>> + priv->snor_config |= TEGRA_GMI_CS_SELECT(property);
>>
>>
>> Should we make sure the CS is a valid value before setting?
>
> The TEGRA_GMI_CS_SELECT(x) macro will truncate any erroneous CS value.
> But yeah we could do a sanity check instead and return an error if it
> is invalid.
>
>>
>>
>>> +
>>> + /* The default values that are provided below are reset values */
>>> + if (!of_property_read_u32(child, "nvidia,snor-muxed-width",
>>> &property))
>>> + priv->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(property);
>>> + else
>>> + priv->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(1);
>>> +
>>> + if (!of_property_read_u32(child, "nvidia,snor-hold-width",
>>> &property))
>>> + priv->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(property);
>>> + else
>>> + priv->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(1);
>>> +
>>> + if (!of_property_read_u32(child, "nvidia,snor-adv-width",
>>> &property))
>>> + priv->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(property);
>>> + else
>>> + priv->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(1);
>>> +
>>> + if (!of_property_read_u32(child, "nvidia,snor-ce-width",
>>> &property))
>>> + priv->snor_timing0 |= TEGRA_GMI_CE_WIDTH(property);
>>> + else
>>> + priv->snor_timing0 |= TEGRA_GMI_CE_WIDTH(4);
>>> +
>>> + if (!of_property_read_u32(child, "nvidia,snor-we-width",
>>> &property))
>>> + priv->snor_timing1 |= TEGRA_GMI_WE_WIDTH(property);
>>> + else
>>> + priv->snor_timing1 |= TEGRA_GMI_WE_WIDTH(1);
>>> +
>>> + if (!of_property_read_u32(child, "nvidia,snor-oe-width",
>>> &property))
>>> + priv->snor_timing1 |= TEGRA_GMI_OE_WIDTH(property);
>>> + else
>>> + priv->snor_timing1 |= TEGRA_GMI_OE_WIDTH(1);
>>> +
>>> + if (!of_property_read_u32(child, "nvidia,snor-wait-width",
>>> &property))
>>> + priv->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(property);
>>> + else
>>> + priv->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(3);
>>> +
>>> +error_cs_decode:
>>> + if (ret < 0)
>>> + dev_err(dev, "failed to decode chip-select number\n");
>>
>>
>> Nit do we need another error message here? Can we add the "failed to decode
>> CS" part the earlier message?
>
> Does it make sense to drop the two earlier messages instead and keep this one?
I think it is nice to have specific errors so we know where it failed.
You could just drop the above and when you add the test for making sure
the CS is valid add another error message for that. Not a big deal
either way. So I will leave to you to decide.
Cheers
Jon
--
nvpublic
^ permalink raw reply
* Re: [PATCH V3 2/6] clk: tegra: add TEGRA30_CLK_NOR to init table
From: Jon Hunter @ 2016-11-03 13:45 UTC (permalink / raw)
To: Mirza Krak, swarren, thierry.reding
Cc: gnurou, linux, pdeschrijver, pgaikwad, mturquette, sboyd, robh+dt,
mark.rutland, devicetree, linux-tegra, linux-kernel,
linux-arm-kernel, linux-clk
In-Reply-To: <1477576872-2665-3-git-send-email-mirza.krak@gmail.com>
On 27/10/16 15:01, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak@gmail.com>
>
> Add TEGRA30_CLK_NOR to init table and set default rate to 127 MHz which
> is max rate.
>
> The maximum rate value of 127 MHz is pulled from the downstream L4T
> kernel.
>
> Signed-off-by: Mirza Krak <mirza.krak@gmail.com>
> Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
Acked-by: Jon Hunter <jonathanh@nvidia.com>
Cheers
Jon
--
nvpublic
^ permalink raw reply
* Re: [PATCH V3 1/6] clk: tegra: add TEGRA20_CLK_NOR to init table
From: Jon Hunter @ 2016-11-03 13:45 UTC (permalink / raw)
To: Mirza Krak, swarren-3lzwWm7+Weoh9ZMKESR00Q,
thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: gnurou-Re5JQEeQqe8AvxtiuMwx3w, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
pdeschrijver-DDmLM1+adcrQT0dZR+AlfA,
pgaikwad-DDmLM1+adcrQT0dZR+AlfA,
mturquette-rdvid1DuHRBWk0Htik3J/w, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1477576872-2665-2-git-send-email-mirza.krak-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On 27/10/16 15:01, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> Add TEGRA20_CLK_NOR to init table and set default rate to 92 MHz which
> is max rate.
>
> The maximum rate value of 92 MHz is pulled from the downstream L4T
> kernel.
>
> Signed-off-by: Mirza Krak <mirza.krak-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Tested-by: Marcel Ziswiler <marcel.ziswiler-2KBjVHiyJgBBDgjK7y7TUQ@public.gmane.org>
> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
Acked-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Cheers
Jon
--
nvpublic
^ 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