* [PATCH] ARM: dts: imx6q-utilite-pro: enable 2nd display pipeline
From: Shawn Guo @ 2016-12-30 14:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ec9676f344eb4786a28a3c7b969f0e94@rwthex-s1-b.rwth-ad.de>
On Fri, Dec 02, 2016 at 03:37:22PM +0100, christopher.spinrath at rwth-aachen.de wrote:
> From: Christopher Spinrath <christopher.spinrath@rwth-aachen.de>
>
> Apart from the already enabled Designware HDMI port, the Utilite Pro
> has a second display pipeline which has the following shape:
>
> IPU1 DI0 --> Parallel display --> tfp410 rgb24 to DVI encoder
> --> HDMI connector.
> Enable support for it.
>
> In addition, since this pipeline is hardwired to IPU1, sever the link
> between IPU1 and the SoC-internal Designware HDMI encoder forcing the
> latter to be connected to IPU2 instead of IPU1. Otherwise, it is not
> possible to drive both displays at high resolution due to the bandwidth
> limitations of a single IPU.
>
> Signed-off-by: Christopher Spinrath <christopher.spinrath@rwth-aachen.de>
@Philipp, can you help review the changes?
> ---
>
> Hi all,
>
> the removal of the link between IPU1 and the Designware HDMI encoder is the
> result of a discussion I had with Philipp Zabel:
>
> https://lists.freedesktop.org/archives/dri-devel/2016-November/125399.html .
>
> Altough it is not possible to connect anything else to IPU1 on the Utilite, this
> approach has at least one disadvantage: if the resolution is low enough such
> that a single IPU can handle both displays then muxing both displays to IPU1
> would reduce the power consumption.
>
> However, IMHO omitting the link IPU1 <--> DW HDMI is still the preferrable
> solution since I'm not aware of any OS/driver that is capable of switching IPUs
> or can handle the bandwidth limitation in a sane way. In particular, Linux is
> unusable when both displays are supposed to be driven at high resolution and
> both muxing options for the DW HDMI are available (this is not a userspace
> issue; the system becomes almost unresponsive as soon as the kernel sets the
> initial resolution).
>
> Cheers,
> Christopher
>
> P.S.: this patch depends on the tfp410 bridge driver which has recently been
> merged into drm-next.
v4.10-rc1 has the driver, so the dependency is gone now, I guess.
>
> arch/arm/boot/dts/imx6q-utilite-pro.dts | 115 ++++++++++++++++++++++++++++++++
> 1 file changed, 115 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts b/arch/arm/boot/dts/imx6q-utilite-pro.dts
> index 2200994..69bdd82 100644
> --- a/arch/arm/boot/dts/imx6q-utilite-pro.dts
> +++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
> @@ -59,6 +59,33 @@
> rtc1 = &snvs_rtc;
> };
>
> + encoder {
> + compatible = "ti,tfp410";
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port at 0 {
> + reg = <0>;
> +
> + tfp410_in: endpoint {
> + remote-endpoint = <¶llel_display_out>;
> + };
> + };
> +
> + port at 1 {
> + reg = <1>;
> +
> + tfp410_out: endpoint {
> + remote-endpoint = <&hdmi_connector_in>;
> + };
> + };
> + };
> + };
> +
> gpio-keys {
> compatible = "gpio-keys";
> pinctrl-names = "default";
> @@ -72,6 +99,19 @@
> };
> };
>
> + hdmi-connector {
> + compatible = "hdmi-connector";
> +
The newline is unnecessary.
> + type = "a";
> + ddc-i2c-bus = <&i2c_dvi_ddc>;
> +
> + port {
> + hdmi_connector_in: endpoint {
> + remote-endpoint = <&tfp410_out>;
> + };
> + };
> + };
> +
> i2cmux {
> compatible = "i2c-mux-gpio";
> pinctrl-names = "default";
> @@ -105,8 +145,46 @@
> #size-cells = <0>;
> };
> };
> +
> + parallel-display {
> + compatible = "fsl,imx-parallel-display";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_ipu1>;
> +
Ditto
I can fix them up if I get a Reviewed-by tag from Philipp on this
version.
Shawn
> + interface-pix-fmt = "rgb24";
> +
> + port at 0 {
> + reg = <0>;
> +
> + parallel_display_in: endpoint {
> + remote-endpoint = <&ipu1_di0_disp0>;
> + };
> + };
> +
> + port at 1 {
> + reg = <1>;
> +
> + parallel_display_out: endpoint {
> + remote-endpoint = <&tfp410_in>;
> + };
> + };
> + };
> };
>
> +/*
> + * A single IPU is not able to drive both display interfaces available on the
> + * Utilite Pro at high resolution due to its bandwidth limitation. Since the
> + * tfp410 encoder is wired up to IPU1, sever the link between IPU1 and the
> + * SoC-internal Designware HDMI encoder forcing the latter to be connected to
> + * IPU2 instead of IPU1.
> + */
> +/delete-node/&ipu1_di0_hdmi;
> +/delete-node/&hdmi_mux_0;
> +/delete-node/&ipu1_di1_hdmi;
> +/delete-node/&hdmi_mux_1;
> +
> &hdmi {
> ddc-i2c-bus = <&i2c2>;
> status = "okay";
> @@ -151,6 +229,39 @@
> >;
> };
>
> + pinctrl_ipu1: ipu1grp {
> + fsl,pins = <
> + MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x38
> + MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x38
> + MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x38
> + MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x38
> + MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x38
> + MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x38
> + MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x38
> + MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x38
> + MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x38
> + MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x38
> + MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x38
> + MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x38
> + MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x38
> + MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x38
> + MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x38
> + MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x38
> + MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x38
> + MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x38
> + MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x38
> + MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x38
> + MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x38
> + MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x38
> + MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x38
> + MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x38
> + MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x38
> + MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x38
> + MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x38
> + MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x38
> + >;
> + };
> +
> pinctrl_uart2: uart2grp {
> fsl,pins = <
> MX6QDL_PAD_GPIO_7__UART2_TX_DATA 0x1b0b1
> @@ -194,6 +305,10 @@
> };
> };
>
> +&ipu1_di0_disp0 {
> + remote-endpoint = <¶llel_display_in>;
> +};
> +
> &pcie {
> pcie at 0,0 {
> reg = <0x000000 0 0 0 0>;
> --
> 2.10.2
>
^ permalink raw reply
* [PATCH] pinctrl: stricten up generic group code
From: Linus Walleij @ 2016-12-30 14:07 UTC (permalink / raw)
To: linux-arm-kernel
Rename the symbol PINCTRL_GENERIC to PINCTRL_GENERIC_GROUPS since
it all pertains to groups. Replace everywhere.
ifdef out the radix tree and the struct when not using the
generic groups.
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/pinctrl/Kconfig | 2 +-
drivers/pinctrl/core.c | 6 ++++--
drivers/pinctrl/core.h | 32 +++++++++++++++++---------------
3 files changed, 22 insertions(+), 18 deletions(-)
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index b986998409d1..add257f80d76 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -8,7 +8,7 @@ config PINCTRL
menu "Pin controllers"
depends on PINCTRL
-config GENERIC_PINCTRL
+config GENERIC_PINCTRL_GROUPS
bool
config PINMUX
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 7b7d706f869c..736149d3a33d 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -540,7 +540,7 @@ void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
}
EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
-#ifdef CONFIG_GENERIC_PINCTRL
+#ifdef CONFIG_GENERIC_PINCTRL_GROUPS
/**
* pinctrl_generic_get_group_count() - returns the number of pin groups
@@ -714,7 +714,7 @@ static void pinctrl_generic_free_groups(struct pinctrl_dev *pctldev)
static inline void pinctrl_generic_free_groups(struct pinctrl_dev *pctldev)
{
}
-#endif /* CONFIG_GENERIC_PINCTRL */
+#endif /* CONFIG_GENERIC_PINCTRL_GROUPS */
/**
* pinctrl_get_group_selector() - returns the group selector for a group
@@ -1993,7 +1993,9 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
pctldev->desc = pctldesc;
pctldev->driver_data = driver_data;
INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
+#ifdef CONFIG_GENERIC_PINCTRL_GROUPS
INIT_RADIX_TREE(&pctldev->pin_group_tree, GFP_KERNEL);
+#endif
INIT_LIST_HEAD(&pctldev->gpio_ranges);
INIT_DELAYED_WORK(&pctldev->late_init, pinctrl_late_init);
pctldev->dev = dev;
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index af98b6313902..b04c59bf9701 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -43,8 +43,10 @@ struct pinctrl_dev {
struct list_head node;
struct pinctrl_desc *desc;
struct radix_tree_root pin_desc_tree;
+#ifdef CONFIG_GENERIC_PINCTRL_GROUPS
struct radix_tree_root pin_group_tree;
unsigned int num_groups;
+#endif
struct list_head gpio_ranges;
struct device *dev;
struct module *owner;
@@ -166,6 +168,20 @@ struct pin_desc {
};
/**
+ * struct pinctrl_maps - a list item containing part of the mapping table
+ * @node: mapping table list node
+ * @maps: array of mapping table entries
+ * @num_maps: the number of entries in @maps
+ */
+struct pinctrl_maps {
+ struct list_head node;
+ struct pinctrl_map const *maps;
+ unsigned num_maps;
+};
+
+#ifdef CONFIG_GENERIC_PINCTRL_GROUPS
+
+/**
* struct group_desc - generic pin group descriptor
* @name: name of the pin group
* @pins: array of pins that belong to the group
@@ -179,20 +195,6 @@ struct group_desc {
void *data;
};
-/**
- * struct pinctrl_maps - a list item containing part of the mapping table
- * @node: mapping table list node
- * @maps: array of mapping table entries
- * @num_maps: the number of entries in @maps
- */
-struct pinctrl_maps {
- struct list_head node;
- struct pinctrl_map const *maps;
- unsigned num_maps;
-};
-
-#ifdef CONFIG_GENERIC_PINCTRL
-
int pinctrl_generic_get_group_count(struct pinctrl_dev *pctldev);
const char *pinctrl_generic_get_group_name(struct pinctrl_dev *pctldev,
@@ -218,7 +220,7 @@ pinctrl_generic_remove_last_group(struct pinctrl_dev *pctldev)
return pinctrl_generic_remove_group(pctldev, pctldev->num_groups - 1);
}
-#endif /* CONFIG_GENERIC_PINCTRL */
+#endif /* CONFIG_GENERIC_PINCTRL_GROUPS */
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np);
--
2.9.3
^ permalink raw reply related
* [PATCH] pinctrl: add some comments to the hog/late init code
From: Linus Walleij @ 2016-12-30 13:45 UTC (permalink / raw)
To: linux-arm-kernel
It confused me a bit so it may confuse others. Make it crystal
clear what is going on here for any future readers.
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/pinctrl/core.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index d02e8def9506..a9e3a75fb67d 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -1753,6 +1753,12 @@ static void pinctrl_late_init(struct work_struct *work)
pctldev = container_of(work, struct pinctrl_dev, late_init.work);
+ /*
+ * If the pin controller does NOT have hogs, this will report an
+ * error and we skip over this entire branch. This is why we can
+ * call this function directly when we do not have hogs on the
+ * device.
+ */
pctldev->p = create_pinctrl(pctldev->dev, pctldev);
if (!IS_ERR(pctldev->p)) {
kref_get(&pctldev->p->users);
@@ -1847,6 +1853,12 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
goto out_err;
}
+ /*
+ * If the device has hogs we want the probe() function of the driver
+ * to complete before we go in and hog them and add the pin controller
+ * to the list of controllers. If it has no hogs, we can just complete
+ * the registration immediately.
+ */
if (pinctrl_dt_has_hogs(pctldev))
schedule_delayed_work(&pctldev->late_init, 0);
else
--
2.9.3
^ permalink raw reply related
* [PATCH v2] ARM64: dts: meson-gx: Add reserved memory zone and usable memory range
From: Neil Armstrong @ 2016-12-30 13:40 UTC (permalink / raw)
To: linux-arm-kernel
The Amlogic Meson GXBB/GXL/GXM secure monitor uses part of the memory space,
this patch adds this reserved zone and redefines the usable memory range.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
Changes since v1 at [1] :
- Renamed reg into linux,usable-memory to ovveride u-boot memory
- only kept secmon memory zone
[1] http://lkml.kernel.org/r/20161212101801.28491-1-narmstrong at baylibre.com
arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi | 2 +-
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 12 ++++++++++++
arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts | 2 +-
11 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
index 7a078be..ca3c7fa 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
@@ -56,7 +56,7 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x80000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x7f000000>;
};
vddio_boot: regulator-vddio_boot {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index eada0b5..7f244b5 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -55,6 +55,18 @@
#address-cells = <2>;
#size-cells = <2>;
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* global autoconfigured region for contiguous allocations */
+ secmon: secmon {
+ reg = <0x0 0x10000000 0x0 0x200000>;
+ no-map;
+ };
+ };
+
cpus {
#address-cells = <0x2>;
#size-cells = <0x0>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
index 4cbd626..c7f008a 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
@@ -62,7 +62,7 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x40000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x3f000000>;
};
leds {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 238fbea..546cbe4 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -61,7 +61,7 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x80000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x7f000000>;
};
usb_otg_pwr: regulator-usb-pwrs {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index 4a96e0f..1fdf6da 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -55,7 +55,7 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x40000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x3f000000>;
};
usb_pwr: regulator-usb-pwrs {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts
index 62fb496..6ac5c89 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts
@@ -50,6 +50,6 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x80000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x7f000000>;
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts
index 9a9663a..58be8b4 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts
@@ -50,6 +50,6 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x40000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x3f000000>;
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts
index 2fe167b..010cb29 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts
@@ -50,6 +50,6 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x80000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x7f000000>;
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
index cea4a3e..fb4a89b 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
@@ -60,7 +60,7 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x80000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x7f000000>;
};
vddio_card: gpio-regulator {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
index 9639f01..908894c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
@@ -59,7 +59,7 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x80000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x7f000000>;
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
index 5a337d3..2077385 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
@@ -62,7 +62,7 @@
memory at 0 {
device_type = "memory";
- reg = <0x0 0x0 0x0 0x80000000>;
+ linux,usable-memory = <0x0 0x1000000 0x0 0x7f000000>;
};
vddio_boot: regulator-vddio-boot {
--
1.9.1
^ permalink raw reply related
* [PATCH 0/5] ARM: dts: boundary: remove hardcoded LVDS bus format
From: Shawn Guo @ 2016-12-30 13:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202090843.22613-1-gary.bisson@boundarydevices.com>
On Fri, Dec 02, 2016 at 10:08:38AM +0100, Gary Bisson wrote:
> Gary Bisson (5):
> ARM: dts: imx6qdl-nit6xlite: remove hardcoded LVDS bus format
> ARM: dts: imx6qdl-nitrogen6_max: remove hardcoded LVDS bus format
> ARM: dts: imx6qdl-nitrogen6_som2: remove hardcoded LVDS bus format
> ARM: dts: imx6qdl-nitrogen6x: remove hardcoded LVDS bus format
> ARM: dts: imx6qdl-sabrelite: remove hardcoded LVDS bus format
I squashed them and applied, thanks.
Shawn
^ permalink raw reply
* [PATCH v4 4/4] clk: samsung: exynos-audss: Use runtime PM
From: Marek Szyprowski @ 2016-12-30 13:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483104816-20885-1-git-send-email-m.szyprowski@samsung.com>
This patch adds support for runtime PM to Exynos Audio SubSystem driver to
enable full support for audio power domain on Exynos5 SoCs. The main change
is moving register saving and restoring code from system sleep PM ops to
runtime PM ops and implementing system sleep PM ops with generic
pm_runtime_force_suspend/resume helpers. Runtime PM of the Exynos AudSS
device is managed from clock core depending on the preparation status
of the provided clocks.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
This patch depends on "clk/samsung: exynos-audss: Replace syscore PM with
platform device PM" patch, which has been already queued for merging:
https://patchwork.kernel.org/patch/9447115/
---
.../devicetree/bindings/clock/clk-exynos-audss.txt | 6 +++
drivers/clk/samsung/clk-exynos-audss.c | 62 +++++++++++++---------
2 files changed, 43 insertions(+), 25 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
index 0c3d6015868d..f3635d5aeba4 100644
--- a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
+++ b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
@@ -33,6 +33,12 @@ Required Properties:
- clock-names: Aliases for the above clocks. They should be "pll_ref",
"pll_in", "cdclk", "sclk_audio", and "sclk_pcm_in" respectively.
+Optional Properties:
+
+ - power-domains: a phandle to respective power domain node as described by
+ generic PM domain bindings (see power/power_domain.txt for more
+ information).
+
The following is the list of clocks generated by the controller. Each clock is
assigned an identifier and client nodes use this identifier to specify the
clock which they consume. Some of the clocks are available only on a particular
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index cb7df358a27d..25bb569bdd30 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -18,6 +18,7 @@
#include <linux/syscore_ops.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <dt-bindings/clock/exynos-audss-clk.h>
@@ -134,6 +135,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in;
const struct exynos_audss_clk_drvdata *variant;
struct resource *res;
+ struct device *dev = &pdev->dev;
int i, ret = 0;
variant = of_device_get_match_data(&pdev->dev);
@@ -141,15 +143,15 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- reg_base = devm_ioremap_resource(&pdev->dev, res);
+ reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(reg_base)) {
- dev_err(&pdev->dev, "failed to map audss registers\n");
+ dev_err(dev, "failed to map audss registers\n");
return PTR_ERR(reg_base);
}
epll = ERR_PTR(-ENODEV);
- clk_table = devm_kzalloc(&pdev->dev,
+ clk_table = devm_kzalloc(dev,
sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS,
GFP_KERNEL);
if (!clk_table)
@@ -158,8 +160,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
clk_data.clks = clk_table;
clk_data.clk_num = variant->num_clks;
- pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
- pll_in = devm_clk_get(&pdev->dev, "pll_in");
+ pll_ref = devm_clk_get(dev, "pll_ref");
+ pll_in = devm_clk_get(dev, "pll_in");
if (!IS_ERR(pll_ref))
mout_audss_p[0] = __clk_get_name(pll_ref);
if (!IS_ERR(pll_in)) {
@@ -170,81 +172,89 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
ret = clk_prepare_enable(epll);
if (ret) {
- dev_err(&pdev->dev,
+ dev_err(dev,
"failed to prepare the epll clock\n");
return ret;
}
}
}
- clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
+
+ /*
+ * Enable runtime PM here, so clock core with use runtime PM for all
+ * registered clocks.
+ */
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(dev, "mout_audss",
mout_audss_p, ARRAY_SIZE(mout_audss_p),
CLK_SET_RATE_NO_REPARENT,
reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
- cdclk = devm_clk_get(&pdev->dev, "cdclk");
- sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio");
+ cdclk = devm_clk_get(dev, "cdclk");
+ sclk_audio = devm_clk_get(dev, "sclk_audio");
if (!IS_ERR(cdclk))
mout_i2s_p[1] = __clk_get_name(cdclk);
if (!IS_ERR(sclk_audio))
mout_i2s_p[2] = __clk_get_name(sclk_audio);
- clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s",
+ clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(dev, "mout_i2s",
mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
CLK_SET_RATE_NO_REPARENT,
reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
- clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp",
+ clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(dev, "dout_srp",
"mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4,
0, &lock);
- clk_table[EXYNOS_DOUT_AUD_BUS] = clk_register_divider(NULL,
+ clk_table[EXYNOS_DOUT_AUD_BUS] = clk_register_divider(dev,
"dout_aud_bus", "dout_srp", 0,
reg_base + ASS_CLK_DIV, 4, 4, 0, &lock);
- clk_table[EXYNOS_DOUT_I2S] = clk_register_divider(NULL, "dout_i2s",
+ clk_table[EXYNOS_DOUT_I2S] = clk_register_divider(dev, "dout_i2s",
"mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0,
&lock);
- clk_table[EXYNOS_SRP_CLK] = clk_register_gate(NULL, "srp_clk",
+ clk_table[EXYNOS_SRP_CLK] = clk_register_gate(dev, "srp_clk",
"dout_srp", CLK_SET_RATE_PARENT,
reg_base + ASS_CLK_GATE, 0, 0, &lock);
- clk_table[EXYNOS_I2S_BUS] = clk_register_gate(NULL, "i2s_bus",
+ clk_table[EXYNOS_I2S_BUS] = clk_register_gate(dev, "i2s_bus",
"dout_aud_bus", CLK_SET_RATE_PARENT,
reg_base + ASS_CLK_GATE, 2, 0, &lock);
- clk_table[EXYNOS_SCLK_I2S] = clk_register_gate(NULL, "sclk_i2s",
+ clk_table[EXYNOS_SCLK_I2S] = clk_register_gate(dev, "sclk_i2s",
"dout_i2s", CLK_SET_RATE_PARENT,
reg_base + ASS_CLK_GATE, 3, 0, &lock);
- clk_table[EXYNOS_PCM_BUS] = clk_register_gate(NULL, "pcm_bus",
+ clk_table[EXYNOS_PCM_BUS] = clk_register_gate(dev, "pcm_bus",
"sclk_pcm", CLK_SET_RATE_PARENT,
reg_base + ASS_CLK_GATE, 4, 0, &lock);
- sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in");
+ sclk_pcm_in = devm_clk_get(dev, "sclk_pcm_in");
if (!IS_ERR(sclk_pcm_in))
sclk_pcm_p = __clk_get_name(sclk_pcm_in);
- clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm",
+ clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(dev, "sclk_pcm",
sclk_pcm_p, CLK_SET_RATE_PARENT,
reg_base + ASS_CLK_GATE, 5, 0, &lock);
if (variant->has_adma_clk) {
- clk_table[EXYNOS_ADMA] = clk_register_gate(NULL, "adma",
+ clk_table[EXYNOS_ADMA] = clk_register_gate(dev, "adma",
"dout_srp", CLK_SET_RATE_PARENT,
reg_base + ASS_CLK_GATE, 9, 0, &lock);
}
for (i = 0; i < clk_data.clk_num; i++) {
if (IS_ERR(clk_table[i])) {
- dev_err(&pdev->dev, "failed to register clock %d\n", i);
+ dev_err(dev, "failed to register clock %d\n", i);
ret = PTR_ERR(clk_table[i]);
goto unregister;
}
}
- ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
+ ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
&clk_data);
if (ret) {
- dev_err(&pdev->dev, "failed to add clock provider\n");
+ dev_err(dev, "failed to add clock provider\n");
goto unregister;
}
@@ -272,8 +282,10 @@ static int exynos_audss_clk_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops exynos_audss_clk_pm_ops = {
- SET_LATE_SYSTEM_SLEEP_PM_OPS(exynos_audss_clk_suspend,
- exynos_audss_clk_resume)
+ SET_RUNTIME_PM_OPS(exynos_audss_clk_suspend, exynos_audss_clk_resume,
+ NULL)
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
};
static struct platform_driver exynos_audss_clk_driver = {
--
1.9.1
^ permalink raw reply related
* [PATCH v4 3/4] clk: samsung: exynos5433: Add runtime PM support
From: Marek Szyprowski @ 2016-12-30 13:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483104816-20885-1-git-send-email-m.szyprowski@samsung.com>
Add runtime pm support for all clock controller units (CMU), which belongs
to power domains and require special handling during on/off operations.
Typically special values has to be written to MUX registers to change
internal clocks parents to OSC clock before turning power off. During such
operation all clocks, which enters CMU has to be enabled to let MUX to
stabilize. Also for each CMU there is one special parent clock, which has
to be enabled all the time when any access to CMU registers is done.
This patch solves most of the mysterious external abort and freeze issues
caused by a lack of proper parent CMU clock enabled or incorrect turn off
procedure.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
.../devicetree/bindings/clock/exynos5433-clock.txt | 16 +
drivers/clk/samsung/clk-exynos5433.c | 415 ++++++++++++++++-----
drivers/clk/samsung/clk.h | 6 +
3 files changed, 352 insertions(+), 85 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/exynos5433-clock.txt b/Documentation/devicetree/bindings/clock/exynos5433-clock.txt
index 1dc80f8811fe..5c7dd12e667a 100644
--- a/Documentation/devicetree/bindings/clock/exynos5433-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos5433-clock.txt
@@ -168,6 +168,11 @@ Required Properties:
- aclk_cam1_400
- aclk_cam1_552
+Optional properties:
+ - power-domains: a phandle to respective power domain node as described by
+ generic PM domain bindings (see power/power_domain.txt for more
+ information).
+
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume.
@@ -270,6 +275,7 @@ Example 2: Examples of clock controller nodes are listed below.
clocks = <&xxti>,
<&cmu_top CLK_ACLK_G2D_266>,
<&cmu_top CLK_ACLK_G2D_400>;
+ power-domains = <&pd_g2d>;
};
cmu_disp: clock-controller at 13b90000 {
@@ -295,6 +301,7 @@ Example 2: Examples of clock controller nodes are listed below.
<&cmu_mif CLK_SCLK_DECON_ECLK_DISP>,
<&cmu_mif CLK_SCLK_DECON_TV_VCLK_DISP>,
<&cmu_mif CLK_ACLK_DISP_333>;
+ power-domains = <&pd_disp>;
};
cmu_aud: clock-controller at 114c0000 {
@@ -304,6 +311,7 @@ Example 2: Examples of clock controller nodes are listed below.
clock-names = "oscclk", "fout_aud_pll";
clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>;
+ power-domains = <&pd_aud>;
};
cmu_bus0: clock-controller at 13600000 {
@@ -340,6 +348,7 @@ Example 2: Examples of clock controller nodes are listed below.
clock-names = "oscclk", "aclk_g3d_400";
clocks = <&xxti>, <&cmu_top CLK_ACLK_G3D_400>;
+ power-domains = <&pd_g3d>;
};
cmu_gscl: clock-controller at 13cf0000 {
@@ -353,6 +362,7 @@ Example 2: Examples of clock controller nodes are listed below.
clocks = <&xxti>,
<&cmu_top CLK_ACLK_GSCL_111>,
<&cmu_top CLK_ACLK_GSCL_333>;
+ power-domains = <&pd_gscl>;
};
cmu_apollo: clock-controller at 11900000 {
@@ -384,6 +394,7 @@ Example 2: Examples of clock controller nodes are listed below.
clocks = <&xxti>,
<&cmu_top CLK_SCLK_JPEG_MSCL>,
<&cmu_top CLK_ACLK_MSCL_400>;
+ power-domains = <&pd_mscl>;
};
cmu_mfc: clock-controller at 15280000 {
@@ -393,6 +404,7 @@ Example 2: Examples of clock controller nodes are listed below.
clock-names = "oscclk", "aclk_mfc_400";
clocks = <&xxti>, <&cmu_top CLK_ACLK_MFC_400>;
+ power-domains = <&pd_mfc>;
};
cmu_hevc: clock-controller at 14f80000 {
@@ -402,6 +414,7 @@ Example 2: Examples of clock controller nodes are listed below.
clock-names = "oscclk", "aclk_hevc_400";
clocks = <&xxti>, <&cmu_top CLK_ACLK_HEVC_400>;
+ power-domains = <&pd_hevc>;
};
cmu_isp: clock-controller at 146d0000 {
@@ -415,6 +428,7 @@ Example 2: Examples of clock controller nodes are listed below.
clocks = <&xxti>,
<&cmu_top CLK_ACLK_ISP_DIS_400>,
<&cmu_top CLK_ACLK_ISP_400>;
+ power-domains = <&pd_isp>;
};
cmu_cam0: clock-controller at 120d0000 {
@@ -430,6 +444,7 @@ Example 2: Examples of clock controller nodes are listed below.
<&cmu_top CLK_ACLK_CAM0_333>,
<&cmu_top CLK_ACLK_CAM0_400>,
<&cmu_top CLK_ACLK_CAM0_552>;
+ power-domains = <&pd_cam0>;
};
cmu_cam1: clock-controller at 145d0000 {
@@ -451,6 +466,7 @@ Example 2: Examples of clock controller nodes are listed below.
<&cmu_top CLK_ACLK_CAM1_333>,
<&cmu_top CLK_ACLK_CAM1_400>,
<&cmu_top CLK_ACLK_CAM1_552>;
+ power-domains = <&pd_cam1>;
};
Example 3: UART controller node that consumes the clock generated by the clock
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index f096bd7df40c..9b12bc20c455 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -9,9 +9,14 @@
* Common Clock Framework support for Exynos5443 SoC.
*/
+#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
#include <dt-bindings/clock/exynos5433.h>
@@ -1989,6 +1994,14 @@ static void __init exynos5433_cmu_peris_init(struct device_node *np)
ENABLE_IP_FSYS1,
};
+static const struct samsung_clk_reg_dump fsys_suspend_regs[] = {
+ { MUX_SEL_FSYS0, 0 },
+ { MUX_SEL_FSYS1, 0 },
+ { MUX_SEL_FSYS2, 0 },
+ { MUX_SEL_FSYS3, 0 },
+ { MUX_SEL_FSYS4, 0 },
+};
+
static const struct samsung_fixed_rate_clock fsys_fixed_clks[] __initconst = {
/* PHY clocks from USBDRD30_PHY */
FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY,
@@ -2294,16 +2307,11 @@ static void __init exynos5433_cmu_peris_init(struct device_node *np)
.nr_clk_ids = FSYS_NR_CLK,
.clk_regs = fsys_clk_regs,
.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs),
+ .suspend_regs = fsys_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(fsys_suspend_regs),
+ .clk_name = "aclk_fsys_200",
};
-static void __init exynos5433_cmu_fsys_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &fsys_cmu_info);
-}
-
-CLK_OF_DECLARE(exynos5433_cmu_fsys, "samsung,exynos5433-cmu-fsys",
- exynos5433_cmu_fsys_init);
-
/*
* Register offset definitions for CMU_G2D
*/
@@ -2333,6 +2341,10 @@ static void __init exynos5433_cmu_fsys_init(struct device_node *np)
DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D,
};
+static const struct samsung_clk_reg_dump g2d_suspend_regs[] = {
+ { MUX_SEL_G2D0, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_aclk_g2d_266_user_p) = { "oscclk", "aclk_g2d_266", };
PNAME(mout_aclk_g2d_400_user_p) = { "oscclk", "aclk_g2d_400", };
@@ -2418,16 +2430,11 @@ static void __init exynos5433_cmu_fsys_init(struct device_node *np)
.nr_clk_ids = G2D_NR_CLK,
.clk_regs = g2d_clk_regs,
.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs),
+ .suspend_regs = g2d_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(g2d_suspend_regs),
+ .clk_name = "aclk_g2d_400",
};
-static void __init exynos5433_cmu_g2d_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &g2d_cmu_info);
-}
-
-CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d",
- exynos5433_cmu_g2d_init);
-
/*
* Register offset definitions for CMU_DISP
*/
@@ -2492,6 +2499,16 @@ static void __init exynos5433_cmu_g2d_init(struct device_node *np)
CLKOUT_CMU_DISP_DIV_STAT,
};
+static const struct samsung_clk_reg_dump disp_suspend_regs[] = {
+ /* ignore status of external PHY muxes during suspend to avoid hangs */
+ { MUX_IGNORE_DISP2, 0x00111111 },
+ { MUX_SEL_DISP0, 0 },
+ { MUX_SEL_DISP1, 0 },
+ { MUX_SEL_DISP2, 0 },
+ { MUX_SEL_DISP3, 0 },
+ { MUX_SEL_DISP4, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_disp_pll_p) = { "oscclk", "fout_disp_pll", };
PNAME(mout_sclk_dsim1_user_p) = { "oscclk", "sclk_dsim1_disp", };
@@ -2837,16 +2854,11 @@ static void __init exynos5433_cmu_g2d_init(struct device_node *np)
.nr_clk_ids = DISP_NR_CLK,
.clk_regs = disp_clk_regs,
.nr_clk_regs = ARRAY_SIZE(disp_clk_regs),
+ .suspend_regs = disp_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(disp_suspend_regs),
+ .clk_name = "aclk_disp_333",
};
-static void __init exynos5433_cmu_disp_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &disp_cmu_info);
-}
-
-CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp",
- exynos5433_cmu_disp_init);
-
/*
* Register offset definitions for CMU_AUD
*/
@@ -2881,6 +2893,11 @@ static void __init exynos5433_cmu_disp_init(struct device_node *np)
ENABLE_IP_AUD1,
};
+static const struct samsung_clk_reg_dump aud_suspend_regs[] = {
+ { MUX_SEL_AUD0, 0 },
+ { MUX_SEL_AUD1, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_aud_pll_user_aud_p) = { "oscclk", "fout_aud_pll", };
PNAME(mout_sclk_aud_pcm_p) = { "mout_aud_pll_user", "ioclk_audiocdclk0",};
@@ -3007,16 +3024,11 @@ static void __init exynos5433_cmu_disp_init(struct device_node *np)
.nr_clk_ids = AUD_NR_CLK,
.clk_regs = aud_clk_regs,
.nr_clk_regs = ARRAY_SIZE(aud_clk_regs),
+ .suspend_regs = aud_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(aud_suspend_regs),
+ .clk_name = "fout_aud_pll",
};
-static void __init exynos5433_cmu_aud_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &aud_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_aud, "samsung,exynos5433-cmu-aud",
- exynos5433_cmu_aud_init);
-
-
/*
* Register offset definitions for CMU_BUS{0|1|2}
*/
@@ -3218,6 +3230,10 @@ static void __init exynos5433_cmu_aud_init(struct device_node *np)
CLK_STOPCTRL,
};
+static const struct samsung_clk_reg_dump g3d_suspend_regs[] = {
+ { MUX_SEL_G3D, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_aclk_g3d_400_p) = { "mout_g3d_pll", "aclk_g3d_400", };
PNAME(mout_g3d_pll_p) = { "oscclk", "fout_g3d_pll", };
@@ -3291,15 +3307,11 @@ static void __init exynos5433_cmu_aud_init(struct device_node *np)
.nr_clk_ids = G3D_NR_CLK,
.clk_regs = g3d_clk_regs,
.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs),
+ .suspend_regs = g3d_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(g3d_suspend_regs),
+ .clk_name = "aclk_g3d_400",
};
-static void __init exynos5433_cmu_g3d_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &g3d_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d",
- exynos5433_cmu_g3d_init);
-
/*
* Register offset definitions for CMU_GSCL
*/
@@ -3338,6 +3350,12 @@ static void __init exynos5433_cmu_g3d_init(struct device_node *np)
ENABLE_IP_GSCL_SECURE_SMMU_GSCL2,
};
+static const struct samsung_clk_reg_dump gscl_suspend_regs[] = {
+ { MUX_SEL_GSCL, 0 },
+ { ENABLE_ACLK_GSCL, 0xfff },
+ { ENABLE_PCLK_GSCL, 0xff },
+};
+
/* list of all parent clock list */
PNAME(aclk_gscl_111_user_p) = { "oscclk", "aclk_gscl_111", };
PNAME(aclk_gscl_333_user_p) = { "oscclk", "aclk_gscl_333", };
@@ -3432,15 +3450,11 @@ static void __init exynos5433_cmu_g3d_init(struct device_node *np)
.nr_clk_ids = GSCL_NR_CLK,
.clk_regs = gscl_clk_regs,
.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs),
+ .suspend_regs = gscl_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(gscl_suspend_regs),
+ .clk_name = "aclk_gscl_111",
};
-static void __init exynos5433_cmu_gscl_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &gscl_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl",
- exynos5433_cmu_gscl_init);
-
/*
* Register offset definitions for CMU_APOLLO
*/
@@ -3966,6 +3980,11 @@ static void __init exynos5433_cmu_atlas_init(struct device_node *np)
ENABLE_IP_MSCL_SECURE_SMMU_JPEG,
};
+static const struct samsung_clk_reg_dump mscl_suspend_regs[] = {
+ { MUX_SEL_MSCL0, 0 },
+ { MUX_SEL_MSCL1, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_sclk_jpeg_user_p) = { "oscclk", "sclk_jpeg_mscl", };
PNAME(mout_aclk_mscl_400_user_p) = { "oscclk", "aclk_mscl_400", };
@@ -4078,15 +4097,11 @@ static void __init exynos5433_cmu_atlas_init(struct device_node *np)
.nr_clk_ids = MSCL_NR_CLK,
.clk_regs = mscl_clk_regs,
.nr_clk_regs = ARRAY_SIZE(mscl_clk_regs),
+ .suspend_regs = mscl_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(mscl_suspend_regs),
+ .clk_name = "aclk_mscl_400",
};
-static void __init exynos5433_cmu_mscl_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &mscl_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl",
- exynos5433_cmu_mscl_init);
-
/*
* Register offset definitions for CMU_MFC
*/
@@ -4116,6 +4131,10 @@ static void __init exynos5433_cmu_mscl_init(struct device_node *np)
ENABLE_IP_MFC_SECURE_SMMU_MFC,
};
+static const struct samsung_clk_reg_dump mfc_suspend_regs[] = {
+ { MUX_SEL_MFC, 0 },
+};
+
PNAME(mout_aclk_mfc_400_user_p) = { "oscclk", "aclk_mfc_400", };
static const struct samsung_mux_clock mfc_mux_clks[] __initconst = {
@@ -4186,15 +4205,11 @@ static void __init exynos5433_cmu_mscl_init(struct device_node *np)
.nr_clk_ids = MFC_NR_CLK,
.clk_regs = mfc_clk_regs,
.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs),
+ .suspend_regs = mfc_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(mfc_suspend_regs),
+ .clk_name = "aclk_mfc_400",
};
-static void __init exynos5433_cmu_mfc_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &mfc_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc",
- exynos5433_cmu_mfc_init);
-
/*
* Register offset definitions for CMU_HEVC
*/
@@ -4224,6 +4239,10 @@ static void __init exynos5433_cmu_mfc_init(struct device_node *np)
ENABLE_IP_HEVC_SECURE_SMMU_HEVC,
};
+static const struct samsung_clk_reg_dump hevc_suspend_regs[] = {
+ { MUX_SEL_HEVC, 0 },
+};
+
PNAME(mout_aclk_hevc_400_user_p) = { "oscclk", "aclk_hevc_400", };
static const struct samsung_mux_clock hevc_mux_clks[] __initconst = {
@@ -4296,15 +4315,11 @@ static void __init exynos5433_cmu_mfc_init(struct device_node *np)
.nr_clk_ids = HEVC_NR_CLK,
.clk_regs = hevc_clk_regs,
.nr_clk_regs = ARRAY_SIZE(hevc_clk_regs),
+ .suspend_regs = hevc_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(hevc_suspend_regs),
+ .clk_name = "aclk_hevc_400",
};
-static void __init exynos5433_cmu_hevc_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &hevc_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc",
- exynos5433_cmu_hevc_init);
-
/*
* Register offset definitions for CMU_ISP
*/
@@ -4338,6 +4353,10 @@ static void __init exynos5433_cmu_hevc_init(struct device_node *np)
ENABLE_IP_ISP3,
};
+static const struct samsung_clk_reg_dump isp_suspend_regs[] = {
+ { MUX_SEL_ISP, 0 },
+};
+
PNAME(mout_aclk_isp_dis_400_user_p) = { "oscclk", "aclk_isp_dis_400", };
PNAME(mout_aclk_isp_400_user_p) = { "oscclk", "aclk_isp_400", };
@@ -4549,15 +4568,11 @@ static void __init exynos5433_cmu_hevc_init(struct device_node *np)
.nr_clk_ids = ISP_NR_CLK,
.clk_regs = isp_clk_regs,
.nr_clk_regs = ARRAY_SIZE(isp_clk_regs),
+ .suspend_regs = isp_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(isp_suspend_regs),
+ .clk_name = "aclk_isp_400",
};
-static void __init exynos5433_cmu_isp_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &isp_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp",
- exynos5433_cmu_isp_init);
-
/*
* Register offset definitions for CMU_CAM0
*/
@@ -4621,6 +4636,15 @@ static void __init exynos5433_cmu_isp_init(struct device_node *np)
ENABLE_IP_CAM02,
ENABLE_IP_CAM03,
};
+
+static const struct samsung_clk_reg_dump cam0_suspend_regs[] = {
+ { MUX_SEL_CAM00, 0 },
+ { MUX_SEL_CAM01, 0 },
+ { MUX_SEL_CAM02, 0 },
+ { MUX_SEL_CAM03, 0 },
+ { MUX_SEL_CAM04, 0 },
+};
+
PNAME(mout_aclk_cam0_333_user_p) = { "oscclk", "aclk_cam0_333", };
PNAME(mout_aclk_cam0_400_user_p) = { "oscclk", "aclk_cam0_400", };
PNAME(mout_aclk_cam0_552_user_p) = { "oscclk", "aclk_cam0_552", };
@@ -5026,15 +5050,11 @@ static void __init exynos5433_cmu_isp_init(struct device_node *np)
.nr_clk_ids = CAM0_NR_CLK,
.clk_regs = cam0_clk_regs,
.nr_clk_regs = ARRAY_SIZE(cam0_clk_regs),
+ .suspend_regs = cam0_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(cam0_suspend_regs),
+ .clk_name = "aclk_cam0_400",
};
-static void __init exynos5433_cmu_cam0_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &cam0_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0",
- exynos5433_cmu_cam0_init);
-
/*
* Register offset definitions for CMU_CAM1
*/
@@ -5081,6 +5101,12 @@ static void __init exynos5433_cmu_cam0_init(struct device_node *np)
ENABLE_IP_CAM12,
};
+static const struct samsung_clk_reg_dump cam1_suspend_regs[] = {
+ { MUX_SEL_CAM10, 0 },
+ { MUX_SEL_CAM11, 0 },
+ { MUX_SEL_CAM12, 0 },
+};
+
PNAME(mout_sclk_isp_uart_user_p) = { "oscclk", "sclk_isp_uart_cam1", };
PNAME(mout_sclk_isp_spi1_user_p) = { "oscclk", "sclk_isp_spi1_cam1", };
PNAME(mout_sclk_isp_spi0_user_p) = { "oscclk", "sclk_isp_spi0_cam1", };
@@ -5399,11 +5425,230 @@ static void __init exynos5433_cmu_cam0_init(struct device_node *np)
.nr_clk_ids = CAM1_NR_CLK,
.clk_regs = cam1_clk_regs,
.nr_clk_regs = ARRAY_SIZE(cam1_clk_regs),
+ .suspend_regs = cam1_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(cam1_suspend_regs),
+ .clk_name = "aclk_cam1_400",
+};
+
+
+struct exynos5433_cmu_data {
+ struct samsung_clk_provider ctx;
+
+ struct samsung_clk_reg_dump *clk_save;
+ unsigned int nr_clk_save;
+ const struct samsung_clk_reg_dump *clk_suspend;
+ unsigned int nr_clk_suspend;
+
+ struct clk *clk;
+ struct clk **pclks;
+ int nr_pclks;
+};
+
+static int exynos5433_cmu_suspend(struct device *dev)
+{
+ struct exynos5433_cmu_data *data = dev_get_drvdata(dev);
+ int i;
+
+ samsung_clk_save(data->ctx.reg_base, data->clk_save,
+ data->nr_clk_save);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_enable(data->pclks[i]);
+
+ samsung_clk_restore(data->ctx.reg_base, data->clk_suspend,
+ data->nr_clk_suspend);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_disable(data->pclks[i]);
+
+ clk_disable(data->clk);
+
+ return 0;
+}
+
+static int exynos5433_cmu_resume(struct device *dev)
+{
+ struct exynos5433_cmu_data *data = dev_get_drvdata(dev);
+ int i;
+
+ clk_enable(data->clk);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_enable(data->pclks[i]);
+
+ samsung_clk_restore(data->ctx.reg_base, data->clk_save,
+ data->nr_clk_save);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_disable(data->pclks[i]);
+
+ return 0;
+}
+
+static int __init exynos5433_cmu_probe(struct platform_device *pdev)
+{
+ const struct samsung_cmu_info *info;
+ struct exynos5433_cmu_data *data;
+ struct samsung_clk_provider *ctx;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ void __iomem *reg_base;
+ struct clk **clk_table;
+ int i;
+
+ info = of_device_get_match_data(dev);
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ ctx = &data->ctx;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg_base = devm_ioremap_resource(dev, res);
+ if (!reg_base) {
+ dev_err(dev, "failed to map registers\n");
+ return -ENOMEM;
+ }
+
+ clk_table = devm_kcalloc(dev, info->nr_clk_ids, sizeof(struct clk *),
+ GFP_KERNEL);
+ if (!clk_table)
+ return -ENOMEM;
+
+ for (i = 0; i < info->nr_clk_ids; ++i)
+ clk_table[i] = ERR_PTR(-ENOENT);
+
+ ctx->clk_data.clks = clk_table;
+ ctx->clk_data.clk_num = info->nr_clk_ids;
+ ctx->reg_base = reg_base;
+ ctx->dev = dev;
+ spin_lock_init(&ctx->lock);
+
+ data->clk_save = samsung_clk_alloc_reg_dump(info->clk_regs,
+ info->nr_clk_regs);
+ data->nr_clk_save = info->nr_clk_regs;
+ data->clk_suspend = info->suspend_regs;
+ data->nr_clk_suspend = info->nr_suspend_regs;
+ data->nr_pclks = of_count_phandle_with_args(dev->of_node, "clocks",
+ "#clock-cells");
+ if (data->nr_pclks > 0) {
+ data->pclks = devm_kcalloc(dev, sizeof(struct clk *),
+ data->nr_pclks, GFP_KERNEL);
+
+ for (i = 0; i < data->nr_pclks; i++) {
+ struct clk *clk = of_clk_get(dev->of_node, i);
+
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ data->pclks[i] = clk;
+ }
+ }
+
+ /*
+ * Prepare all parent clocks here to avoid potential deadlock caused
+ * by global clock "prepare lock" grabbed by runtime pm callbacks
+ * from pm workers.
+ */
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_prepare(data->pclks[i]);
+
+ if (info->clk_name)
+ data->clk = clk_get(dev, info->clk_name);
+ clk_prepare_enable(data->clk);
+
+ platform_set_drvdata(pdev, data);
+
+ /*
+ * Enable runtime pm here, so clock core with use runtime pm for all
+ * registered clocks.
+ */
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ if (info->pll_clks)
+ samsung_clk_register_pll(ctx, info->pll_clks, info->nr_pll_clks,
+ reg_base);
+ if (info->mux_clks)
+ samsung_clk_register_mux(ctx, info->mux_clks,
+ info->nr_mux_clks);
+ if (info->div_clks)
+ samsung_clk_register_div(ctx, info->div_clks,
+ info->nr_div_clks);
+ if (info->gate_clks)
+ samsung_clk_register_gate(ctx, info->gate_clks,
+ info->nr_gate_clks);
+ if (info->fixed_clks)
+ samsung_clk_register_fixed_rate(ctx, info->fixed_clks,
+ info->nr_fixed_clks);
+ if (info->fixed_factor_clks)
+ samsung_clk_register_fixed_factor(ctx, info->fixed_factor_clks,
+ info->nr_fixed_factor_clks);
+
+ samsung_clk_of_add_provider(dev->of_node, ctx);
+
+ return 0;
+}
+
+static const struct of_device_id exynos5433_cmu_of_match[] = {
+ {
+ .compatible = "samsung,exynos5433-cmu-aud",
+ .data = &aud_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-cam0",
+ .data = &cam0_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-cam1",
+ .data = &cam1_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-disp",
+ .data = &disp_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-g2d",
+ .data = &g2d_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-g3d",
+ .data = &g3d_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-fsys",
+ .data = &fsys_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-gscl",
+ .data = &gscl_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-mfc",
+ .data = &mfc_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-hevc",
+ .data = &hevc_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-isp",
+ .data = &isp_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-mscl",
+ .data = &mscl_cmu_info,
+ }, {
+ },
+};
+
+static const struct dev_pm_ops exynos5433_cmu_pm_ops = {
+ SET_RUNTIME_PM_OPS(exynos5433_cmu_suspend, exynos5433_cmu_resume,
+ NULL)
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+};
+
+static struct platform_driver exynos5433_cmu_driver __refdata = {
+ .driver = {
+ .name = "exynos5433-cmu",
+ .of_match_table = exynos5433_cmu_of_match,
+ .suppress_bind_attrs = true,
+ .pm = &exynos5433_cmu_pm_ops,
+ },
+ .probe = exynos5433_cmu_probe,
};
-static void __init exynos5433_cmu_cam1_init(struct device_node *np)
+static int __init exynos5433_cmu_init(void)
{
- samsung_cmu_register_one(np, &cam1_cmu_info);
+ return platform_driver_register(&exynos5433_cmu_driver);
}
-CLK_OF_DECLARE(exynos5433_cmu_cam1, "samsung,exynos5433-cmu-cam1",
- exynos5433_cmu_cam1_init);
+core_initcall(exynos5433_cmu_init);
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 9263d8a27c6b..664020cb4794 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -354,6 +354,12 @@ struct samsung_cmu_info {
/* list and number of clocks registers */
const unsigned long *clk_regs;
unsigned int nr_clk_regs;
+
+ /* list and number of clocks registers to set before suspend */
+ const struct samsung_clk_reg_dump *suspend_regs;
+ unsigned int nr_suspend_regs;
+ /* name of the parent clock needed for CMU register access */
+ const char *clk_name;
};
extern struct samsung_clk_provider *__init samsung_clk_init(
--
1.9.1
^ permalink raw reply related
* [PATCH v4 2/4] clk: samsung: Add support for runtime PM
From: Marek Szyprowski @ 2016-12-30 13:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483104816-20885-1-git-send-email-m.szyprowski@samsung.com>
This patch adds struct device pointer to samsung_clk_provider and forwarding it
to clk_register_* functions, so drivers can register clocks, which use runtime
pm feature.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/clk/samsung/clk-pll.c | 2 +-
drivers/clk/samsung/clk.c | 12 ++++++------
drivers/clk/samsung/clk.h | 1 +
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 9617825daabb..f5249a7e545d 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -1345,7 +1345,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
pll->lock_reg = base + pll_clk->lock_offset;
pll->con_reg = base + pll_clk->con_offset;
- clk = clk_register(NULL, &pll->hw);
+ clk = clk_register(ctx->dev, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll clock %s : %ld\n",
__func__, pll_clk->name, PTR_ERR(clk));
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index b7d87d6db9dc..e6923714f024 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -143,7 +143,7 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
- clk = clk_register_fixed_rate(NULL, list->name,
+ clk = clk_register_fixed_rate(ctx->dev, list->name,
list->parent_name, list->flags, list->fixed_rate);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
@@ -172,7 +172,7 @@ void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
unsigned int idx;
for (idx = 0; idx < nr_clk; idx++, list++) {
- clk = clk_register_fixed_factor(NULL, list->name,
+ clk = clk_register_fixed_factor(ctx->dev, list->name,
list->parent_name, list->flags, list->mult, list->div);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
@@ -193,7 +193,7 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
- clk = clk_register_mux(NULL, list->name, list->parent_names,
+ clk = clk_register_mux(ctx->dev, list->name, list->parent_names,
list->num_parents, list->flags,
ctx->reg_base + list->offset,
list->shift, list->width, list->mux_flags, &ctx->lock);
@@ -226,13 +226,13 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
for (idx = 0; idx < nr_clk; idx++, list++) {
if (list->table)
- clk = clk_register_divider_table(NULL, list->name,
+ clk = clk_register_divider_table(ctx->dev, list->name,
list->parent_name, list->flags,
ctx->reg_base + list->offset,
list->shift, list->width, list->div_flags,
list->table, &ctx->lock);
else
- clk = clk_register_divider(NULL, list->name,
+ clk = clk_register_divider(ctx->dev, list->name,
list->parent_name, list->flags,
ctx->reg_base + list->offset, list->shift,
list->width, list->div_flags, &ctx->lock);
@@ -264,7 +264,7 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
- clk = clk_register_gate(NULL, list->name, list->parent_name,
+ clk = clk_register_gate(ctx->dev, list->name, list->parent_name,
list->flags, ctx->reg_base + list->offset,
list->bit_idx, list->gate_flags, &ctx->lock);
if (IS_ERR(clk)) {
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index da3bdebabf1e..9263d8a27c6b 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -26,6 +26,7 @@
*/
struct samsung_clk_provider {
void __iomem *reg_base;
+ struct device *dev;
struct clk_onecell_data clk_data;
spinlock_t lock;
};
--
1.9.1
^ permalink raw reply related
* [PATCH v4 1/4] clk: Add support for runtime PM
From: Marek Szyprowski @ 2016-12-30 13:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483104816-20885-1-git-send-email-m.szyprowski@samsung.com>
Registers for some clocks might be located in the SOC area, which are under the
power domain. To enable access to those registers respective domain has to be
turned on. Additionally, registers for such clocks will usually loose its
contents when power domain is turned off, so additional saving and restoring of
them might be needed in the clock controller driver.
This patch adds basic infrastructure in the clocks core to allow implementing
driver for such clocks under power domains. Clock provider can supply a
struct device pointer, which is the used by clock core for tracking and managing
clock's controller runtime pm state. Each clk_prepare() operation
will first call pm_runtime_get_sync() on the supplied device, while
clk_unprepare() will do pm_runtime_put() at the end.
Additional calls to pm_runtime_get/put functions are required to ensure that any
register access (like calculating/changing clock rates and unpreparing/disabling
unused clocks on boot) will be done with clock controller in runtime resumend
state.
When one wants to register clock controller, which make use of this feature, he
has to:
1. Provide a struct device to the core when registering the provider.
2. Ensure to enable runtime PM for that device before registering clocks.
3. Make sure that the runtime PM status of the controller device reflects
the HW state.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/clk/clk.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 101 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0fb39fe217d1..3cf202ccf5a9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/device.h>
#include <linux/init.h>
+#include <linux/pm_runtime.h>
#include <linux/sched.h>
#include <linux/clkdev.h>
@@ -46,6 +47,7 @@ struct clk_core {
const struct clk_ops *ops;
struct clk_hw *hw;
struct module *owner;
+ struct device *dev;
struct clk_core *parent;
const char **parent_names;
struct clk_core **parents;
@@ -87,6 +89,26 @@ struct clk {
struct hlist_node clks_node;
};
+/*** runtime pm ***/
+static int clk_pm_runtime_get(struct clk_core *core)
+{
+ int ret = 0;
+
+ if (!core->dev)
+ return 0;
+
+ ret = pm_runtime_get_sync(core->dev);
+ return ret < 0 ? ret : 0;
+}
+
+static void clk_pm_runtime_put(struct clk_core *core)
+{
+ if (!core->dev)
+ return;
+
+ pm_runtime_put(core->dev);
+}
+
/*** locking ***/
static void clk_prepare_lock(void)
{
@@ -150,6 +172,8 @@ static void clk_enable_unlock(unsigned long flags)
static bool clk_core_is_prepared(struct clk_core *core)
{
+ bool status;
+
/*
* .is_prepared is optional for clocks that can prepare
* fall back to software usage counter if it is missing
@@ -157,11 +181,20 @@ static bool clk_core_is_prepared(struct clk_core *core)
if (!core->ops->is_prepared)
return core->prepare_count;
- return core->ops->is_prepared(core->hw);
+ if (clk_pm_runtime_get(core) == 0) {
+ status = core->ops->is_prepared(core->hw);
+ clk_pm_runtime_put(core);
+ } else {
+ status = false;
+ }
+
+ return status;
}
static bool clk_core_is_enabled(struct clk_core *core)
{
+ bool status;
+
/*
* .is_enabled is only mandatory for clocks that gate
* fall back to software usage counter if .is_enabled is missing
@@ -169,7 +202,30 @@ static bool clk_core_is_enabled(struct clk_core *core)
if (!core->ops->is_enabled)
return core->enable_count;
- return core->ops->is_enabled(core->hw);
+ /*
+ * Check if clock controller's device is runtime active before
+ * calling .is_enabled callback. If not, assume that clock is
+ * disabled, because we might be called from atomic context, from
+ * which pm_runtime_get() is not allowed.
+ * This function is called mainly from clk_disable_unused_subtree,
+ * which ensures proper runtime pm activation of controller before
+ * taking enable spinlock, but the below check is needed if one tries
+ * to call it from other places.
+ */
+ if (core->dev) {
+ pm_runtime_get_noresume(core->dev);
+ if (!pm_runtime_active(core->dev)) {
+ status = false;
+ goto done;
+ }
+ }
+
+ status = core->ops->is_enabled(core->hw);
+done:
+ if (core->dev)
+ pm_runtime_put(core->dev);
+
+ return status;
}
/*** helper functions ***/
@@ -489,6 +545,8 @@ static void clk_core_unprepare(struct clk_core *core)
if (core->ops->unprepare)
core->ops->unprepare(core->hw);
+ clk_pm_runtime_put(core);
+
trace_clk_unprepare_complete(core);
clk_core_unprepare(core->parent);
}
@@ -530,10 +588,14 @@ static int clk_core_prepare(struct clk_core *core)
return 0;
if (core->prepare_count == 0) {
- ret = clk_core_prepare(core->parent);
+ ret = clk_pm_runtime_get(core);
if (ret)
return ret;
+ ret = clk_core_prepare(core->parent);
+ if (ret)
+ goto runtime_put;
+
trace_clk_prepare(core);
if (core->ops->prepare)
@@ -541,15 +603,18 @@ static int clk_core_prepare(struct clk_core *core)
trace_clk_prepare_complete(core);
- if (ret) {
- clk_core_unprepare(core->parent);
- return ret;
- }
+ if (ret)
+ goto unprepare;
}
core->prepare_count++;
return 0;
+unprepare:
+ clk_core_unprepare(core->parent);
+runtime_put:
+ clk_pm_runtime_put(core);
+ return ret;
}
static int clk_core_prepare_lock(struct clk_core *core)
@@ -745,6 +810,9 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
if (core->flags & CLK_IGNORE_UNUSED)
return;
+ if (clk_pm_runtime_get(core))
+ return;
+
if (clk_core_is_prepared(core)) {
trace_clk_unprepare(core);
if (core->ops->unprepare_unused)
@@ -753,6 +821,8 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
core->ops->unprepare(core->hw);
trace_clk_unprepare_complete(core);
}
+
+ clk_pm_runtime_put(core);
}
static void clk_disable_unused_subtree(struct clk_core *core)
@@ -768,6 +838,9 @@ static void clk_disable_unused_subtree(struct clk_core *core)
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_prepare_enable(core->parent);
+ if (clk_pm_runtime_get(core))
+ goto unprepare_out;
+
flags = clk_enable_lock();
if (core->enable_count)
@@ -792,6 +865,8 @@ static void clk_disable_unused_subtree(struct clk_core *core)
unlock_out:
clk_enable_unlock(flags);
+ clk_pm_runtime_put(core);
+unprepare_out:
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_disable_unprepare(core->parent);
}
@@ -1563,6 +1638,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
{
struct clk_core *top, *fail_clk;
unsigned long rate = req_rate;
+ int ret = 0;
if (!core)
return 0;
@@ -1579,21 +1655,28 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
if (!top)
return -EINVAL;
+ ret = clk_pm_runtime_get(core);
+ if (ret)
+ return ret;
+
/* notify that we are about to change rates */
fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
if (fail_clk) {
pr_debug("%s: failed to set %s rate\n", __func__,
fail_clk->name);
clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
- return -EBUSY;
+ ret = -EBUSY;
+ goto err;
}
/* change the rates */
clk_change_rate(top);
core->req_rate = req_rate;
+err:
+ clk_pm_runtime_put(core);
- return 0;
+ return ret;
}
/**
@@ -1824,12 +1907,16 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
p_rate = parent->rate;
}
+ ret = clk_pm_runtime_get(core);
+ if (ret)
+ goto out;
+
/* propagate PRE_RATE_CHANGE notifications */
ret = __clk_speculate_rates(core, p_rate);
/* abort if a driver objects */
if (ret & NOTIFY_STOP_MASK)
- goto out;
+ goto runtime_put;
/* do the re-parent */
ret = __clk_set_parent(core, parent, p_index);
@@ -1842,6 +1929,8 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
__clk_recalc_accuracies(core);
}
+runtime_put:
+ clk_pm_runtime_put(core);
out:
clk_prepare_unlock();
@@ -2549,6 +2638,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
goto fail_name;
}
core->ops = hw->init->ops;
+ if (dev && pm_runtime_enabled(dev))
+ core->dev = dev;
if (dev && dev->driver)
core->owner = dev->driver->owner;
core->hw = hw;
--
1.9.1
^ permalink raw reply related
* [PATCH v4 0/4] Add runtime PM support for clocks (on Exynos SoC example)
From: Marek Szyprowski @ 2016-12-30 13:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CGME20161230133344eucas1p21d107e1cf3096916aad1944f7e002bf9@eucas1p2.samsung.com>
Dear All,
This patchset adds runtime PM support to common clock framework. This is an
attempt to implement support for clock controllers, which belongs to a power
domain. This approach works surprisingly well on Exynos 5433 SoC, what allowed
us to solve various freeze/crash issues related to power management.
The main idea behind this patchset is to keep clock's controller power domain
enabled every time when at least one of its clock is enabled or access to its
registers is being made. Clock controller driver (clock provider) can
supply a struct device pointer, which is the used by clock core for tracking and
managing clock's controller runtime pm state. Each clk_prepare() operation will
first call pm_runtime_get_sync() on the supplied device, while clk_unprepare()
will do pm_runtime_put() at the end.
This runtime PM feature has been tested with Exynos4412 (not included in this
patchset) and Exynos5433 clocks drivers. Both have some clocks, which belongs to
respective power domains and need special handling during power on/off
procedures. Till now it wasn't handled at all, what caused various problems.
Patches for clocks drivers change the way the clock provider is initialized.
Instead of CLK_OF_DECLARE based initialization, a complete platform device driver
infrastructure is being used. This is needed to let driver to use runtime PM
feature and integrate with generic power domains. The side-effect of this change
is a delay in clock provider registeration during system boot, so early
initialized drivers might get EPROBEDEFER error when requesting their clocks.
This is an issue for IOMMU drivers, so this patchset will be fully functional
once the deferred probe for IOMMU will be merged.
Patches are based on vanilla v4.10-rc1 kernel.
Best regards
Marek Szyprowski
Samsung R&D Institute Poland
Changelog:
v4:
- Removed patch for Exynos4412 clocks from the patchset. DT bindings for power
domain for ISP sub-controller needs more discussion. It will be handled
separately when the runtime PM for clocks feature gets merged.
- Added patch with runtime PM support for Exynos AudioSS clock controller driver
(needed to enable audio power domain on Exynos5 series).
- Fixes in Exynos5433 driver:
1. added missing clock for Audio CMU
2. added support for FSYS CMU
3. improved support for DISP CMU (thanks to Andrzej Hajda for
investigating that).
- Rebased onto v4.10-rc1
- Waiting for a review...
v3: http://www.spinics.net/lists/arm-kernel/msg538122.html
- Removed CLK_RUNTIME_PM flag, core now simply checks if runtime pm is enabled
for the provided device during clock registration as suggested by Ulf
- Simplified code for exynos4412 isp clock driver registration
- Resolved some other minor issues pointed by Ulf clk core code
- Rebased onto v4.9-rc1 and new version of IOMMU deferred probe patchset
v2: https://www.spinics.net/lists/arm-kernel/msg532798.html
- Simplified clk_pm_runtime_get/put functions, removed workaround for devices
with disabled runtime pm. Such workaround is no longer needed since commit
4d23a5e84806b202d9231929c9507ef7cf7a0185 ("PM / Domains: Allow runtime PM
during system PM phases").
- Added CLK_RUNTIME_PM flag to indicate clocks, for which clock core should
call runtime pm functions. This solves problem with clocks, for which struct
device is already registered, but no runtime pm is enabled.
- Extended commit messages according to Ulf suggestions.
- Fixed some style issues pointed by Barlomiej.
v1: http://www.spinics.net/lists/arm-kernel/msg528128.html
- initial version
Marek Szyprowski (4):
clk: Add support for runtime PM
clk: samsung: Add support for runtime PM
clk: samsung: exynos5433: Add runtime PM support
clk: samsung: exynos-audss: Use runtime PM
.../devicetree/bindings/clock/clk-exynos-audss.txt | 6 +
.../devicetree/bindings/clock/exynos5433-clock.txt | 16 +
drivers/clk/clk.c | 111 +++++-
drivers/clk/samsung/clk-exynos-audss.c | 62 +--
drivers/clk/samsung/clk-exynos5433.c | 415 ++++++++++++++++-----
drivers/clk/samsung/clk-pll.c | 2 +-
drivers/clk/samsung/clk.c | 12 +-
drivers/clk/samsung/clk.h | 7 +
8 files changed, 504 insertions(+), 127 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v2 3/4] ARM64: dts: exynos5433: use macros for pinctrl configuration on Exynos5433
From: Linus Walleij @ 2016-12-30 13:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161230041421.24448-4-andi.shyti@samsung.com>
On Fri, Dec 30, 2016 at 5:14 AM, Andi Shyti <andi.shyti@samsung.com> wrote:
> Use the macros defined in include/dt-bindings/pinctrl/samsung.h
> instead of hardcoded values.
>
> Signed-off-by: Andi Shyti <andi.shyti@samsung.com>
These look fine, but that this and the other DTS patch through ARM SoC.
If you also need the headerfile patch (patch 2) to go through ARM SoC
that is fine,
I can take it out of pinctrl if you want.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v2 2/4] pinctrl: dt-bindings: samsung: add drive strength macros for Exynos5433
From: Linus Walleij @ 2016-12-30 13:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161230041421.24448-3-andi.shyti@samsung.com>
On Fri, Dec 30, 2016 at 5:14 AM, Andi Shyti <andi.shyti@samsung.com> wrote:
> Commit 5db7e3bb87df ("pinctrl: dt-bindings: samsung: Add header with
> values used for configuration") has added a header file for defining the
> pinctrl values in order to avoid hardcoded settings in the Exynos
> DTS related files.
>
> Extend samsung.h to the Exynos5433 for drive strength values
> which are strictly related to the particular SoC and may defer
> from others.
>
> Signed-off-by: Andi Shyti <andi.shyti@samsung.com>
Patch applied with Chanwoo's review tag.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v2 1/4] pinctrl: samsung: Fix the width of PINCFG_TYPE_DRV bitfields for Exynos5433
From: Linus Walleij @ 2016-12-30 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161230041421.24448-2-andi.shyti@samsung.com>
On Fri, Dec 30, 2016 at 5:14 AM, Andi Shyti <andi.shyti@samsung.com> wrote:
> From: Chanwoo Choi <cw00.choi@samsung.com>
>
> This patch fixes the wrong width of PINCFG_TYPE_DRV bitfields for Exynos5433
> because PINCFG_TYPE_DRV of Exynos5433 has 4bit fields in the *_DRV
> registers. Usually, other Exynos have 2bit field for PINCFG_TYPE_DRV.
>
> Fixes: 3c5ecc9ed353 ("pinctrl: exynos: Add support for Exynos5433")
> Cc: stable at vger.kernel.org
> Cc: Tomasz Figa <tomasz.figa@gmail.com>
> Cc: Krzysztof Kozlowski <krzk@kernel.org>
> Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Kukjin Kim <kgene@kernel.org>
> Cc: Javier Martinez Canillas <javier@osg.samsung.com>
> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Nominally I think you should sign this off too Andi, as you are in the delivery
path.
Patch applied for fixes.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 10/20] gpio: pca953x: Add optional reset gpio control
From: Linus Walleij @ 2016-12-30 13:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483050455-10683-11-git-send-email-steve_longerbeam@mentor.com>
On Thu, Dec 29, 2016 at 11:27 PM, Steve Longerbeam
<slongerbeam@gmail.com> wrote:
> Add optional reset-gpios pin control. If present, de-assert the
> specified reset gpio pin to bring the chip out of reset.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Alexandre Courbot <gnurou@gmail.com>
> Cc: linux-gpio at vger.kernel.org
> Cc: linux-kernel at vger.kernel.org
This seems like a separate patch from the other 19 patches so please send it
separately so I can handle logistics easier in the future.
> @@ -133,6 +134,7 @@ struct pca953x_chip {
> const char *const *names;
> unsigned long driver_data;
> struct regulator *regulator;
> + struct gpio_desc *reset_gpio;
Why do you even keep this around in the device state container?
As you only use it in the probe() function, use a local variable.
The descriptor will be free():ed by the devm infrastructure anyways.
> + /* see if we need to de-assert a reset pin */
> + chip->reset_gpio = devm_gpiod_get_optional(&client->dev,
> + "reset",
> + GPIOD_OUT_LOW);
> + if (IS_ERR(chip->reset_gpio)) {
> + dev_err(&client->dev, "request for reset pin failed\n");
> + return PTR_ERR(chip->reset_gpio);
> + }
Nice.
> + if (chip->reset_gpio) {
> + /* bring chip out of reset */
> + dev_info(&client->dev, "releasing reset\n");
> + gpiod_set_value(chip->reset_gpio, 0);
> + }
Is this really needed given that you set it low in the
devm_gpiod_get_optional()?
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH V1] pinctrl:pxa:pinctrl-pxa2xx:- No need of devm functions
From: Linus Walleij @ 2016-12-30 13:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87o9zvw69a.fsf@belgarion.home>
On Thu, Dec 29, 2016 at 8:20 AM, Robert Jarzmik <robert.jarzmik@free.fr> wrote:
> Linus Walleij <linus.walleij@linaro.org> writes:
>
>> On Thu, Dec 8, 2016 at 3:35 PM, Arvind Yadav <arvind.yadav.cs@gmail.com> wrote:
>>
>>> In functions pxa2xx_build_functions, the memory allocated for
>>> 'functions' is live within the function only. After the
>>> allocation it is immediately freed with devm_kfree. There is
>>> no need to allocate memory for 'functions' with devm function
>>> so replace devm_kcalloc with kcalloc and devm_kfree with kfree.
>>>
>>> Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
>>
>> I want the maintainer Robert Jarzmik to review this before I do anything
>
> Hi Linus,
>
> I did review, on December the 10th. I wasn't very enthusiastic about the patch,
> if you check back my reply.
Sorry I missed it (mail overload as usual).
OK dropping this.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] pinctrl: single: fix spelling mistakes on "Ivalid"
From: Linus Walleij @ 2016-12-30 13:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161223004714.7491-1-colin.king@canonical.com>
On Fri, Dec 23, 2016 at 1:47 AM, Colin King <colin.king@canonical.com> wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> Trivial fixe to spelling mistake "Ivalid" to "Invalid" in
> dev_err error message.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
Patch applied with Tony's ACK.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 2/3] ARM: dts: imx6ul: Add OCOTP node
From: Shawn Guo @ 2016-12-30 13:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480689949-17957-2-git-send-email-d.schultz@phytec.de>
On Fri, Dec 02, 2016 at 03:45:48PM +0100, Daniel Schultz wrote:
> This device node adds OCOTP for the i.MX6UL SoC.
>
> Signed-off-by: Daniel Schultz <d.schultz@phytec.de>
Bai Ping (Cc'ed here) from NXP is sending similar patches [1]. DTS
change looks good to me, but I will not apply it until the driver and
bindings get accepted.
Shawn
[1] https://www.spinics.net/lists/arm-kernel/msg540900.html
> ---
> arch/arm/boot/dts/imx6ul.dtsi | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
> index c5c05fd..ee53795 100644
> --- a/arch/arm/boot/dts/imx6ul.dtsi
> +++ b/arch/arm/boot/dts/imx6ul.dtsi
> @@ -849,6 +849,12 @@
> reg = <0x021b0000 0x4000>;
> };
>
> + ocotp: ocotp at 021bc000 {
> + compatible = "fsl,imx6ul-ocotp";
> + reg = <0x021bc000 0x4000>;
> + clocks = <&clks IMX6UL_CLK_OCOTP>;
> + };
> +
> lcdif: lcdif at 021c8000 {
> compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
> reg = <0x021c8000 0x4000>;
> --
> 1.9.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [linux-sunxi] [PATCH 1/2] drivers: pinctrl: add driver for Allwinner H5 SoC
From: Linus Walleij @ 2016-12-30 12:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1280f095-ab03-93f8-14d2-99d13ba1ce55@arm.com>
On Mon, Dec 26, 2016 at 3:33 PM, Andr? Przywara <andre.przywara@arm.com> wrote:
> So while this patch technically looks correct, I was wondering if we
> should really explore the possibility of making the whole of sunxi
> pinctrl DT controlled.
> I brought this up a while ago, but people weren't overly enthusiastic
> about it, though their argument weren't really convincing to me[1].
>
> So:
> As this "driver" here is basically a table linking GPIO bit settings
> (the actual mux value) to names and every pin we care about needs to be
> enumerated in the DT anyway, why not just add something like:
> allwinner,pinmux = <4>;
> to each pin(group) in the DT and get rid of this "driver" file here
> entirely?
I'm open to that if you can use pinctrl-single which is in the kernel
for this purpose only, and is used with both OMAPs and HiSilicon.
It recently was improved and will be improved more in this cycle,
see for example:
commit 42124bc598f64f84b3335d5a058304207695b84f
pinctrl: Introduce generic #pinctrl-cells and pinctrl_parse_index_with_args
> (...) Also I guess the common sunxi
> pinctrl driver code needs some significant rework.
I would guess is just needs replacing with pinctrl-single in that case.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 0/2] Use macros to describe gpios on rockchip platform
From: Heiko Stuebner @ 2016-12-30 12:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477140706-6886-1-git-send-email-andy.yan@rock-chips.com>
Am Samstag, 22. Oktober 2016, 20:51:46 CET schrieb Andy Yan:
> As patch 150696e2e3a4("Add GPIO pin index definition for rockchip pinctrl")
> has been applied, now we can use these macros to describe the corresponding
> gpio ranther than hard code numbers, this will make the dts easier to read
> and write.
>
> Some ideas from Krzysztof's patch on EXYNOS[0].
>
> [0]https://lkml.org/lkml/2016/9/4/71
>
>
>
> Andy Yan (2):
> ARM: dts: rockchip: use pin constants to describe gpios
> ARM64: dts: rockchip: use pin constants to describe gpios
applied to dts branches for 4.11
I've also adapted the gpio interrupts accordingly inside the patches.
Thanks
Heiko
^ permalink raw reply
* Unhandled level 2 translation fault (11) at 0x000000b8, esr 0x92000046, rpi3 (aarch64)
From: Bas van Tiel @ 2016-12-30 12:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161230151323.583b7ac5@xhacker>
>> Hi,
>>
>> when using a signal handler as a way to context switch between
>> different usercontexts a reproducible exception occurs on my rpi3 in
>> 64-bit mode. (https://gist.github.com/DanGe42/7148946)
>>
>> Running the context_demo program as a 32-bit ARM executable on a
>> 64-bit kernel is OK, running as a 32 || 64 bit executable on an x86
>> kernel is OK.
>>
>> In the first exception the PC doesn?t look correct, and the *pmd is 0.
>> The 2nd exception happens after running the program again, the PC is 0x0.
>>
>> A successful function trace was not possible -> complete kernel hangup
>> when enabling.
>>
>> Is there another way to gather more information about what is happening?
>
> I can reproduce Segmentation fault with your program on Marvell berlin SoCs
> my kernel version is 4.1, I didn't tested 4.9, 4.10-rc1 etc..
>
> Then I increased the STACKSIZE from 4096 to 8192 in context_demo.c,
> everything works fine now. Maybe arm64 need a bit larger signalstack?
>
yes, increased STACKSIZE to 8192 helps on 4.9/4,10-rc1 but after a
while the exception still occurs, although the message is different.
The *pmd is not 0 in this case.
to trigger this scenario:
- INTERVAL set to 500 [ns]
- kernel with maxcpus=0
- start a 'find /' command in the shell in parallel of the program
- stdout, stderr > redirected to file.
[ 850.581983] a.out[173]: unhandled level 3 permission fault (11) at
0x004391f0, esr 0x8200000f
[ 850.591833] pgd = ffffffc039311000
[ 850.596725] [004391f0] *pgd=0000000039340003
[ 850.602145] , *pud=0000000039340003
[ 850.608352] , *pmd=000000003922c003
[ 850.611963] , *pte=00e80000359c0f53
[ 850.618111]
[ 850.621102]
[ 850.624032] CPU: 0 PID: 173 Comm: a.out Not tainted 4.9.0-v8+ #5
[ 850.631314] Hardware name: Raspberry Pi 3 Model B (DT)
[ 850.637925] task: ffffffc039a13100 task.stack: ffffffc039a14000
[ 850.645314] PC is at 0x4391f0
[ 850.649783] LR is at 0x4391f0
[ 850.654035] pc : [<00000000004391f0>] lr : [<00000000004391f0>]
pstate: 60000000
[ 850.662920] sp : 0000000000420da0
[ 850.667516] x29: 00000000004391f0 x28: 0000000000000000
[ 850.677145] x27: 0000000000000000 x26: 0000000000000000
When I taskset the context_demo program to other cores that are
completely isolated (CONFIG_NO_HZ_FULL, isolcpus=1,2,3) it will run
continuously with the modified STACKSIZE.
regards
Bas
^ permalink raw reply
* [BUG] ARM64: amlogic: gxbb: unhandled level 2 translation fault (11)
From: Heinrich Schuchardt @ 2016-12-30 12:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <c91b83af-0eb8-c519-3428-12f34b04d725@baylibre.com>
On 12/30/2016 10:44 AM, Neil Armstrong wrote:
> On 12/30/2016 09:51 AM, Neil Armstrong wrote:
>> On 12/29/2016 10:18 PM, Heinrich Schuchardt wrote:
>>> On 12/29/2016 10:07 AM, Neil Armstrong wrote:
>>>> On 12/24/2016 03:00 PM, Heinrich Schuchardt wrote:
>>>>> When trying to run sddm on an Hardkernel Odroid C2 I invariably run into the
>>>>> translation fault below.
>>>>>
>>>>> The following mail thread relates this kind of problem to TLB (translation
>>>>> lookaside buffer) broadcasting.
>>>>>
>>>>> https://lkml.org/lkml/2014/4/15/207
>>>>>
>>>>> [ 3163.014263] sddm[1851]: unhandled level 2 translation fault (11) at 0x00000160, esr 0x82000006
>>>>> [ 3163.017287] pgd = ffff80007bf86000
>>>>> [ 3163.020589] [00000160] *pgd=000000007a8a3003
>>>>> [ 3163.024733] , *pud=000000007be9c003
>>>>> [ 3163.028095] , *pmd=0000000000000000
>>>>>
>>>>>
>>>>> [ 3163.033026] CPU: 1 PID: 1851 Comm: sddm Not tainted 4.9.0-next-20161212-r022-arm64 #1
>>>>> [ 3163.040831] Hardware name: Hardkernel ODROID-C2 (DT)
>>>>> [ 3163.045698] task: ffff80007bc6d780 task.stack: ffff80007c524000
>>>>> [ 3163.051563] PC is at 0x160
>>>>> [ 3163.054231] LR is at 0xffff9a9fbc98
>>>>> [ 3163.057686] pc : [<0000000000000160>] lr : [<0000ffff9a9fbc98>] pstate: 40000000
>>>>> [ 3163.065022] sp : 0000ffffd7180130
>>>>> [ 3163.068281] x29: 0000ffffd7180130 x28: 0000ffffd7180288
>>>>> [ 3163.073538] x27: 0000ffff9aa94000 x26: 0000000000000001
>>>>> [ 3163.078798] x25: 0000000000000000 x24: 0000ffffd7180410
>>>>> [ 3163.084060] x23: 000000000e0c2190 x22: 000000000e0ca5c0
>>>>> [ 3163.089322] x21: 0000ffff9ac35000 x20: 0000000000454fa9
>>>>> [ 3163.094583] x19: 0000000000454fa8 x18: 000000000e0b5938
>>>>> [ 3163.099843] x17: 0000ffff9a3f2988 x16: 0000ffff9ac36aa0
>>>>> [ 3163.105105] x15: 0000000000000000 x14: 0000000000000000
>>>>> [ 3163.110367] x13: 6d00640064007300 x12: 0800000005000000
>>>>> [ 3163.115627] x11: 0000040000000000 x10: 0000a00000000000
>>>>> [ 3163.120889] x9 : 00003fffffffffff x8 : 0000000000000000
>>>>> [ 3163.126150] x7 : 000000000e0cb520 x6 : 0000000000454fc0
>>>>> [ 3163.131412] x5 : 0000ffffd717ffd8 x4 : 000000000e0cb510
>>>>> [ 3163.136680] x3 : 0000000000000004 x2 : f2f9022b551b3900
>>>>> [ 3163.141935] x1 : 0000000000000160 x0 : 000000000e0ca5c0
>>>>>
>>>>> Best regards
>>>>>
>>>>> Heinrich Schuchardt
>>>>
>>>> Hi Heinrich,
>>>>
>>>> I personally never had this issue even while loading huge applications loke LibreOffice and Gnome environment.
>>>>
>>>> I will have a look and try to reproduce this issue, can you provide us your configuration and user-space complete use case ?
>>>>
>>>> Neil
>>>>
>>>
>>> Hello Neil,
>>>
>>> the kernel is build with
>>> https://github.com/xypron/kernel-odroid-c2/tree/f8d565ff755e92fd585f5ae10123ce20abe03968
>>>
>>> Especially look at the patch directory and config/config-next-20161212.
>>>
>>> The userland is Debian Stretch with this package:
>>> https://packages.debian.org/stretch/sddm
>>>
>>> The link
>>> https://www.spinics.net/lists/arm-kernel/msg550204.html
>>> that you mention in a separate mail just links to this very thread due
>>> to linux-arm-kernel at lists.infradead.org being in copy.
>>>
>>> Best regards
>>>
>>> Heinrich Schuchardt
>>>
>>
>> Hi,
>>
>> Thanks for the details, but why do you use the next-20161212 tag ? does it work with 4.10-rc1 or previous next tags ?
>>
>> Neil
>>
>
> Hi Heinrich,
>
> I'm able to reproduce the bug using SDMM from Ubuntu running a 4.10-rc1 patched with memory zones :
> [ 17.988446] sddm-greeter[2366]: unhandled level 2 translation fault (11) at 0x00000000, esr 0x92000006
> [ 17.988451] pgd = ffff80003c3ee000
> [ 17.988472] [00000000] *pgd=00000000398bd003
> [ 17.988474] , *pud=00000000398bf003
> [ 17.990477] , *pmd=0000000000000000
>
>
> [ 17.990485] CPU: 3 PID: 2366 Comm: sddm-greeter Not tainted 4.10.0-rc1-00004-gd3f812382-dirty #488
> [ 17.990487] Hardware name: Amlogic Meson GXBB P200 Development Board (DT)
> [ 17.990489] task: ffff80003c160000 task.stack: ffff80003c314000
> [ 17.990493] PC is at 0xffffb2999994
> [ 17.990495] LR is at 0xffffb299f774
> [ 17.990497] pc : [<0000ffffb2999994>] lr : [<0000ffffb299f774>] pstate: 20000000
> [ 17.990503] sp : 0000ffffd2d1d5b0
> [ 17.990504] x29: 0000ffffd2d1d5b0 x28: 0000ffffad10e010
> [ 17.990508] x27: 0000000009c376d0 x26: 0000000000000001
> [ 17.990511] x25: 0000ffffb2b67000 x24: 0000ffffad10e010
> [ 17.990514] x23: 0000000000000000 x22: 0000000000000000
> [ 17.990517] x21: 0000000009c376d0 x20: 0000ffffb2fcdcb8
> [ 17.990520] x19: 0000ffffb2b2b000 x18: 0000000009c78450
> [ 17.990523] x17: 0000ffffb2b68068 x16: 0000ffffb2022158
> [ 17.990526] x15: 0000ffffb2fcd000 x14: 0000000000000000
> [ 17.990529] x13: aaaaaaaaaaaaaaab x12: 0000000000010000
> [ 17.990532] x11: 0000000000000008 x10: 0000000009c3b980
> [ 17.990535] x9 : 0000000009c38c40 x8 : 0000ffffd2d1d4e0
> [ 17.990538] x7 : 0000000000000000 x6 : 0000000009c3b998
> [ 17.990541] x5 : 0000000009c3b980 x4 : 0000800000000000
> [ 17.990544] x3 : 00000000fffffff0 x2 : 0000ffffad10e010
> [ 17.990547] x1 : 0000000009c379d8 x0 : 0000000000000000
>
> Looking about other occurrence of such error, it seems it may be a issue from sdmm instead.
>
> I'll continue searching,
> Neil
>
>
Hello Neil,
I am seeing a simular error when I try to use x2go
to have a remote desktop on the Odroid C2.
[47912.997112] fuse init (API version 7.26)
[47913.405815] x2goagent[28395]: unhandled level 0 translation fault
(11) at 0x3042415a74614c, esr 0x82000004
[47913.409849] pgd = ffff800079a11000
[47913.413704] [3042415a74614c] *pgd=0000000000000000
[47913.420673] CPU: 1 PID: 28395 Comm: x2goagent Not tainted
4.9.0-next-20161212-r024-arm64 #1
[47913.428992] Hardware name: Hardkernel ODROID-C2 (DT)
[47913.433906] task: ffff80007c670000 task.stack: ffff800079e6c000
[47913.439747] PC is at 0x3042415a74614c
[47913.443400] LR is at 0x323042415a74614c
[47913.447194] pc : [<003042415a74614c>] lr : [<323042415a74614c>]
pstate: 80000000
[47913.454528] sp : 0000ffffd7240140
[47913.457789] x29: 313042414c74614c x28: 000000000000007f
[47913.463016] x27: 000000000000007f x26: 0000000000000001
[47913.468278] x25: 0000000000000000 x24: 0000aaaaee52a7e0
[47913.473540] x23: 0000ffffd7240310 x22: 363042414274614c
[47913.478800] x21: 353042415674614c x20: 343042414374614c
[47913.484061] x19: 333042415874614c x18: 0000000000000000
[47913.489324] x17: 0000ffffb1ce2da0 x16: 0000000000000000
[47913.494589] x15: 0000000000000434 x14: 000000000000001f
[47913.499852] x13: 0000aaaa00703f00 x12: 0000003ff8081fff
[47913.505114] x11: 0000000000000000 x10: 0000000000000002
[47913.510373] x9 : 0000000000000010 x8 : 0000000000000042
[47913.515633] x7 : 011cff0800001fff x6 : 0000022300090101
[47913.520904] x5 : 000000000000088c x4 : 0000000000000007
[47913.526158] x3 : 0000aaaae52c1db0 x2 : 0000aaaae573a5a0
[47913.531417] x1 : 0000000000000000 x0 : 0000000000000000
Best regards
Heinrich Schuchardt
^ permalink raw reply
* [PATCH] drivers: remoteproc: constify rproc_ops structures
From: Bjorn Andersson @ 2016-12-30 12:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481974176-19912-1-git-send-email-bhumirks@gmail.com>
On Sat 17 Dec 03:29 PST 2016, Bhumika Goyal wrote:
> Declare rproc_ops structures as const as they are only passed as an
> argument to the function rproc_alloc. This argument is of type const, so
> rproc_ops structures having this property can be declared const too.
> Done using Coccinelle:
>
> @r1 disable optional_qualifier @
> identifier i;
> position p;
> @@
> static struct rproc_ops i at p = {...};
>
> @ok1@
> identifier r1.i;
> position p;
> @@
> rproc_alloc(...,&i at p,...)
>
> @bad@
> position p!={r1.p,ok1.p};
> identifier r1.i;
> @@
> i at p
>
> @depends on !bad disable optional_qualifier@
> identifier r1.i;
> @@
> +const
> struct rproc_ops i;
>
> File sizes before:
> text data bss dec hex filename
> 1258 416 0 1674 68a remoteproc/omap_remoteproc.o
> 2402 240 0 2642 a52 remoteproc/st_remoteproc.o
> 2064 272 0 2336 920 remoteproc/st_slim_rproc.o
> 2160 240 0 2400 960 remoteproc/wkup_m3_rproc.o
>
> File sizes after:
> text data bss dec hex filename
> 1297 368 0 1665 681 remoteproc/omap_remoteproc.o
> 2434 192 0 2626 a42 remoteproc/st_remoteproc.o
> 2112 240 0 2352 930 remoteproc/st_slim_rproc.o
> 2200 192 0 2392 958 remoteproc/wkup_m3_rproc.o
>
> Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
Thanks Bhumika, this looks good.
But as Suman already asked. Is there any reason why da8xx_remoteproc.c
did not get updated? It looks like the same change would apply there.
Unless I'm missing something, please update the patch and I'll be happy
to apply it.
Regards,
Bjorn
^ permalink raw reply
* [PATCH 2/2] ARM: imx: Add speed grading check for imx6ul
From: Shawn Guo @ 2016-12-30 11:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480475098-2037-2-git-send-email-ping.bai@nxp.com>
On Wed, Nov 30, 2016 at 11:04:58AM +0800, Bai Ping wrote:
> On i.MX6UL, it has two type of part, the difference
> is the max ARM frequency that can run at(528MHz/700MHz).
> The part can be identified by part marking for speed grading
> fuse. This patch add speed grading check to disable the unsupported
> OPP dynamically.
>
> Signed-off-by: Bai Ping <ping.bai@nxp.com>
We chose to handle such speed grading thing in IMX platform code with
the assumption that this is a special case for i.MX6Q only. No, I'm not
going to take such code for any other i.MX6 SoCs. Please patch cpufreq
driver to handle the speed grading check.
Shawn
^ permalink raw reply
* [PATCH 7/9] pinctrl: samsung: Add property to mark pad state as suitable for power down
From: Marek Szyprowski @ 2016-12-30 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161227153331.jbh7ei6oh3obmnri@kozik-lap>
Hi Krzysztof,
On 2016-12-27 16:33, Krzysztof Kozlowski wrote:
> On Tue, Dec 27, 2016 at 11:30:57AM +0100, Marek Szyprowski wrote:
>> On 2016-12-25 20:19, Krzysztof Kozlowski wrote:
>>> On Fri, Dec 23, 2016 at 01:24:47PM +0100, Marek Szyprowski wrote:
>>>> Add support for special property "samsung,off-state", which indicates a special
>>>> state suitable for device's "sleep" state. Its pin values/properties should
>>>> match the configuration in power down mode. It indicates that pin controller
>>>> can notify runtime power management subsystem, that it is ready for runtime
>>>> suspend if its all pins are configured for such state. This in turn might
>>>> allow to turn respective power domain off to reduce power consumption.
>>>>
>>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>>> ---
>>>> Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt | 8 ++++++++
>>>> drivers/pinctrl/samsung/pinctrl-samsung.c | 4 ++++
>>>> drivers/pinctrl/samsung/pinctrl-samsung.h | 1 +
>>>> 3 files changed, 13 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
>>>> index b7bd2e12a269..354eea0e7798 100644
>>>> --- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
>>>> +++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
>>>> @@ -105,6 +105,7 @@ Required Properties:
>>>> - samsung,pin-drv: Drive strength configuration.
>>>> - samsung,pin-pud-pdn: Pull up/down configuration in power down mode.
>>>> - samsung,pin-drv-pdn: Drive strength configuration in power down mode.
>>>> + - samsung,off-state: Mark this configuration as suitable for bank power off.
>>>> The values specified by these config properties should be derived from the
>>>> hardware manual and these values are programmed as-is into the pin
>>>> @@ -113,6 +114,13 @@ Required Properties:
>>>> Note: A child should include atleast a pin function selection property or
>>>> pin configuration property (one or more) or both.
>>>> + Note: Special property "samsung,off-state" indicates that this state can
>>>> + be used for device's "sleep" pins state. Its pin values/properties should
>>>> + match the configuration in power down mode.
>>> Why power down values cannot be used for sleep state? Why you need
>>> separate pin control state? If pins values should match power down
>>> configuration, then they could just be added to default state, couldn't
>>> they?
>> Separate sleep state is needed because of the pin control bindings and
>> design.
>>
>> A separate sleep state is required to let pin control client driver (in this
>> case
>> Exynos I2S driver) let to choose when it is okay to switch pads into sleep
>> state and I see no other way to achieve this.
> Maybe the pinctrl API should be extended for this? Doing this in DTS
> just for purpose of passing information between drivers (consumer and
> provider) looks odd.
Well, I don't know if it is odd or not, but that's how it is used now
and I see
no reason to reinvent wheel. Please check it yourself:
$ git grep \"sleep\" arch/arm/boot/dts | wc -l
101
> Anyway, you are proposing a new binding so please Cc devicetree mailing
> list and device tree maintainers.
I'm just using the generic pinctrl bindings, but it might make some sense to
add a note to Exynos i2s driver that a sleep pin control state is needed if
one wants to get power domain to be turned off.
>>> In the patch 2/9, existing configuration:
>>> 716 i2s0_bus: i2s0-bus {
>>> (...)
>>> 719 samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
>>> 720 samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
>>> 721 samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
>>> 722 };
>>>
>>> additional configuration:
>>> + i2s0_bus_slp: i2s0-bus-slp {
>>> + samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
>>> + samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
>>> + samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
>>> + samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
>>> + samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
>>> + samsung,off-state;
>>> + };
>> I agree that it would be possible to get rid of "samsung,off-state" property
>> and
>> just detect off state when func/pud pair matches power down func/pud.
>>
>>>> It indicates that pin control
>>>> + can notify runtime power management subsystem, that it is ready for runtime
>>>> + suspend if its all pins are configured for such state. This in turn might
>>>> + allow to turn respective power domain off to reduce power consumption.
>>> What do you mean by "notifying RPM subsystem"? Either this is
>>> description of hardware in certain mode (sleep state) or this is not
>>> device tree property.
>> Maybe I wrote the description with a view too limited to the kernel
>> operation
>> perspective, but if we remove the need to mark state as off, the above
>> description
>> will not be needed.
> But still it wouldn't be describing any hardware property, would it?
Well, it somehow describes the hardware, because the pin state when it
is allowed
to turn off the power domain is board specific. I should move that part
to the
Odroid dts, because there might be a board which require other pin
values in power
down mode.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* [PATCH v2 6/6] ARM: mach-mx27_3ds: Remove camera support
From: Fabio Estevam @ 2016-12-30 11:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483097613-21481-1-git-send-email-festevam@gmail.com>
From: Fabio Estevam <fabio.estevam@nxp.com>
Since commit 6b879edf75b316 ("[media] staging/media: remove deprecated
mx2 driver") the mx2 camera driver has been removed, so remove the camera
support from the board file as well.
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
Changes since v1:
- Also remove CSI pins from IOMUX definition
arch/arm/mach-imx/mach-mx27_3ds.c | 107 --------------------------------------
1 file changed, 107 deletions(-)
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 7ba651a..45e16bd 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -31,7 +31,6 @@
#include <linux/regulator/machine.h>
#include <linux/spi/l4f00242t03.h>
-#include <media/soc_camera.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -53,8 +52,6 @@
#define SD1_CD IMX_GPIO_NR(2, 26)
#define LCD_RESET IMX_GPIO_NR(1, 3)
#define LCD_ENABLE IMX_GPIO_NR(1, 31)
-#define CSI_PWRDWN IMX_GPIO_NR(4, 19)
-#define CSI_RESET IMX_GPIO_NR(3, 6)
static const int mx27pdk_pins[] __initconst = {
/* UART1 */
@@ -144,21 +141,6 @@ static const int mx27pdk_pins[] __initconst = {
PA30_PF_CONTRAST,
LCD_ENABLE | GPIO_GPIO | GPIO_OUT,
LCD_RESET | GPIO_GPIO | GPIO_OUT,
- /* CSI */
- PB10_PF_CSI_D0,
- PB11_PF_CSI_D1,
- PB12_PF_CSI_D2,
- PB13_PF_CSI_D3,
- PB14_PF_CSI_D4,
- PB15_PF_CSI_MCLK,
- PB16_PF_CSI_PIXCLK,
- PB17_PF_CSI_D5,
- PB18_PF_CSI_D6,
- PB19_PF_CSI_D7,
- PB20_PF_CSI_VSYNC,
- PB21_PF_CSI_HSYNC,
- CSI_PWRDWN | GPIO_GPIO | GPIO_OUT,
- CSI_RESET | GPIO_GPIO | GPIO_OUT,
/* SSI4 */
PC16_PF_SSI4_FS,
PC17_PF_SSI4_RXD,
@@ -166,11 +148,6 @@ static const int mx27pdk_pins[] __initconst = {
PC19_PF_SSI4_CLK,
};
-static struct gpio mx27_3ds_camera_gpios[] = {
- { CSI_PWRDWN, GPIOF_OUT_INIT_HIGH, "camera-power" },
- { CSI_RESET, GPIOF_OUT_INIT_HIGH, "camera-reset" },
-};
-
static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@@ -270,7 +247,6 @@ static struct regulator_init_data gpo_init = {
static struct regulator_consumer_supply vmmc1_consumers[] = {
REGULATOR_SUPPLY("vcore", "spi0.0"),
- REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
};
static struct regulator_init_data vmmc1_init = {
@@ -299,22 +275,6 @@ static struct regulator_init_data vgen_init = {
.consumer_supplies = vgen_consumers,
};
-static struct regulator_consumer_supply vvib_consumers[] = {
- REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
-};
-
-static struct regulator_init_data vvib_init = {
- .constraints = {
- .min_uV = 1300000,
- .max_uV = 1300000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
- REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(vvib_consumers),
- .consumer_supplies = vvib_consumers,
-};
-
static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
{
.id = MC13783_REG_VMMC1,
@@ -328,9 +288,6 @@ static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
}, {
.id = MC13783_REG_GPO3, /* Turn on 3.3V */
.init_data = &gpo_init,
- }, {
- .id = MC13783_REG_VVIB, /* Power OV2640 */
- .init_data = &vvib_init,
},
};
@@ -370,51 +327,6 @@ static const struct spi_imx_master spi2_pdata __initconst = {
.num_chipselect = ARRAY_SIZE(spi2_chipselect),
};
-static int mx27_3ds_camera_power(struct device *dev, int on)
-{
- /* enable or disable the camera */
- pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
- gpio_set_value(CSI_PWRDWN, on ? 0 : 1);
-
- if (!on)
- goto out;
-
- /* If enabled, give a reset impulse */
- gpio_set_value(CSI_RESET, 0);
- msleep(20);
- gpio_set_value(CSI_RESET, 1);
- msleep(100);
-
-out:
- return 0;
-}
-
-static struct i2c_board_info mx27_3ds_i2c_camera = {
- I2C_BOARD_INFO("ov2640", 0x30),
-};
-
-static struct regulator_bulk_data mx27_3ds_camera_regs[] = {
- { .supply = "cmos_vcore" },
- { .supply = "cmos_2v8" },
-};
-
-static struct soc_camera_link iclink_ov2640 = {
- .bus_id = 0,
- .board_info = &mx27_3ds_i2c_camera,
- .i2c_adapter_id = 0,
- .power = mx27_3ds_camera_power,
- .regulators = mx27_3ds_camera_regs,
- .num_regulators = ARRAY_SIZE(mx27_3ds_camera_regs),
-};
-
-static struct platform_device mx27_3ds_ov2640 = {
- .name = "soc-camera-pdrv",
- .id = 0,
- .dev = {
- .platform_data = &iclink_ov2640,
- },
-};
-
static struct imx_fb_videomode mx27_3ds_modes[] = {
{ /* 480x640 @ 60 Hz */
.mode = {
@@ -471,14 +383,6 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
},
};
-static struct platform_device *devices[] __initdata = {
- &mx27_3ds_ov2640,
-};
-
-static const struct mx2_camera_platform_data mx27_3ds_cam_pdata __initconst = {
- .clk = 26000000,
-};
-
static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {
.bitrate = 100000,
};
@@ -498,7 +402,6 @@ static void __init mx27pdk_init(void)
imx27_add_spi_imx0(&spi1_pdata);
imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
- platform_add_devices(devices, ARRAY_SIZE(devices));
imx27_add_imx_fb(&mx27_3ds_fb_data);
imx27_add_imx_ssi(0, &mx27_3ds_ssi_pdata);
@@ -506,8 +409,6 @@ static void __init mx27pdk_init(void)
static void __init mx27pdk_late_init(void)
{
- int ret;
-
mx27_3ds_sdhc1_enable_level_translator();
imx27_add_mxc_mmc(0, &sdhc1_pdata);
@@ -531,14 +432,6 @@ static void __init mx27pdk_late_init(void)
if (mxc_expio_init(MX27_CS5_BASE_ADDR, IMX_GPIO_NR(3, 28)))
pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
- ret = gpio_request_array(mx27_3ds_camera_gpios,
- ARRAY_SIZE(mx27_3ds_camera_gpios));
- if (ret) {
- pr_err("Failed to request camera gpios");
- iclink_ov2640.power = NULL;
- }
-
- imx27_add_mx2_camera(&mx27_3ds_cam_pdata);
imx_add_platform_device("imx_mc13783", 0, NULL, 0, NULL, 0);
}
--
2.7.4
^ 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