* [PATCH v7 2/5] i2c: Add STM32F4 I2C driver
From: M'boumba Cedric Madianga @ 2016-12-22 13:35 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: <1482413704-17531-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 | 896 +++++++++++++++++++++++++++++++++++++++
3 files changed, 907 insertions(+)
create mode 100644 drivers/i2c/busses/i2c-stm32f4.c
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 0cdc844..2719208 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..ca11dee
--- /dev/null
+++ b/drivers/i2c/busses/i2c-stm32f4.c
@@ -0,0 +1,896 @@
+/*
+ * Driver for STMicroelectronics STM32 I2C controller
+ *
+ * This I2C controller is described in the STM32F429/439 Soc reference manual.
+ * Please see below a link to the documentation:
+ * http://www.st.com/resource/en/reference_manual/DM00031020.pdf
+ *
+ * Copyright (C) M'boumba Cedric Madianga 2016
+ * 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 2U
+#define STM32F4_I2C_MAX_FREQ 42U
+#define HZ_TO_MHZ 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
+ * @scl_period: SCL low/high period in microsecond
+ * @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 duty;
+ u32 scl_period;
+ 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
+ * @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;
+ struct clk *clk;
+ int speed;
+ struct stm32f4_i2c_msg msg;
+};
+
+/*
+ * In standard mode:
+ * SCL high period = SCL low period = CCR * I2C CLK period
+ * So, CCR = SCL period * I2C CLK frequency
+ *
+ * In fast mode:
+ * DUTY = 0: Fast mode tlow/thigh = 2
+ * DUTY = 1: Fast mode tlow/thigh = 16/9
+ * If Duty = 0; SCL high period = 1 * CCR * I2C CLK period
+ * SCL low period = 2 * CCR * I2C CLK period
+ * If Duty = 1; SCL high period = 9 * CCR * I2C CLK period
+ * SCL low period = 16 * CCR * I2C CLK period
+ *
+ * Note that Duty has to bet set to reach 400khz in Fast mode
+ * So, in order to cover both SCL high/low with Duty = 1,
+ * CCR = 16 * SCL period * I2C CLK frequency
+ *
+ * Please note that the minimum allowed value is 0x04, except in FAST DUTY mode
+ * where the minimum allowed value is 0x01
+ */
+static struct stm32f4_i2c_timings i2c_timings[] = {
+ [STM32F4_I2C_SPEED_STANDARD] = {
+ .mul_ccr = 1,
+ .min_ccr = 4,
+ .duty = 0,
+ .scl_period = 5,
+ },
+ [STM32F4_I2C_SPEED_FAST] = {
+ .mul_ccr = 16,
+ .min_ccr = 1,
+ .duty = 1,
+ .scl_period = 2,
+ },
+};
+
+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;
+ u32 val;
+
+ val = readl_relaxed(reg);
+ writel_relaxed(val | STM32F4_I2C_CR1_SWRST, reg);
+ writel_relaxed(val, reg);
+}
+
+static void stm32f4_i2c_disable_irq(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;
+
+ /*
+ * The minimum allowed frequency is 2 MHz, the maximum frequency is
+ * limited by the maximum APB frequency 42 MHz
+ */
+ cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ cr2 &= ~STM32F4_I2C_CR2_FREQ_MASK;
+ clk_rate = clk_get_rate(i2c_dev->clk);
+ freq = DIV_ROUND_UP(clk_rate, HZ_TO_MHZ);
+ 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;
+
+ /*
+ * These bits must be programmed with the maximum SCL rise time given in
+ * the I2C bus specification, incremented by 1.
+ *
+ * In standard mode, the maximum allowed SCL rise time is 1000 ns.
+ * If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to
+ * 0x08 so period = 125 ns therefore the TRISE[5:0] bits must be
+ * programmed with 09h.(1000 ns / 125 ns = 8 + 1)
+ * So, for I2C standard mode TRISE = FREQ[5:0] + 1
+ *
+ * In fast mode, the maximum allowed SCL rise time is 300 ns.
+ * If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to
+ * 0x08 so period = 125 ns therefore the TRISE[5:0] bits must be
+ * programmed with 03h.(300 ns / 125 ns = 2 + 1)
+ * So, for I2C fast mode TRISE = FREQ[5:0] * 300 / 1000 + 1
+ */
+
+ cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ freq = cr2 & STM32F4_I2C_CR2_FREQ_MASK;
+
+ if (i2c_dev->speed == STM32F4_I2C_SPEED_STANDARD)
+ trise = freq + 1;
+ else
+ trise = freq * 300 / 1000 + 1;
+
+ writel_relaxed(STM32F4_I2C_TRISE_VALUE(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 cr2, ccr, freq, val;
+
+ ccr = readl_relaxed(i2c_dev->base + STM32F4_I2C_CCR);
+ ccr &= ~(STM32F4_I2C_CCR_FS | STM32F4_I2C_CCR_DUTY |
+ STM32F4_I2C_CCR_CCR_MASK);
+
+ /*
+ * Please see the comments above regarding i2c_timings[] declaration
+ * to understand the below calculation
+ */
+ cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+ freq = cr2 & STM32F4_I2C_CR2_FREQ_MASK;
+ val = freq * t->scl_period * 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++ = 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_irq(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 buffer interrupts for RXNE/TXE events */
+ 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_irq(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 repeated Start */
+ 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 events and error interrupts */
+ 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;
+
+ switch (msg->count) {
+ case 0:
+ stm32f4_i2c_terminate_xfer(i2c_dev);
+ /* Clear ADDR flag */
+ 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);
+ 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 set POS
+ */
+ 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);
+ readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+ break;
+
+ default:
+ /* N-byte reception: Enable ACK */
+ reg = i2c_dev->base + STM32F4_I2C_CR1;
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_ACK);
+ 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 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_ITEVTEN) {
+ possible_status = STM32F4_I2C_SR1_ITEVTEN_MASK;
+ if (ien & STM32F4_I2C_CR2_ITBUFEN)
+ possible_status |= STM32F4_I2C_SR1_ITBUFEN_MASK;
+ }
+
+ status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+
+ if (!(status & possible_status)) {
+ dev_dbg(i2c_dev->dev,
+ "spurious evt irq (status=0x%08x, ien=0x%08x)\n",
+ status, ien);
+ return IRQ_NONE;
+ }
+
+ while (status & possible_status) {
+ /* Use __fls() to check error bits first */
+ flag = __fls(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
+ readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+
+ /* Enable buffer interrupts for RXNE/TXE events */
+ reg = i2c_dev->base + STM32F4_I2C_CR2;
+ stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+ possible_status |= STM32F4_I2C_SR1_ITBUFEN_MASK;
+ 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 irq unhandled: status=0x%08x)\n",
+ status);
+ return IRQ_NONE;
+ }
+ status &= ~(1 << flag);
+ }
+
+ 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 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;
+
+ status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+
+ if (!(status & possible_status)) {
+ dev_dbg(i2c_dev->dev,
+ "spurious err it (status=0x%08x, ien=0x%08x)\n",
+ status, ien);
+ return IRQ_NONE;
+ }
+
+ /* Use __fls() to check error bits first */
+ flag = __fls(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", status);
+ return IRQ_NONE;
+ }
+
+ stm32f4_i2c_soft_reset(i2c_dev);
+ stm32f4_i2c_disable_irq(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 events and errors 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 : num;
+}
+
+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 irq_event, irq_error, 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);
+
+ irq_event = irq_of_parse_and_map(np, 0);
+ if (!irq_event) {
+ dev_err(&pdev->dev, "IRQ event missing or invalid\n");
+ return -EINVAL;
+ }
+
+ irq_error = irq_of_parse_and_map(np, 1);
+ if (!irq_error) {
+ dev_err(&pdev->dev, "IRQ error 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 >= 40000)
+ i2c_dev->speed = STM32F4_I2C_SPEED_FAST;
+
+ i2c_dev->dev = &pdev->dev;
+
+ ret = devm_request_irq(&pdev->dev, irq_event, stm32f4_i2c_isr_event, 0,
+ pdev->name, i2c_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq event %i\n",
+ irq_event);
+ goto clk_free;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq_error, stm32f4_i2c_isr_error, 0,
+ pdev->name, i2c_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq error %i\n",
+ 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 registered\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 v7 3/5] ARM: dts: stm32: Add I2C1 support for STM32F429 SoC
From: M'boumba Cedric Madianga @ 2016-12-22 13:35 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: <1482413704-17531-1-git-send-email-cedric.madianga@gmail.com>
This patch adds I2C1 support for STM32F429 SoC
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..2277a2d 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 {
@@ -140,6 +141,18 @@
status = "disabled";
};
+ 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";
+ };
+
usart7: serial@40007800 {
compatible = "st,stm32-usart", "st,stm32-uart";
reg = <0x40007800 0x400>;
@@ -337,6 +350,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 {
--
1.9.1
^ permalink raw reply related
* [PATCH v7 4/5] ARM: dts: stm32: Add I2C1 support for STM32429 eval board
From: M'boumba Cedric Madianga @ 2016-12-22 13:35 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: <1482413704-17531-1-git-send-email-cedric.madianga@gmail.com>
This patch adds I2C1 instance support for STM32x9I-Eval board.
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 v7 5/5] ARM: configs: stm32: Add I2C support for STM32 defconfig
From: M'boumba Cedric Madianga @ 2016-12-22 13:35 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: <1482413704-17531-1-git-send-email-cedric.madianga@gmail.com>
This patch adds I2C support for STM32 default configuration
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
arch/arm/configs/stm32_defconfig | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig
index e7b56d4..9494eaf 100644
--- a/arch/arm/configs/stm32_defconfig
+++ b/arch/arm/configs/stm32_defconfig
@@ -52,6 +52,9 @@ CONFIG_SERIAL_NONSTANDARD=y
CONFIG_SERIAL_STM32=y
CONFIG_SERIAL_STM32_CONSOLE=y
# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_STM32F4=y
# CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_NEW_LEDS=y
--
1.9.1
^ permalink raw reply related
* Re: [RESEND PATCH v2] arm64: dts: rockchip: add u2phy clock for ehci and ohci of rk3399
From: wlf @ 2016-12-22 13:54 UTC (permalink / raw)
To: Doug Anderson, Xing Zheng
Cc: Heiko Stübner, open list:ARM/Rockchip SoC..., Rob Herring,
Mark Rutland, Catalin Marinas, Will Deacon, Caesar, Shawn Lin,
Brian Norris, Jianqun, zhangqing, David Wu,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Frank Wang, Huang, Tao
In-Reply-To: <CAD=FV=WFFGSc7yBeaE+++VAuRKwMixpGUwA9bCCro4TCe0+GAA@mail.gmail.com>
Dear Doug & Xing Zheng,
在 2016年12月22日 08:47, Doug Anderson 写道:
> Hi,
>
> On Wed, Dec 21, 2016 at 2:41 AM, Xing Zheng <zhengxing@rock-chips.com> wrote:
>> From: William wu <wulf@rock-chips.com>
>>
>> We found that the suspend process was blocked when it run into
>> ehci/ohci module due to clk-480m of usb2-phy was disabled.
>>
>> The root cause is that usb2-phy suspended earlier than ehci/ohci
>> (usb2-phy will be auto suspended if no devices plug-in). and the
>> clk-480m provided by it was disabled if no module used. However,
I suggest that change the "clk-480m" to "utmi clock" here.
>> some suspend process related ehci/ohci are base on this clock,
>> so we should refer it into ehci/ohci driver to prevent this case.
>>
>> The u2phy clock flow like this:
>> ===
>> u2phy ________________
>> | | |-----> UTMI_CLK ---------> | EHCI |
>> OSC_24M ---|---> PHY_PLL----|----|
>> |________^_______| |-----> 480M_CLK ---|G|---> | USBPHY_480M_SRC| ----> USBPHY_480M for SoC
>> |
>> |
>> GRF
>> ===
>>
>> Signed-off-by: William wu <wulf@rock-chips.com>
>> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
>> ---
>>
>> Changes in v2:
>> - update the commit message
>> - remove patches whic add and export the USBPHYx_480M_SRC clock IDs
>>
>> arch/arm64/boot/dts/rockchip/rk3399.dtsi | 28 ++++++++++++++++++++--------
>> 1 file changed, 20 insertions(+), 8 deletions(-)
>>
>> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>> index b65c193..2ad9255 100644
>> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>> @@ -315,8 +315,10 @@
>> compatible = "generic-ehci";
>> reg = <0x0 0xfe380000 0x0 0x20000>;
>> interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH 0>;
>> - clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
>> - clock-names = "hclk_host0", "hclk_host0_arb";
>> + clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
>> + <&u2phy0>;
>> + clock-names = "usbhost", "arbiter",
>> + "utmi";
>> phys = <&u2phy0_host>;
>> phy-names = "usb";
>> status = "disabled";
>> @@ -326,8 +328,12 @@
>> compatible = "generic-ohci";
>> reg = <0x0 0xfe3a0000 0x0 0x20000>;
>> interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH 0>;
>> - clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
>> - clock-names = "hclk_host0", "hclk_host0_arb";
>> + clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
>> + <&u2phy0>;
>> + clock-names = "usbhost", "arbiter",
>> + "utmi";
>> + phys = <&u2phy0_host>;
>> + phy-names = "usb";
>> status = "disabled";
>> };
>>
>> @@ -335,8 +341,10 @@
>> compatible = "generic-ehci";
>> reg = <0x0 0xfe3c0000 0x0 0x20000>;
>> interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH 0>;
>> - clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
>> - clock-names = "hclk_host1", "hclk_host1_arb";
>> + clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>,
>> + <&u2phy1>;
>> + clock-names = "usbhost", "arbiter",
>> + "utmi";
>> phys = <&u2phy1_host>;
>> phy-names = "usb";
>> status = "disabled";
>> @@ -346,8 +354,12 @@
>> compatible = "generic-ohci";
>> reg = <0x0 0xfe3e0000 0x0 0x20000>;
>> interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH 0>;
>> - clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
>> - clock-names = "hclk_host1", "hclk_host1_arb";
>> + clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>,
>> + <&u2phy1>;
>> + clock-names = "usbhost", "arbiter",
>> + "utmi";
>> + phys = <&u2phy1_host>;
>> + phy-names = "usb";
> This all looks better to me. From a device tree point of view it
> makes lots of sense to expose this PHY clock to the controller. Thus:
>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>
>
>
> I can't say that I understand all the interactions between the PHY
> code and the USB driver, but presumably others have reviewed that
> more? Offline Heiko pointed me at rockchip_usb2phy_otg_sm_work()
> which apparently calls rockchip_usb2phy_power_off() and
> rockchip_usb2phy_power_on() directly sometimes behind the back of the
> PHY framework. Very strange.
Yes, the rockchip_usb2phy_otg_sm_work() in the USB2 PHY driver and
EHCI/OHCI platform
driver via the PHY framework can both do phy power on/off. We do that
because we want
to reduce USB2 PHY consumption in system runtime and deep sleep.
For EHCI/OHCI platform drivers, they call phy_power_on() in probe to
power on USB2 PHY,
and don't power off USB2 PHY in system runtime, even if there's no USB2
device connected.
They just call phy_power_off() in PM suspend, and call phy_power_on() in
PM resume to
power on USB2 PHY again. AKA the EHCI/OHCI platform driver can only
support USB power
management in deep sleep.
So we add a work in USB2 PHY driver to manage USB2 PHY power. The work
scheduled every
60 seconds, check the USB D+/D- and disconnect status in GRF registers
to know if any USB
device connected. If no USB connected, it will call
rockchip_usb2phy_power_off() to power
off USB2 PHY. And also, the USB2 PHY driver use an irq to detect D+/D-
voltage when USB
device connected, and then call rockchip_usb2phy_power_on() to power on
USB2 PHY.
AKA the work is used to support USB PHY power management in runtime.
>
>
> I will also say that there were still some unanswered questions from
> the previous thread, namely:
>
> A) Heiko: Also, with the change, the ehci will keep the clock (and
> thus the phy) always on. Does the phy-autosuspend even save anything
> now?
With this patch, the GRF USB commonon will always enable in system
runtime. But we still
can set USB2 PHY enter suspend mode by power down most of PHY logic
module via GRF,
so the phy-autosuspend is still useful.
On the other hand, commonon bit is used for PLL clock logical, its power
consumption is
not big in theory, I remember that I tested on the other SoC, the
commonon bit consumed
about 1~2mA.
> B) Brian: Is thre a race between power_off() and the delayed work in
> your USB2 PHY driver?
I'm not clear understand the race mentioned here.
IMO, PHY framework power_off() and work rockchip_usb2phy_power_off()
don't have race
problem.
And maybe there is a race between PHY framework power_off() and the
delayed work
rockchip_usb2phy_power_on() in USB2 PHY driver, but I think the
probability is low,
the race case maybe:
1. EHCI/OHCI platform call phy_power_off() in PM suspend;
2. Plug in an USB device after USB2 PHY has entered suspend;
3. Power on USB2 PHY again in work;
4. After these, finally the USB2 PHY is power on when system enter sleep.
>
>
> IMHO neither of those two questions affect the correctness of this
> patch: that this clock ought to be provided to the USB Controller.
> ...but they both are important questions that should be answered.
>
> One other last note is that we probably should be specifying a more
> specific compatible string, like:
>
> "rk3399-ehci", "generic-ehci"
>
> That will allow us later to use these same device tree files and
> perhaps deal with the clocks / PHYs in a more efficient way.
>
>
> -Doug
>
>
>
^ permalink raw reply
* Re: [RFC PATCH v3 2/2] drm/panel: Add support for Chunghwa CLAA070WP03XG panel
From: ayaka @ 2016-12-22 14:17 UTC (permalink / raw)
To: Thierry Reding, devicetree, linux-samsung-soc, linux, krzk,
linux-kernel, kgene, dri-devel, linux-arm-kernel
In-Reply-To: <20161207145555.kdg7azcrpnwnb2r6@phenom.ffwll.local>
On 12/07/2016 10:55 PM, Daniel Vetter wrote:
> On Wed, Dec 07, 2016 at 08:57:23AM +0800, Ayaka wrote:
>>
>> 從我的 iPad 傳送
>>
>>> Thierry Reding <thierry.reding@gmail.com> 於 2016年12月6日 下午11:46 寫道:
>>>
>>>> On Tue, Sep 20, 2016 at 03:02:51AM +0800, Randy Li wrote:
>>>> The Chunghwa CLAA070WP03XG is a 7" 1280x800 panel, which can be
>>>> supported by the simple panel driver.
>>>>
>>>> Signed-off-by: Randy Li <ayaka@soulik.info>
>>>> ---
>>>> .../display/panel/chunghwa,claa070wp03xg.txt | 7 ++++++
>>>> drivers/gpu/drm/panel/panel-simple.c | 27 ++++++++++++++++++++++
>>>> 2 files changed, 34 insertions(+)
>>>> create mode 100644 Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt
>>> Applied, thanks.
>> Wait, it is RFC, not pass the test.
> Well 2 months of silence, it's reasonable to assume that this works for
> you ... I guess you need to supply a fixup patch asap ;-)
Sorry, my exynos 4412 board is broken, I will order one and fix this
problem, please don't merge this patch until somebody confirm that it is
adjusted to correct parameter.
> -Daniel
^ permalink raw reply
* Re: [PATCH v2] power: reset: add linkstation-reset driver
From: Sebastian Reichel @ 2016-12-22 14:49 UTC (permalink / raw)
To: Andrew Lunn
Cc: Roger Shimizu, Rob Herring, linux-pm-u79uwXL29TY76Z2rM5mHXA,
Ryan Tandy, Martin Michlmayr, Sylver Bruneau,
Herbert Valerio Riedel, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161221164136.GM30952-g2DYL2Zd6BY@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 1589 bytes --]
Hi Andrew,
On Wed, Dec 21, 2016 at 05:41:36PM +0100, Andrew Lunn wrote:
> > These models can just be added to qnap-poweroff, which handles
> > exactly this special case as far as I can see.
>
> Nope, qnap is much, much simpler. The configuration of the serial port
> is simpler, and it only needs to send a single byte. Here we have all
> sorts of checksums to calculate, stuff coming back from the
> microcontroller, etc. The complexity is much higher.
>
> V1 of this patchset did extend the qnap driver. But in fact, very
> little of the original code was left afterwards, and lots of new code
> was added. So i requested a new driver be written, rather than extend
> my qnap driver.
>
> I would not like to see the nice and simple qnap driver get all this
> code added to it, making it much harder to maintain, for very little
> gain.
I'm talking about the special case, where it also sends only a
single byte:
> + /* send the power-off command to PIC */
> + if(cfg->cmd[0][0] == 1 && cfg->cmd[1][0] == 0) {
> + /* if it's simply one-byte command, send it directly */
> + writel(cfg->cmd[0][1], UART1_REG(TX));
> + }
The configuration is different, but
a) probably it can just use the config from the qnap driver, since
it just sends a single byte.
b) making the 4 config registers configurable in the qnap driver does
not add much complexity.
So this case should be removed from the linkstation-reset driver. If
any board needs it, it should use the qnap-poweroff driver instead.
-- Sebastian
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v4 3/5] i2c: designware: Add slave definitions
From: Luis Oliveira @ 2016-12-22 14:59 UTC (permalink / raw)
To: Rob Herring, Luis de Oliveira
Cc: wsa@the-dreams.de, mark.rutland@arm.com,
jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com,
mika.westerberg@linux.intel.com, linux-i2c@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Ramiro.Oliveira@synopsys.com, Joao.Pinto@synopsys.com,
CARLOS.PALMINHA@synopsys.com
In-Reply-To: <CAL_Jsq+DDx460jcLj34_X9MdtCqyc4izwc=3ThnFri+NjBaGUA@mail.gmail.com>
On 13-Dec-16 14:11, Rob Herring wrote:
> Again, please don't top post. And your line wrapping is messed up.
> IOW, you can't use Outlook.
>
> On Tue, Dec 13, 2016 at 4:50 AM, Luis de Oliveira
> <Luis.Oliveira@synopsys.com> wrote:
>> The controller for i2c-designware cannot be slave/master at the same time and it has to be enabled knowing beforehand if we want it to be slave or master by something outside of the controller itself.
>>
>> I as looking and I see the use of this I2C_OWN_SLAVE_ADDRESS with the "linux,slave-24c02" slave interface but I am not seeing how it will help me identify a selected i2c-designware block as a "slave" device before instantiation. I'm sorry if I'm not understanding properly.
>> I use the "linux,slave-24c02" to instantiate the i2c-designware as a slave with an address so I can do write/read operations, it is how I tested it.
>
> Something like this:
>
> of_for_each_child_node(child) {
> of_property_read_u32(child, "reg", ®);
> if (reg & I2C_OWN_SLAVE_ADDRESS))
> im_a_slave = true;
> }
>
> ...rather than testing "mode" is equal to "slave".
>
> Rob
>
Hi Rob, Andy,
I'm struggling to implement your suggestion @Rob. I checked the
tegra124-jetson-tk1.dts that uses that approach but I have some doubts.
My DT is as follows
i2c@0x2000 {
compatible = "snps,designware-i2c";
reg = <0x2000 0x100>;
clock-frequency = <400000>;
clocks = <&i2cclk>;
interrupts = <0>;
I could add something like this:
eeprom@64 {
compatible = "linux,slave-24c02";
reg = <(I2C_OWN_SLAVE_ADDRESS | 0x64)>;
}
But I think this is different form what I was doing before. I have two questions:
- This way the I2C controller is identified as a slave controller or just the
subnode eeprom?
- This way looks like my slave address will be fixed
In the previous Patch v3 submission @Andy suggested a property that selects mode
that I did and it's working. And you @Rob suggested to do it a common property.
It is implemented in the DT like:
mode = "slave";
So before I do this changes can you please agree both if you still think this is
the best approach?
Thank you both for your time,
Luis
>>
>> Luis
>>
>> -----Original Message-----
>> From: Rob Herring [mailto:robh@kernel.org]
>> Sent: Monday, December 12, 2016 23:16
>> To: Luis de Oliveira <Luis.Oliveira@synopsys.com>
>> Cc: wsa@the-dreams.de; mark.rutland@arm.com; jarkko.nikula@linux.intel.com; andriy.shevchenko@linux.intel.com; mika.westerberg@linux.intel.com; linux-i2c@vger.kernel.org; devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; Ramiro.Oliveira@synopsys.com; Joao.Pinto@synopsys.com; CARLOS.PALMINHA@synopsys.com
>> Subject: Re: [PATCH v4 3/5] i2c: designware: Add slave definitions
>>
>> On Mon, Dec 12, 2016 at 12:35 PM, Luis de Oliveira <Luis.Oliveira@synopsys.com> wrote:
>>> Hi all,
>>
>> Please don't top post.
>>
>>>
>>> The slave address could be set by the I2C slave backend so I can't use it to setup the controller.
>>> A boolean property was my initial approach then Andy and Wolfram Sang suggested the use of compatible strings and later It was suggested to use a property to select mode but I can do it again if it's the best way.
>>> Can you please tell me where should it be documented?
>>
>> bindings/i2c/i2c.txt.
>>
>> Actually, looking at this some more, we already have a way to describe the controller being a slave device with the I2C_OWN_SLAVE_ADDRESS flag in the reg property. We should just need a helper to read reg property of each child and check for the bit set.
>>
>> Rob
^ permalink raw reply
* Re: [PATCH 3/3] ARM: dts: sun5i: add support for Lichee Pi One board
From: Maxime Ripard @ 2016-12-22 15:10 UTC (permalink / raw)
To: Icenowy Zheng
Cc: devicetree@vger.kernel.org, Zepan, linux-kernel@vger.kernel.org,
Chen-Yu Tsai, Rob Herring, linux-arm-kernel@lists.infradead.org
In-Reply-To: <718681482365231@web25g.yandex.ru>
[-- Attachment #1.1: Type: text/plain, Size: 892 bytes --]
On Thu, Dec 22, 2016 at 08:07:11AM +0800, Icenowy Zheng wrote:
>
>
> 22.12.2016, 06:42, "Maxime Ripard" <maxime.ripard@free-electrons.com>:
> > On Thu, Dec 22, 2016 at 04:02:35AM +0800, Icenowy Zheng wrote:
> >> Lichee Pi One is a low-cost Allwinner A13-based development board, with
> >> an AXP209 PMU, a USB2.0 OTG port, a USB2.0 host port (or an onboard
> >> RTL8723BU Wi-Fi card), optional headers for LCD and CSI, two GPIO
> >> headers and two MicroSD card slots (connected to mmc0 and mmc2, both
> >> bootable).
> >>
> >> Add support for it.
> >>
> >> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> >
> > Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
>
> Excuse me. Who should apply it?
Gaaah, sorry, I meant I applied it...
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [2/3] serial: 8250: Add new port type for TI DA8xx/OMAPL13x/AM17xx/AM18xx
From: Franklin S Cooper Jr @ 2016-12-22 15:21 UTC (permalink / raw)
To: David Lechner, Greg Kroah-Hartman, Rob Herring, Mark Rutland
Cc: devicetree, Axel Haslam, Kevin Hilman, Sekhar Nori, linux-kernel,
Bartosz Golaszewski, Alexandre Bailon, linux-serial, Jiri Slaby,
linux-arm-kernel
In-Reply-To: <1482265384-715-3-git-send-email-david@lechnology.com>
On 12/20/2016 02:23 PM, David Lechner wrote:
> This adds a new UART port type for TI DA8xx/OMAPL13x/AM17xx/AM18xx. These
> SoCs have standard 8250 registers plus some extra non-standard registers.
>
> The UART will not function unless the non-standard Power and Emulation
> Management Register (PWREMU_MGMT) is configured correctly. This is
> currently handled in arch/arm/mach-davinci/serial.c for non-device-tree
> boards. Making this part of the UART driver will allow UART to work on
> device-tree boards as well and the mach code can eventually be removed.
>
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
> drivers/tty/serial/8250/8250_of.c | 1 +
> drivers/tty/serial/8250/8250_port.c | 22 ++++++++++++++++++++++
> include/uapi/linux/serial_core.h | 3 ++-
> include/uapi/linux/serial_reg.h | 8 ++++++++
> 4 files changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
> index d25ab1c..5281252 100644
> --- a/drivers/tty/serial/8250/8250_of.c
> +++ b/drivers/tty/serial/8250/8250_of.c
> @@ -332,6 +332,7 @@ static const struct of_device_id of_platform_serial_table[] = {
> .data = (void *)PORT_ALTR_16550_F128, },
> { .compatible = "mrvl,mmp-uart",
> .data = (void *)PORT_XSCALE, },
> + { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
> { /* end of list */ },
> };
> MODULE_DEVICE_TABLE(of, of_platform_serial_table);
> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> index fe4399b..ea854054 100644
> --- a/drivers/tty/serial/8250/8250_port.c
> +++ b/drivers/tty/serial/8250/8250_port.c
> @@ -273,6 +273,15 @@ static const struct serial8250_config uart_config[] = {
> .rxtrig_bytes = {1, 4, 8, 14},
> .flags = UART_CAP_FIFO,
> },
> + [PORT_DA830] = {
> + .name = "TI DA8xx/OMAPL13x/AM17xx/AM18xx",
> + .fifo_size = 16,
> + .tx_loadsz = 16,
> + .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
> + UART_FCR_R_TRIG_10,
> + .rxtrig_bytes = {1, 4, 8, 14},
> + .flags = UART_CAP_FIFO | UART_CAP_AFE,
> + },
> };
Any reason why the fcr and flags fields are changed when compared
against PORT_16550A?
>
> /* Uart divisor latch read */
> @@ -2118,6 +2127,19 @@ int serial8250_do_startup(struct uart_port *port)
> serial_port_out(port, UART_LCR, 0);
> }
>
> + if (port->type == PORT_DA830) {
> + /* Reset the port */
> + serial_port_out(port, UART_IER, 0);
> + serial_port_out(port, UART_DA830_PWREMU_MGMT, 0);
> + mdelay(10);
> +
> + /* Enable Tx, Rx and free run mode */
> + serial_port_out(port, UART_DA830_PWREMU_MGMT,
> + UART_DA830_PWREMU_MGMT_UTRST |
> + UART_DA830_PWREMU_MGMT_URRST |
> + UART_DA830_PWREMU_MGMT_FREE);
> + }
> +
> #ifdef CONFIG_SERIAL_8250_RSA
> /*
> * If this is an RSA port, see if we can kick it up to the
> diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
> index 99dbed8..a126d05 100644
> --- a/include/uapi/linux/serial_core.h
> +++ b/include/uapi/linux/serial_core.h
> @@ -56,7 +56,8 @@
> #define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */
> #define PORT_RT2880 29 /* Ralink RT2880 internal UART */
> #define PORT_16550A_FSL64 30 /* Freescale 16550 UART with 64 FIFOs */
> -#define PORT_MAX_8250 30 /* max port ID */
> +#define PORT_DA830 31 /* TI DA8xx/OMAP13x/AM17xx/AM18xx */
> +#define PORT_MAX_8250 31 /* max port ID */
>
> /*
> * ARM specific type numbers. These are not currently guaranteed
> diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h
> index b4c0484..0e72eeb 100644
> --- a/include/uapi/linux/serial_reg.h
> +++ b/include/uapi/linux/serial_reg.h
> @@ -327,6 +327,14 @@
> #define SERIAL_RSA_BAUD_BASE (921600)
> #define SERIAL_RSA_BAUD_BASE_LO (SERIAL_RSA_BAUD_BASE / 8)
>
> +/* Extra registers for TI DA8xx/OMAP13x/AM17xx/AM18xx */
> +#define UART_DA830_PWREMU_MGMT 12
> +
> +/* PWREMU_MGMT register bits */
> +#define UART_DA830_PWREMU_MGMT_FREE (1 << 0) /* Free-running mode */
> +#define UART_DA830_PWREMU_MGMT_URRST (1 << 13) /* Receiver reset/enable */
> +#define UART_DA830_PWREMU_MGMT_UTRST (1 << 14) /* Transmitter reset/enable */
> +
> /*
> * Extra serial register definitions for the internal UARTs
> * in TI OMAP processors.
>
^ permalink raw reply
* Re: [PATCH v4 3/5] i2c: designware: Add slave definitions
From: Andy Shevchenko @ 2016-12-22 15:29 UTC (permalink / raw)
To: Luis Oliveira, Rob Herring
Cc: wsa@the-dreams.de, mark.rutland@arm.com,
jarkko.nikula@linux.intel.com, mika.westerberg@linux.intel.com,
linux-i2c@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, Ramiro.Oliveira@synopsys.com,
Joao.Pinto@synopsys.com, CARLOS.PALMINHA@synopsys.com
In-Reply-To: <3ef11852-8dc5-dbb3-7dc3-1ec8f4fc58da@synopsys.com>
On Thu, 2016-12-22 at 14:59 +0000, Luis Oliveira wrote:
> On 13-Dec-16 14:11, Rob Herring wrote:
> > Something like this:
> >
> > of_for_each_child_node(child) {
> > of_property_read_u32(child, "reg", ®);
> > if (reg & I2C_OWN_SLAVE_ADDRESS))
> > im_a_slave = true;
> > }
> >
> > ...rather than testing "mode" is equal to "slave".
> >
> > Rob
> >
>
> Hi Rob, Andy,
>
> I'm struggling to implement your suggestion @Rob. I checked the
> tegra124-jetson-tk1.dts that uses that approach but I have some
> doubts.
>
> My DT is as follows
>
> i2c@0x2000 {
> compatible = "snps,designware-i2c";
> reg = <0x2000 0x100>;
> clock-frequency = <400000>;
> clocks = <&i2cclk>;
> interrupts = <0>;
>
> I could add something like this:
>
> eeprom@64 {
> compatible = "linux,slave-24c02";
> reg = <(I2C_OWN_SLAVE_ADDRESS | 0x64)>;
> }
>
> But I think this is different form what I was doing before. I have two
> questions:
>
> - This way the I2C controller is identified as a slave controller or
> just the
> subnode eeprom?
> - This way looks like my slave address will be fixed
>
> In the previous Patch v3 submission @Andy suggested a property that
> selects mode
> that I did and it's working. And you @Rob suggested to do it a common
> property.
> It is implemented in the DT like:
>
> mode = "slave";
>
> So before I do this changes can you please agree both if you still
> think this is
> the best approach?
I'm a bit lost in the discussion (and TBH busy by something else), so I
would agree on whatever you and Rob make an agreement on.
--
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy
^ permalink raw reply
* Re: [2/3] serial: 8250: Add new port type for TI DA8xx/OMAPL13x/AM17xx/AM18xx
From: Franklin S Cooper Jr @ 2016-12-22 16:02 UTC (permalink / raw)
To: David Lechner, Greg Kroah-Hartman, Rob Herring, Mark Rutland
Cc: devicetree, Axel Haslam, Kevin Hilman, Sekhar Nori, linux-kernel,
Bartosz Golaszewski, Alexandre Bailon, linux-serial, Jiri Slaby,
linux-arm-kernel
In-Reply-To: <306c9ce3-4003-84b9-fd0f-34232399f1aa@ti.com>
On 12/22/2016 09:21 AM, Franklin S Cooper Jr wrote:
>
>
> On 12/20/2016 02:23 PM, David Lechner wrote:
>> This adds a new UART port type for TI DA8xx/OMAPL13x/AM17xx/AM18xx. These
Keystone SoCs also require this PWREMU_MGMT register to be configured.
So it would be nice to update this commit message to include Keystone SoCs.
>> SoCs have standard 8250 registers plus some extra non-standard registers.
>>
>> The UART will not function unless the non-standard Power and Emulation
>> Management Register (PWREMU_MGMT) is configured correctly. This is
>> currently handled in arch/arm/mach-davinci/serial.c for non-device-tree
>> boards. Making this part of the UART driver will allow UART to work on
>> device-tree boards as well and the mach code can eventually be removed.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---
>> drivers/tty/serial/8250/8250_of.c | 1 +
>> drivers/tty/serial/8250/8250_port.c | 22 ++++++++++++++++++++++
>> include/uapi/linux/serial_core.h | 3 ++-
>> include/uapi/linux/serial_reg.h | 8 ++++++++
>> 4 files changed, 33 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
>> index d25ab1c..5281252 100644
>> --- a/drivers/tty/serial/8250/8250_of.c
>> +++ b/drivers/tty/serial/8250/8250_of.c
>> @@ -332,6 +332,7 @@ static const struct of_device_id of_platform_serial_table[] = {
>> .data = (void *)PORT_ALTR_16550_F128, },
>> { .compatible = "mrvl,mmp-uart",
>> .data = (void *)PORT_XSCALE, },
>> + { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
>> { /* end of list */ },
>> };
>> MODULE_DEVICE_TABLE(of, of_platform_serial_table);
>> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
>> index fe4399b..ea854054 100644
>> --- a/drivers/tty/serial/8250/8250_port.c
>> +++ b/drivers/tty/serial/8250/8250_port.c
>> @@ -273,6 +273,15 @@ static const struct serial8250_config uart_config[] = {
>> .rxtrig_bytes = {1, 4, 8, 14},
>> .flags = UART_CAP_FIFO,
>> },
>> + [PORT_DA830] = {
>> + .name = "TI DA8xx/OMAPL13x/AM17xx/AM18xx",
>> + .fifo_size = 16,
>> + .tx_loadsz = 16,
>> + .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
>> + UART_FCR_R_TRIG_10,
>> + .rxtrig_bytes = {1, 4, 8, 14},
>> + .flags = UART_CAP_FIFO | UART_CAP_AFE,
>> + },
>> };
>
>
> Any reason why the fcr and flags fields are changed when compared
> against PORT_16550A?
>>
>> /* Uart divisor latch read */
>> @@ -2118,6 +2127,19 @@ int serial8250_do_startup(struct uart_port *port)
>> serial_port_out(port, UART_LCR, 0);
>> }
>>
>> + if (port->type == PORT_DA830) {
>> + /* Reset the port */
>> + serial_port_out(port, UART_IER, 0);
>> + serial_port_out(port, UART_DA830_PWREMU_MGMT, 0);
>> + mdelay(10);
>> +
>> + /* Enable Tx, Rx and free run mode */
>> + serial_port_out(port, UART_DA830_PWREMU_MGMT,
>> + UART_DA830_PWREMU_MGMT_UTRST |
>> + UART_DA830_PWREMU_MGMT_URRST |
>> + UART_DA830_PWREMU_MGMT_FREE);
>> + }
>> +
>> #ifdef CONFIG_SERIAL_8250_RSA
>> /*
>> * If this is an RSA port, see if we can kick it up to the
>> diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
>> index 99dbed8..a126d05 100644
>> --- a/include/uapi/linux/serial_core.h
>> +++ b/include/uapi/linux/serial_core.h
>> @@ -56,7 +56,8 @@
>> #define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */
>> #define PORT_RT2880 29 /* Ralink RT2880 internal UART */
>> #define PORT_16550A_FSL64 30 /* Freescale 16550 UART with 64 FIFOs */
>> -#define PORT_MAX_8250 30 /* max port ID */
>> +#define PORT_DA830 31 /* TI DA8xx/OMAP13x/AM17xx/AM18xx */
>> +#define PORT_MAX_8250 31 /* max port ID */
>>
>> /*
>> * ARM specific type numbers. These are not currently guaranteed
>> diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h
>> index b4c0484..0e72eeb 100644
>> --- a/include/uapi/linux/serial_reg.h
>> +++ b/include/uapi/linux/serial_reg.h
>> @@ -327,6 +327,14 @@
>> #define SERIAL_RSA_BAUD_BASE (921600)
>> #define SERIAL_RSA_BAUD_BASE_LO (SERIAL_RSA_BAUD_BASE / 8)
>>
>> +/* Extra registers for TI DA8xx/OMAP13x/AM17xx/AM18xx */
>> +#define UART_DA830_PWREMU_MGMT 12
>> +
>> +/* PWREMU_MGMT register bits */
>> +#define UART_DA830_PWREMU_MGMT_FREE (1 << 0) /* Free-running mode */
>> +#define UART_DA830_PWREMU_MGMT_URRST (1 << 13) /* Receiver reset/enable */
>> +#define UART_DA830_PWREMU_MGMT_UTRST (1 << 14) /* Transmitter reset/enable */
>> +
>> /*
>> * Extra serial register definitions for the internal UARTs
>> * in TI OMAP processors.
>>
^ permalink raw reply
* Re: [3/3] ARM: da850: Add ti, da830-uart compatible for serial ports
From: Franklin S Cooper Jr @ 2016-12-22 16:06 UTC (permalink / raw)
To: David Lechner, Greg Kroah-Hartman, Rob Herring, Mark Rutland
Cc: devicetree, Axel Haslam, Kevin Hilman, Sekhar Nori, linux-kernel,
Bartosz Golaszewski, Alexandre Bailon, linux-serial, Jiri Slaby,
linux-arm-kernel
In-Reply-To: <1482265384-715-4-git-send-email-david@lechnology.com>
On 12/20/2016 02:23 PM, David Lechner wrote:
> TI DA8xx/OMAPL13x/AM17xx/AM18xx SoCs have extra UART registers beyond
Similar comment about adding Keystone SoCs to the list of SoCs.
> the standard 8250 registers, so we need a new compatible string to
> indicate this. Also, at least one of these registers uses the full 32
> bits, so we need to specify reg-io-width in addition to reg-shift.
>
> "ns16550a" is left in the compatible specification since it does work
> as long as the bootloader configures the SoC UART power management
> registers.
>
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
> arch/arm/boot/dts/da850.dtsi | 9 ++++++---
Similar changes should be made to the various Keystone dtsi files.
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
> index 104155d..f6cd212 100644
> --- a/arch/arm/boot/dts/da850.dtsi
> +++ b/arch/arm/boot/dts/da850.dtsi
> @@ -266,22 +266,25 @@
> interrupt-names = "edm3_tcerrint";
> };
> serial0: serial@42000 {
> - compatible = "ns16550a";
> + compatible = "ti,da830-uart", "ns16550a";
> reg = <0x42000 0x100>;
> + reg-io-width = <4>;
> reg-shift = <2>;
> interrupts = <25>;
> status = "disabled";
> };
> serial1: serial@10c000 {
> - compatible = "ns16550a";
> + compatible = "ti,da830-uart", "ns16550a";
> reg = <0x10c000 0x100>;
> + reg-io-width = <4>;
> reg-shift = <2>;
> interrupts = <53>;
> status = "disabled";
> };
> serial2: serial@10d000 {
> - compatible = "ns16550a";
> + compatible = "ti,da830-uart", "ns16550a";
> reg = <0x10d000 0x100>;
> + reg-io-width = <4>;
> reg-shift = <2>;
> interrupts = <61>;
> status = "disabled";
>
^ permalink raw reply
* Re: [PATCH 8/9] arm64: dts: rockchip: partially describe PWM regulators for Gru
From: Heiko Stübner @ 2016-12-22 16:09 UTC (permalink / raw)
To: Brian Norris
Cc: linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Caesar Wang, Doug Anderson,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Stephen Barber,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Chris Zhong
In-Reply-To: <13721273.q1HcHZAhdQ@phil>
Am Dienstag, 13. Dezember 2016, 18:48:50 schrieb Heiko Stuebner:
> Am Mittwoch, 7. Dezember 2016, 09:09:17 CET schrieb Brian Norris:
> > Hi Heiko,
> >
> > On Wed, Dec 07, 2016 at 05:48:24PM +0100, Heiko Stuebner wrote:
> > > Am Donnerstag, 1. Dezember 2016, 18:27:32 CET schrieb Brian Norris:
> > > > We need to add regulators to the CPU nodes, so cpufreq doesn't think
> > > > it
> > > > can crank up the clock speed without changing the voltage. However, we
> > > > don't yet have the DT bindings to fully describe the Over Voltage
> > > > Protection (OVP) circuits on these boards. Without that description,
> > > > we
> > > > might end up changing the voltage too much, too fast.
> > > >
> > > > Add the pwm-regulator descriptions and associate the CPU OPPs, but
> > > > leave
> > > > them disabled.
> > > >
> > > > Signed-off-by: Brian Norris <briannorris-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> > >
> > > is there a specific reason for keeping this change separate?
> >
> > Maybe not a great one. I figured they were somewhat controversial, so I
> > at least wanted to split the "cpufreq patches" (i.e., this and the
> > previous) from the main DTS(I) additions. I also figured we typically
> > like to keep the base SoC changes separate from the board DTS(I)
> > changes.
>
> I was scratching my head for a bit where this was affecting the evb, until I
> found the include at the end of patch5 :-) .
>
> > > While it is nice for documentation reasons, as it stands now the
> > > previous
> > > patch introduces a regression (cpufreq trying to scale without
> > > regulators)
> > > and immediately fixes it here.
> >
> > Right. Additionally, as noted on the previous patch, we might do the
> > same with EVB. But I don't know what the regulators are like for EVB.
> > This is probably a bigger deal, since EVB has been working (allegedly)
> > upstream for a while now.
>
> Yep, it was at least booting :-) . I guess I should wire it up again. My
> shiny new Gru somehow did take up its space recently.
>
> > There's no way to split these up without either breaking compilation or
> > breaking bisectability. For Kevin/Gru, they don't function at all before
> > this series, so I figured some "settle" time wasn't a huge deal.
> >
> > > So if you're ok with it, I'd like to merge this one back into the
> > > previous
> > > patch when applying.
> >
> > That'd be OK with me, as long as we're also confident about EVB.
>
> That somehow sounds unrelated, as this patch only touches gru stuff anyway.
> So if the evb breaks, it would do so after patch5 already.
>
> > Maybe at a minimum, I should just patch in some empty regulator nodes,
> > so cpufreq doesn't think there's no need to handle voltage.
>
> So I guess going forward we could do, describe the evb pwm regulators (in
> disabled state), add general OPPs, add gru with pwm regulators?
>
> I'll try to hook up my evb and check on the pwm-regulators in the schematics
> this week.
Now I remember why I retired my evb ... ES1 silicon.
Anyway, I was able to describe the rk808 pmic that is used in some basic way
and was able to see a bit of cpu-scaling on the little cluster, but the big
cluster never was able to scale in a stable way and always hung the system.
I don't think that we should care about ES1 chips as they never reached any
public but that leaves me without the ability to test.
In another issue I read that Caesar also is using a rk3399evb sometimes, so
maybe he can give that a try on real ES2 silicon and I've thus Cc'ed him.
@Caesar I don't know how much the power rails differ between evb versions, so
maybe you can also provide the necessary rk808 devicetree nodes please?
Thanks
Heiko
--
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] ARM64: zynqmp: Fix i2c node's compatible string
From: Moritz Fischer @ 2016-12-22 16:26 UTC (permalink / raw)
To: Michal Simek
Cc: Moritz Fischer, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Moritz Fischer,
Sören Brinkmann, U-Boot List, Rob Herring
In-Reply-To: <d1e69302-8367-7c57-ecd7-f72861c3a49e-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
Hi Michal,
On Wed, Dec 21, 2016 at 11:35 PM, Michal Simek <michal.simek-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org> wrote:
> compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
I keep getting that wrong .. .damn ... :) Will resubmit.
> The same of course for u-boot where also p14 should be added to the driver.
Yeah, I realized that part after submitting...
Thanks
--
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 v6 5/6] Documentation: bindings: add documentation for ir-spi device driver
From: Rob Herring @ 2016-12-22 16:40 UTC (permalink / raw)
To: Andi Shyti
Cc: Mauro Carvalho Chehab, Sean Young, Mark Rutland, Richard Purdie,
Jacek Anaszewski, Heiner Kallweit, linux-media, devicetree,
linux-leds, linux-kernel, Andi Shyti
In-Reply-To: <20161218111138.12831-6-andi.shyti@samsung.com>
On Sun, Dec 18, 2016 at 08:11:37PM +0900, Andi Shyti wrote:
> Document the ir-spi driver's binding which is a IR led driven
> through the SPI line.
>
> Signed-off-by: Andi Shyti <andi.shyti@samsung.com>
> Reviewed-by: Sean Young <sean@mess.org>
> ---
> .../devicetree/bindings/leds/irled/spi-ir-led.txt | 29 ++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/leds/irled/spi-ir-led.txt
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 6/7] dt-bindings: media: Add Renesas R-Car DRIF binding
From: Laurent Pinchart @ 2016-12-22 17:05 UTC (permalink / raw)
To: Ramesh Shanmugasundaram
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
mchehab-DgEjT+Ai2ygdnm+yROfE0A, hverkuil-qWit8jRvyhVmR6Xm/wNWPw,
sakari.ailus-VuQAYsv1563Yd54FQh9/CA, crope-X3B1VOXEql0,
chris.paterson2-zM6kxYcvzFBBDgjK7y7TUQ,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1482307838-47415-7-git-send-email-ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>
Hi Ramesh,
Thank you for the patch.
On Wednesday 21 Dec 2016 08:10:37 Ramesh Shanmugasundaram wrote:
> Add binding documentation for Renesas R-Car Digital Radio Interface
> (DRIF) controller.
>
> Signed-off-by: Ramesh Shanmugasundaram
> <ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org> ---
> .../devicetree/bindings/media/renesas,drif.txt | 202 ++++++++++++++++++
> 1 file changed, 202 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/renesas,drif.txt
>
> diff --git a/Documentation/devicetree/bindings/media/renesas,drif.txt
> b/Documentation/devicetree/bindings/media/renesas,drif.txt new file mode
> 100644
> index 0000000..1f3feaf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/renesas,drif.txt
> @@ -0,0 +1,202 @@
> +Renesas R-Car Gen3 Digital Radio Interface controller (DRIF)
> +------------------------------------------------------------
> +
> +R-Car Gen3 DRIF is a SPI like receive only slave device. A general
> +representation of DRIF interfacing with a master device is shown below.
> +
> ++---------------------+ +---------------------+
> +| |-----SCK------->|CLK |
> +| Master |-----SS-------->|SYNC DRIFn (slave) |
> +| |-----SD0------->|D0 |
> +| |-----SD1------->|D1 |
> ++---------------------+ +---------------------+
> +
> +As per datasheet, each DRIF channel (drifn) is made up of two internal
> +channels (drifn0 & drifn1). These two internal channels share the common
> +CLK & SYNC. Each internal channel has its own dedicated resources like
> +irq, dma channels, address space & clock. This internal split is not
> +visible to the external master device.
> +
> +The device tree model represents each internal channel as a separate node.
> +The internal channels sharing the CLK & SYNC are tied together by their
> +phandles using a new property called "renesas,bonding". For the rest of
> +the documentation, unless explicitly stated, the word channel implies an
> +internal channel.
> +
> +When both internal channels are enabled they need to be managed together
> +as one (i.e.) they cannot operate alone as independent devices. Out of the
> +two, one of them needs to act as a primary device that accepts common
> +properties of both the internal channels. This channel is identified by a
> +new property called "renesas,primary-bond".
> +
> +To summarize,
> + - When both the internal channels that are bonded together are enabled,
> + the zeroth channel is selected as primary-bond. This channels accepts
> + properties common to all the members of the bond.
> + - When only one of the bonded channels need to be enabled, the property
> + "renesas,bonding" or "renesas,primary-bond" will have no effect. That
> + enabled channel can act alone as any other independent device.
> +
> +Required properties of an internal channel:
> +-------------------------------------------
> +- compatible: "renesas,r8a7795-drif" if DRIF controller is a part of
> R8A7795 SoC.
> + "renesas,rcar-gen3-drif" for a generic R-Car Gen3 compatible
> device.
> + When compatible with the generic version, nodes must list the
> + SoC-specific version corresponding to the platform first
> + followed by the generic version.
> +- reg: offset and length of that channel.
> +- interrupts: associated with that channel.
> +- clocks: phandle and clock specifier of that channel.
> +- clock-names: clock input name string: "fck".
> +- dmas: phandles to the DMA channels.
> +- dma-names: names of the DMA channel: "rx".
> +- renesas,bonding: phandle to the other channel.
> +
> +Optional properties of an internal channel:
> +-------------------------------------------
> +- power-domains: phandle to the respective power domain.
> +
> +Required properties of an internal channel when:
> + - It is the only enabled channel of the bond (or)
> + - If it acts as primary among enabled bonds
> +--------------------------------------------------------
> +- pinctrl-0: pin control group to be used for this channel.
> +- pinctrl-names: must be "default".
> +- renesas,primary-bond: empty property indicating the channel acts as
> primary
> + among the bonded channels.
> +- port: child port node of a channel that defines the local and remote
> + endpoints. The remote endpoint is assumed to be a third party tuner
> + device endpoint.
> +
> +Optional properties of an internal channel when:
> + - It is the only enabled channel of the bond (or)
> + - If it acts as primary among enabled bonds
> +--------------------------------------------------------
> +- renesas,syncmd : sync mode
> + 0 (Frame start sync pulse mode. 1-bit width pulse
> + indicates start of a frame)
> + 1 (L/R sync or I2S mode) (default)
> +- renesas,lsb-first : empty property indicates lsb bit is received
> first.
> + When not defined msb bit is received first (default)
> +- renesas,syncac-active: Indicates sync signal polarity, 0/1 for low/high
> + respectively. The default is 1 (active high)
> +- renesas,dtdl : delay between sync signal and start of reception.
> + The possible values are represented in 0.5 clock
> + cycle units and the range is 0 to 4. The default
> + value is 2 (i.e.) 1 clock cycle delay.
> +- renesas,syncdl : delay between end of reception and sync signal
> edge.
> + The possible values are represented in 0.5 clock
> + cycle units and the range is 0 to 4 & 6. The default
> + value is 0 (i.e.) no delay.
Most of these properties are pretty similar to the video bus properties
defined at the endpoint level in
Documentation/devicetree/bindings/media/video-interfaces.txt. I believe it
would make sense to use OF graph and try to standardize these properties
similarly.
> +
> +Example
> +--------
> +
> +SoC common dtsi file
> +
> + drif00: rif@e6f40000 {
> + compatible = "renesas,r8a7795-drif",
> + "renesas,rcar-gen3-drif";
> + reg = <0 0xe6f40000 0 0x64>;
> + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&cpg CPG_MOD 515>;
> + clock-names = "fck";
> + dmas = <&dmac1 0x20>, <&dmac2 0x20>;
> + dma-names = "rx", "rx";
> + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
> + renesas,bonding = <&drif01>;
> + status = "disabled";
> + };
> +
> + drif01: rif@e6f50000 {
> + compatible = "renesas,r8a7795-drif",
> + "renesas,rcar-gen3-drif";
> + reg = <0 0xe6f50000 0 0x64>;
> + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&cpg CPG_MOD 514>;
> + clock-names = "fck";
> + dmas = <&dmac1 0x22>, <&dmac2 0x22>;
> + dma-names = "rx", "rx";
> + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
> + renesas,bonding = <&drif00>;
> + status = "disabled";
> + };
> +
> +
> +Board specific dts file
> +
> +(1) Both internal channels enabled, primary-bond = 0
> +-----------------------------------------------------
> +
> +When interfacing with a third party tuner device with two data pins as
> shown +below.
> +
> ++---------------------+ +---------------------+
> +| |-----SCK------->|CLK |
> +| Master |-----SS-------->|SYNC DRIFn (slave) |
> +| |-----SD0------->|D0 |
> +| |-----SD1------->|D1 |
> ++---------------------+ +---------------------+
> +
> +pfc {
> + ...
> +
> + drif0_pins: drif0 {
> + groups = "drif0_ctrl_a", "drif0_data0_a",
> + "drif0_data1_a";
> + function = "drif0";
> + };
> + ...
> +}
> +
> +&drif00 {
> + pinctrl-0 = <&drif0_pins>;
> + pinctrl-names = "default";
> + renesas,syncac-active = <1>;
> + renesas,primary-bond;
> + status = "okay";
> + port {
> + drif0_ep: endpoint {
> + remote-endpoint = <&tuner_ep>;
> + };
> + };
> +};
> +
> +&drif01 {
> + status = "okay";
> +};
> +
> +(2) Internal channel 1 alone is enabled:
> +----------------------------------------
> +
> +When interfacing with a third party tuner device with one data pin as shown
> +below.
> +
> ++---------------------+ +---------------------+
> +| |-----SCK------->|CLK |
> +| Master |-----SS-------->|SYNC DRIFn (slave) |
> +| | |D0 (unused) |
> +| |-----SD-------->|D1 |
> ++---------------------+ +---------------------+
> +
> +pfc {
> + ...
> +
> + drif0_pins: drif0 {
> + groups = "drif0_ctrl_a", "drif0_data1_a";
> + function = "drif0";
> + };
> + ...
> +}
> +
> +&drif01 {
> + pinctrl-0 = <&drif0_pins>;
> + pinctrl-names = "default";
> + renesas,syncac-active = <0>;
> + status = "okay";
> + port {
> + drif0_ep: endpoint {
> + remote-endpoint = <&tuner_ep>;
> + };
> + };
> +};
--
Regards,
Laurent Pinchart
--
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 v2] ARM64: zynqmp: Fix i2c node's compatible string
From: mdf @ 2016-12-22 17:19 UTC (permalink / raw)
To: devicetree
Cc: linux-kernel, linux-arm-kernel, Moritz Fischer, Michal Simek,
Sören Brinkmann, Rob Herring
From: Moritz Fischer <mdf@kernel.org>
The Zynq Ultrascale MP uses version 1.4 of the Cadence IP core
which fixes some silicon bugs that needed software workarounds
in Version 1.0 that was used on Zynq systems.
Signed-off-by: Moritz Fischer <mdf@kernel.org>
Cc: Michal Simek <michal.simek@xilinx.com>
Cc: Sören Brinkmann <soren.brinkmann@xilinx.com>
Cc: Rob Herring <robh+dt@kernel.org>
---
Changes from v1:
- Added fall through case to cdns,i2c-r1p10
Cheers,
Moritz
---
arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 68a90833..ee86d02 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -175,7 +175,7 @@
};
i2c0: i2c@ff020000 {
- compatible = "cdns,i2c-r1p10";
+ compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
status = "disabled";
interrupt-parent = <&gic>;
interrupts = <0 17 4>;
@@ -185,7 +185,7 @@
};
i2c1: i2c@ff030000 {
- compatible = "cdns,i2c-r1p10";
+ compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
status = "disabled";
interrupt-parent = <&gic>;
interrupts = <0 18 4>;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v2] ARM64: zynqmp: Fix i2c node's compatible string
From: Sören Brinkmann @ 2016-12-22 17:27 UTC (permalink / raw)
To: mdf; +Cc: devicetree, Rob Herring, linux-kernel, linux-arm-kernel,
Michal Simek
In-Reply-To: <1482427165-8951-1-git-send-email-mdf@kernel.org>
On Thu, 2016-12-22 at 09:19:25 -0800, mdf@kernel.org wrote:
> From: Moritz Fischer <mdf@kernel.org>
>
> The Zynq Ultrascale MP uses version 1.4 of the Cadence IP core
> which fixes some silicon bugs that needed software workarounds
> in Version 1.0 that was used on Zynq systems.
>
> Signed-off-by: Moritz Fischer <mdf@kernel.org>
> Cc: Michal Simek <michal.simek@xilinx.com>
> Cc: Sören Brinkmann <soren.brinkmann@xilinx.com>
> Cc: Rob Herring <robh+dt@kernel.org>
Acked-by: Sören Brinkmann <soren.brinkmann@xilinx.com>
Sören
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 0/2] power: supply: add sbs-charger driver
From: Sebastian Reichel @ 2016-12-22 18:04 UTC (permalink / raw)
To: Nicolas Saenz Julienne
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1482247874-28713-1-git-send-email-nicolas.saenz-gbiq2sxWoaasTnJN9+BGXg@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 1132 bytes --]
Hi,
On Tue, Dec 20, 2016 at 04:31:12PM +0100, Nicolas Saenz Julienne wrote:
> This series adds support for all SBS compatible battery chargers, as defined
> here: http://sbs-forum.org/specs/sbc110.pdf.
>
> [...]
>
> Nicolas Saenz Julienne (2):
> power: supply: add sbs-charger driver
> dt-bindings: power: add bindings for sbs-charger
>
> .../bindings/power/supply/sbs_sbs-charger.txt | 23 ++
> drivers/power/supply/Kconfig | 6 +
> drivers/power/supply/Makefile | 1 +
> drivers/power/supply/sbs-charger.c | 274 +++++++++++++++++++++
> 4 files changed, 304 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/sbs_sbs-charger.txt
> create mode 100644 drivers/power/supply/sbs-charger.c
Thanks for your patchset. We are currently in the merge
window and your patchset will appear in linux-next once
4.10-rc1 has been tagged by Linus Torvalds.
Until then I queued it into this branch:
https://git.kernel.org/cgit/linux/kernel/git/sre/linux-power-supply.git/log/?h=for-next-next
-- Sebastian
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH V2 0/2] PM / Domains / OPP: Introduce domain-performance-state binding
From: Rob Herring @ 2016-12-22 18:14 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, linaro-kernel, linux-pm, linux-kernel,
Stephen Boyd, Nishanth Menon, Vincent Guittot, Mark Rutland,
Kevin Hilman, Ulf Hansson, Lina Iyer, devicetree, Nayak Rajendra
In-Reply-To: <cover.1481539827.git.viresh.kumar@linaro.org>
On Mon, Dec 12, 2016 at 04:26:17PM +0530, Viresh Kumar wrote:
> Hello,
>
> Some platforms have the capability to configure the performance state of
> their Power Domains. The performance levels are represented by positive
> integer values, a lower value represents lower performance state.
>
> We had some discussions about it in the past on the PM list [1], which is
> followed by discussions during the LPC. The outcome of all that was that we
> should extend Power Domain framework to support active state power management
> as well.
>
> The power-domains until now were only concentrating on the idle state
> management of the device and this needs to change in order to reuse the
> infrastructure of power domains for active state management.
>From a h/w perspective, are idle states really different from
performance states?
>
> To get a complete picture of the proposed plan, following is what we
> need to do:
> - Create DT bindings to get domain performance state information for the
> platforms.
I would do this last so you can evolve things if you're not certain
about what the bindings should look like. You can always start with
things in the kernel and add to DT later.
While in theory we should be able to just "describe the h/w" in DT and
develop the Linux side independently, this feels too much like the
bindings are just evolving with Linux needs.
Rob
^ permalink raw reply
* Re: [2/3] serial: 8250: Add new port type for TI DA8xx/OMAPL13x/AM17xx/AM18xx
From: David Lechner @ 2016-12-22 18:16 UTC (permalink / raw)
To: Franklin S Cooper Jr, Greg Kroah-Hartman, Rob Herring,
Mark Rutland
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Axel Haslam, Kevin Hilman,
Sekhar Nori, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Bartosz Golaszewski, Alexandre Bailon,
linux-serial-u79uwXL29TY76Z2rM5mHXA, Jiri Slaby,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <306c9ce3-4003-84b9-fd0f-34232399f1aa-l0cyMroinI0@public.gmane.org>
On 12/22/2016 09:21 AM, Franklin S Cooper Jr wrote:
>
>
> On 12/20/2016 02:23 PM, David Lechner wrote:
>> This adds a new UART port type for TI DA8xx/OMAPL13x/AM17xx/AM18xx. These
>> SoCs have standard 8250 registers plus some extra non-standard registers.
>>
>> The UART will not function unless the non-standard Power and Emulation
>> Management Register (PWREMU_MGMT) is configured correctly. This is
>> currently handled in arch/arm/mach-davinci/serial.c for non-device-tree
>> boards. Making this part of the UART driver will allow UART to work on
>> device-tree boards as well and the mach code can eventually be removed.
>>
>> Signed-off-by: David Lechner <david-nq/r/kbU++upp/zk7JDF2g@public.gmane.org>
>> ---
>> drivers/tty/serial/8250/8250_of.c | 1 +
>> drivers/tty/serial/8250/8250_port.c | 22 ++++++++++++++++++++++
>> include/uapi/linux/serial_core.h | 3 ++-
>> include/uapi/linux/serial_reg.h | 8 ++++++++
>> 4 files changed, 33 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
>> index d25ab1c..5281252 100644
>> --- a/drivers/tty/serial/8250/8250_of.c
>> +++ b/drivers/tty/serial/8250/8250_of.c
>> @@ -332,6 +332,7 @@ static const struct of_device_id of_platform_serial_table[] = {
>> .data = (void *)PORT_ALTR_16550_F128, },
>> { .compatible = "mrvl,mmp-uart",
>> .data = (void *)PORT_XSCALE, },
>> + { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
>> { /* end of list */ },
>> };
>> MODULE_DEVICE_TABLE(of, of_platform_serial_table);
>> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
>> index fe4399b..ea854054 100644
>> --- a/drivers/tty/serial/8250/8250_port.c
>> +++ b/drivers/tty/serial/8250/8250_port.c
>> @@ -273,6 +273,15 @@ static const struct serial8250_config uart_config[] = {
>> .rxtrig_bytes = {1, 4, 8, 14},
>> .flags = UART_CAP_FIFO,
>> },
>> + [PORT_DA830] = {
>> + .name = "TI DA8xx/OMAPL13x/AM17xx/AM18xx",
>> + .fifo_size = 16,
>> + .tx_loadsz = 16,
>> + .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
>> + UART_FCR_R_TRIG_10,
>> + .rxtrig_bytes = {1, 4, 8, 14},
>> + .flags = UART_CAP_FIFO | UART_CAP_AFE,
>> + },
>> };
>
>
> Any reason why the fcr and flags fields are changed when compared
> against PORT_16550A?
The AM1808 TRM says to "always enable" the DMA bit. I figured setting it
now could save someone trouble later if they wanted to add DMA support.
It does not matter if it is set even if you are not using DMA.
Since we are using the special reset register that resets the state
machine, setting UART_FCR_CLEAR_RCVR and UART_FCR_CLEAR_XMIT seems
redundant.
And in my testing with an AM1808, UART_CAP_AFE is not automatically
detected even though the chip has this capability, so it needs to be
manually specified.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V2 1/2] PM / Domains: Introduce domain-performance-states binding
From: Rob Herring @ 2016-12-22 18:34 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, linaro-kernel-cunTk1MwBs8s++Sfvej+rw,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Stephen Boyd, Nishanth Menon,
Vincent Guittot, Mark Rutland, Kevin Hilman, Ulf Hansson,
Lina Iyer, devicetree-u79uwXL29TY76Z2rM5mHXA, Nayak Rajendra
In-Reply-To: <dd95df02a1c3efd00bd4890f8aceeb717ad38788.1481539827.git.viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On Mon, Dec 12, 2016 at 04:26:18PM +0530, Viresh Kumar wrote:
> Some platforms have the capability to configure the performance state of
> their Power Domains. The performance levels are represented by positive
> integer values, a lower value represents lower performance state.
>
> The power-domains until now were only concentrating on the idle state
> management of the device and this needs to change in order to reuse the
> infrastructure of power domains for active state management.
>
> This patch adds binding to describe the performance states of a power
> domain.
>
> If the consumers don't need the capability of switching to different
> domain performance states at runtime, then they can simply define their
> required domain performance state in their node directly. Otherwise the
> consumers can define their requirements with help of other
> infrastructure, for example the OPP table.
>
> Signed-off-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> .../devicetree/bindings/power/power_domain.txt | 69 ++++++++++++++++++++++
> 1 file changed, 69 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt
> index 723e1ad937da..a456e0dc04e0 100644
> --- a/Documentation/devicetree/bindings/power/power_domain.txt
> +++ b/Documentation/devicetree/bindings/power/power_domain.txt
> @@ -38,6 +38,40 @@ phandle arguments (so called PM domain specifiers) of length specified by the
> domain's idle states. In the absence of this property, the domain would be
> considered as capable of being powered-on or powered-off.
>
> +- domain-performance-states : A phandle of the performance states node, which
> + defines all the performance states associated with a power
> + domain.
> + The domain-performance-states property reflects the performance states of this
> + PM domain and not the performance states of the devices or sub-domains in the
> + PM domain. Devices and sub-domains have their own performance states, which
> + are dependent on the performance state of the PM domain.
> +
> +* PM domain performance states node
> +
> +This describes the performance states of a PM domain.
> +
> +Required properties:
> +- compatible: Allow performance states to express their compatibility. It should
> + be: "domain-performance-state".
> +
> +- Performance state nodes: This node shall have one or more "Performance State"
> + nodes.
> +
> +* Performance state node
> +
> +Required properties:
> +- performance-level: A positive integer value representing the performance level
> + associated with a performance state. The integer value '1' represents the
> + lowest performance level and the highest value represents the highest
> + performance level.
> +
> +Optional properties:
> +- domain-microvolt: voltage in micro Volts.
> +
> + A single regulator's voltage is specified with an array of size one or three.
> + Single entry is for target voltage and three entries are for <target min max>
> + voltages.
> +
> Example:
>
> power: power-controller@12340000 {
> @@ -118,4 +152,39 @@ The node above defines a typical PM domain consumer device, which is located
> inside a PM domain with index 0 of a power controller represented by a node
> with the label "power".
>
> +Optional properties:
> +- domain-performance-state: A phandle of a Performance state node.
> +
> +Example:
> +
> + parent: power-controller@12340000 {
> + compatible = "foo,power-controller";
> + reg = <0x12340000 0x1000>;
> + #power-domain-cells = <0>;
> + domain-performance-states = <&domain_perf_states>;
> + };
> +
> + domain_perf_states: performance_states {
If you want to have performance states for a domain in DT, then you need
to actually have a node for the domain in DT. Then this should be a
child of the domain. I wouldn't think non-CPU domain performance states
will be common across domains.
> + compatible = "domain-performance-state";
> + domain_perf_state1: pstate@1 {
A unit address should have a reg property.
> + performance-level = <1>;
> + domain-microvolt = <970000 975000 985000>;
> + };
> + domain_perf_state2: pstate@2 {
> + performance-level = <2>;
> + domain-microvolt = <1000000 1075000 1085000>;
> + };
> + domain_perf_state3: pstate@3 {
> + performance-level = <3>;
> + domain-microvolt = <1100000 1175000 1185000>;
> + };
> + }
> +
> + leaky-device@12350000 {
> + compatible = "foo,i-leak-current";
> + reg = <0x12350000 0x1000>;
> + power-domains = <&power 0>;
> + domain-performance-state = <&domain_perf_state2>;
domain-performance-state and domain-performance-states are too similar
in name. The property here should probably reflect the mode needed and
perhaps specific to the device. I assume a device will need multiple
states/modes.
Also, since you refer to the performance state node directly, I'm not
sure why you need the performance-level property.
Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 2/4] dt-bindings: add bindings for rk3328 clock controller
From: Rob Herring @ 2016-12-22 18:39 UTC (permalink / raw)
To: Elaine Zhang
Cc: heiko, mturquette, sboyd, xf, mark.rutland, linux-clk,
linux-arm-kernel, devicetree, huangtao, xxx, cl, linux-rockchip,
linux-kernel
In-Reply-To: <1482112573-11613-3-git-send-email-zhangqing@rock-chips.com>
On Mon, Dec 19, 2016 at 09:56:11AM +0800, Elaine Zhang wrote:
> Add devicetree bindings for Rockchip cru which found on
> Rockchip SoCs.
>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
> .../bindings/clock/rockchip,rk3328-cru.txt | 57 ++++++++++++++++++++++
> 1 file changed, 57 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
> new file mode 100644
> index 000000000000..20053494d49f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
> @@ -0,0 +1,57 @@
> +* Rockchip RK3328 Clock and Reset Unit
> +
> +The RK3328 clock controller generates and supplies clock to various
> +controllers within the SoC and also implements a reset controller for SoC
> +peripherals.
> +
> +Required Properties:
> +
> +- compatible: should be "rockchip,rk3328-cru"
The example shows other compatibles. IMO, I would drop them rather than
add them here.
> +- reg: physical base address of the controller and length of memory mapped
> + region.
> +- #clock-cells: should be 1.
> +- #reset-cells: should be 1.
> +
> +Optional Properties:
> +
> +- rockchip,grf: phandle to the syscon managing the "general register files"
> + If missing pll rates are not changeable, due to the missing pll lock status.
> +
> +Each clock is assigned an identifier and client nodes can use this identifier
> +to specify the clock which they consume. All available clocks are defined as
> +preprocessor macros in the dt-bindings/clock/rk3328-cru.h headers and can be
> +used in device tree sources. Similar macros exist for the reset sources in
> +these files.
> +
> +External clocks:
> +
> +There are several clocks that are generated outside the SoC. It is expected
> +that they are defined using standard clock bindings with following
> +clock-output-names:
> + - "xin24m" - crystal input - required,
> + - "clkin_i2s" - external I2S clock - optional,
> + - "gmac_clkin" - external GMAC clock - optional
> + - "phy_50m_out" - output clock of the pll in the mac phy
> +
> +Example: Clock controller node:
> +
> + cru: clock-controller@ff440000 {
> + compatible = "rockchip,rk3328-cru", "rockchip,cru", "syscon";
> + reg = <0x0 0xff440000 0x0 0x1000>;
> + rockchip,grf = <&grf>;
> +
> + #clock-cells = <1>;
> + #reset-cells = <1>;
> + };
> +
> +Example: UART controller node that consumes the clock generated by the clock
> + controller:
> +
> + uart0: serial@ff120000 {
> + compatible = "snps,dw-apb-uart";
> + reg = <0xff120000 0x100>;
> + interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
> + reg-shift = <2>;
> + reg-io-width = <4>;
> + clocks = <&cru SCLK_UART0>;
> + };
> --
> 1.9.1
>
>
^ permalink raw reply
* Re: [PATCH v3 2/2] crypto: mediatek - add DT bindings documentation
From: Rob Herring @ 2016-12-22 18:41 UTC (permalink / raw)
To: Ryder Lee
Cc: Herbert Xu, David S. Miller, Matthias Brugger,
devicetree-u79uwXL29TY76Z2rM5mHXA, Sean Wang,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Roy Luo,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1482114045-18716-3-git-send-email-ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
On Mon, Dec 19, 2016 at 10:20:45AM +0800, Ryder Lee wrote:
> Add DT bindings documentation for the crypto driver
>
> Signed-off-by: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> ---
> .../devicetree/bindings/crypto/mediatek-crypto.txt | 27 ++++++++++++++++++++++
> 1 file changed, 27 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/crypto/mediatek-crypto.txt
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
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