* [PATCH v5 4/5] ARM: dts: Add I2C1 support for STM32429 eval board
From: M'boumba Cedric Madianga @ 2016-12-08 8:26 UTC (permalink / raw)
To: wsa, robh+dt, mcoquelin.stm32, alexandre.torgue, linus.walleij,
patrice.chotard, linux, linux-i2c, devicetree, linux-arm-kernel,
linux-kernel
Cc: M'boumba Cedric Madianga
In-Reply-To: <1481185563-8735-1-git-send-email-cedric.madianga@gmail.com>
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
arch/arm/boot/dts/stm32429i-eval.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts
index afb90bc..74e0045 100644
--- a/arch/arm/boot/dts/stm32429i-eval.dts
+++ b/arch/arm/boot/dts/stm32429i-eval.dts
@@ -141,3 +141,9 @@
pinctrl-names = "default";
status = "okay";
};
+
+&i2c1 {
+ pinctrl-0 = <&i2c1_pins_b>;
+ pinctrl-names = "default";
+ status = "okay";
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v5 3/5] ARM: dts: Add I2C1 support for STM32F429 SoC
From: M'boumba Cedric Madianga @ 2016-12-08 8:26 UTC (permalink / raw)
To: wsa, robh+dt, mcoquelin.stm32, alexandre.torgue, linus.walleij,
patrice.chotard, linux, linux-i2c, devicetree, linux-arm-kernel,
linux-kernel
Cc: M'boumba Cedric Madianga
In-Reply-To: <1481185563-8735-1-git-send-email-cedric.madianga@gmail.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
arch/arm/boot/dts/stm32f429.dtsi | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 7de52ee..cbdece7 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -48,6 +48,7 @@
#include "skeleton.dtsi"
#include "armv7-m.dtsi"
#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
+#include <dt-bindings/mfd/stm32f4-rcc.h>
/ {
clocks {
@@ -337,6 +338,16 @@
slew-rate = <2>;
};
};
+
+ i2c1_pins_b: i2c1@0 {
+ pins1 {
+ pinmux = <STM32F429_PB9_FUNC_I2C1_SDA>;
+ drive-open-drain;
+ };
+ pins2 {
+ pinmux = <STM32F429_PB6_FUNC_I2C1_SCL>;
+ };
+ };
};
rcc: rcc@40023810 {
@@ -409,6 +420,18 @@
interrupts = <80>;
clocks = <&rcc 0 38>;
};
+
+ i2c1: i2c@40005400 {
+ compatible = "st,stm32f4-i2c";
+ reg = <0x40005400 0x400>;
+ interrupts = <31>,
+ <32>;
+ resets = <&rcc STM32F4_APB1_RESET(I2C1)>;
+ clocks = <&rcc 0 STM32F4_APB1_CLOCK(I2C1)>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
};
--
1.9.1
^ permalink raw reply related
* [PATCH v5 2/5] i2c: Add STM32F4 I2C driver
From: M'boumba Cedric Madianga @ 2016-12-08 8:26 UTC (permalink / raw)
To: wsa, robh+dt, mcoquelin.stm32, alexandre.torgue, linus.walleij,
patrice.chotard, linux, linux-i2c, devicetree, linux-arm-kernel,
linux-kernel
Cc: M'boumba Cedric Madianga
In-Reply-To: <1481185563-8735-1-git-send-email-cedric.madianga@gmail.com>
This patch adds support for the STM32F4 I2C controller.
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
drivers/i2c/busses/Kconfig | 10 +
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-stm32f4.c | 851 +++++++++++++++++++++++++++++++++++++++
3 files changed, 862 insertions(+)
create mode 100644 drivers/i2c/busses/i2c-stm32f4.c
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 8e43914..584e0d7 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -886,6 +886,16 @@ config I2C_ST
This driver can also be built as module. If so, the module
will be called i2c-st.
+config I2C_STM32F4
+ tristate "STMicroelectronics STM32F4 I2C support"
+ depends on ARCH_STM32 || COMPILE_TEST
+ help
+ Enable this option to add support for STM32 I2C controller embedded
+ in STM32F4 SoCs.
+
+ This driver can also be built as module. If so, the module
+ will be called i2c-stm32f4.
+
config I2C_STU300
tristate "ST Microelectronics DDC I2C interface"
depends on MACH_U300
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 1c1bac8..a2c6ff5 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
obj-$(CONFIG_I2C_ST) += i2c-st.o
+obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c
new file mode 100644
index 0000000..0630354
--- /dev/null
+++ b/drivers/i2c/busses/i2c-stm32f4.c
@@ -0,0 +1,851 @@
+/*
+ * Driver for STMicroelectronics STM32 I2C controller
+ *
+ * Copyright (C) M'boumba Cedric Madianga 2015
+ * Author: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
+ *
+ * This driver is based on i2c-st.c
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+/* STM32F4 I2C offset registers */
+#define STM32F4_I2C_CR1 0x00
+#define STM32F4_I2C_CR2 0x04
+#define STM32F4_I2C_DR 0x10
+#define STM32F4_I2C_SR1 0x14
+#define STM32F4_I2C_SR2 0x18
+#define STM32F4_I2C_CCR 0x1C
+#define STM32F4_I2C_TRISE 0x20
+#define STM32F4_I2C_FLTR 0x24
+
+/* STM32F4 I2C control 1*/
+#define STM32F4_I2C_CR1_SWRST BIT(15)
+#define STM32F4_I2C_CR1_POS BIT(11)
+#define STM32F4_I2C_CR1_ACK BIT(10)
+#define STM32F4_I2C_CR1_STOP BIT(9)
+#define STM32F4_I2C_CR1_START BIT(8)
+#define STM32F4_I2C_CR1_PE BIT(0)
+
+/* STM32F4 I2C control 2 */
+#define STM32F4_I2C_CR2_FREQ_MASK GENMASK(5, 0)
+#define STM32F4_I2C_CR2_FREQ(n) ((n & STM32F4_I2C_CR2_FREQ_MASK))
+#define STM32F4_I2C_CR2_ITBUFEN BIT(10)
+#define STM32F4_I2C_CR2_ITEVTEN BIT(9)
+#define STM32F4_I2C_CR2_ITERREN BIT(8)
+#define STM32F4_I2C_CR2_IRQ_MASK (STM32F4_I2C_CR2_ITBUFEN \
+ | STM32F4_I2C_CR2_ITEVTEN \
+ | STM32F4_I2C_CR2_ITERREN)
+
+/* STM32F4 I2C Status 1 */
+#define STM32F4_I2C_SR1_AF BIT(10)
+#define STM32F4_I2C_SR1_ARLO BIT(9)
+#define STM32F4_I2C_SR1_BERR BIT(8)
+#define STM32F4_I2C_SR1_TXE BIT(7)
+#define STM32F4_I2C_SR1_RXNE BIT(6)
+#define STM32F4_I2C_SR1_BTF BIT(2)
+#define STM32F4_I2C_SR1_ADDR BIT(1)
+#define STM32F4_I2C_SR1_SB BIT(0)
+#define STM32F4_I2C_SR1_ITEVTEN_MASK (STM32F4_I2C_SR1_BTF \
+ | STM32F4_I2C_SR1_ADDR \
+ | STM32F4_I2C_SR1_SB)
+#define STM32F4_I2C_SR1_ITBUFEN_MASK (STM32F4_I2C_SR1_TXE \
+ | STM32F4_I2C_SR1_RXNE)
+#define STM32F4_I2C_SR1_ITERREN_MASK (STM32F4_I2C_SR1_AF \
+ | STM32F4_I2C_SR1_ARLO \
+ | STM32F4_I2C_SR1_BERR)
+
+/* STM32F4 I2C Status 2 */
+#define STM32F4_I2C_SR2_BUSY BIT(1)
+
+/* STM32F4 I2C Control Clock */
+#define STM32F4_I2C_CCR_CCR_MASK GENMASK(11, 0)
+#define STM32F4_I2C_CCR_CCR(n) ((n & STM32F4_I2C_CCR_CCR_MASK))
+#define STM32F4_I2C_CCR_FS BIT(15)
+#define STM32F4_I2C_CCR_DUTY BIT(14)
+
+/* STM32F4 I2C Trise */
+#define STM32F4_I2C_TRISE_VALUE_MASK GENMASK(5, 0)
+#define STM32F4_I2C_TRISE_VALUE(n) ((n & STM32F4_I2C_TRISE_VALUE_MASK))
+
+/* STM32F4 I2C Filter */
+#define STM32F4_I2C_FLTR_DNF_MASK GENMASK(3, 0)
+#define STM32F4_I2C_FLTR_DNF(n) ((n & STM32F4_I2C_FLTR_DNF_MASK))
+#define STM32F4_I2C_FLTR_ANOFF BIT(4)
+
+#define STM32F4_I2C_MIN_FREQ 2
+#define STM32F4_I2C_MAX_FREQ 42
+#define FAST_MODE_MAX_RISE_TIME 1000
+#define STD_MODE_MAX_RISE_TIME 300
+#define MHZ_TO_HZ 1000000
+
+enum stm32f4_i2c_speed {
+ STM32F4_I2C_SPEED_STANDARD, /* 100 kHz */
+ STM32F4_I2C_SPEED_FAST, /* 400 kHz */
+ STM32F4_I2C_SPEED_END,
+};
+
+/**
+ * struct stm32f4_i2c_timings - per-Mode tuning parameters
+ * @duty: Fast mode duty cycle
+ * @mul_ccr: Value to be multiplied to CCR to reach 100Khz/400Khz SCL frequency
+ * @min_ccr: Minimum clock ctrl reg value to reach 100Khz/400Khz SCL frequency
+ */
+struct stm32f4_i2c_timings {
+ u32 rate;
+ u32 duty;
+ u32 mul_ccr;
+ u32 min_ccr;
+};
+
+/**
+ * struct stm32f4_i2c_msg - client specific data
+ * @addr: 8-bit slave addr, including r/w bit
+ * @count: number of bytes to be transferred
+ * @buf: data buffer
+ * @result: result of the transfer
+ * @stop: last I2C msg to be sent, i.e. STOP to be generated
+ */
+struct stm32f4_i2c_msg {
+ u8 addr;
+ u32 count;
+ u8 *buf;
+ int result;
+ bool stop;
+};
+
+/**
+ * struct stm32f4_i2c_dev - private data of the controller
+ * @adap: I2C adapter for this controller
+ * @dev: device for this controller
+ * @base: virtual memory area
+ * @complete: completion of I2C message
+ * @irq_event: interrupt event line for the controller
+ * @irq_error: interrupt error line for the controller
+ * @clk: hw i2c clock
+ * speed: I2C clock frequency of the controller. Standard or Fast only supported
+ * @msg: I2C transfer information
+ */
+struct stm32f4_i2c_dev {
+ struct i2c_adapter adap;
+ struct device *dev;
+ void __iomem *base;
+ struct completion complete;
+ int irq_event;
+ int irq_error;
+ struct clk *clk;
+ int speed;
+ struct stm32f4_i2c_msg msg;
+};
+
+static struct stm32f4_i2c_timings i2c_timings[] = {
+ [STM32F4_I2C_SPEED_STANDARD] = {
+ .mul_ccr = 1,
+ .min_ccr = 4,
+ .duty = 0,
+ },
+ [STM32F4_I2C_SPEED_FAST] = {
+ .mul_ccr = 16,
+ .min_ccr = 1,
+ .duty = 1,
+ },
+};
+
+static inline void stm32f4_i2c_set_bits(void __iomem *reg, u32 mask)
+{
+ writel_relaxed(readl_relaxed(reg) | mask, reg);
+}
+
+static inline void stm32f4_i2c_clr_bits(void __iomem *reg, u32 mask)
+{
+ writel_relaxed(readl_relaxed(reg) & ~mask, reg);
+}
+
+static void stm32f4_i2c_soft_reset(struct stm32f4_i2c_dev *i2c_dev)
+{
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_SWRST);
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_SWRST);
+}
+
+static void stm32f4_i2c_disable_it(struct stm32f4_i2c_dev *i2c_dev)
+{
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_IRQ_MASK);
+}
+
+static void stm32f4_i2c_set_periph_clk_freq(struct stm32f4_i2c_dev *i2c_dev)
+{
+ u32 clk_rate, cr2, freq;
+
+ cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ cr2 &= ~STM32F4_I2C_CR2_FREQ_MASK;
+ clk_rate = clk_get_rate(i2c_dev->clk);
+ freq = clk_rate / MHZ_TO_HZ;
+ freq = clamp(freq, STM32F4_I2C_MIN_FREQ, STM32F4_I2C_MAX_FREQ);
+ cr2 |= STM32F4_I2C_CR2_FREQ(freq);
+ writel_relaxed(cr2, i2c_dev->base + STM32F4_I2C_CR2);
+}
+
+static void stm32f4_i2c_set_rise_time(struct stm32f4_i2c_dev *i2c_dev)
+{
+ u32 trise, freq, cr2, val;
+
+ cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ freq = cr2 & STM32F4_I2C_CR2_FREQ_MASK;
+
+ trise = readl_relaxed(i2c_dev->base + STM32F4_I2C_TRISE);
+ trise &= ~STM32F4_I2C_TRISE_VALUE_MASK;
+
+ /* Maximum rise time computation */
+ if (i2c_dev->speed == STM32F4_I2C_SPEED_STANDARD) {
+ trise |= STM32F4_I2C_TRISE_VALUE((freq + 1));
+ } else {
+ val = freq * FAST_MODE_MAX_RISE_TIME / STD_MODE_MAX_RISE_TIME;
+ trise |= STM32F4_I2C_TRISE_VALUE((val + 1));
+ }
+
+ writel_relaxed(trise, i2c_dev->base + STM32F4_I2C_TRISE);
+}
+
+static void stm32f4_i2c_set_speed_mode(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_timings *t = &i2c_timings[i2c_dev->speed];
+ u32 ccr, clk_rate;
+ int val;
+
+ ccr = readl_relaxed(i2c_dev->base + STM32F4_I2C_CCR);
+ ccr &= ~(STM32F4_I2C_CCR_FS | STM32F4_I2C_CCR_DUTY |
+ STM32F4_I2C_CCR_CCR_MASK);
+
+ clk_rate = clk_get_rate(i2c_dev->clk);
+ val = clk_rate / MHZ_TO_HZ * t->mul_ccr;
+ if (val < t->min_ccr)
+ val = t->min_ccr;
+ ccr |= STM32F4_I2C_CCR_CCR(val);
+
+ if (t->duty)
+ ccr |= STM32F4_I2C_CCR_FS | STM32F4_I2C_CCR_DUTY;
+
+ writel_relaxed(ccr, i2c_dev->base + STM32F4_I2C_CCR);
+}
+
+static void stm32f4_i2c_set_filter(struct stm32f4_i2c_dev *i2c_dev)
+{
+ u32 filter;
+
+ /* Enable analog noise filter and disable digital noise filter */
+ filter = readl_relaxed(i2c_dev->base + STM32F4_I2C_FLTR);
+ filter &= ~(STM32F4_I2C_FLTR_ANOFF | STM32F4_I2C_FLTR_DNF_MASK);
+ writel_relaxed(filter, i2c_dev->base + STM32F4_I2C_FLTR);
+}
+
+/**
+ * stm32f4_i2c_hw_config() - Prepare I2C block
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_hw_config(struct stm32f4_i2c_dev *i2c_dev)
+{
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+
+ /* Disable I2C */
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_PE);
+
+ stm32f4_i2c_set_periph_clk_freq(i2c_dev);
+
+ stm32f4_i2c_set_rise_time(i2c_dev);
+
+ stm32f4_i2c_set_speed_mode(i2c_dev);
+
+ stm32f4_i2c_set_filter(i2c_dev);
+
+ /* Enable I2C */
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_PE);
+}
+
+static int stm32f4_i2c_wait_free_bus(struct stm32f4_i2c_dev *i2c_dev)
+{
+ u32 status;
+ int ret;
+
+ ret = readl_relaxed_poll_timeout(i2c_dev->base + STM32F4_I2C_SR2,
+ status,
+ !(status & STM32F4_I2C_SR2_BUSY),
+ 10, 1000);
+ if (ret) {
+ dev_err(i2c_dev->dev, "bus not free\n");
+ ret = -EBUSY;
+ }
+
+ return ret;
+}
+
+/**
+ * stm32f4_i2c_write_ byte() - Write a byte in the data register
+ * @i2c_dev: Controller's private data
+ * @byte: Data to write in the register
+ */
+static void stm32f4_i2c_write_byte(struct stm32f4_i2c_dev *i2c_dev, u8 byte)
+{
+ writel_relaxed(byte, i2c_dev->base + STM32F4_I2C_DR);
+}
+
+/**
+ * stm32f4_i2c_write_msg() - Fill the data register in write mode
+ * @i2c_dev: Controller's private data
+ *
+ * This function fills the data register with I2C transfer buffer
+ */
+static void stm32f4_i2c_write_msg(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+
+ stm32f4_i2c_write_byte(i2c_dev, *msg->buf++);
+ msg->count--;
+}
+
+static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ u32 rbuf;
+
+ rbuf = readl_relaxed(i2c_dev->base + STM32F4_I2C_DR);
+ *msg->buf++ = (u8)rbuf & 0xff;
+ msg->count--;
+}
+
+static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+ stm32f4_i2c_disable_it(i2c_dev);
+
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ if (msg->stop)
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+ else
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+
+ complete(&i2c_dev->complete);
+}
+
+/**
+ * stm32f4_i2c_handle_write() - Handle FIFO empty interrupt in case of write
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_write(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+ if (msg->count) {
+ stm32f4_i2c_write_msg(i2c_dev);
+ if (!msg->count) {
+ /* Disable BUF interrupt */
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+ }
+ } else {
+ stm32f4_i2c_terminate_xfer(i2c_dev);
+ }
+}
+
+/**
+ * stm32f4_i2c_handle_read() - Handle FIFO empty interrupt in case of read
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_read(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+ switch (msg->count) {
+ case 1:
+ stm32f4_i2c_disable_it(i2c_dev);
+ stm32f4_i2c_read_msg(i2c_dev);
+ complete(&i2c_dev->complete);
+ break;
+ case 2:
+ case 3:
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+ break;
+ default:
+ stm32f4_i2c_read_msg(i2c_dev);
+ }
+}
+
+/**
+ * stm32f4_i2c_handle_rx_btf() - Handle byte transfer finished interrupt
+ * in case of read
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_rx_btf(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg;
+ u32 mask;
+ int i;
+
+ switch (msg->count) {
+ case 2:
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ /* Generate STOP or REPSTART */
+ if (msg->stop)
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+ else
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+
+ /* Read two last data bytes */
+ for (i = 2; i > 0; i--)
+ stm32f4_i2c_read_msg(i2c_dev);
+
+ /* Disable EVT and ERR interrupt */
+ reg = i2c_dev->base + STM32F4_I2C_CR2;
+ mask = STM32F4_I2C_CR2_ITEVTEN | STM32F4_I2C_CR2_ITERREN;
+ stm32f4_i2c_clr_bits(reg, mask);
+
+ complete(&i2c_dev->complete);
+ break;
+ case 3:
+ /* Enable ACK and read data */
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+ stm32f4_i2c_read_msg(i2c_dev);
+ break;
+ default:
+ stm32f4_i2c_read_msg(i2c_dev);
+ }
+}
+
+/**
+ * stm32f4_i2c_handle_rx_addr() - Handle address matched interrupt in case of
+ * master receiver
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_rx_addr(struct stm32f4_i2c_dev *i2c_dev)
+{
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg;
+ u32 sr2;
+
+ switch (msg->count) {
+ case 0:
+ stm32f4_i2c_terminate_xfer(i2c_dev);
+ /* Clear ADDR flag */
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+ break;
+ case 1:
+ /*
+ * Single byte reception:
+ * Enable NACK, clear ADDR flag and generate STOP or RepSTART
+ */
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+ if (msg->stop)
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+ else
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+ break;
+ case 2:
+ /*
+ * 2-byte reception:
+ * Enable NACK and PEC Position Ack and clear ADDR flag
+ */
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_POS);
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+ break;
+
+ default:
+ /* N-byte reception: Enable ACK and clear ADDR flag */
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_ACK);
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+ break;
+ }
+}
+
+/**
+ * stm32f4_i2c_isr_event() - Interrupt routine for I2C bus event
+ * @irq: interrupt number
+ * @data: Controller's private data
+ */
+static irqreturn_t stm32f4_i2c_isr_event(int irq, void *data)
+{
+ struct stm32f4_i2c_dev *i2c_dev = data;
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg;
+ u32 real_status, possible_status, ien, sr2;
+ int flag;
+
+ ien = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ ien &= STM32F4_I2C_CR2_IRQ_MASK;
+ possible_status = 0;
+
+ /* Check possible status combinations */
+ if (ien & STM32F4_I2C_CR2_ITEVTEN) {
+ possible_status = STM32F4_I2C_SR1_ITEVTEN_MASK;
+ if (ien & STM32F4_I2C_CR2_ITBUFEN)
+ possible_status |= STM32F4_I2C_SR1_ITBUFEN_MASK;
+ }
+
+ real_status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+
+ if (!(real_status & possible_status)) {
+ dev_dbg(i2c_dev->dev,
+ "spurious evt it (status=0x%08x, ien=0x%08x)\n",
+ real_status, ien);
+ return IRQ_NONE;
+ }
+
+ /* Use __fls() to check error bits first */
+ flag = __fls(real_status & possible_status);
+
+ switch (1 << flag) {
+ case STM32F4_I2C_SR1_SB:
+ stm32f4_i2c_write_byte(i2c_dev, msg->addr);
+ break;
+
+ case STM32F4_I2C_SR1_ADDR:
+ if (msg->addr & I2C_M_RD)
+ stm32f4_i2c_handle_rx_addr(i2c_dev);
+ else
+ sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+
+ /* Enable ITBUF interrupts */
+ reg = i2c_dev->base + STM32F4_I2C_CR2;
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+ break;
+
+ case STM32F4_I2C_SR1_BTF:
+ if (msg->addr & I2C_M_RD)
+ stm32f4_i2c_handle_rx_btf(i2c_dev);
+ else
+ stm32f4_i2c_handle_write(i2c_dev);
+ break;
+
+ case STM32F4_I2C_SR1_TXE:
+ stm32f4_i2c_handle_write(i2c_dev);
+ break;
+
+ case STM32F4_I2C_SR1_RXNE:
+ stm32f4_i2c_handle_read(i2c_dev);
+ break;
+
+ default:
+ dev_err(i2c_dev->dev,
+ "evt it unhandled: status=0x%08x)\n", real_status);
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * stm32f4_i2c_isr_error() - Interrupt routine for I2C bus error
+ * @irq: interrupt number
+ * @data: Controller's private data
+ */
+static irqreturn_t stm32f4_i2c_isr_error(int irq, void *data)
+{
+ struct stm32f4_i2c_dev *i2c_dev = data;
+ struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+ void __iomem *reg;
+ u32 real_status, possible_status, ien;
+ int flag;
+
+ ien = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ ien &= STM32F4_I2C_CR2_IRQ_MASK;
+ possible_status = 0;
+
+ /* Check possible status combinations */
+ if (ien & STM32F4_I2C_CR2_ITERREN)
+ possible_status = STM32F4_I2C_SR1_ITERREN_MASK;
+
+ real_status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+
+ if (!(real_status & possible_status)) {
+ dev_dbg(i2c_dev->dev,
+ "spurious err it (status=0x%08x, ien=0x%08x)\n",
+ real_status, ien);
+ return IRQ_NONE;
+ }
+
+ /* Use __fls() to check error bits first */
+ flag = __fls(real_status & possible_status);
+
+ switch (1 << flag) {
+ case STM32F4_I2C_SR1_BERR:
+ reg = i2c_dev->base + STM32F4_I2C_SR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_SR1_BERR);
+ msg->result = -EIO;
+ break;
+
+ case STM32F4_I2C_SR1_ARLO:
+ reg = i2c_dev->base + STM32F4_I2C_SR1;
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_SR1_ARLO);
+ msg->result = -EAGAIN;
+ break;
+
+ case STM32F4_I2C_SR1_AF:
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+ msg->result = -EIO;
+ break;
+
+ default:
+ dev_err(i2c_dev->dev,
+ "err it unhandled: status=0x%08x)\n", real_status);
+ return IRQ_NONE;
+ }
+
+ stm32f4_i2c_soft_reset(i2c_dev);
+ stm32f4_i2c_disable_it(i2c_dev);
+ complete(&i2c_dev->complete);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * stm32f4_i2c_xfer_msg() - Transfer a single I2C message
+ * @i2c_dev: Controller's private data
+ * @msg: I2C message to transfer
+ * @is_first: first message of the sequence
+ * @is_last: last message of the sequence
+ */
+static int stm32f4_i2c_xfer_msg(struct stm32f4_i2c_dev *i2c_dev,
+ struct i2c_msg *msg, bool is_first,
+ bool is_last)
+{
+ struct stm32f4_i2c_msg *f4_msg = &i2c_dev->msg;
+ void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+ unsigned long timeout;
+ u32 mask;
+ int ret;
+
+ f4_msg->addr = i2c_8bit_addr_from_msg(msg);
+ f4_msg->buf = msg->buf;
+ f4_msg->count = msg->len;
+ f4_msg->result = 0;
+ f4_msg->stop = is_last;
+
+ reinit_completion(&i2c_dev->complete);
+
+ /* Enable ITEVT and ITERR interrupts */
+ mask = STM32F4_I2C_CR2_ITEVTEN | STM32F4_I2C_CR2_ITERREN;
+ stm32f4_i2c_set_bits(i2c_dev->base + STM32F4_I2C_CR2, mask);
+
+ if (is_first) {
+ ret = stm32f4_i2c_wait_free_bus(i2c_dev);
+ if (ret)
+ return ret;
+
+ /* START generation */
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+ }
+
+ timeout = wait_for_completion_timeout(&i2c_dev->complete,
+ i2c_dev->adap.timeout);
+ ret = f4_msg->result;
+
+ /* Disable PEC position Ack */
+ stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_POS);
+
+ if (!timeout)
+ ret = -ETIMEDOUT;
+
+ return ret;
+}
+
+/**
+ * stm32f4_i2c_xfer() - Transfer combined I2C message
+ * @i2c_adap: Adapter pointer to the controller
+ * @msgs: Pointer to data to be written.
+ * @num: Number of messages to be executed
+ */
+static int stm32f4_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+ int num)
+{
+ struct stm32f4_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
+ int ret, i;
+
+ ret = clk_enable(i2c_dev->clk);
+ if (ret) {
+ dev_err(i2c_dev->dev, "Failed to enable clock\n");
+ return ret;
+ }
+
+ stm32f4_i2c_hw_config(i2c_dev);
+
+ for (i = 0; i < num && !ret; i++)
+ ret = stm32f4_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0,
+ i == num - 1);
+
+ clk_disable(i2c_dev->clk);
+
+ return (ret < 0) ? ret : i;
+}
+
+static u32 stm32f4_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm stm32f4_i2c_algo = {
+ .master_xfer = stm32f4_i2c_xfer,
+ .functionality = stm32f4_i2c_func,
+};
+
+static int stm32f4_i2c_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct stm32f4_i2c_dev *i2c_dev;
+ struct resource *res;
+ u32 clk_rate;
+ struct i2c_adapter *adap;
+ struct reset_control *rst;
+ int ret;
+
+ i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+ if (!i2c_dev)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(i2c_dev->base))
+ return PTR_ERR(i2c_dev->base);
+
+ i2c_dev->irq_event = irq_of_parse_and_map(np, 0);
+ if (!i2c_dev->irq_event) {
+ dev_err(&pdev->dev, "IRQ missing or invalid\n");
+ return -EINVAL;
+ }
+
+ i2c_dev->irq_error = irq_of_parse_and_map(np, 1);
+ if (!i2c_dev->irq_error) {
+ dev_err(&pdev->dev, "IRQ missing or invalid\n");
+ return -EINVAL;
+ }
+
+ i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(i2c_dev->clk)) {
+ dev_err(&pdev->dev, "Error: Missing controller clock\n");
+ return PTR_ERR(i2c_dev->clk);
+ }
+ ret = clk_prepare(i2c_dev->clk);
+ if (ret) {
+ dev_err(i2c_dev->dev, "Failed to prepare clock\n");
+ return ret;
+ }
+
+ rst = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(rst)) {
+ dev_err(&pdev->dev, "Error: Missing controller reset\n");
+ ret = PTR_ERR(rst);
+ goto clk_free;
+ }
+ reset_control_assert(rst);
+ udelay(2);
+ reset_control_deassert(rst);
+
+ i2c_dev->speed = STM32F4_I2C_SPEED_STANDARD;
+ ret = of_property_read_u32(np, "clock-frequency", &clk_rate);
+ if ((!ret) && (clk_rate == 400000))
+ i2c_dev->speed = STM32F4_I2C_SPEED_FAST;
+
+ i2c_dev->dev = &pdev->dev;
+
+ ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq_event,
+ NULL, stm32f4_i2c_isr_event,
+ IRQF_ONESHOT, pdev->name, i2c_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq %i\n",
+ i2c_dev->irq_error);
+ goto clk_free;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq_error,
+ NULL, stm32f4_i2c_isr_error,
+ IRQF_ONESHOT, pdev->name, i2c_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq %i\n",
+ i2c_dev->irq_error);
+ goto clk_free;
+ }
+
+ adap = &i2c_dev->adap;
+ i2c_set_adapdata(adap, i2c_dev);
+ snprintf(adap->name, sizeof(adap->name), "STM32 I2C(%pa)", &res->start);
+ adap->owner = THIS_MODULE;
+ adap->timeout = 2 * HZ;
+ adap->retries = 0;
+ adap->algo = &stm32f4_i2c_algo;
+ adap->dev.parent = &pdev->dev;
+ adap->dev.of_node = pdev->dev.of_node;
+
+ init_completion(&i2c_dev->complete);
+
+ ret = i2c_add_adapter(adap);
+ if (ret)
+ goto clk_free;
+
+ platform_set_drvdata(pdev, i2c_dev);
+
+ dev_info(i2c_dev->dev, "STM32F4 I2C driver initialized\n");
+
+ return 0;
+
+clk_free:
+ clk_unprepare(i2c_dev->clk);
+ return ret;
+}
+
+static int stm32f4_i2c_remove(struct platform_device *pdev)
+{
+ struct stm32f4_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&i2c_dev->adap);
+
+ clk_unprepare(i2c_dev->clk);
+
+ return 0;
+}
+
+static const struct of_device_id stm32f4_i2c_match[] = {
+ { .compatible = "st,stm32f4-i2c", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, stm32f4_i2c_match);
+
+static struct platform_driver stm32f4_i2c_driver = {
+ .driver = {
+ .name = "stm32f4-i2c",
+ .of_match_table = stm32f4_i2c_match,
+ },
+ .probe = stm32f4_i2c_probe,
+ .remove = stm32f4_i2c_remove,
+};
+
+module_platform_driver(stm32f4_i2c_driver);
+
+MODULE_AUTHOR("M'boumba Cedric Madianga <cedric.madianga@gmail.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32F4 I2C driver");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related
* [PATCH v5 1/5] dt-bindings: Document the STM32 I2C bindings
From: M'boumba Cedric Madianga @ 2016-12-08 8:25 UTC (permalink / raw)
To: wsa, robh+dt, mcoquelin.stm32, alexandre.torgue, linus.walleij,
patrice.chotard, linux, linux-i2c, devicetree, linux-arm-kernel,
linux-kernel
Cc: M'boumba Cedric Madianga
In-Reply-To: <1481185563-8735-1-git-send-email-cedric.madianga@gmail.com>
This patch adds documentation of device tree bindings for the STM32 I2C
controller.
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/i2c/i2c-stm32.txt | 33 ++++++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt
diff --git a/Documentation/devicetree/bindings/i2c/i2c-stm32.txt b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
new file mode 100644
index 0000000..78eaf7b
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
@@ -0,0 +1,33 @@
+* I2C controller embedded in STMicroelectronics STM32 I2C platform
+
+Required properties :
+- compatible : Must be "st,stm32f4-i2c"
+- reg : Offset and length of the register set for the device
+- interrupts : Must contain the interrupt id for I2C event and then the
+ interrupt id for I2C error.
+- resets: Must contain the phandle to the reset controller.
+- clocks: Must contain the input clock of the I2C instance.
+- A pinctrl state named "default" must be defined to set pins in mode of
+ operation for I2C transfer
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties :
+- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified,
+ the default 100 kHz frequency will be used. As only Normal and Fast modes
+ are supported, possible values are 100000 and 400000.
+
+Example :
+
+ i2c@40005400 {
+ compatible = "st,stm32f4-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x40005400 0x400>;
+ interrupts = <31>,
+ <32>;
+ resets = <&rcc 277>;
+ clocks = <&rcc 0 149>;
+ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
+ pinctrl-names = "default";
+ };
--
1.9.1
^ permalink raw reply related
* [PATCH v5 0/5] Add support for the STM32F4 I2C
From: M'boumba Cedric Madianga @ 2016-12-08 8:25 UTC (permalink / raw)
To: wsa-z923LK4zBo2bacvFa/9K2g, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w,
alexandre.torgue-qxv4g6HH51o,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A, patrice.chotard-qxv4g6HH51o,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: M'boumba Cedric Madianga
This patchset adds support for the I2C controller embedded in STM32F4xx SoC.
It enables I2C transfer in interrupt mode with Standard-mode and Fast-mode bus
speed.
Changes since v4:
- Use clamp() function to use a value in a given range as it was missed in V4
M'boumba Cedric Madianga (5):
dt-bindings: Document the STM32 I2C bindings
i2c: Add STM32F4 I2C driver
ARM: dts: Add I2C1 support for STM32F429 SoC
ARM: dts: Add I2C1 support for STM32429 eval board
ARM: configs: Add I2C support for STM32 defconfig
.../devicetree/bindings/i2c/i2c-stm32.txt | 33 +
arch/arm/boot/dts/stm32429i-eval.dts | 6 +
arch/arm/boot/dts/stm32f429.dtsi | 23 +
arch/arm/configs/stm32_defconfig | 3 +
drivers/i2c/busses/Kconfig | 10 +
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-stm32f4.c | 851 +++++++++++++++++++++
7 files changed, 927 insertions(+)
create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt
create mode 100644 drivers/i2c/busses/i2c-stm32f4.c
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] fsl/usb: Add USB node in FSL's ls1012a DTS
From: Changming Huang @ 2016-12-08 6:06 UTC (permalink / raw)
To: robh+dt, mark.rutland, catalin.marinas, will.deacon, scott.wood
Cc: devicetree, linux-kernel, linux-arm-kernel, Changming Huang
Add USB node in ls1012a device tree
Signed-off-by: Changming Huang <jerry.huang@nxp.com>
---
Dependence on patch "[v3] arm64: Add DTS support for FSL's LS1012A SoC".
https://patchwork.kernel.org/patch/9462399/
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index 92e64f3..3e4bda6 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -235,6 +235,23 @@
<&clockgen 4 3>;
};
+ usb0: usb3@2f00000 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0x2f00000 0x0 0x10000>;
+ interrupts = <0 60 0x4>;
+ dr_mode = "host";
+ snps,quirk-frame-length-adjustment = <0x20>;
+ snps,dis_rxdet_inp3_quirk;
+ };
+
+ usb1: usb2@8600000 {
+ compatible = "fsl-usb2-dr-v2.5", "fsl-usb2-dr";
+ reg = <0x0 0x8600000 0x0 0x1000>;
+ interrupts = <0 139 0x4>;
+ dr_mode = "host";
+ phy_type = "ulpi";
+ };
+
sata: sata@3200000 {
compatible = "fsl,ls1012a-ahci", "fsl,ls1043a-ahci";
reg = <0x0 0x3200000 0x0 0x10000>;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 5/5] arm64: dts: exynos5433: Add support of bus frequency using VDD_INT on TM2
From: Chanwoo Choi @ 2016-12-08 4:58 UTC (permalink / raw)
To: krzk, javier, kgene, robh+dt, s.nawrocki, tomasz.figa
Cc: cw00.choi, myungjoo.ham, kyungmin.park, devicetree,
linux-samsung-soc, linux-arm-kernel, linux-kernel
In-Reply-To: <1481173091-9728-1-git-send-email-cw00.choi@samsung.com>
This patch adds the bus Device-tree nodes for INT (Internal) block
to enable the bus frequency scaling.
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
---
arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 70 +++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
index c08589970134..451788642b21 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
+++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
@@ -170,6 +170,58 @@
};
};
+&bus_g2d_400 {
+ devfreq-events = <&ppmu_event0_d0_general>, <&ppmu_event0_d1_general>;
+ vdd-supply = <&buck4_reg>;
+ exynos,saturation-ratio = <10>;
+ status = "okay";
+};
+
+&bus_g2d_266 {
+ devfreq = <&bus_g2d_400>;
+ status = "okay";
+};
+
+&bus_gscl {
+ devfreq = <&bus_g2d_400>;
+ status = "okay";
+};
+
+&bus_hevc {
+ devfreq = <&bus_g2d_400>;
+ status = "okay";
+};
+
+&bus_jpeg {
+ devfreq = <&bus_g2d_400>;
+ status = "okay";
+};
+
+&bus_mfc {
+ devfreq = <&bus_g2d_400>;
+ status = "okay";
+};
+
+&bus_mscl {
+ devfreq = <&bus_g2d_400>;
+ status = "okay";
+};
+
+&bus_noc0 {
+ devfreq = <&bus_g2d_400>;
+ status = "okay";
+};
+
+&bus_noc1 {
+ devfreq = <&bus_g2d_400>;
+ status = "okay";
+};
+
+&bus_noc2 {
+ devfreq = <&bus_g2d_400>;
+ status = "okay";
+};
+
&cmu_aud {
assigned-clocks = <&cmu_aud CLK_MOUT_AUD_PLL_USER>;
assigned-clock-parents = <&cmu_top CLK_FOUT_AUD_PLL>;
@@ -794,6 +846,24 @@
bus-width = <4>;
};
+&ppmu_d0_general {
+ status = "okay";
+ events {
+ ppmu_event0_d0_general: ppmu-event0-d0-general {
+ event-name = "ppmu-event0-d0-general";
+ };
+ };
+};
+
+&ppmu_d1_general {
+ status = "okay";
+ events {
+ ppmu_event0_d1_general: ppmu-event0-d1-general {
+ event-name = "ppmu-event0-d1-general";
+ };
+ };
+};
+
&pinctrl_alive {
pinctrl-names = "default";
pinctrl-0 = <&initial_alive>;
--
1.9.1
^ permalink raw reply related
* [PATCH v2 4/5] arm64: dts: exynos5433: Add bus dt node using VDD_INT for Exynos5433
From: Chanwoo Choi @ 2016-12-08 4:58 UTC (permalink / raw)
To: krzk, javier, kgene, robh+dt, s.nawrocki, tomasz.figa
Cc: cw00.choi, myungjoo.ham, kyungmin.park, devicetree,
linux-samsung-soc, linux-arm-kernel, linux-kernel
In-Reply-To: <1481173091-9728-1-git-send-email-cw00.choi@samsung.com>
This patch adds the bus nodes using VDD_INT for Exynos5433 SoC.
Exynos5433 has the following AMBA AXI buses to translate data
between DRAM and sub-blocks.
Following list specify the detailed correlation between sub-block and clock:
- CLK_ACLK_G2D_{400|266} : Bus clock for G2D (2D graphic engine)
- CLK_ACLK_MSCL_400 : Bus clock for MSCL (Memory to memory Scaler)
- CLK_ACLK_GSCL_333 : Bus clock for GSCL (General Scaler)
- CLK_SCLK_JPEG_MSCL : Bus clock for JPEG
- CLK_ACLK_MFC_400 : Bus clock for MFC (Multi Format Codec)
- CLK_ACLK_HEVC_400 : Bus clock for HEVC (High Efficient Video Codec)
- CLK_ACLK_BUS0_400 : NoC(Network On Chip)'s bus clock for PERIC/PERIS/FSYS/MSCL
- CLK_ACLK_BUS1_400 : NoC's bus clock for MFC/HEVC/G3D
- CLK_ACLK_BUS2_400 : NoC's bus clock for GSCL/DISP/G2D/CAM0/CAM1/ISP
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
---
arch/arm64/boot/dts/exynos/exynos5433-bus.dtsi | 197 +++++++++++++++++++++++++
arch/arm64/boot/dts/exynos/exynos5433.dtsi | 1 +
2 files changed, 198 insertions(+)
create mode 100644 arch/arm64/boot/dts/exynos/exynos5433-bus.dtsi
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-bus.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-bus.dtsi
new file mode 100644
index 000000000000..09dac0124f73
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos5433-bus.dtsi
@@ -0,0 +1,197 @@
+/*
+ * Samsung's Exynos5433 SoC Memory interface and AMBA bus device tree source
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&soc {
+ bus_g2d_400: bus0 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_top CLK_ACLK_G2D_400>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_g2d_400_opp_table>;
+ status ="disabled";
+ };
+
+ bus_g2d_266: bus1 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_top CLK_ACLK_G2D_266>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_g2d_266_opp_table>;
+ status ="disabled";
+ };
+
+ bus_gscl: bus2 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_top CLK_ACLK_GSCL_333>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_gscl_opp_table>;
+ status ="disabled";
+ };
+
+ bus_hevc: bus3 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_top CLK_ACLK_HEVC_400>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_hevc_opp_table>;
+ status ="disabled";
+ };
+
+ bus_jpeg: bus4 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_top CLK_SCLK_JPEG_MSCL>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_g2d_400_opp_table>;
+ status ="disabled";
+ };
+
+ bus_mfc: bus5 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_top CLK_ACLK_MFC_400>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_g2d_400_opp_table>;
+ status ="disabled";
+ };
+
+ bus_mscl: bus6 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_top CLK_ACLK_MSCL_400>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_g2d_400_opp_table>;
+ status ="disabled";
+ };
+
+ bus_noc0: bus7 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_top CLK_ACLK_BUS0_400>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_hevc_opp_table>;
+ status ="disabled";
+ };
+
+ bus_noc1: bus8 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_top CLK_ACLK_BUS1_400>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_hevc_opp_table>;
+ status ="disabled";
+ };
+
+ bus_noc2: bus9 {
+ compatible = "samsung,exynos-bus";
+ clocks = <&cmu_mif CLK_ACLK_BUS2_400>;
+ clock-names = "bus";
+ operating-points-v2 = <&bus_noc2_opp_table>;
+ status ="disabled";
+ };
+
+ bus_g2d_400_opp_table: opp_table2 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp@400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <1075000>;
+ };
+ opp@267000000 {
+ opp-hz = /bits/ 64 <267000000>;
+ opp-microvolt = <1000000>;
+ };
+ opp@200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <975000>;
+ };
+ opp@160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ opp-microvolt = <962500>;
+ };
+ opp@134000000 {
+ opp-hz = /bits/ 64 <134000000>;
+ opp-microvolt = <950000>;
+ };
+ opp@100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <937500>;
+ };
+ };
+
+ bus_g2d_266_opp_table: opp_table3 {
+ compatible = "operating-points-v2";
+
+ opp@267000000 {
+ opp-hz = /bits/ 64 <267000000>;
+ };
+ opp@200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ };
+ opp@160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ };
+ opp@134000000 {
+ opp-hz = /bits/ 64 <134000000>;
+ };
+ opp@100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ };
+ };
+
+ bus_gscl_opp_table: opp_table4 {
+ compatible = "operating-points-v2";
+
+ opp@333000000 {
+ opp-hz = /bits/ 64 <333000000>;
+ };
+ opp@222000000 {
+ opp-hz = /bits/ 64 <222000000>;
+ };
+ opp@166500000 {
+ opp-hz = /bits/ 64 <166500000>;
+ };
+ };
+
+ bus_hevc_opp_table: opp_table5 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp@400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ };
+ opp@267000000 {
+ opp-hz = /bits/ 64 <267000000>;
+ };
+ opp@200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ };
+ opp@160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ };
+ opp@134000000 {
+ opp-hz = /bits/ 64 <134000000>;
+ };
+ opp@100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ };
+ };
+
+ bus_noc2_opp_table: opp_table6 {
+ compatible = "operating-points-v2";
+
+ opp@400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ };
+ opp@200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ };
+ opp@134000000 {
+ opp-hz = /bits/ 64 <134000000>;
+ };
+ opp@100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
index 8c4ee84d5232..68f764e5851c 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
@@ -1482,5 +1482,6 @@
};
};
+#include "exynos5433-bus.dtsi"
#include "exynos5433-pinctrl.dtsi"
#include "exynos5433-tmu.dtsi"
--
1.9.1
^ permalink raw reply related
* [PATCH v2 3/5] arm64: dts: exynos5433: Add PPMU dt node
From: Chanwoo Choi @ 2016-12-08 4:58 UTC (permalink / raw)
To: krzk, javier, kgene, robh+dt, s.nawrocki, tomasz.figa
Cc: cw00.choi, myungjoo.ham, kyungmin.park, devicetree,
linux-samsung-soc, linux-arm-kernel, linux-kernel
In-Reply-To: <1481173091-9728-1-git-send-email-cw00.choi@samsung.com>
This patch adds PPMU (Platform Performance Monitoring Unit) Device-tree node
to measure the utilization of each IP in Exynos SoC.
- PPMU_D{0|1}_CPU are used to measure the utilization of MIF (Memory Interface)
block with VDD_MIF power source.
- PPMU_D{0|1}_GENERAL are used to measure the utilization of INT(Internal)
block with VDD_INT power source.
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
---
arch/arm64/boot/dts/exynos/exynos5433.dtsi | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
index 64226d5ae471..8c4ee84d5232 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
@@ -599,6 +599,30 @@
clock-names = "fin_pll", "mct";
};
+ ppmu_d0_cpu: ppmu@10480000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x10480000 0x2000>;
+ status = "disabled";
+ };
+
+ ppmu_d0_general: ppmu@10490000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x10490000 0x2000>;
+ status = "disabled";
+ };
+
+ ppmu_d1_cpu: ppmu@104b0000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x104b0000 0x2000>;
+ status = "disabled";
+ };
+
+ ppmu_d1_general: ppmu@104c0000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x104c0000 0x2000>;
+ status = "disabled";
+ };
+
pinctrl_alive: pinctrl@10580000 {
compatible = "samsung,exynos5433-pinctrl";
reg = <0x10580000 0x1a20>, <0x11090000 0x100>;
--
1.9.1
^ permalink raw reply related
* [PATCH v2 2/5] PM / devfreq: exynos-bus: Add the detailed correlation for Exynos5433
From: Chanwoo Choi @ 2016-12-08 4:58 UTC (permalink / raw)
To: krzk-DgEjT+Ai2ygdnm+yROfE0A, javier-JPH+aEBZ4P+UEJcrhfAQsw,
kgene-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
tomasz.figa-Re5JQEeQqe8AvxtiuMwx3w
Cc: cw00.choi-Sze3O3UU22JBDgjK7y7TUQ,
myungjoo.ham-Sze3O3UU22JBDgjK7y7TUQ,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1481173091-9728-1-git-send-email-cw00.choi-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
This patch adds the detailed corrleation between sub-blocks and VDD_INT power
line for Exynos5433. VDD_INT provided the power source to INT (Internal) block.
Cc: MyungJoo Ham <myungjoo.ham-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Cc: Kyungmin Park <kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Chanwoo Choi <cw00.choi-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
Documentation/devicetree/bindings/devfreq/exynos-bus.txt | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
index d3ec8e676b6b..d6107770face 100644
--- a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
+++ b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
@@ -123,6 +123,21 @@ Detailed correlation between sub-blocks and power line according to Exynos SoC:
|--- FSYS
|--- FSYS2
+- In case of Exynos5433, there is VDD_INT power line as following:
+ VDD_INT |--- G2D_400 (parent device)
+ |--- G2D_266
+ |--- GSCL
+ |--- JPEG
+ |--- HEVC
+ |--- MFC
+ |--- MSCL
+ |--- NoC0
+ |--- NoC1
+ |--- NoC2
+ |--- PERIS (Fixed clock rate)
+ |--- PERIC (Fixed clock rate)
+ |--- FSYS (Fixed clock rate)
+
Example1:
Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to
power line (regulator). The MIF (Memory Interface) AXI bus is used to
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 1/5] clk: samsung: exynos5433: Set NoC (Network On Chip) clocks as critical
From: Chanwoo Choi @ 2016-12-08 4:58 UTC (permalink / raw)
To: krzk, javier, kgene, robh+dt, s.nawrocki, tomasz.figa
Cc: cw00.choi, myungjoo.ham, kyungmin.park, devicetree,
linux-samsung-soc, linux-arm-kernel, linux-kernel,
Michael Turquette, Stephen Boyd
In-Reply-To: <1481173091-9728-1-git-send-email-cw00.choi@samsung.com>
The ACLK_BUS0/1/2 are used for NoC (Network on Chip). If NoC's clocks are
disabled, the system halt happen. Following clock must be always enabled.
- CLK_ACLK_BUS0_400 : NoC's bus clock for PERIC/PERIS/FSYS/MSCL
- CLK_ACLK_BUS1_400 : NoC's bus clock for MFC/HEVC/G3D
- CLK_ACLK_BUS2_400 : NoC's bus clock for GSCL/DISP/G2D/CAM0/CAM1/ISP
Also, this patch adds the CLK_SET_RATE_PARENT flag to the CLK_SCLK_JPEG_MSCL
because this clock should be used for bus frequency scaling. This clock need to
be changed on the fly with CLK_SET_RATE_PARENT flag.
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Chanwoo Choi <cw00.choi@samsung.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc:linux-clk@vger.kernel.org
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
---
drivers/clk/samsung/clk-exynos5433.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index f096bd7df40c..0db5204c307c 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -549,10 +549,10 @@
29, CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_BUS0_400, "aclk_bus0_400", "div_aclk_bus0_400",
ENABLE_ACLK_TOP, 26,
- CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_BUS1_400, "aclk_bus1_400", "div_aclk_bus1_400",
ENABLE_ACLK_TOP, 25,
- CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_266",
ENABLE_ACLK_TOP, 24,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
@@ -616,7 +616,7 @@
/* ENABLE_SCLK_TOP_MSCL */
GATE(CLK_SCLK_JPEG_MSCL, "sclk_jpeg_mscl", "div_sclk_jpeg",
- ENABLE_SCLK_TOP_MSCL, 0, 0, 0),
+ ENABLE_SCLK_TOP_MSCL, 0, CLK_SET_RATE_PARENT, 0),
/* ENABLE_SCLK_TOP_CAM1 */
GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "div_sclk_isp_sensor2_b",
@@ -1382,7 +1382,7 @@ static void __init exynos5433_cmu_cpif_init(struct device_node *np)
/* ENABLE_ACLK_MIF3 */
GATE(CLK_ACLK_BUS2_400, "aclk_bus2_400", "div_aclk_bus2_400",
ENABLE_ACLK_MIF3, 4,
- CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_DISP_333, "aclk_disp_333", "div_aclk_disp_333",
ENABLE_ACLK_MIF3, 1,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
--
1.9.1
^ permalink raw reply related
* [PATCH v2 0/5] arm64: dts: Enable bus frequency scaling on Exynos5433-based TM2 board
From: Chanwoo Choi @ 2016-12-08 4:58 UTC (permalink / raw)
To: krzk, javier, kgene, robh+dt, s.nawrocki, tomasz.figa
Cc: cw00.choi, myungjoo.ham, kyungmin.park, devicetree,
linux-samsung-soc, linux-arm-kernel, linux-kernel
This patches add the AMBA bus Device-tree node unsing VDD_INT
to enable the bus frequency scaling on Exynos5433-based TM2 board.
There are two kind of bus device with devfreq framework.
- Parent bus device : Change the frequency/voltage according to bus's utilization.
- Passive bus device : Change only frequency according to the new level
of parent bus device.
The VDD_INT regulator provides the power source to INT (Internal) block as
following. The sub-blocks in the INT block share the one power source.
VDD_INT |--- G2D_400 (parent device)
|--- G2D_266
|--- GSCL
|--- JPEG
|--- HEVC
|--- MFC
|--- MSCL
|--- NoC0
|--- NoC1
|--- NoC2
|--- PERIS (Fixed clock rate)
|--- PERIC (Fixed clock rate)
|--- FSYS (Fixed clock rate)
Each sub-block has the bus clock as following:
- CLK_ACLK_G2D_{400|266} : Bus clock for G2D (2D graphic engine)
- CLK_ACLK_MSCL_400 : Bus clock for MSCL (Memory to memory Scaler)
- CLK_ACLK_GSCL_333 : Bus clock for GSCL (General Scaler)
- CLK_SCLK_JPEG_MSCL : Bus clock for JPEG
- CLK_ACLK_MFC_400 : Bus clock for MFC (Multi Format Codec)
- CLK_ACLK_HEVC_400 : Bus clock for HEVC (High Effective Video Codec)
- CLK_ACLK_BUS0_400 : NoC(Network On Chip)'s bus clock for PERIC/PERIS/FSYS/MSCL
- CLK_ACLK_BUS1_400 : NoC's bus clock for MFC/HEVC/G3D
- CLK_ACLK_BUS2_400 : NoC's bus clock for GSCL/DISP/G2D/CAM0/CAM1/ISP
Changes from v1:
- Remove duplicate description of exynos5433-bus.dtsi
- Move the bus device-tree node under the 'soc'
- Modify the node name of bus from 'bus_xxx_xxx' to 'bus[number]'
- Reorder the bus device-tree node alpabetically
- Change the node name from 'bus_busX' to 'bus_nocX'
- Fix minor issue
- Add reviewed-by tag of Krzysztof Kozlowski for patch3/5
Chanwoo Choi (5):
clk: samsung: exynos5433: Set NoC (Network On Chip) clocks as critical
PM / devfreq: exynos-bus: Add the detailed correlation for Exynos5433
arm64: dts: exynos5433: Add PPMU dt node
arm64: dts: exynos5433: Add bus dt node using VDD_INT for Exynos5433
arm64: dts: exynos5433: Add support of bus frequency using VDD_INT on TM2
.../devicetree/bindings/devfreq/exynos-bus.txt | 15 ++
arch/arm64/boot/dts/exynos/exynos5433-bus.dtsi | 197 +++++++++++++++++++++
arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 70 ++++++++
arch/arm64/boot/dts/exynos/exynos5433.dtsi | 25 +++
drivers/clk/samsung/clk-exynos5433.c | 8 +-
5 files changed, 311 insertions(+), 4 deletions(-)
create mode 100644 arch/arm64/boot/dts/exynos/exynos5433-bus.dtsi
--
1.9.1
^ permalink raw reply
* Re: [PATCH v4 4/5] i2c: designware: Add slave mode as separated driver
From: kbuild test robot @ 2016-12-08 4:38 UTC (permalink / raw)
Cc: kbuild-all-JC7UmRfGjtg, wsa-z923LK4zBo2bacvFa/9K2g,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
jarkko.nikula-VuQAYsv1563Yd54FQh9/CA,
andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA,
mika.westerberg-VuQAYsv1563Yd54FQh9/CA,
linux-i2c-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Luis.Oliveira-HKixBCOQz3hWk0Htik3J/w,
Ramiro.Oliveira-HKixBCOQz3hWk0Htik3J/w,
Joao.Pinto-HKixBCOQz3hWk0Htik3J/w,
CARLOS.PALMINHA-HKixBCOQz3hWk0Htik3J/w
In-Reply-To: <a7ca5014ad1c3f4905349a02ebe5294fe64c318e.1481131072.git.lolivei-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 5155 bytes --]
Hi Luis,
[auto build test WARNING on wsa/i2c/for-next]
[also build test WARNING on next-20161207]
[cannot apply to v4.9-rc8]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Luis-Oliveira/i2c-designware-Refactoring-of-the-i2c-designware/20161208-044045
base: https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: i386-randconfig-h0-12081126 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All warnings (new ones prefixed by >>):
drivers/i2c/busses/i2c-designware-slave.c: In function 'i2c_dw_irq_handler_slave':
drivers/i2c/busses/i2c-designware-slave.c:294:3: error: implicit declaration of function 'i2c_slave_event' [-Werror=implicit-function-declaration]
i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, &val);
^~~~~~~~~~~~~~~
drivers/i2c/busses/i2c-designware-slave.c:294:31: error: 'I2C_SLAVE_WRITE_REQUESTED' undeclared (first use in this function)
i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, &val);
^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/i2c/busses/i2c-designware-slave.c:294:31: note: each undeclared identifier is reported only once for each function it appears in
In file included from include/linux/err.h:4:0,
from drivers/i2c/busses/i2c-designware-slave.c:26:
drivers/i2c/busses/i2c-designware-slave.c:301:6: error: 'I2C_SLAVE_WRITE_RECEIVED' undeclared (first use in this function)
I2C_SLAVE_WRITE_RECEIVED, &val)) {
^
include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
>> drivers/i2c/busses/i2c-designware-slave.c:300:5: note: in expansion of macro 'if'
if (!i2c_slave_event(dev->slave,
^~
drivers/i2c/busses/i2c-designware-slave.c:313:7: error: 'I2C_SLAVE_READ_REQUESTED' undeclared (first use in this function)
I2C_SLAVE_READ_REQUESTED, &val))
^
include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
drivers/i2c/busses/i2c-designware-slave.c:312:4: note: in expansion of macro 'if'
if (!i2c_slave_event(dev->slave,
^~
drivers/i2c/busses/i2c-designware-slave.c:319:36: error: 'I2C_SLAVE_READ_PROCESSED' undeclared (first use in this function)
if (!i2c_slave_event(dev->slave, I2C_SLAVE_READ_PROCESSED,
^
include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
drivers/i2c/busses/i2c-designware-slave.c:319:3: note: in expansion of macro 'if'
if (!i2c_slave_event(dev->slave, I2C_SLAVE_READ_PROCESSED,
^~
drivers/i2c/busses/i2c-designware-slave.c:323:31: error: 'I2C_SLAVE_STOP' undeclared (first use in this function)
i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val);
^~~~~~~~~~~~~~
drivers/i2c/busses/i2c-designware-slave.c: At top level:
drivers/i2c/busses/i2c-designware-slave.c:358:2: error: unknown field 'reg_slave' specified in initializer
.reg_slave = i2c_dw_reg_slave,
^
drivers/i2c/busses/i2c-designware-slave.c:358:15: warning: excess elements in struct initializer
.reg_slave = i2c_dw_reg_slave,
^~~~~~~~~~~~~~~~
drivers/i2c/busses/i2c-designware-slave.c:358:15: note: (near initialization for 'i2c_dw_algo')
drivers/i2c/busses/i2c-designware-slave.c:359:2: error: unknown field 'unreg_slave' specified in initializer
.unreg_slave = i2c_dw_unreg_slave,
^
drivers/i2c/busses/i2c-designware-slave.c:359:17: warning: excess elements in struct initializer
.unreg_slave = i2c_dw_unreg_slave,
^~~~~~~~~~~~~~~~~~
drivers/i2c/busses/i2c-designware-slave.c:359:17: note: (near initialization for 'i2c_dw_algo')
cc1: some warnings being treated as errors
vim +/if +300 drivers/i2c/busses/i2c-designware-slave.c
288 dw_readl(dev, DW_IC_CLR_START_DET);
289 if (stat & DW_IC_INTR_ACTIVITY)
290 dw_readl(dev, DW_IC_CLR_ACTIVITY);
291 if (stat & DW_IC_INTR_RX_OVER)
292 dw_readl(dev, DW_IC_CLR_RX_OVER);
293 if ((stat & DW_IC_INTR_RX_FULL) && (stat & DW_IC_INTR_STOP_DET))
> 294 i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, &val);
295
296 if (slave_activity) {
297 if (stat & DW_IC_INTR_RD_REQ) {
298 if (stat & DW_IC_INTR_RX_FULL) {
299 val = dw_readl(dev, DW_IC_DATA_CMD);
> 300 if (!i2c_slave_event(dev->slave,
301 I2C_SLAVE_WRITE_RECEIVED, &val)) {
302 dev_dbg(dev->dev, "Byte %X acked!",
303 val);
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 20667 bytes --]
^ permalink raw reply
* [PATCH 2/2] arm64:dt:ls1012a: Add TMU device tree support for LS1012A
From: Jia Hongtao @ 2016-12-08 3:28 UTC (permalink / raw)
To: shawnguo, rui.zhang, edubezval, robh+dt, scott.wood
Cc: hongtao.jia, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <1481167706-44234-1-git-send-email-hongtao.jia@nxp.com>
Also add nodes and properties for thermal management support.
Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
---
Depend on patch "[v3] arm64: Add DTS support for FSL's LS1012A SoC".
https://patchwork.kernel.org/patch/9462399/
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 76 ++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index 92e64f3..bc694b4 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -43,6 +43,7 @@
*/
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
compatible = "fsl,ls1012a";
@@ -127,6 +128,81 @@
#clock-cells = <2>;
clocks = <&sysclk>;
};
+ tmu: tmu@1f00000 {
+ compatible = "fsl,qoriq-tmu";
+ reg = <0x0 0x1f00000 0x0 0x10000>;
+ interrupts = <0 33 0x4>;
+ fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
+ fsl,tmu-calibration = <0x00000000 0x00000026
+ 0x00000001 0x0000002d
+ 0x00000002 0x00000032
+ 0x00000003 0x00000039
+ 0x00000004 0x0000003f
+ 0x00000005 0x00000046
+ 0x00000006 0x0000004d
+ 0x00000007 0x00000054
+ 0x00000008 0x0000005a
+ 0x00000009 0x00000061
+ 0x0000000a 0x0000006a
+ 0x0000000b 0x00000071
+
+ 0x00010000 0x00000025
+ 0x00010001 0x0000002c
+ 0x00010002 0x00000035
+ 0x00010003 0x0000003d
+ 0x00010004 0x00000045
+ 0x00010005 0x0000004e
+ 0x00010006 0x00000057
+ 0x00010007 0x00000061
+ 0x00010008 0x0000006b
+ 0x00010009 0x00000076
+
+ 0x00020000 0x00000029
+ 0x00020001 0x00000033
+ 0x00020002 0x0000003d
+ 0x00020003 0x00000049
+ 0x00020004 0x00000056
+ 0x00020005 0x00000061
+ 0x00020006 0x0000006d
+
+ 0x00030000 0x00000021
+ 0x00030001 0x0000002a
+ 0x00030002 0x0000003c
+ 0x00030003 0x0000004e>;
+ big-endian;
+ #thermal-sensor-cells = <1>;
+ };
+
+ thermal-zones {
+ cpu_thermal: cpu-thermal {
+ polling-delay-passive = <1000>;
+ polling-delay = <5000>;
+
+ thermal-sensors = <&tmu 0>;
+
+ trips {
+ cpu_alert: cpu-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit: cpu-crit {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert>;
+ cooling-device =
+ <&cpu0 THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
i2c0: i2c@2180000 {
compatible = "fsl,vf610-i2c";
--
2.1.0.27.g96db324
^ permalink raw reply related
* [PATCH 1/2] arm64:dt:ls1046a: Add TMU device tree support for LS1046A
From: Jia Hongtao @ 2016-12-08 3:28 UTC (permalink / raw)
To: shawnguo, rui.zhang, edubezval, robh+dt, scott.wood
Cc: hongtao.jia, devicetree, linux-kernel, linux-arm-kernel
Also add nodes and properties for thermal management support.
Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
---
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 79 ++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 38806ca..40604e9 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -45,6 +45,8 @@
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
+
/ {
compatible = "fsl,ls1046a";
@@ -67,6 +69,7 @@
clocks = <&clockgen 1 0>;
next-level-cache = <&l2>;
cpu-idle-states = <&CPU_PH20>;
+ #cooling-cells = <2>;
};
cpu1: cpu@1 {
@@ -279,6 +282,82 @@
clocks = <&sysclk>;
};
+ tmu: tmu@1f00000 {
+ compatible = "fsl,qoriq-tmu";
+ reg = <0x0 0x1f00000 0x0 0x10000>;
+ interrupts = <0 33 0x4>;
+ fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
+ fsl,tmu-calibration = <0x00000000 0x00000026
+ 0x00000001 0x0000002d
+ 0x00000002 0x00000032
+ 0x00000003 0x00000039
+ 0x00000004 0x0000003f
+ 0x00000005 0x00000046
+ 0x00000006 0x0000004d
+ 0x00000007 0x00000054
+ 0x00000008 0x0000005a
+ 0x00000009 0x00000061
+ 0x0000000a 0x0000006a
+ 0x0000000b 0x00000071
+
+ 0x00010000 0x00000025
+ 0x00010001 0x0000002c
+ 0x00010002 0x00000035
+ 0x00010003 0x0000003d
+ 0x00010004 0x00000045
+ 0x00010005 0x0000004e
+ 0x00010006 0x00000057
+ 0x00010007 0x00000061
+ 0x00010008 0x0000006b
+ 0x00010009 0x00000076
+
+ 0x00020000 0x00000029
+ 0x00020001 0x00000033
+ 0x00020002 0x0000003d
+ 0x00020003 0x00000049
+ 0x00020004 0x00000056
+ 0x00020005 0x00000061
+ 0x00020006 0x0000006d
+
+ 0x00030000 0x00000021
+ 0x00030001 0x0000002a
+ 0x00030002 0x0000003c
+ 0x00030003 0x0000004e>;
+ big-endian;
+ #thermal-sensor-cells = <1>;
+ };
+
+ thermal-zones {
+ cpu_thermal: cpu-thermal {
+ polling-delay-passive = <1000>;
+ polling-delay = <5000>;
+
+ thermal-sensors = <&tmu 3>;
+
+ trips {
+ cpu_alert: cpu-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit: cpu-crit {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert>;
+ cooling-device =
+ <&cpu0 THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
+
dspi: dspi@2100000 {
compatible = "fsl,ls1021a-v1.0-dspi";
#address-cells = <1>;
--
2.1.0.27.g96db324
^ permalink raw reply related
* [RESEND-PATCH] ARM: EXYNOS: remove smp hook from machine descriptor
From: Pankaj Dubey @ 2016-12-08 3:02 UTC (permalink / raw)
To: linux-samsung-soc, linux-arm-kernel, devicetree
Cc: arnd, krzk, kgene, javier, thomas.ab, Pankaj Dubey
Use CPU_METHOD_OF_DECLARE() for smp_ops instead of using it
via machine descriptor.
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
---
Resending as I missed to include samsung mailing list.
arch/arm/boot/dts/exynos3250.dtsi | 1 +
arch/arm/boot/dts/exynos4210.dtsi | 1 +
arch/arm/boot/dts/exynos4212.dtsi | 1 +
arch/arm/boot/dts/exynos4412.dtsi | 1 +
arch/arm/boot/dts/exynos5250.dtsi | 1 +
arch/arm/boot/dts/exynos5260.dtsi | 1 +
arch/arm/boot/dts/exynos5410.dtsi | 1 +
arch/arm/boot/dts/exynos5420-cpus.dtsi | 1 +
arch/arm/boot/dts/exynos5422-cpus.dtsi | 1 +
arch/arm/boot/dts/exynos5440.dtsi | 1 +
arch/arm/mach-exynos/common.h | 2 --
arch/arm/mach-exynos/exynos.c | 1 -
arch/arm/mach-exynos/platsmp.c | 2 ++
13 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index ba17ee1..f28f669 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -53,6 +53,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu0: cpu@0 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 7f3a18c..6dfd98d 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -35,6 +35,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu0: cpu@900 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
index 5389011..3e8982e 100644
--- a/arch/arm/boot/dts/exynos4212.dtsi
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -25,6 +25,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu0: cpu@A00 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index 40beede..faf2fb8 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -25,6 +25,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu0: cpu@A00 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index b6d7444..580897c 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -52,6 +52,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu0: cpu@0 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/exynos5260.dtsi b/arch/arm/boot/dts/exynos5260.dtsi
index 5818718..1af6e76 100644
--- a/arch/arm/boot/dts/exynos5260.dtsi
+++ b/arch/arm/boot/dts/exynos5260.dtsi
@@ -32,6 +32,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu@0 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 2b6adaf..b092cdc 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -33,6 +33,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu0: cpu@0 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/exynos5420-cpus.dtsi b/arch/arm/boot/dts/exynos5420-cpus.dtsi
index 5c052d7..a587704 100644
--- a/arch/arm/boot/dts/exynos5420-cpus.dtsi
+++ b/arch/arm/boot/dts/exynos5420-cpus.dtsi
@@ -24,6 +24,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu0: cpu@0 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/exynos5422-cpus.dtsi b/arch/arm/boot/dts/exynos5422-cpus.dtsi
index bf3c6f1..7fcdfd0 100644
--- a/arch/arm/boot/dts/exynos5422-cpus.dtsi
+++ b/arch/arm/boot/dts/exynos5422-cpus.dtsi
@@ -23,6 +23,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu0: cpu@100 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi
index 2a2e570..0a958e8 100644
--- a/arch/arm/boot/dts/exynos5440.dtsi
+++ b/arch/arm/boot/dts/exynos5440.dtsi
@@ -50,6 +50,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "samsung,exynos-smp";
cpu@0 {
device_type = "cpu";
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index fb12d11..051e1ab 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -143,8 +143,6 @@ static inline void exynos_pm_init(void) {}
extern void exynos_cpu_resume(void);
extern void exynos_cpu_resume_ns(void);
-extern const struct smp_operations exynos_smp_ops;
-
extern void exynos_cpu_power_down(int cpu);
extern void exynos_cpu_power_up(int cpu);
extern int exynos_cpu_power_state(int cpu);
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index fa08ef9..f0a766e 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -211,7 +211,6 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
.l2c_aux_val = 0x3c400001,
.l2c_aux_mask = 0xc20fffff,
- .smp = smp_ops(exynos_smp_ops),
.map_io = exynos_init_io,
.init_early = exynos_firmware_init,
.init_irq = exynos_init_irq,
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 94405c7..43eec10 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -474,3 +474,5 @@ const struct smp_operations exynos_smp_ops __initconst = {
.cpu_die = exynos_cpu_die,
#endif
};
+
+CPU_METHOD_OF_DECLARE(exynos_smp, "samsung,exynos-smp", &exynos_smp_ops);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v3 4/4] pinctrl: aspeed: Fix kerneldoc return descriptions
From: Joel Stanley @ 2016-12-08 2:20 UTC (permalink / raw)
To: Andrew Jeffery
Cc: Linus Walleij, Rob Herring, Mark Rutland,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161206031152.3004-5-andrew-zrmu5oMJ5Fs@public.gmane.org>
On Tue, Dec 6, 2016 at 1:41 PM, Andrew Jeffery <andrew-zrmu5oMJ5Fs@public.gmane.org> wrote:
> Signed-off-by: Andrew Jeffery <andrew-zrmu5oMJ5Fs@public.gmane.org>
Acked-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
> ---
> drivers/pinctrl/aspeed/pinctrl-aspeed.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 1/4] pinctrl: aspeed: Read and write bits in LPC and GFX controllers
From: Joel Stanley @ 2016-12-08 2:19 UTC (permalink / raw)
To: Andrew Jeffery
Cc: Linus Walleij, Rob Herring, Mark Rutland, linux-gpio, devicetree,
linux-kernel
In-Reply-To: <20161206031152.3004-2-andrew@aj.id.au>
On Tue, Dec 6, 2016 at 1:41 PM, Andrew Jeffery <andrew@aj.id.au> wrote:
> The System Control Unit IP block in the Aspeed SoCs is typically where
> the pinmux configuration is found, but not always. A number of pins
> depend on state in one of LPC Host Control (LHC) or SoC Display
> Controller (GFX) IP blocks, so the Aspeed pinmux drivers should have the
> means to adjust these as necessary.
>
> We use syscon to cast a regmap over the GFX and LPC blocks, which is
> used as an arbitration layer between the relevant driver and the pinctrl
> subsystem. The regmaps are then exposed to the SoC-specific pinctrl
> drivers by phandles in the devicetree, and are selected during a mux
> request by querying a new 'ip' member in struct aspeed_sig_desc.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Reviewed-by: Joel Stanley <joel@jms.id.au>
(I think I've reviewed these on the openbmc list; feel free to keep my
reviewed-by tag when that's happened).
We might need to split the bindings update and the code changes into
separate patches so they can go via their respective trees.
Cheers,
Joel
> ---
> .../devicetree/bindings/pinctrl/pinctrl-aspeed.txt | 50 ++++++-
> drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c | 18 +--
> drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 48 ++++--
> drivers/pinctrl/aspeed/pinctrl-aspeed.c | 161 +++++++++++++--------
> drivers/pinctrl/aspeed/pinctrl-aspeed.h | 32 ++--
> 5 files changed, 214 insertions(+), 95 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
> index 2ad18c4ea55c..115b0cce6c1c 100644
> --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
> +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
> @@ -4,12 +4,19 @@ Aspeed Pin Controllers
> The Aspeed SoCs vary in functionality inside a generation but have a common mux
> device register layout.
>
> -Required properties:
> -- compatible : Should be any one of the following:
> - "aspeed,ast2400-pinctrl"
> - "aspeed,g4-pinctrl"
> - "aspeed,ast2500-pinctrl"
> - "aspeed,g5-pinctrl"
> +Required properties for g4:
> +- compatible : Should be any one of the following:
> + "aspeed,ast2400-pinctrl"
> + "aspeed,g4-pinctrl"
> +
> +Required properties for g5:
> +- compatible : Should be any one of the following:
> + "aspeed,ast2500-pinctrl"
> + "aspeed,g5-pinctrl"
> +
> +- aspeed,external-nodes: A cell of phandles to external controller nodes:
> + 0: compatible with "aspeed,ast2500-gfx", "syscon"
> + 1: compatible with "aspeed,ast2500-lpchc", "syscon"
>
> The pin controller node should be a child of a syscon node with the required
> property:
> @@ -47,7 +54,7 @@ RGMII1 RGMII2 RMII1 RMII2 SD1 SPI1 SPI1DEBUG SPI1PASSTHRU TIMER4 TIMER5 TIMER6
> TIMER7 TIMER8 VGABIOSROM
>
>
> -Examples:
> +g4 Example:
>
> syscon: scu@1e6e2000 {
> compatible = "syscon", "simple-mfd";
> @@ -63,5 +70,34 @@ syscon: scu@1e6e2000 {
> };
> };
>
> +g5 Example:
> +
> +apb {
> + gfx: display@1e6e6000 {
> + compatible = "aspeed,ast2500-gfx", "syscon";
> + reg = <0x1e6e6000 0x1000>;
> + };
> +
> + lpchc: lpchc@1e7890a0 {
> + compatible = "aspeed,ast2500-lpchc", "syscon";
> + reg = <0x1e7890a0 0xc4>;
> + };
> +
> + syscon: scu@1e6e2000 {
> + compatible = "syscon", "simple-mfd";
> + reg = <0x1e6e2000 0x1a8>;
> +
> + pinctrl: pinctrl {
> + compatible = "aspeed,g5-pinctrl";
> + aspeed,external-nodes = <&gfx, &lpchc>;
> +
> + pinctrl_i2c3_default: i2c3_default {
> + function = "I2C3";
> + groups = "I2C3";
> + };
> + };
> + };
> +};
> +
> Please refer to pinctrl-bindings.txt in this directory for details of the
> common pinctrl bindings used by client devices.
> diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
> index a21b071ff290..558bd102416c 100644
> --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
> +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
> @@ -292,7 +292,7 @@ SSSF_PIN_DECL(U18, GPIOG7, FLWP, SIG_DESC_SET(SCU84, 7));
> #define UART6_DESC SIG_DESC_SET(SCU90, 7)
> #define ROM16_DESC SIG_DESC_SET(SCU90, 6)
> #define FLASH_WIDE SIG_DESC_SET(HW_STRAP1, 4)
> -#define BOOT_SRC_NOR { HW_STRAP1, GENMASK(1, 0), 0, 0 }
> +#define BOOT_SRC_NOR { ASPEED_IP_SCU, HW_STRAP1, GENMASK(1, 0), 0, 0 }
>
> #define A8 56
> SIG_EXPR_DECL(ROMD8, ROM16, ROM16_DESC);
> @@ -418,9 +418,9 @@ FUNC_GROUP_DECL(I2C8, G5, F3);
> #define U1 88
> SSSF_PIN_DECL(U1, GPIOL0, NCTS1, SIG_DESC_SET(SCU84, 16));
>
> -#define VPI18_DESC { SCU90, GENMASK(5, 4), 1, 0 }
> -#define VPI24_DESC { SCU90, GENMASK(5, 4), 2, 0 }
> -#define VPI30_DESC { SCU90, GENMASK(5, 4), 3, 0 }
> +#define VPI18_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 1, 0 }
> +#define VPI24_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 2, 0 }
> +#define VPI30_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 3, 0 }
>
> #define T5 89
> #define T5_DESC SIG_DESC_SET(SCU84, 17)
> @@ -641,11 +641,11 @@ SSSF_PIN_DECL(Y22, GPIOR2, ROMCS3, SIG_DESC_SET(SCU88, 26));
> #define U19 139
> SSSF_PIN_DECL(U19, GPIOR3, ROMCS4, SIG_DESC_SET(SCU88, 27));
>
> -#define VPOOFF0_DESC { SCU94, GENMASK(1, 0), 0, 0 }
> -#define VPO12_DESC { SCU94, GENMASK(1, 0), 1, 0 }
> -#define VPO24_DESC { SCU94, GENMASK(1, 0), 2, 0 }
> -#define VPOOFF1_DESC { SCU94, GENMASK(1, 0), 3, 0 }
> -#define VPO_OFF_12 { SCU94, 0x2, 0, 0 }
> +#define VPOOFF0_DESC { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 0, 0 }
> +#define VPO12_DESC { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 1, 0 }
> +#define VPO24_DESC { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 2, 0 }
> +#define VPOOFF1_DESC { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 3, 0 }
> +#define VPO_OFF_12 { ASPEED_IP_SCU, SCU94, 0x2, 0, 0 }
> #define VPO_24_OFF SIG_DESC_SET(SCU94, 1)
>
> #define V21 140
> diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
> index 87b46390b695..c5c9a1b6fa1c 100644
> --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
> +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
> @@ -10,6 +10,7 @@
> #include <linux/init.h>
> #include <linux/io.h>
> #include <linux/kernel.h>
> +#include <linux/mfd/syscon.h>
> #include <linux/mutex.h>
> #include <linux/of.h>
> #include <linux/platform_device.h>
> @@ -26,8 +27,8 @@
>
> #define ASPEED_G5_NR_PINS 228
>
> -#define COND1 { SCU90, BIT(6), 0, 0 }
> -#define COND2 { SCU94, GENMASK(1, 0), 0, 0 }
> +#define COND1 { ASPEED_IP_SCU, SCU90, BIT(6), 0, 0 }
> +#define COND2 { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 0, 0 }
>
> #define B14 0
> SSSF_PIN_DECL(B14, GPIOA0, MAC1LINK, SIG_DESC_SET(SCU80, 0));
> @@ -186,9 +187,12 @@ MS_PIN_DECL(C20, GPIOE1, NDCD3, GPIE0OUT);
>
> FUNC_GROUP_DECL(GPIE0, B20, C20);
>
> -#define SPI1_DESC { HW_STRAP1, GENMASK(13, 12), 1, 0 }
> -#define SPI1DEBUG_DESC { HW_STRAP1, GENMASK(13, 12), 2, 0 }
> -#define SPI1PASSTHRU_DESC { HW_STRAP1, GENMASK(13, 12), 3, 0 }
> +#define SPI1_DESC \
> + { ASPEED_IP_SCU, HW_STRAP1, GENMASK(13, 12), 1, 0 }
> +#define SPI1DEBUG_DESC \
> + { ASPEED_IP_SCU, HW_STRAP1, GENMASK(13, 12), 2, 0 }
> +#define SPI1PASSTHRU_DESC \
> + { ASPEED_IP_SCU, HW_STRAP1, GENMASK(13, 12), 3, 0 }
>
> #define C18 64
> SIG_EXPR_DECL(SYSCS, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
> @@ -325,10 +329,11 @@ SS_PIN_DECL(R1, GPIOK7, SDA8);
>
> FUNC_GROUP_DECL(I2C8, P2, R1);
>
> -#define VPIOFF0_DESC { SCU90, GENMASK(5, 4), 0, 0 }
> -#define VPIOFF1_DESC { SCU90, GENMASK(5, 4), 1, 0 }
> -#define VPI24_DESC { SCU90, GENMASK(5, 4), 2, 0 }
> -#define VPIRSVD_DESC { SCU90, GENMASK(5, 4), 3, 0 }
> +#define VPIOFF0_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 0, 0 }
> +#define VPIOFF1_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 1, 0 }
> +#define VPI24_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 2, 0 }
> +#define VPIRSVD_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 3, 0 }
> +
>
> #define V2 104
> #define V2_DESC SIG_DESC_SET(SCU88, 0)
> @@ -848,10 +853,35 @@ static struct pinctrl_desc aspeed_g5_pinctrl_desc = {
> static int aspeed_g5_pinctrl_probe(struct platform_device *pdev)
> {
> int i;
> + struct regmap *map;
> + struct device_node *node;
>
> for (i = 0; i < ARRAY_SIZE(aspeed_g5_pins); i++)
> aspeed_g5_pins[i].number = i;
>
> + node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 0);
> + map = syscon_node_to_regmap(node);
> + of_node_put(node);
> + if (IS_ERR(map)) {
> + dev_warn(&pdev->dev, "No GFX phandle found, some mux configurations may fail\n");
> + map = NULL;
> + }
> + aspeed_g5_pinctrl_data.maps[ASPEED_IP_GFX] = map;
> +
> + node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 1);
> + if (node) {
> + map = syscon_node_to_regmap(node->parent);
> + if (IS_ERR(map)) {
> + dev_warn(&pdev->dev, "LHC parent is not a syscon, some mux configurations may fail\n");
> + map = NULL;
> + }
> + } else {
> + dev_warn(&pdev->dev, "No LHC phandle found, some mux configurations may fail\n");
> + map = NULL;
> + }
> + of_node_put(node);
> + aspeed_g5_pinctrl_data.maps[ASPEED_IP_LPC] = map;
> +
> return aspeed_pinctrl_probe(pdev, &aspeed_g5_pinctrl_desc,
> &aspeed_g5_pinctrl_data);
> }
> diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
> index 49aeba912531..782c5c97f853 100644
> --- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
> +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
> @@ -14,6 +14,12 @@
> #include "../core.h"
> #include "pinctrl-aspeed.h"
>
> +static const char *const aspeed_pinmux_ips[] = {
> + [ASPEED_IP_SCU] = "SCU",
> + [ASPEED_IP_GFX] = "GFX",
> + [ASPEED_IP_LPC] = "LPC",
> +};
> +
> int aspeed_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
> {
> struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
> @@ -78,7 +84,8 @@ int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
> static inline void aspeed_sig_desc_print_val(
> const struct aspeed_sig_desc *desc, bool enable, u32 rv)
> {
> - pr_debug("SCU%x[0x%08x]=0x%x, got 0x%x from 0x%08x\n", desc->reg,
> + pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n",
> + aspeed_pinmux_ips[desc->ip], desc->reg,
> desc->mask, enable ? desc->enable : desc->disable,
> (rv & desc->mask) >> __ffs(desc->mask), rv);
> }
> @@ -88,10 +95,11 @@ static inline void aspeed_sig_desc_print_val(
> *
> * @desc: The signal descriptor of interest
> * @enabled: True to query the enabled state, false to query disabled state
> - * @regmap: The SCU regmap instance
> + * @regmap: The IP block's regmap instance
> *
> - * @return True if the descriptor's bitfield is configured to the state
> - * selected by @enabled, false otherwise
> + * @return 1 if the descriptor's bitfield is configured to the state
> + * selected by @enabled, 0 if not, and less than zero if an unrecoverable
> + * failure occurred
> *
> * Evaluation of descriptor state is non-trivial in that it is not a binary
> * outcome: The bitfields can be greater than one bit in size and thus can take
> @@ -99,14 +107,19 @@ static inline void aspeed_sig_desc_print_val(
> * descriptor (typically this means a different function to the one of interest
> * is enabled). Thus we must explicitly test for either condition as required.
> */
> -static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
> +static int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
> bool enabled, struct regmap *map)
> {
> + int ret;
> unsigned int raw;
> u32 want;
>
> - if (regmap_read(map, desc->reg, &raw) < 0)
> - return false;
> + if (!map)
> + return -ENODEV;
> +
> + ret = regmap_read(map, desc->reg, &raw);
> + if (ret)
> + return ret;
>
> aspeed_sig_desc_print_val(desc, enabled, raw);
> want = enabled ? desc->enable : desc->disable;
> @@ -119,10 +132,10 @@ static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
> *
> * @expr: An expression controlling the signal for a mux function on a pin
> * @enabled: True to query the enabled state, false to query disabled state
> - * @regmap: The SCU regmap instance
> + * @maps: The list of regmap instances
> *
> - * @return True if the expression composed by @enabled evaluates true, false
> - * otherwise
> + * @return 1 if the expression composed by @enabled evaluates true, 0 if not,
> + * and less than zero if an unrecoverable failure occurred.
> *
> * A mux function is enabled or disabled if the function's signal expression
> * for each pin in the function's pin group evaluates true for the desired
> @@ -135,19 +148,21 @@ static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
> * neither the enabled nor disabled state. Thus we must explicitly test for
> * either condition as required.
> */
> -static bool aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
> - bool enabled, struct regmap *map)
> +static int aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
> + bool enabled, struct regmap * const *maps)
> {
> int i;
> + int ret;
>
> for (i = 0; i < expr->ndescs; i++) {
> const struct aspeed_sig_desc *desc = &expr->descs[i];
>
> - if (!aspeed_sig_desc_eval(desc, enabled, map))
> - return false;
> + ret = aspeed_sig_desc_eval(desc, enabled, maps[desc->ip]);
> + if (ret <= 0)
> + return ret;
> }
>
> - return true;
> + return 1;
> }
>
> /**
> @@ -158,19 +173,24 @@ static bool aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
> * configured
> * @enable: true to enable an function's signal through a pin's signal
> * expression, false to disable the function's signal
> - * @map: The SCU's regmap instance for pinmux register access.
> + * @maps: The list of regmap instances for pinmux register access.
> *
> - * @return true if the expression is configured as requested, false otherwise
> + * @return 0 if the expression is configured as requested and a negative error
> + * code otherwise
> */
> -static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
> - bool enable, struct regmap *map)
> +static int aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
> + bool enable, struct regmap * const *maps)
> {
> + int ret;
> int i;
>
> for (i = 0; i < expr->ndescs; i++) {
> - bool ret;
> const struct aspeed_sig_desc *desc = &expr->descs[i];
> u32 pattern = enable ? desc->enable : desc->disable;
> + u32 val = (pattern << __ffs(desc->mask));
> +
> + if (!maps[desc->ip])
> + return -ENODEV;
>
> /*
> * Strap registers are configured in hardware or by early-boot
> @@ -179,64 +199,79 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
> * deconfigured and is the reason we re-evaluate after writing
> * all descriptor bits.
> */
> - if (desc->reg == HW_STRAP1 || desc->reg == HW_STRAP2)
> + if ((desc->reg == HW_STRAP1 || desc->reg == HW_STRAP2) &&
> + desc->ip == ASPEED_IP_SCU)
> continue;
>
> - ret = regmap_update_bits(map, desc->reg, desc->mask,
> - pattern << __ffs(desc->mask)) == 0;
> + ret = regmap_update_bits(maps[desc->ip], desc->reg,
> + desc->mask, val);
>
> - if (!ret)
> + if (ret)
> return ret;
> }
>
> - return aspeed_sig_expr_eval(expr, enable, map);
> + ret = aspeed_sig_expr_eval(expr, enable, maps);
> + if (ret < 0)
> + return ret;
> +
> + if (!ret)
> + return -EPERM;
> +
> + return 0;
> }
>
> -static bool aspeed_sig_expr_enable(const struct aspeed_sig_expr *expr,
> - struct regmap *map)
> +static int aspeed_sig_expr_enable(const struct aspeed_sig_expr *expr,
> + struct regmap * const *maps)
> {
> - if (aspeed_sig_expr_eval(expr, true, map))
> - return true;
> + int ret;
> +
> + ret = aspeed_sig_expr_eval(expr, true, maps);
> + if (ret < 0)
> + return ret;
>
> - return aspeed_sig_expr_set(expr, true, map);
> + if (!ret)
> + return aspeed_sig_expr_set(expr, true, maps);
> +
> + return 0;
> }
>
> -static bool aspeed_sig_expr_disable(const struct aspeed_sig_expr *expr,
> - struct regmap *map)
> +static int aspeed_sig_expr_disable(const struct aspeed_sig_expr *expr,
> + struct regmap * const *maps)
> {
> - if (!aspeed_sig_expr_eval(expr, true, map))
> - return true;
> + int ret;
> +
> + ret = aspeed_sig_expr_eval(expr, true, maps);
> + if (ret < 0)
> + return ret;
> +
> + if (ret)
> + return aspeed_sig_expr_set(expr, false, maps);
>
> - return aspeed_sig_expr_set(expr, false, map);
> + return 0;
> }
>
> /**
> * Disable a signal on a pin by disabling all provided signal expressions.
> *
> * @exprs: The list of signal expressions (from a priority level on a pin)
> - * @map: The SCU's regmap instance for pinmux register access.
> + * @maps: The list of regmap instances for pinmux register access.
> *
> - * @return true if all expressions in the list are successfully disabled, false
> - * otherwise
> + * @return 0 if all expressions are disabled, otherwise a negative error code
> */
> -static bool aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
> - struct regmap *map)
> +static int aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
> + struct regmap * const *maps)
> {
> - bool disabled = true;
> + int ret = 0;
>
> if (!exprs)
> return true;
>
> - while (*exprs) {
> - bool ret;
> -
> - ret = aspeed_sig_expr_disable(*exprs, map);
> - disabled = disabled && ret;
> -
> + while (*exprs && !ret) {
> + ret = aspeed_sig_expr_disable(*exprs, maps);
> exprs++;
> }
>
> - return disabled;
> + return ret;
> }
>
> /**
> @@ -330,6 +365,7 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
> unsigned int group)
> {
> int i;
> + int ret;
> const struct aspeed_pinctrl_data *pdata =
> pinctrl_dev_get_drvdata(pctldev);
> const struct aspeed_pin_group *pgroup = &pdata->groups[group];
> @@ -343,6 +379,8 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
> const struct aspeed_sig_expr **funcs;
> const struct aspeed_sig_expr ***prios;
>
> + pr_debug("Muxing pin %d for %s\n", pin, pfunc->name);
> +
> if (!pdesc)
> return -EINVAL;
>
> @@ -358,8 +396,9 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
> if (expr)
> break;
>
> - if (!aspeed_disable_sig(funcs, pdata->map))
> - return -EPERM;
> + ret = aspeed_disable_sig(funcs, pdata->maps);
> + if (ret)
> + return ret;
>
> prios++;
> }
> @@ -377,8 +416,9 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
> return -ENXIO;
> }
>
> - if (!aspeed_sig_expr_enable(expr, pdata->map))
> - return -EPERM;
> + ret = aspeed_sig_expr_enable(expr, pdata->maps);
> + if (ret)
> + return ret;
> }
>
> return 0;
> @@ -414,6 +454,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
> struct pinctrl_gpio_range *range,
> unsigned int offset)
> {
> + int ret;
> const struct aspeed_pinctrl_data *pdata =
> pinctrl_dev_get_drvdata(pctldev);
> const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data;
> @@ -432,8 +473,9 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
> if (aspeed_gpio_in_exprs(funcs))
> break;
>
> - if (!aspeed_disable_sig(funcs, pdata->map))
> - return -EPERM;
> + ret = aspeed_disable_sig(funcs, pdata->maps);
> + if (ret)
> + return ret;
>
> prios++;
> }
> @@ -462,10 +504,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
> * If GPIO is not the lowest priority signal type, assume there is only
> * one expression defined to enable the GPIO function
> */
> - if (!aspeed_sig_expr_enable(expr, pdata->map))
> - return -EPERM;
> -
> - return 0;
> + return aspeed_sig_expr_enable(expr, pdata->maps);
> }
>
> int aspeed_pinctrl_probe(struct platform_device *pdev,
> @@ -481,10 +520,10 @@ int aspeed_pinctrl_probe(struct platform_device *pdev,
> return -ENODEV;
> }
>
> - pdata->map = syscon_node_to_regmap(parent->of_node);
> - if (IS_ERR(pdata->map)) {
> + pdata->maps[ASPEED_IP_SCU] = syscon_node_to_regmap(parent->of_node);
> + if (IS_ERR(pdata->maps[ASPEED_IP_SCU])) {
> dev_err(&pdev->dev, "No regmap for syscon pincontroller parent\n");
> - return PTR_ERR(pdata->map);
> + return PTR_ERR(pdata->maps[ASPEED_IP_SCU]);
> }
>
> pctl = pinctrl_register(pdesc, &pdev->dev, pdata);
> diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.h b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
> index 3e72ef8c54bf..0e93cbf2ff33 100644
> --- a/drivers/pinctrl/aspeed/pinctrl-aspeed.h
> +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
> @@ -232,6 +232,11 @@
> * group.
> */
>
> +#define ASPEED_IP_SCU 0
> +#define ASPEED_IP_GFX 1
> +#define ASPEED_IP_LPC 2
> +#define ASPEED_NR_PINMUX_IPS 3
> +
> /*
> * The "Multi-function Pins Mapping and Control" table in the SoC datasheet
> * references registers by the device/offset mnemonic. The register macros
> @@ -261,7 +266,9 @@
> * A signal descriptor, which describes the register, bits and the
> * enable/disable values that should be compared or written.
> *
> - * @reg: The register offset from base in bytes
> + * @ip: The IP block identifier, used as an index into the regmap array in
> + * struct aspeed_pinctrl_data
> + * @reg: The register offset with respect to the base address of the IP block
> * @mask: The mask to apply to the register. The lowest set bit of the mask is
> * used to derive the shift value.
> * @enable: The value that enables the function. Value should be in the LSBs,
> @@ -270,6 +277,7 @@
> * LSBs, not at the position of the mask.
> */
> struct aspeed_sig_desc {
> + unsigned int ip;
> unsigned int reg;
> u32 mask;
> u32 enable;
> @@ -313,24 +321,30 @@ struct aspeed_pin_desc {
>
> /* Macro hell */
>
> +#define SIG_DESC_IP_BIT(ip, reg, idx, val) \
> + { ip, reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
> +
> /**
> - * Short-hand macro for describing a configuration enabled by the state of one
> - * bit. The disable value is derived.
> + * Short-hand macro for describing an SCU descriptor enabled by the state of
> + * one bit. The disable value is derived.
> *
> * @reg: The signal's associated register, offset from base
> * @idx: The signal's bit index in the register
> * @val: The value (0 or 1) that enables the function
> */
> #define SIG_DESC_BIT(reg, idx, val) \
> - { reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
> + SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, val)
> +
> +#define SIG_DESC_IP_SET(ip, reg, idx) SIG_DESC_IP_BIT(ip, reg, idx, 1)
>
> /**
> - * A further short-hand macro describing a configuration enabled with a set bit.
> + * A further short-hand macro expanding to an SCU descriptor enabled by a set
> + * bit.
> *
> - * @reg: The configuration's associated register, offset from base
> - * @idx: The configuration's bit index in the register
> + * @reg: The register, offset from base
> + * @idx: The bit index in the register
> */
> -#define SIG_DESC_SET(reg, idx) SIG_DESC_BIT(reg, idx, 1)
> +#define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1)
>
> #define SIG_DESC_LIST_SYM(sig, func) sig_descs_ ## sig ## _ ## func
> #define SIG_DESC_LIST_DECL(sig, func, ...) \
> @@ -500,7 +514,7 @@ struct aspeed_pin_desc {
> MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(gpio))
>
> struct aspeed_pinctrl_data {
> - struct regmap *map;
> + struct regmap *maps[ASPEED_NR_PINMUX_IPS];
>
> const struct pinctrl_pin_desc *pins;
> const unsigned int npins;
> --
> 2.9.3
>
^ permalink raw reply
* Re: [PATCH v3 4/6] mfd: dt: Add bindings for the Aspeed LPC Host Controller (LHC)
From: Joel Stanley @ 2016-12-08 2:12 UTC (permalink / raw)
To: Andrew Jeffery
Cc: Lee Jones, Rob Herring, Mark Rutland, Linus Walleij,
Corey Minyard, Cédric Le Goater,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161206025321.1792-5-andrew-zrmu5oMJ5Fs@public.gmane.org>
On Tue, Dec 6, 2016 at 1:23 PM, Andrew Jeffery <andrew-zrmu5oMJ5Fs@public.gmane.org> wrote:
> The LPC bus pinmux configuration on fifth generation Aspeed SoCs depends
> on bits in both the System Control Unit and the LPC Host Controller.
>
> The Aspeed LPC Host Controller is described as a child node of the
> LPC host-range syscon device for arbitration of access by the host
> controller and pinmux drivers.
>
> Signed-off-by: Andrew Jeffery <andrew-zrmu5oMJ5Fs@public.gmane.org>
> ---
> .../devicetree/bindings/mfd/aspeed-lpc.txt | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt b/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
> index a97131aba446..9de318ef72da 100644
> --- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
> +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
> @@ -109,3 +109,25 @@ lpc: lpc@1e789000 {
> };
> };
>
> +Host Node Children
> +==================
> +
> +LPC Host Controller
> +-------------------
> +
> +The Aspeed LPC Host Controller configures the Low Pin Count (LPC) bus behaviour
> +between the host and the baseboard management controller. The registers exist
> +in the "host" portion of the Aspeed LPC controller, which must be the parent of
> +the LPC host controller node.
> +
> +Required properties:
> +- compatible: "aspeed,ast2500-lhc";
Can you remind me why this binding doesn't cover the ast2400?
Cheers,
Joel
> +- reg: contains offset/length value of the LHC memory
> + region.
> +
> +Example:
> +
> +lhc: lhc@20 {
> + compatible = "aspeed,ast2500-lhc";
> + reg = <0x20 0x24 0x48 0x8>;
> +};
> --
> 2.9.3
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 3/6] mfd: dt: Add Aspeed Low Pin Count Controller bindings
From: Joel Stanley @ 2016-12-08 2:07 UTC (permalink / raw)
To: Andrew Jeffery
Cc: Lee Jones, Rob Herring, Mark Rutland, Linus Walleij,
Corey Minyard, Cédric Le Goater, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <20161206025321.1792-4-andrew@aj.id.au>
On Tue, Dec 6, 2016 at 1:23 PM, Andrew Jeffery <andrew@aj.id.au> wrote:
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Reviewed-by: Joel Stanley <joel@jms.id.au>
> ---
> .../devicetree/bindings/mfd/aspeed-lpc.txt | 111 +++++++++++++++++++++
> 1 file changed, 111 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
^ permalink raw reply
* Re: [PATCH v5 01/14] Documentation: of: add type property
From: Kuninori Morimoto @ 2016-12-08 1:57 UTC (permalink / raw)
To: Rob Herring
Cc: Mark Brown, Linux-ALSA, Liam Girdwood, Simon, Laurent, Guennadi,
Grant Likely, Frank Rowand, Linux-DT, Linux-Kernel
In-Reply-To: <20161201162631.6jtubjiap7w7y3pd@rob-hp-laptop>
Hi Rob
> > From: Kuninori Morimoto <kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
> >
> > OF graph indicates each devices connection. But it doesn't support type
> > of each port. For example HDMI case, it has video port and sound port
> > in one device node.
> > In this case, current driver can't handle each port correctly.
> > This patch enables to use type property on OF graph.
>
> I still don't think this is necessary. Simply define which port number
> is which for each HDMI chip.
>
> If this is necessary, then the types, video and sound, are too generic.
About this, if OF-graph can have "query" function to each port,
I can remove this "type" property from DT, and driver can answer
each port feature.
But is this OK approach ?
Best regards
---
Kuninori Morimoto
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v7 0/5] Add intial support to DW MMC host on ZTE SoC
From: Jun Nie @ 2016-12-08 1:28 UTC (permalink / raw)
To: Rob Herring, mark.rutland-5wv7dgnIgG8, Shawn Guo, xie.baoyou,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: Ulf Hansson, Jaehoon Chung, Jason Liu,
chen.chaokai-Th6q7B73Y6EnDS1+zs4M5A,
lai.binz-Th6q7B73Y6EnDS1+zs4M5A, linux-mmc, Jun Nie
In-Reply-To: <1480904976-7081-1-git-send-email-jun.nie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-12-05 10:29 GMT+08:00 Jun Nie <jun.nie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>:
> Add intial support to DW MMC host on ZTE SoC. It include platform
> specific wrapper driver and workarounds for fifo quirk.
>
> Patches are prepared based on latest dw mmc runtime change:
> https://github.com/jh80chung/dw-mmc.git for-ulf
>
> Changes vs version 6:
> - Resolve confilict when rebase to latest dw-mmc.git for-ulf branch.
> - Add Shawn Lin's review tag.
>
> Changes vs version 5:
> - Add clock delay lock status check to save CPU cycle in timing tuning CMD.
>
> Changes vs version 4:
> - Fix missing empty dts compatible element in the end of compatible array.
>
> Changes vs version 3:
> - Fix brace error in document.
>
> Changes vs version 2:
> - Change dt property fifo-addr to data-addr and fifo-watermark-quirk to
> fifo-watermark-aligned.
> - Polish ZX MMC driver on minor coding style issues.
>
> Changes vs version 1:
> - Change fifo-addr-override to fifo-addr and remove its workaround tag in comments.
> - Remove ZX DW MMC driver reset cap in driver, which can be added in dt nodes.
>
> Jun Nie (5):
> mmc: dt-bindings: add ZTE ZX296718 MMC bindings
> mmc: zx: Initial support for ZX mmc controller
> Documentation: synopsys-dw-mshc: add binding for fifo quirks
> mmc: dw: Add fifo address property
> mmc: dw: Add fifo watermark alignment property
>
> .../devicetree/bindings/mmc/synopsys-dw-mshc.txt | 13 ++
> .../devicetree/bindings/mmc/zx-dw-mshc.txt | 34 +++
> drivers/mmc/host/Kconfig | 9 +
> drivers/mmc/host/Makefile | 1 +
> drivers/mmc/host/dw_mmc-zx.c | 242 +++++++++++++++++++++
> drivers/mmc/host/dw_mmc-zx.h | 31 +++
> drivers/mmc/host/dw_mmc.c | 17 +-
> include/linux/mmc/dw_mmc.h | 5 +
> 8 files changed, 349 insertions(+), 3 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/mmc/zx-dw-mshc.txt
> create mode 100644 drivers/mmc/host/dw_mmc-zx.c
> create mode 100644 drivers/mmc/host/dw_mmc-zx.h
>
> --
> 1.9.1
>
Hi Rob & Mark,
Could you help act DT patches in this set?
Thank you!
Jun
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 12/12] gpu: ipu-v3: Add smfc and ic client devices
From: Steve Longerbeam @ 2016-12-08 0:57 UTC (permalink / raw)
To: shawnguo, kernel, fabio.estevam, robh+dt, mark.rutland, linux,
tomi.valkeinen, p.zabel
Cc: linux-arm-kernel, devicetree, linux-kernel, linux-fbdev,
dri-devel, Steve Longerbeam
In-Reply-To: <1481158673-15937-1-git-send-email-steve_longerbeam@mentor.com>
Adds IPU client devices for the SMFC and IC task units.
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
drivers/gpu/ipu-v3/ipu-common.c | 87 +++++++++++++++++++++++++++++++++++++++--
include/video/imx-ipu-v3.h | 3 ++
2 files changed, 87 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index b6ca36b..729581d 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -1161,18 +1161,77 @@ static struct ipu_platform_reg client_reg[] = {
.pdata = {
.type = IPU_CSI,
.csi = 0,
- .dma[0] = IPUV3_CHANNEL_CSI0,
- .dma[1] = -EINVAL,
+ .dma[0] = -EINVAL,
},
.name = "imx-ipuv3-csi",
}, {
.pdata = {
.type = IPU_CSI,
.csi = 1,
+ .dma[0] = -EINVAL,
+ },
+ .name = "imx-ipuv3-csi",
+ }, {
+ .pdata = {
+ .type = IPU_SMFC,
+ .smfc = 0,
+ .dma[0] = IPUV3_CHANNEL_CSI0,
+ .dma[1] = -EINVAL,
+ },
+ .name = "imx-ipuv3-smfc",
+ }, {
+ .pdata = {
+ .type = IPU_SMFC,
+ .smfc = 1,
.dma[0] = IPUV3_CHANNEL_CSI1,
.dma[1] = -EINVAL,
},
- .name = "imx-ipuv3-csi",
+ .name = "imx-ipuv3-smfc",
+ }, {
+ .pdata = {
+ .type = IPU_IC,
+ .ic_task = IC_TASK_ENCODER,
+ .ic = 0,
+ .dma[0] = IPUV3_CHANNEL_IC_PRP_ENC_MEM,
+ .dma[1] = -EINVAL,
+ },
+ .name = "imx-ipuv3-ic",
+ }, {
+ .pdata = {
+ .type = IPU_IC,
+ .ic_task = IC_TASK_VIEWFINDER,
+ .ic = 0,
+ .dma[0] = IPUV3_CHANNEL_IC_PRP_VF_MEM,
+ .dma[1] = -EINVAL,
+ },
+ .name = "imx-ipuv3-ic",
+ }, {
+ .pdata = {
+ .type = IPU_IC,
+ .ic_task = IC_TASK_POST_PROCESSOR,
+ .ic = 0,
+ .dma[0] = IPUV3_CHANNEL_IC_PP_MEM,
+ .dma[1] = -EINVAL,
+ },
+ .name = "imx-ipuv3-ic",
+ }, {
+ .pdata = {
+ .type = IPU_IC,
+ .ic_task = IC_TASK_POST_PROCESSOR,
+ .ic = 1,
+ .dma[0] = IPUV3_CHANNEL_IC_PP_MEM,
+ .dma[1] = -EINVAL,
+ },
+ .name = "imx-ipuv3-ic",
+ }, {
+ .pdata = {
+ .type = IPU_IC,
+ .ic_task = IC_TASK_POST_PROCESSOR,
+ .ic = 2,
+ .dma[0] = IPUV3_CHANNEL_IC_PP_MEM,
+ .dma[1] = -EINVAL,
+ },
+ .name = "imx-ipuv3-ic",
}, {
.pdata = {
.type = IPU_DI,
@@ -1213,6 +1272,28 @@ of_get_ipu_client_node(struct ipu_soc *ipu, struct ipu_platform_reg *reg)
"ipu%d_csi", ipu->id + 1);
client_id = reg->pdata.csi;
break;
+ case IPU_SMFC:
+ snprintf(node_name, sizeof(node_name), "ipu%d_smfc",
+ ipu->id + 1);
+ client_id = reg->pdata.smfc;
+ break;
+ case IPU_IC:
+ switch (reg->pdata.ic_task) {
+ case IC_TASK_ENCODER:
+ snprintf(node_name, sizeof(node_name),
+ "ipu%d_ic_prpenc", ipu->id + 1);
+ break;
+ case IC_TASK_VIEWFINDER:
+ snprintf(node_name, sizeof(node_name),
+ "ipu%d_ic_prpvf", ipu->id + 1);
+ break;
+ case IC_TASK_POST_PROCESSOR:
+ snprintf(node_name, sizeof(node_name),
+ "ipu%d_ic_pp", ipu->id + 1);
+ break;
+ }
+ client_id = reg->pdata.ic;
+ break;
case IPU_DI:
snprintf(node_name, sizeof(node_name),
"ipu%d_di", ipu->id + 1);
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 7709af7..4e70ca4 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -418,6 +418,9 @@ int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
struct ipu_client_platformdata {
enum ipu_unit_type type;
int csi;
+ int smfc;
+ int ic_task;
+ int ic;
int di;
int dc;
int dp;
--
2.7.4
^ permalink raw reply related
* [PATCH 11/12] gpu: ipu-v3: lookup ipu client nodes by name
From: Steve Longerbeam @ 2016-12-08 0:57 UTC (permalink / raw)
To: shawnguo-DgEjT+Ai2ygdnm+yROfE0A, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
fabio.estevam-3arQi8VN3Tc, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
tomi.valkeinen-l0cyMroinI0, p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Steve Longerbeam
In-Reply-To: <1481158673-15937-1-git-send-email-steve_longerbeam-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
To allow for IPU clients containing multiple ports, they are no longer
a single port node name, but have a name of the format
"ipu<id>_<unit>". So we can no longer use of_graph_get_port_by_id()
to lookup the client node.
Create the function of_get_ipu_client_node() that looks up the client
node by node name and unit id. The ipu_unit_type enumeration is added
to the client_reg[] entries to compose the node names.
Signed-off-by: Steve Longerbeam <steve_longerbeam-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
---
drivers/gpu/ipu-v3/ipu-common.c | 55 +++++++++++++++++++++++++++++++++++------
1 file changed, 47 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 97218af..b6ca36b 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -1159,6 +1159,7 @@ struct ipu_platform_reg {
static struct ipu_platform_reg client_reg[] = {
{
.pdata = {
+ .type = IPU_CSI,
.csi = 0,
.dma[0] = IPUV3_CHANNEL_CSI0,
.dma[1] = -EINVAL,
@@ -1166,6 +1167,7 @@ static struct ipu_platform_reg client_reg[] = {
.name = "imx-ipuv3-csi",
}, {
.pdata = {
+ .type = IPU_CSI,
.csi = 1,
.dma[0] = IPUV3_CHANNEL_CSI1,
.dma[1] = -EINVAL,
@@ -1173,6 +1175,7 @@ static struct ipu_platform_reg client_reg[] = {
.name = "imx-ipuv3-csi",
}, {
.pdata = {
+ .type = IPU_DI,
.di = 0,
.dc = 5,
.dp = IPU_DP_FLOW_SYNC_BG,
@@ -1182,6 +1185,7 @@ static struct ipu_platform_reg client_reg[] = {
.name = "imx-ipuv3-crtc",
}, {
.pdata = {
+ .type = IPU_DI,
.di = 1,
.dc = 1,
.dp = -EINVAL,
@@ -1195,6 +1199,46 @@ static struct ipu_platform_reg client_reg[] = {
static DEFINE_MUTEX(ipu_client_id_mutex);
static int ipu_client_id;
+static struct device_node *
+of_get_ipu_client_node(struct ipu_soc *ipu, struct ipu_platform_reg *reg)
+{
+ struct device *dev = ipu->dev;
+ struct device_node *client;
+ char node_name[32];
+ u32 id, client_id = 0;
+
+ switch (reg->pdata.type) {
+ case IPU_CSI:
+ snprintf(node_name, sizeof(node_name),
+ "ipu%d_csi", ipu->id + 1);
+ client_id = reg->pdata.csi;
+ break;
+ case IPU_DI:
+ snprintf(node_name, sizeof(node_name),
+ "ipu%d_di", ipu->id + 1);
+ client_id = reg->pdata.di;
+ break;
+ default:
+ client = NULL;
+ goto out;
+ }
+
+ for_each_child_of_node(dev->of_node, client) {
+ if (client->name &&
+ (of_node_cmp(client->name, node_name) == 0)) {
+ of_property_read_u32(client, "reg", &id);
+ if (id == client_id)
+ break;
+ }
+ }
+out:
+ if (!client)
+ dev_info(dev, "no %s%d node in %s, not using %s%d\n",
+ node_name, client_id, dev->of_node->full_name,
+ node_name, client_id);
+ return client;
+}
+
static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
{
struct device *dev = ipu->dev;
@@ -1211,15 +1255,10 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
struct platform_device *pdev;
struct device_node *of_node;
- /* Associate subdevice with the corresponding port node */
- of_node = of_graph_get_port_by_id(dev->of_node, i);
- if (!of_node) {
- dev_info(dev,
- "no port@%d node in %s, not using %s%d\n",
- i, dev->of_node->full_name,
- (i / 2) ? "DI" : "CSI", i % 2);
+ /* Associate subdevice with the corresponding client node */
+ of_node = of_get_ipu_client_node(ipu, reg);
+ if (!of_node)
continue;
- }
pdev = platform_device_alloc(reg->name, id++);
if (!pdev) {
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 10/12] gpu: ipu-v3: Add ipu_unit_type enumeration
From: Steve Longerbeam @ 2016-12-08 0:57 UTC (permalink / raw)
To: shawnguo, kernel, fabio.estevam, robh+dt, mark.rutland, linux,
tomi.valkeinen, p.zabel
Cc: linux-arm-kernel, devicetree, linux-kernel, linux-fbdev,
dri-devel, Steve Longerbeam
In-Reply-To: <1481158673-15937-1-git-send-email-steve_longerbeam@mentor.com>
Adds an enumeration of the major IPUv3 subunits. Provide that info
in struct ipu_client_platformdata to more easily determine the IPU
client type.
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
include/video/imx-ipu-v3.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 53cd07c..7709af7 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -28,6 +28,23 @@ enum ipuv3_type {
IPUV3H,
};
+/*
+ * Enumeration of the major IPU subunits
+ */
+enum ipu_unit_type {
+ IPU_IDMAC = 0,
+ IPU_CM,
+ IPU_CSI,
+ IPU_SMFC,
+ IPU_IC,
+ IPU_VDI,
+ IPU_IRT,
+ IPU_DC,
+ IPU_DI,
+ IPU_DP,
+ IPU_DMFC,
+};
+
#define IPU_PIX_FMT_GBR24 v4l2_fourcc('G', 'B', 'R', '3')
/*
@@ -399,6 +416,7 @@ int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
bool hflip, bool vflip);
struct ipu_client_platformdata {
+ enum ipu_unit_type type;
int csi;
int di;
int dc;
--
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