* [PATCH v5 4/5] ARM: multi_v7: enable VGA bridge
From: Maxime Ripard @ 2016-09-30 14:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160930143709.1388-1-maxime.ripard@free-electrons.com>
Enable the RGB to VGA bridge driver in the defconfig
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/configs/multi_v7_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 2c8665cd9dc5..22ef41afc658 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -567,6 +567,7 @@ CONFIG_DRM=y
CONFIG_DRM_I2C_ADV7511=m
# CONFIG_DRM_I2C_CH7006 is not set
# CONFIG_DRM_I2C_SIL164 is not set
+CONFIG_DRM_RGB_TO_VGA=m
CONFIG_DRM_NXP_PTN3460=m
CONFIG_DRM_PARADE_PS8622=m
CONFIG_DRM_NOUVEAU=m
--
2.9.3
^ permalink raw reply related
* [PATCH v5 3/5] ARM: sun5i: a13-olinuxino: Enable VGA bridge
From: Maxime Ripard @ 2016-09-30 14:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160930143709.1388-1-maxime.ripard@free-electrons.com>
Now that we have support for the VGA bridges using our DRM driver, enable
the display engine for the Olimex A13-Olinuxino.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 54 +++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
index b3c234c65ea1..01ce7ea9032d 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
@@ -72,6 +72,47 @@
default-state = "on";
};
};
+
+ bridge {
+ compatible = "rgb-to-vga-bridge";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port at 0 {
+ reg = <0>;
+
+ vga_bridge_in: endpoint {
+ remote-endpoint = <&tcon0_out_vga>;
+ };
+ };
+
+ port at 1 {
+ reg = <1>;
+
+ vga_bridge_out: endpoint {
+ remote-endpoint = <&vga_con_in>;
+ };
+ };
+ };
+ };
+
+ vga {
+ compatible = "vga-connector";
+
+ port {
+ vga_con_in: endpoint {
+ remote-endpoint = <&vga_bridge_out>;
+ };
+ };
+ };
+};
+
+&be0 {
+ status = "okay";
};
&ehci0 {
@@ -211,6 +252,19 @@
status = "okay";
};
+&tcon0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_rgb666_pins>;
+ status = "okay";
+};
+
+&tcon0_out {
+ tcon0_out_vga: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&vga_bridge_in>;
+ };
+};
+
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins_b>;
--
2.9.3
^ permalink raw reply related
* [PATCH v5 2/5] drm/bridge: Add RGB to VGA bridge support
From: Maxime Ripard @ 2016-09-30 14:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160930143709.1388-1-maxime.ripard@free-electrons.com>
Some boards have an entirely passive RGB to VGA bridge, based on either
DACs or resistor ladders.
Those might or might not have an i2c bus routed to the VGA connector in
order to access the screen EDIDs.
Add a bridge that doesn't do anything but expose the modes available on the
screen, either based on the EDIDs if available, or based on the XGA
standards.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
.../bindings/display/bridge/rgb-to-vga-bridge.txt | 48 +++++
drivers/gpu/drm/bridge/Kconfig | 7 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/rgb-to-vga.c | 229 +++++++++++++++++++++
4 files changed, 285 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
create mode 100644 drivers/gpu/drm/bridge/rgb-to-vga.c
diff --git a/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
new file mode 100644
index 000000000000..a8375bc1f9cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
@@ -0,0 +1,48 @@
+Dumb RGB to VGA bridge
+----------------------
+
+This binding is aimed for dumb RGB to VGA bridges that do not require
+any configuration.
+
+Required properties:
+
+- compatible: Must be "rgb-to-vga-bridge"
+
+Required nodes:
+
+This device has two video ports. Their connections are modeled using the OF
+graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+- Video port 0 for RGB input
+- Video port 1 for VGA output
+
+
+Example
+-------
+
+bridge {
+ compatible = "rgb-to-vga-bridge";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port at 0 {
+ reg = <0>;
+
+ vga_bridge_in: endpoint {
+ remote-endpoint = <&tcon0_out_vga>;
+ };
+ };
+
+ port at 1 {
+ reg = <1>;
+
+ vga_bridge_out: endpoint {
+ remote-endpoint = <&vga_con_in>;
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index b590e678052d..d690398c541c 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -17,6 +17,13 @@ config DRM_ANALOGIX_ANX78XX
the HDMI output of an application processor to MyDP
or DisplayPort.
+config DRM_RGB_TO_VGA
+ tristate "Dumb RGB to VGA Bridge support"
+ depends on OF
+ select DRM_KMS_HELPER
+ help
+ Support for passive RGB to VGA bridges
+
config DRM_DW_HDMI
tristate
select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index efdb07e878f5..3bb8cbe09fe9 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,6 +1,7 @@
ccflags-y := -Iinclude/drm
obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
+obj-$(CONFIG_DRM_RGB_TO_VGA) += rgb-to-vga.o
obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
diff --git a/drivers/gpu/drm/bridge/rgb-to-vga.c b/drivers/gpu/drm/bridge/rgb-to-vga.c
new file mode 100644
index 000000000000..5ff4d4f3598f
--- /dev/null
+++ b/drivers/gpu/drm/bridge/rgb-to-vga.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2015-2016 Free Electrons
+ * Copyright (C) 2015-2016 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#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 dumb_vga {
+ struct drm_bridge bridge;
+ struct drm_connector connector;
+
+ struct i2c_adapter *ddc;
+};
+
+static inline struct dumb_vga *
+drm_bridge_to_dumb_vga(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct dumb_vga, bridge);
+}
+
+static inline struct dumb_vga *
+drm_connector_to_dumb_vga(struct drm_connector *connector)
+{
+ return container_of(connector, struct dumb_vga, connector);
+}
+
+static int dumb_vga_get_modes(struct drm_connector *connector)
+{
+ struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+ struct edid *edid;
+ int ret;
+
+ if (IS_ERR(vga->ddc))
+ goto fallback;
+
+ edid = drm_get_edid(connector, vga->ddc);
+ if (!edid) {
+ DRM_INFO("EDID readout failed, falling back to standard modes\n");
+ goto fallback;
+ }
+
+ drm_mode_connector_update_edid_property(connector, edid);
+ return drm_add_edid_modes(connector, edid);
+
+fallback:
+ /*
+ * In case we cannot retrieve the EDIDs (broken or missing i2c
+ * bus), fallback on the XGA standards
+ */
+ ret = drm_add_modes_noedid(connector, 1920, 1200);
+
+ /* And prefer a mode pretty much anyone can handle */
+ drm_set_preferred_mode(connector, 1024, 768);
+
+ return ret;
+}
+
+static const struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
+ .get_modes = dumb_vga_get_modes,
+};
+
+static enum drm_connector_status
+dumb_vga_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+
+ /*
+ * Even if we have an I2C bus, we can't assume that the cable
+ * is disconnected if drm_probe_ddc fails. Some cables don't
+ * wire the DDC pins, or the I2C bus might not be working at
+ * all.
+ */
+ if (!IS_ERR(vga->ddc) && drm_probe_ddc(vga->ddc))
+ return connector_status_connected;
+
+ return connector_status_unknown;
+}
+
+static void
+dumb_vga_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs dumb_vga_con_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = dumb_vga_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = dumb_vga_connector_destroy,
+ .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 dumb_vga_attach(struct drm_bridge *bridge)
+{
+ struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+ int ret;
+
+ if (!bridge->encoder) {
+ DRM_ERROR("Missing encoder\n");
+ return -ENODEV;
+ }
+
+ drm_connector_helper_add(&vga->connector,
+ &dumb_vga_con_helper_funcs);
+ ret = drm_connector_init(bridge->dev, &vga->connector,
+ &dumb_vga_con_funcs, DRM_MODE_CONNECTOR_VGA);
+ if (ret) {
+ DRM_ERROR("Failed to initialize connector\n");
+ return ret;
+ }
+
+ drm_mode_connector_attach_encoder(&vga->connector,
+ bridge->encoder);
+
+ return 0;
+}
+
+static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
+ .attach = dumb_vga_attach,
+};
+
+static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
+{
+ struct device_node *end_node, *phandle, *remote;
+ struct i2c_adapter *ddc;
+
+ end_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
+ if (!end_node) {
+ dev_err(dev, "Missing connector endpoint\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ remote = of_graph_get_remote_port_parent(end_node);
+ of_node_put(end_node);
+ if (!remote) {
+ dev_err(dev, "Enable to parse remote node\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0);
+ of_node_put(remote);
+ if (!phandle)
+ return ERR_PTR(-ENODEV);
+
+ ddc = of_get_i2c_adapter_by_node(phandle);
+ of_node_put(phandle);
+ if (!ddc)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ return ddc;
+}
+
+static int dumb_vga_probe(struct platform_device *pdev)
+{
+ struct dumb_vga *vga;
+ int ret;
+
+ vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL);
+ if (!vga)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, vga);
+
+ vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
+ if (IS_ERR(vga->ddc)) {
+ if (PTR_ERR(vga->ddc) == -ENODEV) {
+ dev_info(&pdev->dev,
+ "No i2c bus specified... Disabling EDID readout\n");
+ } else {
+ dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n");
+ return PTR_ERR(vga->ddc);
+ }
+ }
+
+ vga->bridge.funcs = &dumb_vga_bridge_funcs;
+ vga->bridge.of_node = pdev->dev.of_node;
+
+ ret = drm_bridge_add(&vga->bridge);
+ if (ret && !IS_ERR(vga->ddc))
+ i2c_put_adapter(vga->ddc);
+
+ return ret;
+}
+
+static int dumb_vga_remove(struct platform_device *pdev)
+{
+ struct dumb_vga *vga = platform_get_drvdata(pdev);
+
+ drm_bridge_remove(&vga->bridge);
+
+ if (!IS_ERR(vga->ddc))
+ i2c_put_adapter(vga->ddc);
+
+ return 0;
+}
+
+static const struct of_device_id dumb_vga_match[] = {
+ { .compatible = "rgb-to-vga-bridge" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, dumb_vga_match);
+
+struct platform_driver dumb_vga_driver = {
+ .probe = dumb_vga_probe,
+ .remove = dumb_vga_remove,
+ .driver = {
+ .name = "rgb-to-vga-bridge",
+ .of_match_table = dumb_vga_match,
+ },
+};
+module_platform_driver(dumb_vga_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Dumb RGB to VGA bridge driver");
+MODULE_LICENSE("GPL");
--
2.9.3
^ permalink raw reply related
* [PATCH v5 1/5] drm/sun4i: rgb: Remove the bridge enable/disable functions
From: Maxime Ripard @ 2016-09-30 14:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160930143709.1388-1-maxime.ripard@free-electrons.com>
The atomic helpers already call the drm_bridge_enable on our behalf,
there's no need to do it a second time.
Reported-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/gpu/drm/sun4i/sun4i_rgb.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 4e4bea6f395c..d198ad7e5323 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -155,9 +155,6 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
if (!IS_ERR(tcon->panel))
drm_panel_prepare(tcon->panel);
- /* encoder->bridge can be NULL; drm_bridge_enable checks for it */
- drm_bridge_enable(encoder->bridge);
-
sun4i_tcon_channel_enable(tcon, 0);
if (!IS_ERR(tcon->panel))
@@ -177,9 +174,6 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
sun4i_tcon_channel_disable(tcon, 0);
- /* encoder->bridge can be NULL; drm_bridge_disable checks for it */
- drm_bridge_disable(encoder->bridge);
-
if (!IS_ERR(tcon->panel))
drm_panel_unprepare(tcon->panel);
}
--
2.9.3
^ permalink raw reply related
* No subject
From: Maxime Ripard @ 2016-09-30 14:37 UTC (permalink / raw)
To: linux-arm-kernel
Subject: [PATCH v5 0/5] drm: Add Support for Passive RGB to VGA bridges
Hi,
This serie is about adding support for the RGB to VGA bridge found in
the A13-Olinuxino and the CHIP VGA adapter.
Both these boards rely on an entirely passive bridge made out of
resitor ladders that do not require any initialisation. The only thing
needed is to get the timings from the screen if available (and if not,
fall back on XGA standards), set up the display pipeline to output on
the RGB bus with the proper timings, and you're done.
This serie also fixes a bunch of bugs uncovered when trying to
increase the resolution, and hence the pixel clock, of our
pipeline. It also fixes a few bugs in the DRM driver itself that went
unnoticed before.
Let me know what you think,
Maxime
Changes from v4:
- Removed unused functions
Changes from v3:
- Depends on OF in Kconfig
- Fixed typos in the driver comments
- Removed the mention of a "passive" bridge in the bindings doc
- Made the strcuture const
- Removed the nops and best_encoders implementations
- Removed the call to drm_bridge_enable in the sun4i driver
Changes from v2:
- Changed the compatible as suggested
- Rebased on top 4.8
Changes from v1:
- Switch to using a vga-connector
- Use drm_encoder bridge pointer instead of doing our own
- Report the connector status as unknown instead of connected by
default, and as connected only if we can retrieve the EDID.
- Switch to of_i2c_get_adapter by node, and put the reference when done
- Rebased on linux-next
Maxime Ripard (5):
drm/sun4i: rgb: Remove the bridge enable/disable functions
drm/bridge: Add RGB to VGA bridge support
ARM: sun5i: a13-olinuxino: Enable VGA bridge
ARM: multi_v7: enable VGA bridge
ARM: sunxi: Enable VGA bridge
.../bindings/display/bridge/rgb-to-vga-bridge.txt | 48 +++++
arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 54 +++++
arch/arm/configs/multi_v7_defconfig | 1 +
arch/arm/configs/sunxi_defconfig | 1 +
drivers/gpu/drm/bridge/Kconfig | 7 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/rgb-to-vga.c | 229 +++++++++++++++++++++
drivers/gpu/drm/sun4i/sun4i_rgb.c | 6 -
8 files changed, 341 insertions(+), 6 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
create mode 100644 drivers/gpu/drm/bridge/rgb-to-vga.c
--
2.9.3
^ permalink raw reply
* [PATCH] drm/sun4i: Check that the plane coordinates are not negative
From: Maxime Ripard @ 2016-09-30 14:33 UTC (permalink / raw)
To: linux-arm-kernel
Our planes cannot be set at negative coordinates. Make sure we reject such
configuration.
Reported-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/gpu/drm/sun4i/sun4i_layer.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index f0035bf5efea..f5463c4c2cde 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -29,6 +29,9 @@ struct sun4i_plane_desc {
static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
+ if ((state->crtc_x < 0) || (state->crtc_y < 0))
+ return -EINVAL;
+
return 0;
}
--
2.9.3
^ permalink raw reply related
* [PATCH 6/6] ARM: dts: stm32f429: Add QSPI clock
From: gabriel.fernandez at st.com @ 2016-09-30 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475245509-6487-1-git-send-email-gabriel.fernandez@st.com>
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 cb55ac8..80aecc0 100644
--- a/arch/arm/boot/dts/stm32f469-disco.dts
+++ b/arch/arm/boot/dts/stm32f469-disco.dts
@@ -66,6 +66,10 @@
};
};
+&rcc {
+ compatible = "st,stm32f46xx-rcc", "st,stm32-rcc";
+};
+
&clk_hse {
clock-frequency = <8000000>;
};
--
1.9.1
^ permalink raw reply related
* [PATCH 5/6] clk: stm32f469: Add QSPI clock
From: gabriel.fernandez at st.com @ 2016-09-30 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475245509-6487-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch adds the QSPI clock for stm32f469 discovery board.
The gate mapping is a little bit different from stm32f429 soc.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
.../devicetree/bindings/clock/st,stm32-rcc.txt | 4 +-
drivers/clk/clk-stm32f4.c | 173 ++++++++++++++++++---
2 files changed, 158 insertions(+), 19 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
index fee3205..eace3de 100644
--- a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
+++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
@@ -8,7 +8,9 @@ Please also refer to clock-bindings.txt in this directory for common clock
controller binding usage.
Required properties:
-- compatible: Should be "st,stm32f42xx-rcc"
+- compatible: Should be:
+ "st,stm32f42xx-rcc"
+ "st,stm32f46xx-rcc"
- reg: should be register base and length as documented in the
datasheet
- #clock-cells: 2, device nodes should specify the clock in their "clocks"
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 6e26d39..bc75d83 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -54,7 +54,7 @@ struct stm32f4_rgate_data {
unsigned long flags;
};
-static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
+static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
{ STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
@@ -134,23 +134,109 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
};
+static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
+ { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 20, "ccmdatam", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
+
+ { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
+ { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
+
+ { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
+ CLK_IGNORE_UNUSED },
+ { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
+ CLK_IGNORE_UNUSED },
+
+ { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 17, "uart2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 18, "uart3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 19, "uart4", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 20, "uart5", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 21, "i2c1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 22, "i2c2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 23, "i2c3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 30, "uart7", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 31, "uart8", "apb1_div" },
+
+ { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 4, "usart1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 5, "usart6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 11, "sdio", "pll48" },
+ { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
+};
+
enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK };
-/*
- * MAX_CLKS is the maximum value in the enumeration below plus the combined
- * hweight of stm32f42xx_gate_map (plus one).
- */
-#define MAX_CLKS (71 + END_PRIMARY_CLK + 1)
/*
* This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
* have gate bits associated with them. Its combined hweight is 71.
*/
-static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull,
- 0x0000000000000001ull,
- 0x04777f33f6fec9ffull };
+#define MAX_GATE_MAP 3
+
+static const u64 stm32f42xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+ 0x0000000000000001ull,
+ 0x04777f33f6fec9ffull };
+
+static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+ 0x0000000000000003ull,
+ 0x0c777f33f6fec9ffull };
+
+const u64 *stm32f4_gate_map;
+
+static struct clk_hw **clks;
-static struct clk_hw *clks[MAX_CLKS];
static DEFINE_SPINLOCK(stm32f4_clk_lock);
static void __iomem *base;
@@ -270,7 +356,7 @@ static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
*/
static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
{
- u64 table[ARRAY_SIZE(stm32f42xx_gate_map)];
+ u64 table[MAX_GATE_MAP];
if (primary == 1) {
if (WARN_ON(secondary >= END_PRIMARY_CLK))
@@ -278,7 +364,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
return secondary;
}
- memcpy(table, stm32f42xx_gate_map, sizeof(table));
+ memcpy(table, stm32f4_gate_map, sizeof(table));
/* only bits set in table can be used as indices */
if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
@@ -540,10 +626,42 @@ static const struct clk_div_table apb_div_table[] = {
{ 0 },
};
+struct stm32f4_clk_data {
+ const struct stm32f4_gate_data *gates_data;
+ const u64 *gates_map;
+ int gates_num;
+};
+
+static const struct stm32f4_clk_data stm32f429_clk_data = {
+ .gates_data = stm32f429_gates,
+ .gates_map = stm32f42xx_gate_map,
+ .gates_num = ARRAY_SIZE(stm32f429_gates),
+};
+
+static const struct stm32f4_clk_data stm32f469_clk_data = {
+ .gates_data = stm32f469_gates,
+ .gates_map = stm32f46xx_gate_map,
+ .gates_num = ARRAY_SIZE(stm32f469_gates),
+};
+
+static const struct of_device_id stm32f4_of_match[] = {
+ {
+ .compatible = "st,stm32f42xx-rcc",
+ .data = &stm32f429_clk_data
+ },
+ {
+ .compatible = "st,stm32f46xx-rcc",
+ .data = &stm32f469_clk_data
+ },
+ {}
+};
+
static void __init stm32f4_rcc_init(struct device_node *np)
{
const char *hse_clk;
int n;
+ const struct of_device_id *match;
+ const struct stm32f4_clk_data *data;
base = of_iomap(np, 0);
if (!base) {
@@ -557,6 +675,19 @@ static void __init stm32f4_rcc_init(struct device_node *np)
goto fail;
}
+ match = of_match_node(stm32f4_of_match, np);
+ if (WARN_ON(!match))
+ return;
+
+ data = match->data;
+
+ clks = kmalloc_array(data->gates_num + END_PRIMARY_CLK,
+ sizeof(struct clk_hw *), GFP_KERNEL);
+ if (!clks)
+ goto fail;
+
+ stm32f4_gate_map = data->gates_map;
+
hse_clk = of_clk_get_parent_name(np, 0);
clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
@@ -589,11 +720,15 @@ static void __init stm32f4_rcc_init(struct device_node *np)
clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div",
0, 1, 1);
- for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) {
- const struct stm32f4_gate_data *gd = &stm32f4_gates[n];
- unsigned int secondary =
- 8 * (gd->offset - STM32F4_RCC_AHB1ENR) + gd->bit_idx;
- int idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
+ for (n = 0; n < data->gates_num; n++) {
+ const struct stm32f4_gate_data *gd;
+ unsigned int secondary;
+ int idx;
+
+ gd = (struct stm32f4_gate_data *) &data->gates_data[n];
+ secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) +
+ gd->bit_idx;
+ idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
if (idx < 0)
goto fail;
@@ -645,6 +780,8 @@ static void __init stm32f4_rcc_init(struct device_node *np)
of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
return;
fail:
+ kfree(clks);
iounmap(base);
}
-CLK_OF_DECLARE(stm32f4_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE(stm32f46xx_rcc, "st,stm32f46xx-rcc", stm32f4_rcc_init);
--
1.9.1
^ permalink raw reply related
* [PATCH 4/6] clk: stm32f4: Add RTC clock
From: gabriel.fernandez at st.com @ 2016-09-30 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475245509-6487-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch introduces the support of the RTC clock.
RTC clock can have 3 sources: lsi, lse and hse_rtc.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
drivers/clk/clk-stm32f4.c | 135 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 134 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index f57e73c..6e26d39 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -134,7 +134,7 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
};
-enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, END_PRIMARY_CLK };
+enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK };
/*
* MAX_CLKS is the maximum value in the enumeration below plus the combined
* hweight of stm32f42xx_gate_map (plus one).
@@ -318,6 +318,15 @@ static inline void enable_power_domain_write_protection(void)
regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8));
}
+static inline void sofware_reset_backup_domain(void)
+{
+ unsigned long val;
+
+ val = readl(base + STM32F4_RCC_BDCR);
+ writel(val |= (1 << 16), base + STM32F4_RCC_BDCR);
+ writel(val & ~(1 << 16), base + STM32F4_RCC_BDCR);
+}
+
struct stm32_rgate {
struct clk_hw hw;
struct clk_gate gate;
@@ -404,6 +413,113 @@ static struct clk_hw *clk_register_rgate(struct device *dev, const char *name,
return hw;
}
+static int cclk_gate_enable(struct clk_hw *hw)
+{
+ int ret;
+
+ disable_power_domain_write_protection();
+
+ ret = clk_gate_ops.enable(hw);
+
+ enable_power_domain_write_protection();
+
+ return ret;
+}
+
+static void cclk_gate_disable(struct clk_hw *hw)
+{
+ disable_power_domain_write_protection();
+
+ clk_gate_ops.disable(hw);
+
+ enable_power_domain_write_protection();
+}
+
+static int cclk_gate_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops cclk_gate_ops = {
+ .enable = cclk_gate_enable,
+ .disable = cclk_gate_disable,
+ .is_enabled = cclk_gate_is_enabled,
+};
+
+static u8 cclk_mux_get_parent(struct clk_hw *hw)
+{
+ return clk_mux_ops.get_parent(hw);
+}
+
+
+static int cclk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ int ret;
+
+ disable_power_domain_write_protection();
+
+ sofware_reset_backup_domain();
+
+ ret = clk_mux_ops.set_parent(hw, index);
+
+ enable_power_domain_write_protection();
+
+ return ret;
+}
+
+
+static const struct clk_ops cclk_mux_ops = {
+ .get_parent = cclk_mux_get_parent,
+ .set_parent = cclk_mux_set_parent,
+};
+
+static struct clk_hw *stm32_register_cclk(struct device *dev, const char *name,
+ const char * const *parent_names, int num_parents,
+ void __iomem *reg, u8 bit_idx, u8 shift, unsigned long flags,
+ spinlock_t *lock)
+{
+ struct clk_hw *hw;
+ struct clk_gate *gate;
+ struct clk_mux *mux;
+
+ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+ if (!gate) {
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+ if (!mux) {
+ kfree(gate);
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ gate->reg = reg;
+ gate->bit_idx = bit_idx;
+ gate->flags = 0;
+ gate->lock = lock;
+
+ mux->reg = reg;
+ mux->shift = shift;
+ mux->mask = 3;
+ mux->flags = 0;
+
+ hw = clk_hw_register_composite(dev, name, parent_names, num_parents,
+ &mux->hw, &cclk_mux_ops,
+ NULL, NULL,
+ &gate->hw, &cclk_gate_ops,
+ flags);
+
+ if (IS_ERR(hw)) {
+ kfree(gate);
+ kfree(mux);
+ }
+
+fail:
+ return hw;
+}
+
static const char *sys_parents[] __initdata = { "hsi", NULL, "pll" };
const char *rtc_parents[4] = {
@@ -509,6 +625,23 @@ static void __init stm32f4_rcc_init(struct device_node *np)
goto fail;
}
+ clks[CLK_HSE_RTC] = clk_hw_register_divider(NULL, "hse-rtc", "clk-hse",
+ 0, base + STM32F4_RCC_CFGR, 16, 5, 0,
+ &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_HSE_RTC])) {
+ pr_err("Unable to register hse-rtc clock\n");
+ goto fail;
+ }
+
+ clks[CLK_RTC] = stm32_register_cclk(NULL, "rtc", rtc_parents, 4,
+ base + STM32F4_RCC_BDCR, 15, 8, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_RTC])) {
+ pr_err("Unable to register rtc clock\n");
+ goto fail;
+ }
+
of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
return;
fail:
--
1.9.1
^ permalink raw reply related
* [PATCH 3/6] arm: stmf32: Enable SYSCON
From: gabriel.fernandez at st.com @ 2016-09-30 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475245509-6487-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
The clock drivers needs to disable the power domain write protection
using syscon/regmap to enable RTC clock.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
arch/arm/configs/stm32_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig
index 08786d8..f3b1ea5 100644
--- a/arch/arm/configs/stm32_defconfig
+++ b/arch/arm/configs/stm32_defconfig
@@ -49,6 +49,7 @@ CONFIG_SERIAL_STM32=y
CONFIG_SERIAL_STM32_CONSOLE=y
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
+CONFIG_MFD_SYSCON=y
# CONFIG_USB_SUPPORT is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
--
1.9.1
^ permalink raw reply related
* [PATCH 2/6] ARM: dts: stm32f429: add LSI and LSE clocks
From: gabriel.fernandez at st.com @ 2016-09-30 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475245509-6487-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch adds lsi / lse oscillators. These clocks can be use by
RTC clocks.
The clock drivers needs to disable the power domain write protection using
syscon / regmap to enable these clocks.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
arch/arm/boot/dts/stm32f429.dtsi | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 35df462..0979fb6 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -55,6 +55,18 @@
compatible = "fixed-clock";
clock-frequency = <0>;
};
+
+ clk-lse {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ };
+
+ clk-lsi {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32000>;
+ };
};
soc {
@@ -176,6 +188,11 @@
reg = <0x40013800 0x400>;
};
+ pwrcfg: power-config at 40007000 {
+ compatible = "syscon";
+ reg = <0x40007000 0x400>;
+ };
+
pin-controller {
#address-cells = <1>;
#size-cells = <1>;
@@ -330,6 +347,7 @@
compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
reg = <0x40023800 0x400>;
clocks = <&clk_hse>;
+ st,syscfg = <&pwrcfg>;
};
dma1: dma-controller at 40026000 {
--
1.9.1
^ permalink raw reply related
* [PATCH 1/6] clk: stm32f4: Add LSI & LSE clocks
From: gabriel.fernandez at st.com @ 2016-09-30 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475245509-6487-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch introduces the support of the LSI & LSE clocks.
The clock drivers needs to disable the power domain write protection
using syscon/regmap to enable these clocks.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
drivers/clk/clk-stm32f4.c | 146 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 142 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 02d6810..f57e73c 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -19,10 +19,14 @@
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
#define STM32F4_RCC_PLLCFGR 0x04
#define STM32F4_RCC_CFGR 0x08
@@ -31,6 +35,8 @@
#define STM32F4_RCC_AHB3ENR 0x38
#define STM32F4_RCC_APB1ENR 0x40
#define STM32F4_RCC_APB2ENR 0x44
+#define STM32F4_RCC_BDCR 0x70
+#define STM32F4_RCC_CSR 0x74
struct stm32f4_gate_data {
u8 offset;
@@ -39,6 +45,14 @@ struct stm32f4_gate_data {
const char *parent_name;
unsigned long flags;
};
+struct stm32f4_rgate_data {
+ u8 offset;
+ u8 bit_idx;
+ u8 bit_rdy_idx;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+};
static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
{ STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
@@ -120,13 +134,13 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
};
+enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, END_PRIMARY_CLK };
/*
* MAX_CLKS is the maximum value in the enumeration below plus the combined
* hweight of stm32f42xx_gate_map (plus one).
*/
-#define MAX_CLKS 74
+#define MAX_CLKS (71 + END_PRIMARY_CLK + 1)
-enum { SYSTICK, FCLK };
/*
* This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
@@ -259,7 +273,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
u64 table[ARRAY_SIZE(stm32f42xx_gate_map)];
if (primary == 1) {
- if (WARN_ON(secondary > FCLK))
+ if (WARN_ON(secondary >= END_PRIMARY_CLK))
return -EINVAL;
return secondary;
}
@@ -276,7 +290,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
table[BIT_ULL_WORD(secondary)] &=
GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0);
- return FCLK + hweight64(table[0]) +
+ return END_PRIMARY_CLK - 1 + hweight64(table[0]) +
(BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) +
(BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
}
@@ -292,8 +306,110 @@ stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data)
return clks[i];
}
+static struct regmap *pdrm;
+
+static inline void disable_power_domain_write_protection(void)
+{
+ regmap_update_bits(pdrm, 0x00, (1 << 8), (1 << 8));
+}
+
+static inline void enable_power_domain_write_protection(void)
+{
+ regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8));
+}
+
+struct stm32_rgate {
+ struct clk_hw hw;
+ struct clk_gate gate;
+ u8 bit_rdy_idx;
+};
+
+#define RTC_TIMEOUT 1000000
+
+#define to_rgclk(_hw) container_of(_hw, struct stm32_rgate, hw)
+
+static int rgclk_enable(struct clk_hw *hw)
+{
+ struct stm32_rgate *rgate = to_rgclk(hw);
+ struct clk_hw *gate_hw = &rgate->gate.hw;
+ struct clk_gate *gate = to_clk_gate(gate_hw);
+ u32 reg;
+ int ret;
+
+ __clk_hw_set_clk(gate_hw, hw);
+
+ disable_power_domain_write_protection();
+
+ clk_gate_ops.enable(gate_hw);
+
+ ret = readl_relaxed_poll_timeout_atomic(gate->reg, reg,
+ reg & rgate->bit_rdy_idx, 1000, RTC_TIMEOUT);
+
+ enable_power_domain_write_protection();
+
+ return ret;
+}
+
+static void rgclk_disable(struct clk_hw *hw)
+{
+ clk_gate_ops.disable(hw);
+}
+
+static int rgclk_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+
+static const struct clk_ops rgclk_ops = {
+ .enable = rgclk_enable,
+ .disable = rgclk_disable,
+ .is_enabled = rgclk_is_enabled,
+};
+
+static struct clk_hw *clk_register_rgate(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx, u8 bit_rdy_idx,
+ u8 clk_gate_flags, spinlock_t *lock)
+{
+ struct stm32_rgate *rgate;
+ struct clk_init_data init = { NULL };
+ struct clk_hw *hw;
+ int ret;
+
+ rgate = kzalloc(sizeof(*rgate), GFP_KERNEL);
+ if (!rgate)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &rgclk_ops;
+ init.flags = flags | CLK_IS_BASIC;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ rgate->hw.init = &init;
+ rgate->bit_rdy_idx = bit_rdy_idx;
+
+ rgate->gate.lock = lock;
+ rgate->gate.reg = reg;
+ rgate->gate.bit_idx = bit_idx;
+
+ hw = &rgate->hw;
+ ret = clk_hw_register(dev, hw);
+ if (ret) {
+ kfree(rgate);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
+
static const char *sys_parents[] __initdata = { "hsi", NULL, "pll" };
+const char *rtc_parents[4] = {
+ "no-clock", "lse", "lsi", "hse-rtc"
+};
+
static const struct clk_div_table ahb_div_table[] = {
{ 0x0, 1 }, { 0x1, 1 }, { 0x2, 1 }, { 0x3, 1 },
{ 0x4, 1 }, { 0x5, 1 }, { 0x6, 1 }, { 0x7, 1 },
@@ -319,6 +435,12 @@ static void __init stm32f4_rcc_init(struct device_node *np)
return;
}
+ pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (IS_ERR(pdrm)) {
+ pr_err("%s: Unable to get syscfg\n", __func__);
+ goto fail;
+ }
+
hse_clk = of_clk_get_parent_name(np, 0);
clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
@@ -371,6 +493,22 @@ static void __init stm32f4_rcc_init(struct device_node *np)
}
}
+ clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0,
+ base + STM32F4_RCC_CSR, 0, 2, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_LSI])) {
+ pr_err("Unable to register lsi clock\n");
+ goto fail;
+ }
+
+ clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0,
+ base + STM32F4_RCC_BDCR, 0, 2, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_LSE])) {
+ pr_err("Unable to register lse clock\n");
+ goto fail;
+ }
+
of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
return;
fail:
--
1.9.1
^ permalink raw reply related
* [PATCH 0/6] STM32F4 Add RTC & QSPI clocks
From: gabriel.fernandez at st.com @ 2016-09-30 14:25 UTC (permalink / raw)
To: linux-arm-kernel
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch-set introduce RTC and QSPI clocks for STM32F4 socs
RTC clock has 3 parents clock oscillators (lsi/lse/hse_rtc)
example to use rtc clock:
rtc: rtc at 40002800 {
compatible = "st,stm32-rtc";
reg = <0x40002800 0x400>;
...
clocks = <&rcc 1 CLK_RTC>;
assigned-clocks = <&rcc 1 CLK_RTC>;
assigned-clock-parents = <&rcc 1 CLK_LSE>;
...
};
Gabriel Fernandez (6):
clk: stm32f4: Add LSI & LSE clocks
ARM: dts: stm32f429: add LSI and LSE clocks
arm: stmf32: Enable SYSCON
clk: stm32f4: Add RTC clock
clk: stm32f469: Add QSPI clock
ARM: dts: stm32f429: Add QSPI clock
.../devicetree/bindings/clock/st,stm32-rcc.txt | 4 +-
arch/arm/boot/dts/stm32f429.dtsi | 18 +
arch/arm/boot/dts/stm32f469-disco.dts | 4 +
arch/arm/configs/stm32_defconfig | 1 +
drivers/clk/clk-stm32f4.c | 450 ++++++++++++++++++++-
5 files changed, 455 insertions(+), 22 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH 3/6] ARM: dts: da850-lcdk: enable the LCD controller
From: Sekhar Nori @ 2016-09-30 14:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475166715-7857-4-git-send-email-bgolaszewski@baylibre.com>
On Thursday 29 September 2016 10:01 PM, Bartosz Golaszewski wrote:
> From: Karl Beldan <kbeldan@baylibre.com>
>
> This adds the pins used by the LCD controller, and uses 'tilcdc,panel'
> with some default timings for 800x600.
>
> Tested on an LCDK connected on the VGA port (the LCDC is connected to
> this port via a THS8135).
>
> Signed-off-by: Karl Beldan <kbeldan@baylibre.com>
> [Bartosz:
> - fixed whitespace errors
> - tweaked the description
> - fixed the incorrect hback-porch value
> - other minor tweaks]
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> ---
> + lcd_pins: pinmux_lcd_pins {
> + pinctrl-single,bits = <
> + /*
> + * LCD_D[2], LCD_D[3], LCD_D[4], LCD_D[5],
> + * LCD_D[6], LCD_D[7]
> + */
> + 0x40 0x22222200 0xffffff00
> + /*
> + * LCD_D[10], LCD_D[11], LCD_D[12], LCD_D[13],
> + * LCD_D[14], LCD_D[15], LCD_D[0], LCD_D[1]
> + */
> + 0x44 0x22222222 0xffffffff
> + /* LCD_D[8], LCD_D[9] */
> + 0x48 0x00000022 0x000000ff
> +
> + /* LCD_PCLK */
> + 0x48 0x02000000 0x0f000000
> + /* LCD_AC_ENB_CS, LCD_VSYNC, LCD_HSYNC */
> + 0x4c 0x02000022 0x0f0000ff
> + >;
> + };
Since almost all boards that use LCD will configure the pins in the same
way, we can move this to da850.dtsi. Please see existing examples of the
same.
The only place where we don't do this is if the common pinmux definition
may not find much reuse because of differing nature of how the external
peripherals are interfaced.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v2 1/1] arm64: Add DTS support for FSL's LS1012A SoC
From: Stuart Yoder @ 2016-09-30 13:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1472207241-18461-1-git-send-email-Bhaskar.Upadhaya@nxp.com>
> + dspi0: dspi at 2100000 {
> + compatible = "fsl,ls1012a-dspi",
> + "fsl,ls1043a-dspi",
> + "fsl,ls1021a-v1.0-dspi";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x0 0x2100000 0x0 0x10000>;
> + interrupts = <0 64 0x4>;
> + clock-names = "dspi";
> + clocks = <&clockgen 4 0>;
> + spi-num-chipselects = <5>;
> + big-endian;
> + status = "enabled";
"enabled" is not a valid status value.
Stuart
^ permalink raw reply
* [PATCH v2 1/1] arm64: Add DTS support for FSL's LS1012A SoC
From: Stuart Yoder @ 2016-09-30 13:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AM4PR0401MB22753C87DE074EE7BF456CE48CC10@AM4PR0401MB2275.eurprd04.prod.outlook.com>
> >> +&qspi {
> >> + num-cs = <2>;
> >> + bus-num = <0>;
> >> + status = "disabled";
> >
> >Why is it being disabled?
>
> Ok, will change like below.
> status = "okay";
The comment was not "change this to okay". The question is why is this disabled?
Can you explain why it was disabled? Should it have been disasbled? Is qspi
working and tested on this board?
>
> >
> >> + fsl,ddr-sampling-point = <4>;
> >
> >I do not find the bindings for this property, neither how driver supports it.
>
> Yes the QSPI DDR mode is not yet up-streamed, so I will remove this property as of now.
>
> >
> >> +
> >> + qflash0: s25fs512s at 0 {
> >> + compatible = "spansion,m25p80";
> >> + #address-cells = <1>;
> >> + #size-cells = <1>;
> >> + spi-max-frequency = <20000000>;
> >> + m25p,fast-read;
> >> + reg = <0>;
> >> + };
> >> +};
> >> +
> >> +&i2c0 {
> >> + status = "okay";
> >> +
> >> + codec: sgtl5000 at a {
> >> + #sound-dai-cells = <0>;
> >> + compatible = "fsl,sgtl5000";
> >> + reg = <0xa>;
> >> + VDDA-supply = <®_1p8v>;
> >> + VDDIO-supply = <®_1p8v>;
> >> + clocks = <&sys_mclk>;
> >> + };
> >> +};
> >> +
> >> +&duart0 {
> >> + status = "okay";
> >> +};
> >> +
> >> +&esdhc0 {
> >> + status = "disabled";
> >
> >We prefer to disable devices which have board level options by default in
> ><soc>.dtsi, and enable them per availability in <board>.dts.
>
> Ok , will make the status as okay i.e. status = "okay";
Again, the feedback was not "set this to okay". Why was esdhc0 set to "disabled"
here in the first place? Was there a reason?
The comment is that if there are certain boards where esdhc0 is not available,
then fsl-ls1012a.dtsi should set this to "disabled" and board .dts files should
override it.
> >
> >> +};
> >> +
> >> +&esdhc1 {
> >> + status = "disabled";
> >> +};
> >> +
> >> +&sai2 {
> >> + status = "disabled";
> >> +};
Same comment for the above nodes. The fsl-ls1012a.dtsi should set them to
disabled and any .dts file should override with "ok" if applicable.
Stuart
^ permalink raw reply
* [PATCH] drm: tilcdc: add a da850-specific compatible string
From: Bartosz Golaszewski @ 2016-09-30 13:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475240456-22936-1-git-send-email-bgolaszewski@baylibre.com>
2016-09-30 15:00 GMT+02:00 Bartosz Golaszewski <bgolaszewski@baylibre.com>:
> Due to some potential tweaks for the da850 LCDC (for example: the
> required memory bandwith settings) we need a separate compatible
> for the IP present on the da850 boards.
>
> Suggested-by: Sekhar Nori <nsekhar@ti.com>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> ---
> drivers/gpu/drm/tilcdc/tilcdc_drv.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> index a694977..231f2c7 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> @@ -723,6 +723,7 @@ static int tilcdc_pdev_remove(struct platform_device *pdev)
>
> static struct of_device_id tilcdc_of_match[] = {
> { .compatible = "ti,am33xx-tilcdc", },
> + { .compatible = "ti,da850-tilcdc", },
> { },
> };
> MODULE_DEVICE_TABLE(of, tilcdc_of_match);
> --
> 2.9.3
>
Superseded by v2.
^ permalink raw reply
* [PATCH v2] drm: tilcdc: add a da850-specific compatible string
From: Bartosz Golaszewski @ 2016-09-30 13:52 UTC (permalink / raw)
To: linux-arm-kernel
Due to some potential tweaks for the da850 LCDC (for example: the
required memory bandwith settings) we need a separate compatible
for the IP present on the da850 boards.
Suggested-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
v1 -> v2:
- added the new compatible to the bindings documentation
Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt | 4 ++--
drivers/gpu/drm/tilcdc/tilcdc_drv.c | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
index a83abd7..33b6e8a 100644
--- a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
+++ b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
@@ -1,7 +1,7 @@
Device-Tree bindings for tilcdc DRM driver
Required properties:
- - compatible: value should be "ti,am33xx-tilcdc".
+ - compatible: value should be "ti,am33xx-tilcdc" or "ti,da850-tilcdc".
- interrupts: the interrupt number
- reg: base address and size of the LCDC device
@@ -51,7 +51,7 @@ Optional nodes:
Example:
fb: fb at 4830e000 {
- compatible = "ti,am33xx-tilcdc";
+ compatible = "ti,am33xx-tilcdc", "ti,da850-tilcdc";
reg = <0x4830e000 0x1000>;
interrupt-parent = <&intc>;
interrupts = <36>;
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index a694977..231f2c7 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -723,6 +723,7 @@ static int tilcdc_pdev_remove(struct platform_device *pdev)
static struct of_device_id tilcdc_of_match[] = {
{ .compatible = "ti,am33xx-tilcdc", },
+ { .compatible = "ti,da850-tilcdc", },
{ },
};
MODULE_DEVICE_TABLE(of, tilcdc_of_match);
--
2.9.3
^ permalink raw reply related
* [PATCH 4/6] ARM: dts: da850-lcdk: add support for 1024x768 resolution
From: Bartosz Golaszewski @ 2016-09-30 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160930124942.ul737vxmdmkxqdre@gobelin>
2016-09-30 14:49 GMT+02:00 Karl Beldan <karl.beldan@gmail.com>:
> On Fri, Sep 30, 2016 at 11:37:57AM +0200, Bartosz Golaszewski wrote:
>> 2016-09-29 20:58 GMT+02:00 Karl Beldan <karl.beldan@gmail.com>:
>> > Hi,
>> >
>> > On Thu, Sep 29, 2016 at 06:31:53PM +0200, Bartosz Golaszewski wrote:
>> >> Add svga timings for 1024x768 resolution to the da850-lcdk
>> >> device tree.
>> >>
>> >
>>
>> [snip]
>>
>> >
>> > Why do you also call 1024x768 svga ?
>> >
>>
>> Thanks, should have been xga. will fix in v2.
>>
>> > I don't think the LCDK can cope with this resolution at this frequency
>> > (in terms of mem bandwidth), at least that's what I observed back in
>> > August. If confirmed I think it is worth mentioning in the log at least,
>> > but then I doubt adding this config would be useful.
>> >
>>
>> Thanks for the heads up. How would that manifest itself? This seems to
>> work fine for me - I'm not getting any warnings on a simple system -
>> maybe if I added some additional memory load it would complain.
>>
>
> A mere dmesg > /dev/tty0 (or repeatedly cat-ting a file to /dev/tty0)
> should suffice to make the issue visible and trigger FIFO underflows.
>
Thanks, this is correct unfortunately.
Best regards,
Bartosz Golaszewski
^ permalink raw reply
* [PATCH] drm: tilcdc: add a da850-specific compatible string
From: Sekhar Nori @ 2016-09-30 13:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475240456-22936-1-git-send-email-bgolaszewski@baylibre.com>
On Friday 30 September 2016 06:30 PM, Bartosz Golaszewski wrote:
> Due to some potential tweaks for the da850 LCDC (for example: the
> required memory bandwith settings) we need a separate compatible
> for the IP present on the da850 boards.
>
> Suggested-by: Sekhar Nori <nsekhar@ti.com>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> ---
> drivers/gpu/drm/tilcdc/tilcdc_drv.c | 1 +
This patch should document the new compatible in
Documentation/devicetree/bindings/..
Thanks,
Sekhar
^ permalink raw reply
* [RFC 05/11] iommu/dma: iommu_dma_(un)map_mixed
From: Robin Murphy @ 2016-09-30 13:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475009318-2617-6-git-send-email-eric.auger@redhat.com>
Hi Eric,
On 27/09/16 21:48, Eric Auger wrote:
> iommu_dma_map_mixed and iommu_dma_unmap_mixed operate on
> IOMMU_DOMAIN_MIXED typed domains. On top of standard iommu_map/unmap
> they reserve the IOVA window to prevent the iova allocator to
> allocate in those areas.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
> drivers/iommu/dma-iommu.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/dma-iommu.h | 18 ++++++++++++++++++
> 2 files changed, 66 insertions(+)
>
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 04bbc85..db21143 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -759,3 +759,51 @@ int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain,
> return 0;
> }
> EXPORT_SYMBOL(iommu_get_dma_msi_region_cookie);
> +
> +int iommu_dma_map_mixed(struct iommu_domain *domain, unsigned long iova,
> + phys_addr_t paddr, size_t size, int prot)
> +{
> + struct iova_domain *iovad;
> + unsigned long lo, hi;
> + int ret;
> +
> + if (domain->type != IOMMU_DOMAIN_MIXED)
> + return -EINVAL;
> +
> + if (!domain->iova_cookie)
> + return -EINVAL;
> +
> + iovad = cookie_iovad(domain);
> +
> + lo = iova_pfn(iovad, iova);
> + hi = iova_pfn(iovad, iova + size - 1);
> + reserve_iova(iovad, lo, hi);
This can't work reliably - reserve_iova() will (for good reason) merge
any adjacent or overlapping entries, so any unmap is liable to free more
IOVA space than actually gets unmapped, and things will get subtly out
of sync and go wrong later.
The more general issue with this whole approach, though, is that it
effectively rules out userspace doing guest memory hotplug or similar,
and I'm not we want to paint ourselves into that corner. Basically, as
soon as a device is attached to a guest, the entirety of the unallocated
IPA space becomes reserved, and userspace can never add anything further
to it, because any given address *might* be in use for an MSI mapping.
I think it still makes most sense to stick with the original approach of
cooperating with userspace to reserve a bounded area - it's just that we
can then let automatic mapping take care of itself within that area.
Speaking of which, I've realised the same fundamental reservation
problem already applies to PCI without ACS, regardless of MSIs. I just
tried on my Juno with guest memory placed at 0x4000000000, (i.e.
matching the host PA of the 64-bit PCI window), and sure enough when the
guest kicks off some DMA on the passed-through NIC, the root complex
interprets the guest IPA as (unsupported) peer-to-peer DMA to a BAR
claimed by the video card, and it fails. I guess this doesn't get hit in
practice on x86 because the guest memory map is unlikely to be much
different from the host's.
It seems like we basically need a general way of communicating fixed and
movable host reservations to userspace :/
Robin.
> + ret = iommu_map(domain, iova, paddr, size, prot);
> + if (ret)
> + free_iova(iovad, lo);
> + return ret;
> +}
> +EXPORT_SYMBOL(iommu_dma_map_mixed);
> +
> +size_t iommu_dma_unmap_mixed(struct iommu_domain *domain, unsigned long iova,
> + size_t size)
> +{
> + struct iova_domain *iovad;
> + unsigned long lo;
> + size_t ret;
> +
> + if (domain->type != IOMMU_DOMAIN_MIXED)
> + return -EINVAL;
> +
> + if (!domain->iova_cookie)
> + return -EINVAL;
> +
> + iovad = cookie_iovad(domain);
> + lo = iova_pfn(iovad, iova);
> +
> + ret = iommu_unmap(domain, iova, size);
> + if (ret == size)
> + free_iova(iovad, lo);
> + return ret;
> +}
> +EXPORT_SYMBOL(iommu_dma_unmap_mixed);
> diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
> index 1c55413..f2aa855 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -70,6 +70,12 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
> int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain,
> dma_addr_t base, u64 size);
>
> +int iommu_dma_map_mixed(struct iommu_domain *domain, unsigned long iova,
> + phys_addr_t paddr, size_t size, int prot);
> +
> +size_t iommu_dma_unmap_mixed(struct iommu_domain *domain, unsigned long iova,
> + size_t size);
> +
> #else
>
> struct iommu_domain;
> @@ -99,6 +105,18 @@ static inline int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain,
> return -ENODEV;
> }
>
> +int iommu_dma_map_mixed(struct iommu_domain *domain, unsigned long iova,
> + phys_addr_t paddr, size_t size, int prot)
> +{
> + return -ENODEV;
> +}
> +
> +size_t iommu_dma_unmap_mixed(struct iommu_domain *domain, unsigned long iova,
> + size_t size)
> +{
> + return -ENODEV;
> +}
> +
> #endif /* CONFIG_IOMMU_DMA */
> #endif /* __KERNEL__ */
> #endif /* __DMA_IOMMU_H */
>
^ permalink raw reply
* [PATCH 3/6] ARM: dts: da850-lcdk: enable the LCD controller
From: Karl Beldan @ 2016-09-30 13:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMpxmJU45aP7=vs5h6s2T=v-gB5q06AvhGJdcRV9WDgNzs+Enw@mail.gmail.com>
On Fri, Sep 30, 2016 at 11:42:14AM +0200, Bartosz Golaszewski wrote:
> 2016-09-29 20:40 GMT+02:00 Karl Beldan <karl.beldan@gmail.com>:
> > Hi,
> >
> > On Thu, Sep 29, 2016 at 06:31:52PM +0200, Bartosz Golaszewski wrote:
> >> From: Karl Beldan <kbeldan@baylibre.com>
> >>
> >> This adds the pins used by the LCD controller, and uses 'tilcdc,panel'
> >> with some default timings for 800x600.
> >>
> >> Tested on an LCDK connected on the VGA port (the LCDC is connected to
> >> this port via a THS8135).
> >>
> >> Signed-off-by: Karl Beldan <kbeldan@baylibre.com>
> >> [Bartosz:
> >> - fixed whitespace errors
> >> - tweaked the description
> >
> > The description tweak you mention is the removal of an erratum which is
> > in the mentioned commit I put on github @
> > (https://github.com/kbeldan/linux/commit/b7720bc983c00a083dece119f68ea9d2f522c6c4)
> > it included an erratum wrt FIFO threshold I think is worth keeping:
> > {
> > There is an erratum (fifo-th) "LCDC: Underflow During Initialization":
> > [...]
> > "This problem may occur if the LCDC FIFO threshold size (
> > LCDDMA_CTRL[TH_FIFO_READY]) is left at its default value after reset.
> > Increasing the FIFO threshold size will reduce or eliminate underflows.
> > Setting the threshold size to 256 double words or larger is
> > recommended."
> > }
>
> Isn't this the issue that is fixed by changing the memory priority for lcdc?
>
It is possible that the erratum and the memory priority settings try to
address the symptoms of the same underlying issue, it is impossible to
state with the publicly available information, however, the erratum
relates to the LCDC registers settings, namely the fifo-th propperty of
panel-info in the dts, which is really different from the memory
priority adjustments in the SYSCFG and DDR_CTL.
Regards,
Karl
> >
> >> - fixed the incorrect hback-porch value
> >
> > It can't be a fix, this value depends on the monitor connected.
> >
>
> Thanks, I'm new to drm. From reading the datasheet it seemed to me
> that this depends on the resolution. FWIW it seems that most LCDs are
> able to adjust to this themselves - I tested with two different
> displays and the value I introduced worked on both while the previous
> one shifted the image to the right. I'll look into that.
>
> >> - other minor tweaks]
> >
> > I didn't see any other change while diffing.
> >
>
> Dropped the refresh rate from the timings node name.
>
> Thanks,
> Bartosz
^ permalink raw reply
* [PATCH] arm: dts: imx6dl: force the 'compatible' field for the uart[12345] to 'fsl, imx21-uart'.
From: Giorgio Dal Molin @ 2016-09-30 13:13 UTC (permalink / raw)
To: linux-arm-kernel
Without this fix the imx uart kernel driver selects 'fsl,imx6q-uart' as
its compatible value and the port does not work properly.
The kind of malfunctioning I noticed was while receiving bytes from the
uart, sending out was OK.
Signed-off-by: Giorgio Dal Molin <iw3gtf@arcor.de>
---
arch/arm/boot/dts/imx6dl.dtsi | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 9a4c22c..1a1d5fd 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -131,3 +131,23 @@
&vpu {
compatible = "fsl,imx6dl-vpu", "cnm,coda960";
};
+
+&uart1 {
+ compatible = "fsl,imx21-uart";
+};
+
+&uart2 {
+ compatible = "fsl,imx21-uart";
+};
+
+&uart3 {
+ compatible = "fsl,imx21-uart";
+};
+
+&uart4 {
+ compatible = "fsl,imx21-uart";
+};
+
+&uart5 {
+ compatible = "fsl,imx21-uart";
+};
--
2.10.0
^ permalink raw reply related
* [PATCH 2/6] ARM: dts: da850: add a node for the LCD controller
From: Bartosz Golaszewski @ 2016-09-30 13:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4e0586e9-7f95-fbab-924a-fe046892a66b@ti.com>
2016-09-30 11:34 GMT+02:00 Sekhar Nori <nsekhar@ti.com>:
> On Thursday 29 September 2016 10:01 PM, Bartosz Golaszewski wrote:
>> From: Karl Beldan <kbeldan@baylibre.com>
>>
>> Add a disabled LCDC node to be reused in device trees including
>> da850.dtsi for boards equipped with tilcdc enabled.
>>
>> Signed-off-by: Karl Beldan <kbeldan@baylibre.com>
>> [Bartosz: added the commit description]
>> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>> ---
>> arch/arm/boot/dts/da850.dtsi | 8 ++++++++
>> 1 file changed, 8 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
>> index f79e1b9..9f39296 100644
>> --- a/arch/arm/boot/dts/da850.dtsi
>> +++ b/arch/arm/boot/dts/da850.dtsi
>> @@ -399,6 +399,14 @@
>> <&edma0 0 1>;
>> dma-names = "tx", "rx";
>> };
>> +
>> + lcdc: lcdc at 213000 {
>
> node name should be generic per the ePAPR so please use "display".
>
>> + compatible = "ti,am33xx-tilcdc";
>
> Can you please introduce a da850 specific compatible. Something like:
>
> compatible = "ti,da850-tilcdc", "ti,am33xx-tilcdc";
>
I sent a relevant patch to the drm mailing list.
> Even if you dont use it in the driver today, please have it in the .dts
> I am pretty sure there will be some da850 specific tweak required for
> the LCDC at some point. Having a compatible already in place will make
> migration easier. You will have to document the compatible though.
>
> This will affect 1/6 too.
>
I'll include these changes in v2.
Thanks,
Bartosz
^ permalink raw reply
* [PATCH] drm: tilcdc: add a da850-specific compatible string
From: Bartosz Golaszewski @ 2016-09-30 13:00 UTC (permalink / raw)
To: linux-arm-kernel
Due to some potential tweaks for the da850 LCDC (for example: the
required memory bandwith settings) we need a separate compatible
for the IP present on the da850 boards.
Suggested-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
drivers/gpu/drm/tilcdc/tilcdc_drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index a694977..231f2c7 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -723,6 +723,7 @@ static int tilcdc_pdev_remove(struct platform_device *pdev)
static struct of_device_id tilcdc_of_match[] = {
{ .compatible = "ti,am33xx-tilcdc", },
+ { .compatible = "ti,da850-tilcdc", },
{ },
};
MODULE_DEVICE_TABLE(of, tilcdc_of_match);
--
2.9.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox