* [PATCH 0/7] Add support for triggered buffer mode to STM32 ADC
From: Fabrice Gasnier @ 2017-01-19 13:34 UTC (permalink / raw)
To: jic23, linux, robh+dt, linux-arm-kernel, devicetree, linux-kernel
Cc: linux-iio, mark.rutland, mcoquelin.stm32, alexandre.torgue, lars,
knaack.h, pmeerw, fabrice.gasnier, benjamin.gaignard,
benjamin.gaignard
The following patches add support for triggered buffer mode.
These are based on top of "Add PWM and IIO timer drivers for STM32"
series. Reference:
https://lkml.org/lkml/2017/1/18/588
STM32 ADC, can use either interrupts or DMA to collect data.
Either timer trigger output (TRGO) or PWM can be used as trigger source.
This patchset has been tested on STM32F429 eval board.
- Example to enable timer1 PWM:
cd /sys/devices/platform/soc/40010000.timers/40010000.timers:pwm/pwm/pwmchip4/
echo 0 > export # timer 1 channel 1
echo 1000000 > pwm0/period # 1000Hz
echo 500000 > pwm0/duty_cycle
echo 1 > pwm0/enable
- Example to enable timer3 TRGO:
cd /sys/bus/iio/devices/
cat trigger6/name
tim1_ch1
cat trigger0/name
tim3_trgo
echo 1000 > trigger0/sampling_frequency
- Example to configure STM32ADC in triggered buffer mode, with timer1 PWM
or timer3 TRGO:
cd /sys/bus/iio/devices/iio\:device0
echo tim1_ch1 > trigger/current_trigger
OR: echo tim3_trgo > trigger/current_trigger
echo 1 > scan_elements/in_voltage8_en
echo 1 > buffer/enable
Fabrice Gasnier (7):
iio: adc: stm32: add support for triggered buffer mode
iio: adc: stm32: Enable use of stm32 timer triggers
iio: adc: stm32: add trigger polarity extended attribute
Documentation: dt: iio: stm32-adc: optional dma support
iio: adc: stm32: add optional dma support
ARM: dts: stm32: Enable dma by default on stm32f4 adc
ARM: dts: stm32: Enable pwm1 and pwm3 for stm32f469-eval
.../devicetree/bindings/iio/adc/st,stm32-adc.txt | 7 +
arch/arm/boot/dts/stm32429i-eval.dts | 28 +
arch/arm/boot/dts/stm32f429.dtsi | 6 +
drivers/iio/adc/Kconfig | 6 +
drivers/iio/adc/stm32-adc-core.c | 1 +
drivers/iio/adc/stm32-adc-core.h | 2 +
drivers/iio/adc/stm32-adc.c | 643 ++++++++++++++++++++-
7 files changed, 690 insertions(+), 3 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH 1/7] iio: adc: stm32: add support for triggered buffer mode
From: Fabrice Gasnier @ 2017-01-19 13:34 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w,
alexandre.torgue-qxv4g6HH51o, lars-Qo5EllUWu/uELgA04lAiVw,
knaack.h-Mmb7MZpHnFY, pmeerw-jW+XmwGofnusTnJN9+BGXg,
fabrice.gasnier-qxv4g6HH51o,
benjamin.gaignard-QSEj5FYQhm4dnm+yROfE0A,
benjamin.gaignard-qxv4g6HH51o
In-Reply-To: <1484832854-6314-1-git-send-email-fabrice.gasnier-qxv4g6HH51o@public.gmane.org>
STM32 ADC conversions can be launched using hardware triggers.
It can be used to start conversion sequences (group of channels).
Selected channels are select via sequence registers.
Trigger source is selected via 'extsel' (external trigger mux).
Trigger polarity is set to rising edge by default.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier-qxv4g6HH51o@public.gmane.org>
---
drivers/iio/adc/Kconfig | 2 +
drivers/iio/adc/stm32-adc.c | 349 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 348 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 9c8b558..33341f4 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -446,6 +446,8 @@ config STM32_ADC_CORE
depends on ARCH_STM32 || COMPILE_TEST
depends on OF
depends on REGULATOR
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
Select this option to enable the core driver for STMicroelectronics
STM32 analog-to-digital converter (ADC).
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 5715e79..8d0b74b 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -22,11 +22,16 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
+#include <linux/slab.h>
#include "stm32-adc-core.h"
@@ -58,21 +63,66 @@
/* STM32F4_ADC_CR2 - bit fields */
#define STM32F4_SWSTART BIT(30)
+#define STM32F4_EXTEN_SHIFT 28
#define STM32F4_EXTEN_MASK GENMASK(29, 28)
+#define STM32F4_EXTSEL_SHIFT 24
+#define STM32F4_EXTSEL_MASK GENMASK(27, 24)
#define STM32F4_EOCS BIT(10)
#define STM32F4_ADON BIT(0)
/* STM32F4_ADC_SQR1 - bit fields */
#define STM32F4_L_SHIFT 20
#define STM32F4_L_MASK GENMASK(23, 20)
+#define STM32F4_SQ16_SHIFT 15
+#define STM32F4_SQ16_MASK GENMASK(19, 15)
+#define STM32F4_SQ15_SHIFT 10
+#define STM32F4_SQ15_MASK GENMASK(14, 10)
+#define STM32F4_SQ14_SHIFT 5
+#define STM32F4_SQ14_MASK GENMASK(9, 5)
+#define STM32F4_SQ13_SHIFT 0
+#define STM32F4_SQ13_MASK GENMASK(4, 0)
+
+/* STM32F4_ADC_SQR2 - bit fields */
+#define STM32F4_SQ12_SHIFT 25
+#define STM32F4_SQ12_MASK GENMASK(29, 25)
+#define STM32F4_SQ11_SHIFT 20
+#define STM32F4_SQ11_MASK GENMASK(24, 20)
+#define STM32F4_SQ10_SHIFT 15
+#define STM32F4_SQ10_MASK GENMASK(19, 15)
+#define STM32F4_SQ9_SHIFT 10
+#define STM32F4_SQ9_MASK GENMASK(14, 10)
+#define STM32F4_SQ8_SHIFT 5
+#define STM32F4_SQ8_MASK GENMASK(9, 5)
+#define STM32F4_SQ7_SHIFT 0
+#define STM32F4_SQ7_MASK GENMASK(4, 0)
/* STM32F4_ADC_SQR3 - bit fields */
+#define STM32F4_SQ6_SHIFT 25
+#define STM32F4_SQ6_MASK GENMASK(29, 25)
+#define STM32F4_SQ5_SHIFT 20
+#define STM32F4_SQ5_MASK GENMASK(24, 20)
+#define STM32F4_SQ4_SHIFT 15
+#define STM32F4_SQ4_MASK GENMASK(19, 15)
+#define STM32F4_SQ3_SHIFT 10
+#define STM32F4_SQ3_MASK GENMASK(14, 10)
+#define STM32F4_SQ2_SHIFT 5
+#define STM32F4_SQ2_MASK GENMASK(9, 5)
#define STM32F4_SQ1_SHIFT 0
#define STM32F4_SQ1_MASK GENMASK(4, 0)
+#define STM32_ADC_MAX_SQ 16 /* SQ1..SQ16 */
#define STM32_ADC_TIMEOUT_US 100000
#define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
+/* External trigger enable */
+enum stm32_adc_exten {
+ STM32_EXTEN_SWTRIG,
+ STM32_EXTEN_HWTRIG_RISING_EDGE,
+ STM32_EXTEN_HWTRIG_FALLING_EDGE,
+ STM32_EXTEN_HWTRIG_BOTH_EDGES,
+};
+
+
/**
* struct stm32_adc - private data of each ADC IIO instance
* @common: reference to ADC block common data
@@ -82,6 +132,8 @@
* @clk: clock for this adc instance
* @irq: interrupt for this adc instance
* @lock: spinlock
+ * @bufi: data buffer index
+ * @num_conv: expected number of scan conversions
*/
struct stm32_adc {
struct stm32_adc_common *common;
@@ -91,6 +143,8 @@ struct stm32_adc {
struct clk *clk;
int irq;
spinlock_t lock; /* interrupt lock */
+ int bufi;
+ int num_conv;
};
/**
@@ -105,6 +159,18 @@ struct stm32_adc_chan_spec {
const char *name;
};
+/**
+ * stm32_adc_regs - stm32 ADC misc registers & bitfield desc
+ * @reg: register offset
+ * @mask: bitfield mask
+ * @shift: left shift
+ */
+struct stm32_adc_regs {
+ int reg;
+ int mask;
+ int shift;
+};
+
/* Input definitions common for all STM32F4 instances */
static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = {
{ IIO_VOLTAGE, 0, "in0" },
@@ -126,6 +192,33 @@ struct stm32_adc_chan_spec {
};
/**
+ * stm32f4_sqr_regs - describe regular sequence registers
+ * - L: sequence len (register & bit field)
+ * - SQ1..SQ16: sequence entries (register & bit field)
+ */
+static const struct stm32_adc_regs stm32f4_sqr_regs[STM32_ADC_MAX_SQ + 1] = {
+ /* L: len bit field description to be kept as first element */
+ { STM32F4_ADC_SQR1, STM32F4_L_MASK, STM32F4_L_SHIFT },
+ /* SQ1..SQ16 registers & bit fields */
+ { STM32F4_ADC_SQR3, STM32F4_SQ1_MASK, STM32F4_SQ1_SHIFT },
+ { STM32F4_ADC_SQR3, STM32F4_SQ2_MASK, STM32F4_SQ2_SHIFT },
+ { STM32F4_ADC_SQR3, STM32F4_SQ3_MASK, STM32F4_SQ3_SHIFT },
+ { STM32F4_ADC_SQR3, STM32F4_SQ4_MASK, STM32F4_SQ4_SHIFT },
+ { STM32F4_ADC_SQR3, STM32F4_SQ5_MASK, STM32F4_SQ5_SHIFT },
+ { STM32F4_ADC_SQR3, STM32F4_SQ6_MASK, STM32F4_SQ6_SHIFT },
+ { STM32F4_ADC_SQR2, STM32F4_SQ7_MASK, STM32F4_SQ7_SHIFT },
+ { STM32F4_ADC_SQR2, STM32F4_SQ8_MASK, STM32F4_SQ8_SHIFT },
+ { STM32F4_ADC_SQR2, STM32F4_SQ9_MASK, STM32F4_SQ9_SHIFT },
+ { STM32F4_ADC_SQR2, STM32F4_SQ10_MASK, STM32F4_SQ10_SHIFT },
+ { STM32F4_ADC_SQR2, STM32F4_SQ11_MASK, STM32F4_SQ11_SHIFT },
+ { STM32F4_ADC_SQR2, STM32F4_SQ12_MASK, STM32F4_SQ12_SHIFT },
+ { STM32F4_ADC_SQR1, STM32F4_SQ13_MASK, STM32F4_SQ13_SHIFT },
+ { STM32F4_ADC_SQR1, STM32F4_SQ14_MASK, STM32F4_SQ14_SHIFT },
+ { STM32F4_ADC_SQR1, STM32F4_SQ15_MASK, STM32F4_SQ15_SHIFT },
+ { STM32F4_ADC_SQR1, STM32F4_SQ16_MASK, STM32F4_SQ16_SHIFT },
+};
+
+/**
* STM32 ADC registers access routines
* @adc: stm32 adc instance
* @reg: reg offset in adc instance
@@ -211,6 +304,106 @@ static void stm32_adc_stop_conv(struct stm32_adc *adc)
}
/**
+ * stm32_adc_conf_scan_seq() - Build regular channels scan sequence
+ * @indio_dev: IIO device
+ * @scan_mask: channels to be converted
+ *
+ * Conversion sequence :
+ * Configure ADC scan sequence based on selected channels in scan_mask.
+ * Add channels to SQR registers, from scan_mask LSB to MSB, then
+ * program sequence len.
+ */
+static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ const struct iio_chan_spec *chan;
+ u32 val, bit;
+ int i = 0;
+
+ for_each_set_bit(bit, scan_mask, indio_dev->masklength) {
+ chan = indio_dev->channels + bit;
+ /*
+ * Assign one channel per SQ entry in regular
+ * sequence, starting with SQ1.
+ */
+ i++;
+ if (i > STM32_ADC_MAX_SQ)
+ return -EINVAL;
+
+ dev_dbg(&indio_dev->dev, "%s chan %d to SQ%d\n",
+ __func__, chan->channel, i);
+
+ val = stm32_adc_readl(adc, stm32f4_sqr_regs[i].reg);
+ val &= ~stm32f4_sqr_regs[i].mask;
+ val |= chan->channel << stm32f4_sqr_regs[i].shift;
+ stm32_adc_writel(adc, stm32f4_sqr_regs[i].reg, val);
+ }
+
+ if (!i)
+ return -EINVAL;
+
+ /* Sequence len */
+ val = stm32_adc_readl(adc, stm32f4_sqr_regs[0].reg);
+ val &= ~stm32f4_sqr_regs[0].mask;
+ val |= ((i - 1) << stm32f4_sqr_regs[0].shift);
+ stm32_adc_writel(adc, stm32f4_sqr_regs[0].reg, val);
+
+ return 0;
+}
+
+/**
+ * stm32_adc_get_trig_extsel() - Get external trigger selection
+ * @indio_dev: IIO device
+ * @trig: trigger
+ *
+ * Returns trigger extsel value, if trig matches, -EINVAL otherwise.
+ */
+static int stm32_adc_get_trig_extsel(struct iio_dev *indio_dev,
+ struct iio_trigger *trig)
+{
+ return -EINVAL;
+}
+
+/**
+ * stm32_adc_set_trig() - Set a regular trigger
+ * @indio_dev: IIO device
+ * @trig: IIO trigger
+ *
+ * Set trigger source/polarity (e.g. SW, or HW with polarity) :
+ * - if HW trigger disabled (e.g. trig == NULL, conversion launched by sw)
+ * - if HW trigger enabled, set source & polarity
+ */
+static int stm32_adc_set_trig(struct iio_dev *indio_dev,
+ struct iio_trigger *trig)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ u32 val, extsel = 0, exten = STM32_EXTEN_SWTRIG;
+ unsigned long flags;
+ int ret;
+
+ if (trig) {
+ ret = stm32_adc_get_trig_extsel(indio_dev, trig);
+ if (ret < 0)
+ return ret;
+
+ /* set trigger source, default to rising edge */
+ extsel = ret;
+ exten = STM32_EXTEN_HWTRIG_RISING_EDGE;
+ }
+
+ spin_lock_irqsave(&adc->lock, flags);
+ val = stm32_adc_readl(adc, STM32F4_ADC_CR2);
+ val &= ~(STM32F4_EXTEN_MASK | STM32F4_EXTSEL_MASK);
+ val |= exten << STM32F4_EXTEN_SHIFT;
+ val |= extsel << STM32F4_EXTSEL_SHIFT;
+ stm32_adc_writel(adc, STM32F4_ADC_CR2, val);
+ spin_unlock_irqrestore(&adc->lock, flags);
+
+ return 0;
+}
+
+/**
* stm32_adc_single_conv() - Performs a single conversion
* @indio_dev: IIO device
* @chan: IIO channel
@@ -234,6 +427,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
reinit_completion(&adc->completion);
adc->buffer = &result;
+ adc->bufi = 0;
/* Program chan number in regular sequence */
val = stm32_adc_readl(adc, STM32F4_ADC_SQR3);
@@ -301,17 +495,58 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
static irqreturn_t stm32_adc_isr(int irq, void *data)
{
struct stm32_adc *adc = data;
+ struct iio_dev *indio_dev = iio_priv_to_dev(adc);
u32 status = stm32_adc_readl(adc, STM32F4_ADC_SR);
if (status & STM32F4_EOC) {
- *adc->buffer = stm32_adc_readw(adc, STM32F4_ADC_DR);
- complete(&adc->completion);
+ adc->buffer[adc->bufi] = stm32_adc_readw(adc, STM32F4_ADC_DR);
+ if (iio_buffer_enabled(indio_dev)) {
+ adc->bufi++;
+ if (adc->bufi >= adc->num_conv) {
+ stm32_adc_conv_irq_disable(adc);
+ iio_trigger_poll(indio_dev->trig);
+ }
+ } else {
+ complete(&adc->completion);
+ }
return IRQ_HANDLED;
}
return IRQ_NONE;
}
+/**
+ * stm32_adc_validate_trigger() - validate trigger for stm32 adc
+ * @indio_dev: IIO device
+ * @trig: new trigger
+ *
+ * Returns: 0 if trig matches one of the triggers registered by stm32 adc
+ * driver, -EINVAL otherwise.
+ */
+static int stm32_adc_validate_trigger(struct iio_dev *indio_dev,
+ struct iio_trigger *trig)
+{
+ return stm32_adc_get_trig_extsel(indio_dev, trig) < 0 ? -EINVAL : 0;
+}
+
+static int stm32_adc_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ int ret;
+ u32 bit;
+
+ adc->num_conv = 0;
+ for_each_set_bit(bit, scan_mask, indio_dev->masklength)
+ adc->num_conv++;
+
+ ret = stm32_adc_conf_scan_seq(indio_dev, scan_mask);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int stm32_adc_of_xlate(struct iio_dev *indio_dev,
const struct of_phandle_args *iiospec)
{
@@ -350,11 +585,106 @@ static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
static const struct iio_info stm32_adc_iio_info = {
.read_raw = stm32_adc_read_raw,
+ .validate_trigger = stm32_adc_validate_trigger,
+ .update_scan_mode = stm32_adc_update_scan_mode,
.debugfs_reg_access = stm32_adc_debugfs_reg_access,
.of_xlate = stm32_adc_of_xlate,
.driver_module = THIS_MODULE,
};
+static int stm32_adc_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+
+ /* Reset adc buffer index */
+ adc->bufi = 0;
+
+ /* Allocate adc buffer */
+ adc->buffer = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
+ if (!adc->buffer)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ int ret;
+
+ ret = stm32_adc_set_trig(indio_dev, indio_dev->trig);
+ if (ret) {
+ dev_err(&indio_dev->dev, "Can't set trigger\n");
+ return ret;
+ }
+
+ ret = iio_triggered_buffer_postenable(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ stm32_adc_conv_irq_enable(adc);
+ stm32_adc_start_conv(adc);
+
+ return 0;
+}
+
+static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ int ret;
+
+ stm32_adc_stop_conv(adc);
+ stm32_adc_conv_irq_disable(adc);
+
+ ret = iio_triggered_buffer_predisable(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ ret = stm32_adc_set_trig(indio_dev, NULL);
+ if (ret)
+ dev_err(&indio_dev->dev, "Can't clear trigger\n");
+
+ return ret;
+}
+
+static int stm32_adc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+
+ kfree(adc->buffer);
+ adc->buffer = NULL;
+
+ return 0;
+}
+
+static const struct iio_buffer_setup_ops stm32_adc_buffer_setup_ops = {
+ .preenable = &stm32_adc_buffer_preenable,
+ .postenable = &stm32_adc_buffer_postenable,
+ .predisable = &stm32_adc_buffer_predisable,
+ .postdisable = &stm32_adc_buffer_postdisable,
+};
+
+static irqreturn_t stm32_adc_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct stm32_adc *adc = iio_priv(indio_dev);
+
+ dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
+
+ /* reset buffer index */
+ adc->bufi = 0;
+ iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer,
+ pf->timestamp);
+
+ iio_trigger_notify_done(indio_dev->trig);
+
+ /* re-enable eoc irq */
+ stm32_adc_conv_irq_enable(adc);
+
+ return IRQ_HANDLED;
+}
+
static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
struct iio_chan_spec *chan,
const struct stm32_adc_chan_spec *channel,
@@ -471,14 +801,26 @@ static int stm32_adc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_clk_disable;
+ ret = iio_triggered_buffer_setup(indio_dev,
+ &iio_pollfunc_store_time,
+ &stm32_adc_trigger_handler,
+ &stm32_adc_buffer_setup_ops);
+ if (ret) {
+ dev_err(&pdev->dev, "buffer setup failed\n");
+ goto err_clk_disable;
+ }
+
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&pdev->dev, "iio dev register failed\n");
- goto err_clk_disable;
+ goto err_buffer_cleanup;
}
return 0;
+err_buffer_cleanup:
+ iio_triggered_buffer_cleanup(indio_dev);
+
err_clk_disable:
clk_disable_unprepare(adc->clk);
@@ -491,6 +833,7 @@ static int stm32_adc_remove(struct platform_device *pdev)
struct iio_dev *indio_dev = iio_priv_to_dev(adc);
iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
clk_disable_unprepare(adc->clk);
return 0;
--
1.9.1
^ permalink raw reply related
* [PATCH 2/7] iio: adc: stm32: Enable use of stm32 timer triggers
From: Fabrice Gasnier @ 2017-01-19 13:34 UTC (permalink / raw)
To: jic23, linux, robh+dt, linux-arm-kernel, devicetree, linux-kernel
Cc: linux-iio, mark.rutland, mcoquelin.stm32, alexandre.torgue, lars,
knaack.h, pmeerw, fabrice.gasnier, benjamin.gaignard,
benjamin.gaignard
In-Reply-To: <1484832854-6314-1-git-send-email-fabrice.gasnier@st.com>
STM32 ADC has external timer trigger sources. Use stm32 timer triggers
API (e.g. is_stm32_timer_trigger()) with local ADC lookup table to
validate a trigger can be used.
This also provides correct trigger selection value (e.g. extsel).
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
drivers/iio/adc/Kconfig | 2 ++
drivers/iio/adc/stm32-adc.c | 60 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 33341f4..9a7b090 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -447,6 +447,8 @@ config STM32_ADC_CORE
depends on OF
depends on REGULATOR
select IIO_BUFFER
+ select MFD_STM32_TIMERS
+ select IIO_STM32_TIMER_TRIGGER
select IIO_TRIGGERED_BUFFER
help
Select this option to enable the core driver for STMicroelectronics
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 8d0b74b..30708bc 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/timer/stm32-timer-trigger.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
@@ -122,6 +123,35 @@ enum stm32_adc_exten {
STM32_EXTEN_HWTRIG_BOTH_EDGES,
};
+/* extsel - trigger mux selection value */
+enum stm32_adc_extsel {
+ STM32_EXT0,
+ STM32_EXT1,
+ STM32_EXT2,
+ STM32_EXT3,
+ STM32_EXT4,
+ STM32_EXT5,
+ STM32_EXT6,
+ STM32_EXT7,
+ STM32_EXT8,
+ STM32_EXT9,
+ STM32_EXT10,
+ STM32_EXT11,
+ STM32_EXT12,
+ STM32_EXT13,
+ STM32_EXT14,
+ STM32_EXT15,
+};
+
+/**
+ * struct stm32_adc_trig_info - ADC trigger info
+ * @name: name of the trigger, corresponding to its source
+ * @extsel: trigger selection
+ */
+struct stm32_adc_trig_info {
+ const char *name;
+ enum stm32_adc_extsel extsel;
+};
/**
* struct stm32_adc - private data of each ADC IIO instance
@@ -218,6 +248,26 @@ struct stm32_adc_regs {
{ STM32F4_ADC_SQR1, STM32F4_SQ16_MASK, STM32F4_SQ16_SHIFT },
};
+/* STM32F4 external trigger sources for all instances */
+static struct stm32_adc_trig_info stm32f4_adc_timer_trigs[] = {
+ { TIM1_CH1, STM32_EXT0 },
+ { TIM1_CH2, STM32_EXT1 },
+ { TIM1_CH3, STM32_EXT2 },
+ { TIM2_CH2, STM32_EXT3 },
+ { TIM2_CH3, STM32_EXT4 },
+ { TIM2_CH4, STM32_EXT5 },
+ { TIM2_TRGO, STM32_EXT6 },
+ { TIM3_CH1, STM32_EXT7 },
+ { TIM3_TRGO, STM32_EXT8 },
+ { TIM4_CH4, STM32_EXT9 },
+ { TIM5_CH1, STM32_EXT10 },
+ { TIM5_CH2, STM32_EXT11 },
+ { TIM5_CH3, STM32_EXT12 },
+ { TIM8_CH1, STM32_EXT13 },
+ { TIM8_TRGO, STM32_EXT14 },
+ {}, /* sentinel */
+};
+
/**
* STM32 ADC registers access routines
* @adc: stm32 adc instance
@@ -362,6 +412,16 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
static int stm32_adc_get_trig_extsel(struct iio_dev *indio_dev,
struct iio_trigger *trig)
{
+ int i;
+
+ /* lookup triggers registered by stm32 timer trigger driver */
+ for (i = 0; stm32f4_adc_timer_trigs[i].name; i++) {
+ if (is_stm32_timer_trigger(trig) &&
+ !strcmp(stm32f4_adc_timer_trigs[i].name, trig->name)) {
+ return stm32f4_adc_timer_trigs[i].extsel;
+ }
+ }
+
return -EINVAL;
}
--
1.9.1
^ permalink raw reply related
* [PATCH 3/7] iio: adc: stm32: add trigger polarity extended attribute
From: Fabrice Gasnier @ 2017-01-19 13:34 UTC (permalink / raw)
To: jic23, linux, robh+dt, linux-arm-kernel, devicetree, linux-kernel
Cc: mark.rutland, benjamin.gaignard, lars, alexandre.torgue,
linux-iio, pmeerw, mcoquelin.stm32, knaack.h, fabrice.gasnier,
benjamin.gaignard
In-Reply-To: <1484832854-6314-1-git-send-email-fabrice.gasnier@st.com>
Define extended attribute so that user may choose rising, falling or both
edges for external trigger sources.
Default to rising edge in case it isn't set.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
drivers/iio/adc/stm32-adc.c | 51 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 30708bc..9753c39 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -164,6 +164,7 @@ struct stm32_adc_trig_info {
* @lock: spinlock
* @bufi: data buffer index
* @num_conv: expected number of scan conversions
+ * @exten: external trigger config (enable/polarity)
*/
struct stm32_adc {
struct stm32_adc_common *common;
@@ -175,6 +176,7 @@ struct stm32_adc {
spinlock_t lock; /* interrupt lock */
int bufi;
int num_conv;
+ enum stm32_adc_exten exten;
};
/**
@@ -449,7 +451,9 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev,
/* set trigger source, default to rising edge */
extsel = ret;
- exten = STM32_EXTEN_HWTRIG_RISING_EDGE;
+ if (adc->exten == STM32_EXTEN_SWTRIG)
+ adc->exten = STM32_EXTEN_HWTRIG_RISING_EDGE;
+ exten = adc->exten;
}
spin_lock_irqsave(&adc->lock, flags);
@@ -463,6 +467,39 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev,
return 0;
}
+static int stm32_adc_set_trig_pol(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ unsigned int type)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+
+ adc->exten = type;
+
+ return 0;
+}
+
+static int stm32_adc_get_trig_pol(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+
+ return adc->exten;
+}
+
+static const char * const stm32_trig_pol_items[] = {
+ [STM32_EXTEN_SWTRIG] = "swtrig",
+ [STM32_EXTEN_HWTRIG_RISING_EDGE] = "rising-edge",
+ [STM32_EXTEN_HWTRIG_FALLING_EDGE] = "falling-edge",
+ [STM32_EXTEN_HWTRIG_BOTH_EDGES] = "both-edges",
+};
+
+const struct iio_enum stm32_adc_trig_pol = {
+ .items = stm32_trig_pol_items,
+ .num_items = ARRAY_SIZE(stm32_trig_pol_items),
+ .get = stm32_adc_get_trig_pol,
+ .set = stm32_adc_set_trig_pol,
+};
+
/**
* stm32_adc_single_conv() - Performs a single conversion
* @indio_dev: IIO device
@@ -745,6 +782,17 @@ static irqreturn_t stm32_adc_trigger_handler(int irq, void *p)
return IRQ_HANDLED;
}
+static const struct iio_chan_spec_ext_info stm32_adc_ext_info[] = {
+ IIO_ENUM("trigger_pol", IIO_SHARED_BY_ALL, &stm32_adc_trig_pol),
+ {
+ .name = "trigger_pol_available",
+ .shared = IIO_SHARED_BY_ALL,
+ .read = iio_enum_available_read,
+ .private = (uintptr_t)&stm32_adc_trig_pol,
+ },
+ {},
+};
+
static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
struct iio_chan_spec *chan,
const struct stm32_adc_chan_spec *channel,
@@ -760,6 +808,7 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
chan->scan_type.sign = 'u';
chan->scan_type.realbits = 12;
chan->scan_type.storagebits = 16;
+ chan->ext_info = stm32_adc_ext_info;
}
static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
--
1.9.1
^ permalink raw reply related
* [PATCH 4/7] Documentation: dt: iio: stm32-adc: optional dma support
From: Fabrice Gasnier @ 2017-01-19 13:34 UTC (permalink / raw)
To: jic23, linux, robh+dt, linux-arm-kernel, devicetree, linux-kernel
Cc: linux-iio, mark.rutland, mcoquelin.stm32, alexandre.torgue, lars,
knaack.h, pmeerw, fabrice.gasnier, benjamin.gaignard,
benjamin.gaignard
In-Reply-To: <1484832854-6314-1-git-send-email-fabrice.gasnier@st.com>
STM32 ADC can use dma. Add dt documentation for optional dma support.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
index 49ed82e..5dfc88e 100644
--- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
@@ -53,6 +53,11 @@ Required properties:
- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
Documentation/devicetree/bindings/iio/iio-bindings.txt
+Optional properties:
+- dmas: Phandle to dma channel for this ADC instance.
+ See ../../dma/dma.txt for details.
+- dma-names: Must be "rx" when dmas property is being used.
+
Example:
adc: adc@40012000 {
compatible = "st,stm32f4-adc-core";
@@ -77,6 +82,8 @@ Example:
interrupt-parent = <&adc>;
interrupts = <0>;
st,adc-channels = <8>;
+ dmas = <&dma2 0 0 0x400 0x0>;
+ dma-names = "rx";
};
...
other adc child nodes follow...
--
1.9.1
^ permalink raw reply related
* [PATCH 5/7] iio: adc: stm32: add optional dma support
From: Fabrice Gasnier @ 2017-01-19 13:34 UTC (permalink / raw)
To: jic23, linux, robh+dt, linux-arm-kernel, devicetree, linux-kernel
Cc: mark.rutland, benjamin.gaignard, lars, alexandre.torgue,
linux-iio, pmeerw, mcoquelin.stm32, knaack.h, fabrice.gasnier,
benjamin.gaignard
In-Reply-To: <1484832854-6314-1-git-send-email-fabrice.gasnier@st.com>
Add optional DMA support to STM32 ADC.
Use dma cyclic mode with at least two periods.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
drivers/iio/adc/Kconfig | 2 +
drivers/iio/adc/stm32-adc-core.c | 1 +
drivers/iio/adc/stm32-adc-core.h | 2 +
drivers/iio/adc/stm32-adc.c | 209 ++++++++++++++++++++++++++++++++++++---
4 files changed, 202 insertions(+), 12 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 9a7b090..2a2ef78 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -444,12 +444,14 @@ config ROCKCHIP_SARADC
config STM32_ADC_CORE
tristate "STMicroelectronics STM32 adc core"
depends on ARCH_STM32 || COMPILE_TEST
+ depends on HAS_DMA
depends on OF
depends on REGULATOR
select IIO_BUFFER
select MFD_STM32_TIMERS
select IIO_STM32_TIMER_TRIGGER
select IIO_TRIGGERED_BUFFER
+ select IRQ_WORK
help
Select this option to enable the core driver for STMicroelectronics
STM32 analog-to-digital converter (ADC).
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index 4214b0c..22b7c93 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -201,6 +201,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
priv->common.base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->common.base))
return PTR_ERR(priv->common.base);
+ priv->common.phys_base = res->start;
priv->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(priv->vref)) {
diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
index 081fa5f..2ec7abb 100644
--- a/drivers/iio/adc/stm32-adc-core.h
+++ b/drivers/iio/adc/stm32-adc-core.h
@@ -42,10 +42,12 @@
/**
* struct stm32_adc_common - stm32 ADC driver common data (for all instances)
* @base: control registers base cpu addr
+ * @phys_base: control registers base physical addr
* @vref_mv: vref voltage (mv)
*/
struct stm32_adc_common {
void __iomem *base;
+ phys_addr_t phys_base;
int vref_mv;
};
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 9753c39..3439f4c 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -21,6 +21,8 @@
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/timer/stm32-timer-trigger.h>
@@ -29,6 +31,7 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/irq_work.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
@@ -69,6 +72,8 @@
#define STM32F4_EXTSEL_SHIFT 24
#define STM32F4_EXTSEL_MASK GENMASK(27, 24)
#define STM32F4_EOCS BIT(10)
+#define STM32F4_DDS BIT(9)
+#define STM32F4_DMA BIT(8)
#define STM32F4_ADON BIT(0)
/* STM32F4_ADC_SQR1 - bit fields */
@@ -165,6 +170,11 @@ struct stm32_adc_trig_info {
* @bufi: data buffer index
* @num_conv: expected number of scan conversions
* @exten: external trigger config (enable/polarity)
+ * @work: irq work used to call trigger poll routine
+ * @dma_chan: dma channel
+ * @rx_buf: dma rx buffer cpu address
+ * @rx_dma_buf: dma rx buffer bus address
+ * @rx_buf_sz: dma rx buffer size
*/
struct stm32_adc {
struct stm32_adc_common *common;
@@ -177,6 +187,11 @@ struct stm32_adc {
int bufi;
int num_conv;
enum stm32_adc_exten exten;
+ struct irq_work work;
+ struct dma_chan *dma_chan;
+ u8 *rx_buf;
+ dma_addr_t rx_dma_buf;
+ int rx_buf_sz;
};
/**
@@ -332,10 +347,20 @@ static void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
/**
* stm32_adc_start_conv() - Start conversions for regular channels.
* @adc: stm32 adc instance
+ *
+ * Start conversions for regular channels.
+ * Also take care of normal or DMA mode. DMA is used in circular mode for
+ * regular conversions, in IIO buffer modes. Rely on rx_buf as raw
+ * read doesn't use dma, but direct DR read.
*/
static void stm32_adc_start_conv(struct stm32_adc *adc)
{
stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
+
+ if (adc->rx_buf)
+ stm32_adc_set_bits(adc, STM32F4_ADC_CR2,
+ STM32F4_DMA | STM32F4_DDS);
+
stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_EOCS | STM32F4_ADON);
/* Wait for Power-up time (tSTAB from datasheet) */
@@ -353,6 +378,10 @@ static void stm32_adc_stop_conv(struct stm32_adc *adc)
stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_ADON);
+
+ if (adc->rx_buf)
+ stm32_adc_clr_bits(adc, STM32F4_ADC_CR2,
+ STM32F4_DMA | STM32F4_DDS);
}
/**
@@ -689,19 +718,138 @@ static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
.driver_module = THIS_MODULE,
};
+static int stm32_adc_dma_residue(struct stm32_adc *adc)
+{
+ struct dma_tx_state state;
+ enum dma_status status;
+
+ if (!adc->rx_buf)
+ return 0;
+
+ status = dmaengine_tx_status(adc->dma_chan,
+ adc->dma_chan->cookie,
+ &state);
+ if (status == DMA_IN_PROGRESS) {
+ /* Residue is size in bytes from end of buffer */
+ int i = adc->rx_buf_sz - state.residue;
+ int size;
+
+ /* Return available bytes */
+ if (i >= adc->bufi)
+ size = i - adc->bufi;
+ else
+ size = adc->rx_buf_sz - adc->bufi + i;
+
+ return size;
+ }
+
+ return 0;
+}
+
+static void stm32_adc_dma_irq_work(struct irq_work *work)
+{
+ struct stm32_adc *adc = container_of(work, struct stm32_adc, work);
+ struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+
+ /**
+ * iio_trigger_poll calls generic_handle_irq(). So, it requires hard
+ * irq context, and cannot be called directly from dma callback,
+ * dma cb has to schedule this work instead.
+ */
+ iio_trigger_poll(indio_dev->trig);
+}
+
+static void stm32_adc_dma_buffer_done(void *data)
+{
+ struct stm32_adc *adc = data;
+
+ /* invoques iio_trigger_poll() from hard irq context */
+ irq_work_queue(&adc->work);
+}
+
static int stm32_adc_buffer_preenable(struct iio_dev *indio_dev)
{
struct stm32_adc *adc = iio_priv(indio_dev);
+ struct dma_async_tx_descriptor *desc;
+ struct dma_slave_config config;
+ dma_cookie_t cookie;
+ int ret, size, watermark;
/* Reset adc buffer index */
adc->bufi = 0;
- /* Allocate adc buffer */
- adc->buffer = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
- if (!adc->buffer)
+ if (!adc->dma_chan) {
+ /* Allocate adc buffer */
+ adc->buffer = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
+ if (!adc->buffer)
+ return -ENOMEM;
+
+ return 0;
+ }
+
+ /*
+ * Allocate at least twice the buffer size for dma cyclic transfers, so
+ * we can work with at least two dma periods. There should be :
+ * - always one buffer (period) dma is working on
+ * - one buffer (period) driver can push with iio_trigger_poll().
+ */
+ size = indio_dev->buffer->bytes_per_datum * indio_dev->buffer->length;
+ size = max(indio_dev->scan_bytes * 2, size);
+
+ adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev,
+ PAGE_ALIGN(size), &adc->rx_dma_buf,
+ GFP_KERNEL);
+ if (!adc->rx_buf)
return -ENOMEM;
+ adc->rx_buf_sz = size;
+ watermark = indio_dev->buffer->bytes_per_datum
+ * indio_dev->buffer->watermark;
+ watermark = max(indio_dev->scan_bytes, watermark);
+ watermark = rounddown(watermark, indio_dev->scan_bytes);
+
+ dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__, size,
+ watermark);
+
+ /* Configure DMA channel to read data register */
+ memset(&config, 0, sizeof(config));
+ config.src_addr = (dma_addr_t)adc->common->phys_base;
+ config.src_addr += adc->offset + STM32F4_ADC_DR;
+ config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+ ret = dmaengine_slave_config(adc->dma_chan, &config);
+ if (ret)
+ goto config_err;
+
+ /* Prepare a DMA cyclic transaction */
+ desc = dmaengine_prep_dma_cyclic(adc->dma_chan,
+ adc->rx_dma_buf,
+ size, watermark,
+ DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT);
+ if (!desc) {
+ ret = -ENODEV;
+ goto config_err;
+ }
+
+ desc->callback = stm32_adc_dma_buffer_done;
+ desc->callback_param = adc;
+
+ cookie = dmaengine_submit(desc);
+ if (dma_submit_error(cookie)) {
+ ret = dma_submit_error(cookie);
+ goto config_err;
+ }
+
+ /* Issue pending DMA requests */
+ dma_async_issue_pending(adc->dma_chan);
return 0;
+
+config_err:
+ dma_free_coherent(adc->dma_chan->device->dev, PAGE_ALIGN(size),
+ adc->rx_buf, adc->rx_dma_buf);
+
+ return ret;
}
static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
@@ -719,7 +867,8 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
if (ret < 0)
return ret;
- stm32_adc_conv_irq_enable(adc);
+ if (!adc->dma_chan)
+ stm32_adc_conv_irq_enable(adc);
stm32_adc_start_conv(adc);
return 0;
@@ -731,7 +880,8 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
int ret;
stm32_adc_stop_conv(adc);
- stm32_adc_conv_irq_disable(adc);
+ if (!adc->dma_chan)
+ stm32_adc_conv_irq_disable(adc);
ret = iio_triggered_buffer_predisable(indio_dev);
if (ret < 0)
@@ -748,7 +898,16 @@ static int stm32_adc_buffer_postdisable(struct iio_dev *indio_dev)
{
struct stm32_adc *adc = iio_priv(indio_dev);
- kfree(adc->buffer);
+ if (!adc->dma_chan) {
+ kfree(adc->buffer);
+ } else {
+ dmaengine_terminate_all(adc->dma_chan);
+ irq_work_sync(&adc->work);
+ dma_free_coherent(adc->dma_chan->device->dev,
+ PAGE_ALIGN(adc->rx_buf_sz),
+ adc->rx_buf, adc->rx_dma_buf);
+ adc->rx_buf = NULL;
+ }
adc->buffer = NULL;
return 0;
@@ -769,15 +928,31 @@ static irqreturn_t stm32_adc_trigger_handler(int irq, void *p)
dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
- /* reset buffer index */
- adc->bufi = 0;
- iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer,
- pf->timestamp);
+ if (!adc->dma_chan) {
+ /* reset buffer index */
+ adc->bufi = 0;
+ iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer,
+ pf->timestamp);
+ } else {
+ int residue = stm32_adc_dma_residue(adc);
+
+ while (residue >= indio_dev->scan_bytes) {
+ adc->buffer = (u16 *)&adc->rx_buf[adc->bufi];
+ iio_push_to_buffers_with_timestamp(indio_dev,
+ adc->buffer,
+ pf->timestamp);
+ residue -= indio_dev->scan_bytes;
+ adc->bufi += indio_dev->scan_bytes;
+ if (adc->bufi >= adc->rx_buf_sz)
+ adc->bufi = 0;
+ }
+ }
iio_trigger_notify_done(indio_dev->trig);
/* re-enable eoc irq */
- stm32_adc_conv_irq_enable(adc);
+ if (!adc->dma_chan)
+ stm32_adc_conv_irq_enable(adc);
return IRQ_HANDLED;
}
@@ -910,13 +1085,17 @@ static int stm32_adc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_clk_disable;
+ adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx");
+ if (adc->dma_chan)
+ init_irq_work(&adc->work, stm32_adc_dma_irq_work);
+
ret = iio_triggered_buffer_setup(indio_dev,
&iio_pollfunc_store_time,
&stm32_adc_trigger_handler,
&stm32_adc_buffer_setup_ops);
if (ret) {
dev_err(&pdev->dev, "buffer setup failed\n");
- goto err_clk_disable;
+ goto err_dma_disable;
}
ret = iio_device_register(indio_dev);
@@ -930,6 +1109,10 @@ static int stm32_adc_probe(struct platform_device *pdev)
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
+err_dma_disable:
+ if (adc->dma_chan)
+ dma_release_channel(adc->dma_chan);
+
err_clk_disable:
clk_disable_unprepare(adc->clk);
@@ -943,6 +1126,8 @@ static int stm32_adc_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
+ if (adc->dma_chan)
+ dma_release_channel(adc->dma_chan);
clk_disable_unprepare(adc->clk);
return 0;
--
1.9.1
^ permalink raw reply related
* [PATCH 6/7] ARM: dts: stm32: Enable dma by default on stm32f4 adc
From: Fabrice Gasnier @ 2017-01-19 13:34 UTC (permalink / raw)
To: jic23, linux, robh+dt, linux-arm-kernel, devicetree, linux-kernel
Cc: linux-iio, mark.rutland, mcoquelin.stm32, alexandre.torgue, lars,
knaack.h, pmeerw, fabrice.gasnier, benjamin.gaignard,
benjamin.gaignard
In-Reply-To: <1484832854-6314-1-git-send-email-fabrice.gasnier@st.com>
Configure STM32F4 ADC to use dma by default.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
arch/arm/boot/dts/stm32f429.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 11d2715..e85db07 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -207,6 +207,8 @@
clocks = <&rcc 0 168>;
interrupt-parent = <&adc>;
interrupts = <0>;
+ dmas = <&dma2 0 0 0x400 0x0>;
+ dma-names = "rx";
status = "disabled";
};
@@ -217,6 +219,8 @@
clocks = <&rcc 0 169>;
interrupt-parent = <&adc>;
interrupts = <1>;
+ dmas = <&dma2 3 1 0x400 0x0>;
+ dma-names = "rx";
status = "disabled";
};
@@ -227,6 +231,8 @@
clocks = <&rcc 0 170>;
interrupt-parent = <&adc>;
interrupts = <2>;
+ dmas = <&dma2 1 2 0x400 0x0>;
+ dma-names = "rx";
status = "disabled";
};
};
--
1.9.1
^ permalink raw reply related
* [PATCH 7/7] ARM: dts: stm32: Enable pwm1 and pwm3 for stm32f469-eval
From: Fabrice Gasnier @ 2017-01-19 13:34 UTC (permalink / raw)
To: jic23, linux, robh+dt, linux-arm-kernel, devicetree, linux-kernel
Cc: mark.rutland, benjamin.gaignard, lars, alexandre.torgue,
linux-iio, pmeerw, mcoquelin.stm32, knaack.h, fabrice.gasnier,
benjamin.gaignard
In-Reply-To: <1484832854-6314-1-git-send-email-fabrice.gasnier@st.com>
Define and enable pwm1 and pwm3, timers1 & 3 trigger outputs on
stm32f469-eval board.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
arch/arm/boot/dts/stm32429i-eval.dts | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts
index 2181220..892100f 100644
--- a/arch/arm/boot/dts/stm32429i-eval.dts
+++ b/arch/arm/boot/dts/stm32429i-eval.dts
@@ -171,3 +171,31 @@
pinctrl-names = "default";
status = "okay";
};
+
+&timers1 {
+ status = "okay";
+
+ pwm {
+ pinctrl-0 = <&pwm1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+ };
+
+ timer@0 {
+ status = "okay";
+ };
+};
+
+&timers3 {
+ status = "okay";
+
+ pwm {
+ pinctrl-0 = <&pwm3_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+ };
+
+ timer@2 {
+ status = "okay";
+ };
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v9 0/4] arm64: arch_timer: Add workaround for hisilicon-161010101 erratum
From: Ding Tianhong @ 2017-01-19 13:35 UTC (permalink / raw)
To: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
marc.zyngier-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
oss-fOR+EgIDQEHk1uMJSBkQmQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
shawnguo-DgEjT+Ai2ygdnm+yROfE0A, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linuxarm-hv44wF8Li93QT0dZR+AlfA
Cc: Ding Tianhong
Erratum Hisilicon-161010101 says that the ARM generic timer counter "has the
potential to contain an erroneous value when the timer value changes".
Accesses to TVAL (both read and write) are also affected due to the implicit counter
read. Accesses to CVAL are not affected.
The workaround is to reread the system count registers until the value of the second
read is larger than the first one by less than 32, the system counter can be guaranteed
not to return wrong value twice by back-to-back read and the error value is always larger
than the correct one by 32. Writes to TVAL are replaced with an equivalent write to CVAL.
v2: Introducing a new generic erratum handling mechanism for fsl,a008585 and hisilicon,161601.
Significant rework based on feedback, including seperate the fsl erratum a008585
to another patch, update the erratum name and remove unwanted code.
v3: Introducing the erratum_workaround_set_sne generic function for fsl erratum a008585
and make the #define __fsl_a008585_read_reg to be private to the .c file instead of
being globally visible. After discussion with Marc and Will, a consensus decision was
made to remove the commandline parameter for enabling fsl,erratum-a008585 erratum,
and make some generic name more specific, export timer_unstable_counter_workaround
for module access.
Significant rework based on feedback, including fix some alignment problem, make the
#define __hisi_161601_read_reg to be private to the .c file instead of being globally
visible, add more accurate annotation and modify a bit of logical format to enable
arch_timer_read_ool_enabled, remove the kernel commandline parameter
clocksource.arm_arch_timer.hisilicon-161601.
Introduce a generic aquick framework for erratum in ACPI mode.
v4: rename the quirk handler parameter to make it more generic, and
avoid break loop when handling the quirk becasue it need to
support multi quirks handler.
update some data structures for acpi mode.
v5: Adapt the new kernel-parameters.txt for latest kernel version.
Set the retries of reread system counter to 50, because it is possible
that some interrupts may lead to more than twice read errors and break the loop,
it will trigger the warning, so we set the number of retries far beyond the number of
iterations the loop has been observed to take.
v6: The last 2 patches in the previous version about the ACPI mode will conflict witch Fuwei's
GTDT patches, so remove the ACPI part and only support the DT base code for this patch set.
We have trigger a bug when select the CONFIG_FUNCTION_GRAPH_TRACER and enable function_graph
to /sys/kernel/debug/tracing/current_tracer, the system will stall into an endless loop, it looks
like that the ftrace_graph_caller will be related to xxx.read_cntvct_el0 and read the system counter
again, so mark the xxx.read_cntvct_el0 with notrace to fix the problem.
v7: Introduce a new general config symbol named CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND to enable the workaround
for any chips which has similar arch timer erratum just like "fsl,erratum_a008585" and "hisilicon,erratum_161601",
modify the struct arch_timer_erratum_workaround to be compatible different chip erratum more easily, and
reconstruction some code base on the new config symbol and struct, thanks to Marc's suggestion.
v8: The original erratum ID could not cover all modules, which only specified <Errata-Prefix><SerialNum>, so after
discussion with the soc team, we decide to use the new ID "161010101" for this timer erratum which consist of
<Errata-Prefix><SeriesFlag><ModuleID><SerialNum> and also update the hisilicon erratum official documents.
v9: Modify the workaround description and remove the message for CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND.
Ding Tianhong (4):
arm64: arch_timer: Add device tree binding for hisilicon-161010101
erratum
arm64: arch_timer: Introduce a generic erratum handing mechanism for
fsl-a008585
arm64: arch_timer: Work around Erratum Hisilicon-161010101
arm64: arch timer: Add timer erratum property for Hip05-d02 and
Hip06-d03
Documentation/admin-guide/kernel-parameters.txt | 9 --
Documentation/arm64/silicon-errata.txt | 43 +++---
.../devicetree/bindings/arm/arch_timer.txt | 6 +
arch/arm64/boot/dts/hisilicon/hip05.dtsi | 1 +
arch/arm64/boot/dts/hisilicon/hip06.dtsi | 1 +
arch/arm64/include/asm/arch_timer.h | 38 ++----
drivers/clocksource/Kconfig | 18 +++
drivers/clocksource/arm_arch_timer.c | 150 +++++++++++++++------
8 files changed, 171 insertions(+), 95 deletions(-)
--
1.9.0
--
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 v9 1/4] arm64: arch_timer: Add device tree binding for hisilicon-161010101 erratum
From: Ding Tianhong @ 2017-01-19 13:35 UTC (permalink / raw)
To: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
marc.zyngier-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
oss-fOR+EgIDQEHk1uMJSBkQmQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
shawnguo-DgEjT+Ai2ygdnm+yROfE0A, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linuxarm-hv44wF8Li93QT0dZR+AlfA
Cc: Ding Tianhong
In-Reply-To: <1484832916-7248-1-git-send-email-dingtianhong-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
This erratum describes a bug in logic outside the core, so MIDR can't be
used to identify its presence, and reading an SoC-specific revision
register from common arch timer code would be awkward. So, describe it
in the device tree.
Signed-off-by: Ding Tianhong <dingtianhong-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Documentation/devicetree/bindings/arm/arch_timer.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
index ad440a2..e926aea 100644
--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -31,6 +31,12 @@ to deliver its interrupts via SPIs.
This also affects writes to the tval register, due to the implicit
counter read.
+- hisilicon,erratum-161010101 : A boolean property. Indicates the
+ presence of Hisilicon erratum 161010101, which says that reading the
+ counters is unreliable in some cases, and reads may return a value 32
+ beyond the correct value. This also affects writes to the tval
+ registers, due to the implicit counter read.
+
** Optional properties:
- arm,cpu-registers-not-fw-configured : Firmware does not initialize
--
1.9.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v9 2/4] arm64: arch_timer: Introduce a generic erratum handing mechanism for fsl-a008585
From: Ding Tianhong @ 2017-01-19 13:35 UTC (permalink / raw)
To: catalin.marinas, will.deacon, marc.zyngier, mark.rutland, oss,
devicetree, shawnguo, stuart.yoder, linux-arm-kernel, linuxarm
Cc: Ding Tianhong
In-Reply-To: <1484832916-7248-1-git-send-email-dingtianhong@huawei.com>
The workaround for hisilicon,161010101 will check the return value of the system counter
by different way, in order to distinguish with the fsl-a008585 workaround, introduce
a new generic erratum handing mechanism for fsl-a008585 and rename some functions.
After discussion with Marc and Will, a consensus decision was made to remove the commandline
parameter for enabling fsl,erratum-a008585 erratum.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
Documentation/admin-guide/kernel-parameters.txt | 9 --
arch/arm64/include/asm/arch_timer.h | 38 +++------
drivers/clocksource/Kconfig | 8 ++
drivers/clocksource/arm_arch_timer.c | 105 ++++++++++++++----------
4 files changed, 84 insertions(+), 76 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 21e2d88..76437ad 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -539,15 +539,6 @@
loops can be debugged more effectively on production
systems.
- clocksource.arm_arch_timer.fsl-a008585=
- [ARM64]
- Format: <bool>
- Enable/disable the workaround of Freescale/NXP
- erratum A-008585. This can be useful for KVM
- guests, if the guest device tree doesn't show the
- erratum. If unspecified, the workaround is
- enabled based on the device tree.
-
clearcpuid=BITNUM [X86]
Disable CPUID feature X for the kernel. See
arch/x86/include/asm/cpufeatures.h for the valid bit
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index eaa5bbe..b4b3400 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -29,41 +29,29 @@
#include <clocksource/arm_arch_timer.h>
-#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585)
+#if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND)
extern struct static_key_false arch_timer_read_ool_enabled;
-#define needs_fsl_a008585_workaround() \
+#define needs_unstable_timer_counter_workaround() \
static_branch_unlikely(&arch_timer_read_ool_enabled)
#else
-#define needs_fsl_a008585_workaround() false
+#define needs_unstable_timer_counter_workaround() false
#endif
-u32 __fsl_a008585_read_cntp_tval_el0(void);
-u32 __fsl_a008585_read_cntv_tval_el0(void);
-u64 __fsl_a008585_read_cntvct_el0(void);
-/*
- * The number of retries is an arbitrary value well beyond the highest number
- * of iterations the loop has been observed to take.
- */
-#define __fsl_a008585_read_reg(reg) ({ \
- u64 _old, _new; \
- int _retries = 200; \
- \
- do { \
- _old = read_sysreg(reg); \
- _new = read_sysreg(reg); \
- _retries--; \
- } while (unlikely(_old != _new) && _retries); \
- \
- WARN_ON_ONCE(!_retries); \
- _new; \
-})
+struct arch_timer_erratum_workaround {
+ const char *id; /* Indicate the Erratum ID */
+ u32 (*read_cntp_tval_el0)(void);
+ u32 (*read_cntv_tval_el0)(void);
+ u64 (*read_cntvct_el0)(void);
+};
+
+extern const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround;
#define arch_timer_reg_read_stable(reg) \
({ \
u64 _val; \
- if (needs_fsl_a008585_workaround()) \
- _val = __fsl_a008585_read_##reg(); \
+ if (needs_unstable_timer_counter_workaround()) \
+ _val = timer_unstable_counter_workaround->read_##reg();\
else \
_val = read_sysreg(reg); \
_val; \
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 4866f7a..6693e07 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -325,10 +325,18 @@ config ARM_ARCH_TIMER_EVTSTREAM
This must be disabled for hardware validation purposes to detect any
hardware anomalies of missing events.
+config ARM_ARCH_TIMER_OOL_WORKAROUND
+ bool
+ depends on FSL_ERRATUM_A008585
+ help
+ This option would only be enabled by Freescale/NXP Erratum A-008585
+ or something else chip has similar erratum.
+
config FSL_ERRATUM_A008585
bool "Workaround for Freescale/NXP Erratum A-008585"
default y
depends on ARM_ARCH_TIMER && ARM64
+ select ARM_ARCH_TIMER_OOL_WORKAROUND
help
This option enables a workaround for Freescale/NXP Erratum
A-008585 ("ARM generic timer may contain an erroneous
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 02fef68..2487c66 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -96,41 +96,59 @@ static int __init early_evtstrm_cfg(char *buf)
*/
#ifdef CONFIG_FSL_ERRATUM_A008585
-DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
-EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
-
-static int fsl_a008585_enable = -1;
-
-static int __init early_fsl_a008585_cfg(char *buf)
-{
- int ret;
- bool val;
- ret = strtobool(buf, &val);
- if (ret)
- return ret;
-
- fsl_a008585_enable = val;
- return 0;
-}
-early_param("clocksource.arm_arch_timer.fsl-a008585", early_fsl_a008585_cfg);
-
-u32 __fsl_a008585_read_cntp_tval_el0(void)
+/*
+ * The number of retries is an arbitrary value well beyond the highest number
+ * of iterations the loop has been observed to take.
+ */
+#define __fsl_a008585_read_reg(reg) ({ \
+ u64 _old, _new; \
+ int _retries = 200; \
+ \
+ do { \
+ _old = read_sysreg(reg); \
+ _new = read_sysreg(reg); \
+ _retries--; \
+ } while (unlikely(_old != _new) && _retries); \
+ \
+ WARN_ON_ONCE(!_retries); \
+ _new; \
+})
+
+static u32 notrace fsl_a008585_read_cntp_tval_el0(void)
{
return __fsl_a008585_read_reg(cntp_tval_el0);
}
-u32 __fsl_a008585_read_cntv_tval_el0(void)
+static u32 notrace fsl_a008585_read_cntv_tval_el0(void)
{
return __fsl_a008585_read_reg(cntv_tval_el0);
}
-u64 __fsl_a008585_read_cntvct_el0(void)
+static u64 notrace fsl_a008585_read_cntvct_el0(void)
{
return __fsl_a008585_read_reg(cntvct_el0);
}
-EXPORT_SYMBOL(__fsl_a008585_read_cntvct_el0);
-#endif /* CONFIG_FSL_ERRATUM_A008585 */
+#endif
+
+#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
+const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL;
+EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
+
+DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
+EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
+
+static const struct arch_timer_erratum_workaround ool_workarounds[] = {
+#ifdef CONFIG_FSL_ERRATUM_A008585
+ {
+ .id = "fsl,erratum-a008585",
+ .read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0,
+ .read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0,
+ .read_cntvct_el0 = fsl_a008585_read_cntvct_el0,
+ },
+#endif
+};
+#endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */
static __always_inline
void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val,
@@ -281,8 +299,8 @@ static __always_inline void set_next_event(const int access, unsigned long evt,
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
}
-#ifdef CONFIG_FSL_ERRATUM_A008585
-static __always_inline void fsl_a008585_set_next_event(const int access,
+#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
+static __always_inline void erratum_set_next_event_generic(const int access,
unsigned long evt, struct clock_event_device *clk)
{
unsigned long ctrl;
@@ -300,20 +318,20 @@ static __always_inline void fsl_a008585_set_next_event(const int access,
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
}
-static int fsl_a008585_set_next_event_virt(unsigned long evt,
+static int erratum_set_next_event_virt(unsigned long evt,
struct clock_event_device *clk)
{
- fsl_a008585_set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk);
+ erratum_set_next_event_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk);
return 0;
}
-static int fsl_a008585_set_next_event_phys(unsigned long evt,
+static int erratum_set_next_event_phys(unsigned long evt,
struct clock_event_device *clk)
{
- fsl_a008585_set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk);
+ erratum_set_next_event_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk);
return 0;
}
-#endif /* CONFIG_FSL_ERRATUM_A008585 */
+#endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */
static int arch_timer_set_next_event_virt(unsigned long evt,
struct clock_event_device *clk)
@@ -343,16 +361,16 @@ static int arch_timer_set_next_event_phys_mem(unsigned long evt,
return 0;
}
-static void fsl_a008585_set_sne(struct clock_event_device *clk)
+static void erratum_workaround_set_sne(struct clock_event_device *clk)
{
-#ifdef CONFIG_FSL_ERRATUM_A008585
+#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
if (!static_branch_unlikely(&arch_timer_read_ool_enabled))
return;
if (arch_timer_uses_ppi == VIRT_PPI)
- clk->set_next_event = fsl_a008585_set_next_event_virt;
+ clk->set_next_event = erratum_set_next_event_virt;
else
- clk->set_next_event = fsl_a008585_set_next_event_phys;
+ clk->set_next_event = erratum_set_next_event_phys;
#endif
}
@@ -385,7 +403,7 @@ static void __arch_timer_setup(unsigned type,
BUG();
}
- fsl_a008585_set_sne(clk);
+ erratum_workaround_set_sne(clk);
} else {
clk->features |= CLOCK_EVT_FEAT_DYNIRQ;
clk->name = "arch_mem_timer";
@@ -605,7 +623,7 @@ static void __init arch_counter_register(unsigned type)
clocksource_counter.archdata.vdso_direct = true;
-#ifdef CONFIG_FSL_ERRATUM_A008585
+#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
/*
* Don't use the vdso fastpath if errata require using
* the out-of-line counter accessor.
@@ -893,12 +911,15 @@ static int __init arch_timer_of_init(struct device_node *np)
arch_timer_c3stop = !of_property_read_bool(np, "always-on");
-#ifdef CONFIG_FSL_ERRATUM_A008585
- if (fsl_a008585_enable < 0)
- fsl_a008585_enable = of_property_read_bool(np, "fsl,erratum-a008585");
- if (fsl_a008585_enable) {
- static_branch_enable(&arch_timer_read_ool_enabled);
- pr_info("Enabling workaround for FSL erratum A-008585\n");
+#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
+ for (i = 0; i < ARRAY_SIZE(ool_workarounds); i++) {
+ if (of_property_read_bool(np, ool_workarounds[i].id)) {
+ timer_unstable_counter_workaround = &ool_workarounds[i];
+ static_branch_enable(&arch_timer_read_ool_enabled);
+ pr_info("arch_timer: Enabling workaround for %s\n",
+ timer_unstable_counter_workaround->id);
+ break;
+ }
}
#endif
--
1.9.0
^ permalink raw reply related
* [PATCH v9 3/4] arm64: arch_timer: Work around Erratum Hisilicon-161010101
From: Ding Tianhong @ 2017-01-19 13:35 UTC (permalink / raw)
To: catalin.marinas, will.deacon, marc.zyngier, mark.rutland, oss,
devicetree, shawnguo, stuart.yoder, linux-arm-kernel, linuxarm
Cc: Ding Tianhong
In-Reply-To: <1484832916-7248-1-git-send-email-dingtianhong@huawei.com>
Erratum Hisilicon-161010101 says that the ARM generic timer counter "has the
potential to contain an erroneous value when the timer value changes".
Accesses to TVAL (both read and write) are also affected due to the implicit counter
read. Accesses to CVAL are not affected.
The workaround is to reread the system count registers until the value of the second
read is larger than the first one by less than 32, the system counter can be guaranteed
not to return wrong value twice by back-to-back read and the error value is always larger
than the correct one by 32. Writes to TVAL are replaced with an equivalent write to CVAL.
The hisilicon erratum CONFIG name is too long, breaking the line format in silicon-errata.txt,
so extended the character spacing to fit all the erratum config.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
Documentation/arm64/silicon-errata.txt | 43 ++++++++++++++---------------
drivers/clocksource/Kconfig | 12 ++++++++-
drivers/clocksource/arm_arch_timer.c | 49 ++++++++++++++++++++++++++++++++++
3 files changed, 82 insertions(+), 22 deletions(-)
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index 405da11..0aaae35 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -42,24 +42,25 @@ file acts as a registry of software workarounds in the Linux Kernel and
will be updated when new workarounds are committed and backported to
stable kernels.
-| Implementor | Component | Erratum ID | Kconfig |
-+----------------+-----------------+-----------------+-------------------------+
-| ARM | Cortex-A53 | #826319 | ARM64_ERRATUM_826319 |
-| ARM | Cortex-A53 | #827319 | ARM64_ERRATUM_827319 |
-| ARM | Cortex-A53 | #824069 | ARM64_ERRATUM_824069 |
-| ARM | Cortex-A53 | #819472 | ARM64_ERRATUM_819472 |
-| ARM | Cortex-A53 | #845719 | ARM64_ERRATUM_845719 |
-| ARM | Cortex-A53 | #843419 | ARM64_ERRATUM_843419 |
-| ARM | Cortex-A57 | #832075 | ARM64_ERRATUM_832075 |
-| ARM | Cortex-A57 | #852523 | N/A |
-| ARM | Cortex-A57 | #834220 | ARM64_ERRATUM_834220 |
-| ARM | Cortex-A72 | #853709 | N/A |
-| ARM | MMU-500 | #841119,#826419 | N/A |
-| | | | |
-| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |
-| Cavium | ThunderX ITS | #23144 | CAVIUM_ERRATUM_23144 |
-| Cavium | ThunderX GICv3 | #23154 | CAVIUM_ERRATUM_23154 |
-| Cavium | ThunderX Core | #27456 | CAVIUM_ERRATUM_27456 |
-| Cavium | ThunderX SMMUv2 | #27704 | N/A |
-| | | | |
-| Freescale/NXP | LS2080A/LS1043A | A-008585 | FSL_ERRATUM_A008585 |
+| Implementor | Component | Erratum ID | Kconfig |
++----------------+-----------------+-----------------+---------------------------------+
+| ARM | Cortex-A53 | #826319 | ARM64_ERRATUM_826319 |
+| ARM | Cortex-A53 | #827319 | ARM64_ERRATUM_827319 |
+| ARM | Cortex-A53 | #824069 | ARM64_ERRATUM_824069 |
+| ARM | Cortex-A53 | #819472 | ARM64_ERRATUM_819472 |
+| ARM | Cortex-A53 | #845719 | ARM64_ERRATUM_845719 |
+| ARM | Cortex-A53 | #843419 | ARM64_ERRATUM_843419 |
+| ARM | Cortex-A57 | #832075 | ARM64_ERRATUM_832075 |
+| ARM | Cortex-A57 | #852523 | N/A |
+| ARM | Cortex-A57 | #834220 | ARM64_ERRATUM_834220 |
+| ARM | Cortex-A72 | #853709 | N/A |
+| ARM | MMU-500 | #841119,#826419 | N/A |
+| | | | |
+| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |
+| Cavium | ThunderX ITS | #23144 | CAVIUM_ERRATUM_23144 |
+| Cavium | ThunderX GICv3 | #23154 | CAVIUM_ERRATUM_23154 |
+| Cavium | ThunderX Core | #27456 | CAVIUM_ERRATUM_27456 |
+| Cavium | ThunderX SMMUv2 | #27704 | N/A |
+| | | | |
+| Freescale/NXP | LS2080A/LS1043A | A-008585 | FSL_ERRATUM_A008585 |
+| Hisilicon | Hip0{5,6,7} | #161010101 | HISILICON_ERRATUM_161010101 |
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 6693e07..b30f44f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -327,7 +327,7 @@ config ARM_ARCH_TIMER_EVTSTREAM
config ARM_ARCH_TIMER_OOL_WORKAROUND
bool
- depends on FSL_ERRATUM_A008585
+ depends on FSL_ERRATUM_A008585 || HISILICON_ERRATUM_161010101
help
This option would only be enabled by Freescale/NXP Erratum A-008585
or something else chip has similar erratum.
@@ -343,6 +343,16 @@ config FSL_ERRATUM_A008585
value"). The workaround will only be active if the
fsl,erratum-a008585 property is found in the timer node.
+config HISILICON_ERRATUM_161010101
+ bool "Workaround for Hisilicon Erratum 161010101"
+ default y
+ select ARM_ARCH_TIMER_OOL_WORKAROUND
+ depends on ARM_ARCH_TIMER && ARM64
+ help
+ This option enables a workaround for Hisilicon Erratum
+ 161010101. The workaround will be active if the hisilicon,erratum-161010101
+ property is found in the timer node.
+
config ARM_GLOBAL_TIMER
bool "Support for the ARM global timer" if COMPILE_TEST
select CLKSRC_OF if OF
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 2487c66..7451b62 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -131,6 +131,47 @@ static u64 notrace fsl_a008585_read_cntvct_el0(void)
}
#endif
+#ifdef CONFIG_HISILICON_ERRATUM_161010101
+/*
+ * Verify whether the value of the second read is larger than the first by
+ * less than 32 is the only way to confirm the value is correct, so clear the
+ * lower 5 bits to check whether the difference is greater than 32 or not.
+ * Theoretically the erratum should not occur more than twice in succession
+ * when reading the system counter, but it is possible that some interrupts
+ * may lead to more than twice read errors, triggering the warning, so setting
+ * the number of retries far beyond the number of iterations the loop has been
+ * observed to take.
+ */
+#define __hisi_161010101_read_reg(reg) ({ \
+ u64 _old, _new; \
+ int _retries = 50; \
+ \
+ do { \
+ _old = read_sysreg(reg); \
+ _new = read_sysreg(reg); \
+ _retries--; \
+ } while (unlikely((_new - _old) >> 5) && _retries); \
+ \
+ WARN_ON_ONCE(!_retries); \
+ _new; \
+})
+
+static u32 notrace hisi_161010101_read_cntp_tval_el0(void)
+{
+ return __hisi_161010101_read_reg(cntp_tval_el0);
+}
+
+static u32 notrace hisi_161010101_read_cntv_tval_el0(void)
+{
+ return __hisi_161010101_read_reg(cntv_tval_el0);
+}
+
+static u64 notrace hisi_161010101_read_cntvct_el0(void)
+{
+ return __hisi_161010101_read_reg(cntvct_el0);
+}
+#endif
+
#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL;
EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
@@ -147,6 +188,14 @@ static u64 notrace fsl_a008585_read_cntvct_el0(void)
.read_cntvct_el0 = fsl_a008585_read_cntvct_el0,
},
#endif
+#ifdef CONFIG_HISILICON_ERRATUM_161010101
+ {
+ .id = "hisilicon,erratum-161010101",
+ .read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0,
+ .read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0,
+ .read_cntvct_el0 = hisi_161010101_read_cntvct_el0,
+ },
+#endif
};
#endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */
--
1.9.0
^ permalink raw reply related
* [PATCH v9 4/4] arm64: arch timer: Add timer erratum property for Hip05-d02 and Hip06-d03
From: Ding Tianhong @ 2017-01-19 13:35 UTC (permalink / raw)
To: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
marc.zyngier-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
oss-fOR+EgIDQEHk1uMJSBkQmQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
shawnguo-DgEjT+Ai2ygdnm+yROfE0A, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linuxarm-hv44wF8Li93QT0dZR+AlfA
Cc: Ding Tianhong
In-Reply-To: <1484832916-7248-1-git-send-email-dingtianhong-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Enable workaround for hisilicon erratum 161010101 on Hip05-d02 and Hip06-d03 board.
Signed-off-by: Ding Tianhong <dingtianhong-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
---
arch/arm64/boot/dts/hisilicon/hip05.dtsi | 1 +
arch/arm64/boot/dts/hisilicon/hip06.dtsi | 1 +
2 files changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi
index 4b472a3..6b76f3a 100644
--- a/arch/arm64/boot/dts/hisilicon/hip05.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi
@@ -281,6 +281,7 @@
<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ hisilicon,erratum-161010101;
};
pmu {
diff --git a/arch/arm64/boot/dts/hisilicon/hip06.dtsi b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
index a049b64..cf8b9db 100644
--- a/arch/arm64/boot/dts/hisilicon/hip06.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
@@ -260,6 +260,7 @@
<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ hisilicon,erratum-161010101;
};
pmu {
--
1.9.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH 0/4] Bluetooth support for GXBB/GXL/GXM based devices
From: Greg KH @ 2017-01-19 13:39 UTC (permalink / raw)
To: Kevin Hilman
Cc: mark.rutland, devicetree, Martin Blumenstingl, catalin.marinas,
will.deacon, robh+dt, linux-serial, jslaby, carlo, linux-amlogic,
linux-arm-kernel
In-Reply-To: <m2fukgyqld.fsf@baylibre.com>
On Wed, Jan 18, 2017 at 02:02:06PM -0800, Kevin Hilman wrote:
> Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:
>
> > Kevin,
> >
> > On Sun, Jan 15, 2017 at 11:32 PM, Martin Blumenstingl
> > <martin.blumenstingl@googlemail.com> wrote:
> >> This adds the missing kernel bits for Bluetooth support on the
> >> Tronsmart Vega S95 (GXBB based) boards as well as for the GXL
> >> P230/P231 and GXM Q200/Q201 reference boards.
> >>
> >> The Bluetooth functionality on these boards is provided by the
> >> SDIO wifi/Bluetooth combo-chip (Broadcom bcm43xx based). The
> >> Bluetooth module on that combo-chip has to be taken out of reset,
> >> which is taken care of the GPIO in the sdio_pwrseq.
> >>
> >> Once the module is taken out of reset it can be set up from userspace
> >> using the "hciattach" tool from bluez, which talks to the Bluetooth
> >> module which is connected to one of the serial ports (in our case
> >> uart_A). To get the Bluetooth module initialized within the timeout
> >> defined by "hciattach" (and to achieve usable speeds for Bluetooth
> >> transfers) the communication uses a speed of 2000000 baud, which was
> >> not supported by meson_uart before.
> >>
> >> NOTE: The .dts-changes from this series depends on my previous series
> >> "add support for uart_AO_B" - see [0]
> >>
> >>
> >> [0] http://lists.infradead.org/pipermail/linux-amlogic/2017-January/001982.html
> >>
> >>
> >> Martin Blumenstingl (4):
> >> tty: serial: meson: allow baud-rates higher than 115200
> >> ARM64: dts: meson-gx: add the serial CTS and RTS pin groups
> >
> > Neil just informed me that Rob Herring is working on defining the UART
> > Bluetooth device properly using devicetree (preparation for this is
> > named "[PATCH v2 0/9] Serial slave device bus", see [0] for the
> > mailing-list conversation and [1] for a WiP git repo).
>
> Ah, good news. I knew Rob had been talking about that for awhile, so
> I'm glad to see it coming into existence. Thanks for the pointers.
>
> > This means that there will be a better solution than the one proposed
> > in the meson-gx-p23x-q20x and meson-gxbb-vega-s95 patches (patches #1
> > and #2 are not affected by this),> namely:
> > - I'm currently (ab)using sdio-pwrseq node to power on the UART
> > Bluetooth module, this can solved by specifying a bluetooth { } node
> > inside the &uart_A node in the future and providing the corresponding
> > GPIOs there
>
> Good. I didn't like the (ab)use of sdio_pwrseq GPIO resets for the
> bluetooth either.
>
> > - all the userspace commands will not be necessary once
> > drivers/bluetooth/hci_bcm.c is changed to the serio framework and gets
> > devicetree support
>
> Cool. Maybe you can setup a WIP branch based on Rob's work for broader
> testing on Amlogic boards until this gets merged?
>
> In the mean time, I've applied patch 2/4 and hopefully the drivers/tty
> patch will go through the serial tree.
Yes, I've taken it now, thanks.
greg k-h
^ permalink raw reply
* [PATCH 0/3] Add RTC support on STM32F746
From: Amelie Delaunay @ 2017-01-19 13:45 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Maxime Coquelin,
Alexandre Torgue
Cc: devicetree, Amelie Delaunay, linux-kernel, linux-arm-kernel
This patchset enables STM32 RTC on STM32F746 MCU.
Amelie Delaunay (3):
ARM: dts: stm32: set HSE_RTC clock frequency to 1 MHz on stm32f746
ARM: dts: stm32: Add RTC support for STM32F746 MCU
ARM: dts: stm32: enable RTC on stm32746g-eval
arch/arm/boot/dts/stm32746g-eval.dts | 4 ++++
arch/arm/boot/dts/stm32f746.dtsi | 16 ++++++++++++++++
2 files changed, 20 insertions(+)
--
1.9.1
^ permalink raw reply
* [PATCH 1/3] ARM: dts: stm32: set HSE_RTC clock frequency to 1 MHz on stm32f746
From: Amelie Delaunay @ 2017-01-19 13:45 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Maxime Coquelin,
Alexandre Torgue
Cc: devicetree, Amelie Delaunay, linux-kernel, linux-arm-kernel
In-Reply-To: <1484833519-9298-1-git-send-email-amelie.delaunay@st.com>
This patch set HSE_RTC clock frequency to 1 MHz, as the clock supplied to
the RTC must be 1 MHz.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
arch/arm/boot/dts/stm32f746.dtsi | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/stm32f746.dtsi
index 5bbee56..b42f23d 100644
--- a/arch/arm/boot/dts/stm32f746.dtsi
+++ b/arch/arm/boot/dts/stm32f746.dtsi
@@ -343,6 +343,8 @@
reg = <0x40023800 0x400>;
clocks = <&clk_hse>, <&clk_i2s_ckin>;
st,syscfg = <&pwrcfg>;
+ assigned-clocks = <&rcc 1 CLK_HSE_RTC>;
+ assigned-clock-rates = <1000000>;
};
dma1: dma-controller@40026000 {
--
1.9.1
^ permalink raw reply related
* [PATCH 2/3] ARM: dts: stm32: Add RTC support for STM32F746 MCU
From: Amelie Delaunay @ 2017-01-19 13:45 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Maxime Coquelin,
Alexandre Torgue
Cc: devicetree, Amelie Delaunay, linux-kernel, linux-arm-kernel
In-Reply-To: <1484833519-9298-1-git-send-email-amelie.delaunay@st.com>
This patch adds STM32 RTC bindings for STM32F746.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
arch/arm/boot/dts/stm32f746.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/stm32f746.dtsi
index b42f23d..c57d265 100644
--- a/arch/arm/boot/dts/stm32f746.dtsi
+++ b/arch/arm/boot/dts/stm32f746.dtsi
@@ -121,6 +121,20 @@
status = "disabled";
};
+ rtc: rtc@40002800 {
+ compatible = "st,stm32-rtc";
+ reg = <0x40002800 0x400>;
+ clocks = <&rcc 1 CLK_RTC>;
+ clock-names = "ck_rtc";
+ assigned-clocks = <&rcc 1 CLK_RTC>;
+ assigned-clock-parents = <&rcc 1 CLK_LSE>;
+ interrupt-parent = <&exti>;
+ interrupts = <17 1>;
+ interrupt-names = "alarm";
+ st,syscfg = <&pwrcfg>;
+ status = "disabled";
+ };
+
usart2: serial@40004400 {
compatible = "st,stm32f7-usart", "st,stm32f7-uart";
reg = <0x40004400 0x400>;
--
1.9.1
^ permalink raw reply related
* [PATCH 3/3] ARM: dts: stm32: enable RTC on stm32746g-eval
From: Amelie Delaunay @ 2017-01-19 13:45 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Maxime Coquelin,
Alexandre Torgue
Cc: devicetree, Amelie Delaunay, linux-kernel, linux-arm-kernel
In-Reply-To: <1484833519-9298-1-git-send-email-amelie.delaunay@st.com>
This patch enables RTC on stm32746g-eval with default LSE clock source.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
arch/arm/boot/dts/stm32746g-eval.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/boot/dts/stm32746g-eval.dts b/arch/arm/boot/dts/stm32746g-eval.dts
index 58d5393..ae64ea4 100644
--- a/arch/arm/boot/dts/stm32746g-eval.dts
+++ b/arch/arm/boot/dts/stm32746g-eval.dts
@@ -82,6 +82,10 @@
};
};
+&rtc {
+ status = "okay";
+};
+
&usart1 {
pinctrl-0 = <&usart1_pins_a>;
pinctrl-names = "default";
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v9 0/4] arm64: arch_timer: Add workaround for hisilicon-161010101 erratum
From: Marc Zyngier @ 2017-01-19 13:49 UTC (permalink / raw)
To: Ding Tianhong, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
oss-fOR+EgIDQEHk1uMJSBkQmQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
shawnguo-DgEjT+Ai2ygdnm+yROfE0A, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linuxarm-hv44wF8Li93QT0dZR+AlfA
In-Reply-To: <1484832916-7248-1-git-send-email-dingtianhong-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
On 19/01/17 13:35, Ding Tianhong wrote:
> Erratum Hisilicon-161010101 says that the ARM generic timer counter "has the
> potential to contain an erroneous value when the timer value changes".
> Accesses to TVAL (both read and write) are also affected due to the implicit counter
> read. Accesses to CVAL are not affected.
Please. 3 series in 2 hours is not fun, and is not helping your case
either. Give us the time to properly review your patches, and wait until
we ask you to respin if we think that this is required.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
--
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] ARM: dts: imx: Pass 'chosen' and 'memory' nodes
From: Fabio Estevam @ 2017-01-19 14:02 UTC (permalink / raw)
To: shawnguo-DgEjT+Ai2ygdnm+yROfE0A
Cc: kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, javier-JPH+aEBZ4P+UEJcrhfAQsw,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, Fabio Estevam
Commit 7f107887d199 ("ARM: dts: imx: Remove skeleton.dtsi") causes boot
issues when the bootloader does not create a 'chosen' node if such node
is not present in the dtb.
The reason for the boot failure is well explained by Javier Martinez
Canillas: "the decompressor relies on a pre-existing chosen node to be
available to insert the command line and merge other ATAGS info."
, so pass an empty 'chosen' node to fix the boot problem.
This issue has been seen in the kernelci reports with Barebox as
bootloader.
Also pass the 'memory' node in order to fix boot issues on the SolidRun
iMX6 platforms.
Fixes: 7f107887d199 ("ARM: dts: imx: Remove skeleton.dtsi")
Reported-by: kernelci.org bot <bot-ssFOTAMYnuFg9hUCZPvPmw@public.gmane.org>
Reported-by: Russell King <rmk+kernel-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org>
Signed-off-by: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
---
Changes since v1:
- Also pass the memory node.
arch/arm/boot/dts/imx1.dtsi | 2 ++
arch/arm/boot/dts/imx23.dtsi | 2 ++
arch/arm/boot/dts/imx25.dtsi | 2 ++
arch/arm/boot/dts/imx27.dtsi | 2 ++
arch/arm/boot/dts/imx28.dtsi | 2 ++
arch/arm/boot/dts/imx31.dtsi | 2 ++
arch/arm/boot/dts/imx35.dtsi | 2 ++
arch/arm/boot/dts/imx50.dtsi | 2 ++
arch/arm/boot/dts/imx51.dtsi | 2 ++
arch/arm/boot/dts/imx53.dtsi | 2 ++
arch/arm/boot/dts/imx6qdl.dtsi | 2 ++
arch/arm/boot/dts/imx6sl.dtsi | 2 ++
arch/arm/boot/dts/imx6sx.dtsi | 2 ++
arch/arm/boot/dts/imx6ul.dtsi | 2 ++
arch/arm/boot/dts/imx7s.dtsi | 2 ++
15 files changed, 30 insertions(+)
diff --git a/arch/arm/boot/dts/imx1.dtsi b/arch/arm/boot/dts/imx1.dtsi
index dd3de38..7ef0d36 100644
--- a/arch/arm/boot/dts/imx1.dtsi
+++ b/arch/arm/boot/dts/imx1.dtsi
@@ -18,6 +18,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
gpio0 = &gpio1;
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 96eae64..7bb662c 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -16,6 +16,8 @@
#size-cells = <1>;
interrupt-parent = <&icoll>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
gpio0 = &gpio0;
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
index 213d86e..f328ecc 100644
--- a/arch/arm/boot/dts/imx25.dtsi
+++ b/arch/arm/boot/dts/imx25.dtsi
@@ -14,6 +14,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &fec;
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 6a7cb9e..3271ec49 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -19,6 +19,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &fec;
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 905bdb5..5f47558 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -17,6 +17,8 @@
#size-cells = <1>;
interrupt-parent = <&icoll>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &mac0;
diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi
index c0a5d5f..afd4106 100644
--- a/arch/arm/boot/dts/imx31.dtsi
+++ b/arch/arm/boot/dts/imx31.dtsi
@@ -12,6 +12,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
serial0 = &uart1;
diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi
index 6f7b943..e08e574 100644
--- a/arch/arm/boot/dts/imx35.dtsi
+++ b/arch/arm/boot/dts/imx35.dtsi
@@ -13,6 +13,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &fec;
diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/imx50.dtsi
index fe0221e..46329ff 100644
--- a/arch/arm/boot/dts/imx50.dtsi
+++ b/arch/arm/boot/dts/imx50.dtsi
@@ -17,6 +17,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &fec;
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 33526ca..c6ffc7b 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -19,6 +19,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &fec;
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index ca51dc0..2d56f26 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -19,6 +19,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &fec;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 89b834f..c88a373 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -16,6 +16,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &fec;
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 19cbd87..89e8315 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -14,6 +14,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &fec;
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 10f3330..f52d017 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -15,6 +15,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
can0 = &flexcan1;
diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index 0f69a3f..1d93601 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -15,6 +15,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
ethernet0 = &fec1;
diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 8db1eb9..1757789 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -50,6 +50,8 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
+ chosen {};
+ memory { device_type = "memory"; reg = <0 0>; };
aliases {
gpio0 = &gpio1;
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH] ARM: dts: fix SolidRun iMX6 platforms
From: Fabio Estevam @ 2017-01-19 14:04 UTC (permalink / raw)
To: Russell King
Cc: Mark Rutland, devicetree@vger.kernel.org, Rob Herring,
Sascha Hauer, Fabio Estevam, Shawn Guo,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <E1cUC4p-00087z-NF@rmk-PC.armlinux.org.uk>
Hi Russell,
On Thu, Jan 19, 2017 at 10:44 AM, Russell King
<rmk+kernel@armlinux.org.uk> wrote:
> Removal of skeleton.dtsi from imx6qdl.dtsi caused a regression on
> SolidRun platforms as the /chosen and /memory nodes are no longer
> populated. Fix this by adding the nodes into the platform .dtsi
> files.
>
> Uncompressing Linux... done, booting the kernel.
> Booting Linux on physical CPU 0x0
> Linux version 4.10.0-rc3+ (rmk@rmk-PC.arm.linux.org.uk) (gcc version 4.7.4 (GCC) ) #2066 SMP Thu Jan 19 12:31:19 GMT 2017
> CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c5387d
> CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
> OF: fdt:Machine model: SolidRun Cubox-i Dual/Quad
> INITRD: 0x20000000+0x001cd000 is not a memory region - disabling initrd
> cma: Failed to reserve 256 MiB
> Memory policy: Data cache writealloc
> Kernel panic - not syncing: ERROR: Failed to allocate 0x2000 bytes below 0x0.
>
> CPU: 0 PID: 0 Comm: swapper Not tainted 4.10.0-rc3+ #2066
> Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
> Backtrace: invalid frame pointer 0xc09e5e44c
> ---[ end Kernel panic - not syncing: ERROR: Failed to allocate 0x2000 bytes below 0x0.
>
> Fixes: 7f107887d199 ("ARM: dts: imx: Remove skeleton.dtsi")
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
I made a previous attempt to fix this issue and realized that it was
not complete.
Just sent a v2, which hopefully will fix this problem for all i.MX dtsi files.
^ permalink raw reply
* Re: [PATCH v3 2/2] mmc: pwrseq: add support for Marvell SD8787 chip
From: Ulf Hansson @ 2017-01-19 14:13 UTC (permalink / raw)
To: Matt Ranostay
Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mmc@vger.kernel.org, devicetree@vger.kernel.org,
Tony Lindgren, Shawn Lin
In-Reply-To: <20170113052937.12538-3-matt@ranostay.consulting>
+Shawn
On 13 January 2017 at 06:29, Matt Ranostay <matt@ranostay.consulting> wrote:
> Allow power sequencing for the Marvell SD8787 Wifi/BT chip.
> This can be abstracted to other chipsets if needed in the future.
>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: Ulf Hansson <ulf.hansson@linaro.org>
> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
> ---
> drivers/mmc/core/Kconfig | 10 ++++
> drivers/mmc/core/Makefile | 1 +
> drivers/mmc/core/pwrseq_sd8787.c | 117 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 128 insertions(+)
> create mode 100644 drivers/mmc/core/pwrseq_sd8787.c
>
> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
> index cdfa8520a4b1..fc1ecdaaa9ca 100644
> --- a/drivers/mmc/core/Kconfig
> +++ b/drivers/mmc/core/Kconfig
> @@ -12,6 +12,16 @@ config PWRSEQ_EMMC
> This driver can also be built as a module. If so, the module
> will be called pwrseq_emmc.
>
> +config PWRSEQ_SD8787
> + tristate "HW reset support for SD8787 BT + Wifi module"
> + depends on OF && (MWIFIEX || BT_MRVL_SDIO)
> + help
> + This selects hardware reset support for the SD8787 BT + Wifi
> + module. By default this option is set to n.
> +
> + This driver can also be built as a module. If so, the module
> + will be called pwrseq_sd8787.
> +
> config PWRSEQ_SIMPLE
> tristate "Simple HW reset support for MMC"
> default y
> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
> index b2a257dc644f..0f81464fa824 100644
> --- a/drivers/mmc/core/Makefile
> +++ b/drivers/mmc/core/Makefile
> @@ -10,6 +10,7 @@ mmc_core-y := core.o bus.o host.o \
> quirks.o slot-gpio.o
> mmc_core-$(CONFIG_OF) += pwrseq.o
> obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o
> +obj-$(CONFIG_PWRSEQ_SD8787) += pwrseq_sd8787.o
> obj-$(CONFIG_PWRSEQ_EMMC) += pwrseq_emmc.o
> mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
> obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
> diff --git a/drivers/mmc/core/pwrseq_sd8787.c b/drivers/mmc/core/pwrseq_sd8787.c
> new file mode 100644
> index 000000000000..f4080fe6439e
> --- /dev/null
> +++ b/drivers/mmc/core/pwrseq_sd8787.c
> @@ -0,0 +1,117 @@
> +/*
> + * pwrseq_sd8787.c - power sequence support for Marvell SD8787 BT + Wifi chip
> + *
> + * Copyright (C) 2016 Matt Ranostay <matt@ranostay.consulting>
> + *
> + * Based on the original work pwrseq_simple.c
> + * Copyright (C) 2014 Linaro Ltd
> + * Author: Ulf Hansson <ulf.hansson@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/gpio/consumer.h>
> +
> +#include <linux/mmc/host.h>
> +
> +#include "pwrseq.h"
> +
> +struct mmc_pwrseq_sd8787 {
> + struct mmc_pwrseq pwrseq;
> + struct gpio_desc *reset_gpio;
> + struct gpio_desc *pwrdn_gpio;
> +};
> +
> +#define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787, pwrseq)
> +
> +static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host)
> +{
> + struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
> +
> + gpiod_set_value_cansleep(pwrseq->reset_gpio, 1);
> +
> + msleep(300);
> + gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1);
> +}
> +
> +static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host)
> +{
> + struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
> +
> + gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0);
> + gpiod_set_value_cansleep(pwrseq->reset_gpio, 0);
> +}
> +
> +static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = {
> + .pre_power_on = mmc_pwrseq_sd8787_pre_power_on,
> + .power_off = mmc_pwrseq_sd8787_power_off,
> +};
> +
> +static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = {
> + { .compatible = "mmc-pwrseq-sd8787",},
> + {/* sentinel */},
> +};
> +MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match);
> +
> +static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
> +{
> + struct mmc_pwrseq_sd8787 *pwrseq;
> + struct device *dev = &pdev->dev;
> +
> + pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
> + if (!pwrseq)
> + return -ENOMEM;
> +
> + pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "pwrdn", GPIOD_OUT_LOW);
> + if (IS_ERR(pwrseq->pwrdn_gpio))
> + return PTR_ERR(pwrseq->pwrdn_gpio);
> +
> + pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> + if (IS_ERR(pwrseq->reset_gpio))
> + return PTR_ERR(pwrseq->reset_gpio);
> +
> + pwrseq->pwrseq.dev = dev;
> + pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops;
> + pwrseq->pwrseq.owner = THIS_MODULE;
> + platform_set_drvdata(pdev, pwrseq);
> +
> + return mmc_pwrseq_register(&pwrseq->pwrseq);
> +}
> +
> +static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
> +{
> + struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev);
> +
> + mmc_pwrseq_unregister(&pwrseq->pwrseq);
> +
> + return 0;
> +}
> +
> +static struct platform_driver mmc_pwrseq_sd8787_driver = {
> + .probe = mmc_pwrseq_sd8787_probe,
> + .remove = mmc_pwrseq_sd8787_remove,
> + .driver = {
> + .name = "pwrseq_sd8787",
> + .of_match_table = mmc_pwrseq_sd8787_of_match,
> + },
> +};
> +
> +module_platform_driver(mmc_pwrseq_sd8787_driver);
> +MODULE_LICENSE("GPL v2");
> --
> 2.10.2
>
Twisting my head around how this could be integrated smoothly into
pwrseq simple. No, I just can find a good way forward without messing
up pwrseq simple itself.
So, for now I decided (once more :-), that let's keep this as separate driver!
Perhaps, following device specific mmc pwrseq drivers will needs
something similar, but in such case we can look into that then.
Thinking about cw1200 for example.
Let's get Rob's ack for the DT bindings, seems almost there, then I
will queue this.
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH v2] ARM: dts: imx: Pass 'chosen' and 'memory' nodes
From: Uwe Kleine-König @ 2017-01-19 14:13 UTC (permalink / raw)
To: Fabio Estevam
Cc: devicetree, linux, javier, kernel, shawnguo, linux-arm-kernel
In-Reply-To: <1484834566-19845-1-git-send-email-fabio.estevam@nxp.com>
On Thu, Jan 19, 2017 at 12:02:46PM -0200, Fabio Estevam wrote:
> Commit 7f107887d199 ("ARM: dts: imx: Remove skeleton.dtsi") causes boot
> issues when the bootloader does not create a 'chosen' node if such node
> is not present in the dtb.
>
> The reason for the boot failure is well explained by Javier Martinez
> Canillas: "the decompressor relies on a pre-existing chosen node to be
> available to insert the command line and merge other ATAGS info."
>
> , so pass an empty 'chosen' node to fix the boot problem.
>
> This issue has been seen in the kernelci reports with Barebox as
> bootloader.
>
> Also pass the 'memory' node in order to fix boot issues on the SolidRun
> iMX6 platforms.
>
> Fixes: 7f107887d199 ("ARM: dts: imx: Remove skeleton.dtsi")
> Reported-by: kernelci.org bot <bot@kernelci.org>
> Reported-by: Russell King <rmk+kernel@armlinux.org.uk>
> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
> ---
> Changes since v1:
> - Also pass the memory node.
>
> arch/arm/boot/dts/imx1.dtsi | 2 ++
> arch/arm/boot/dts/imx23.dtsi | 2 ++
> arch/arm/boot/dts/imx25.dtsi | 2 ++
> arch/arm/boot/dts/imx27.dtsi | 2 ++
> arch/arm/boot/dts/imx28.dtsi | 2 ++
> arch/arm/boot/dts/imx31.dtsi | 2 ++
> arch/arm/boot/dts/imx35.dtsi | 2 ++
> arch/arm/boot/dts/imx50.dtsi | 2 ++
> arch/arm/boot/dts/imx51.dtsi | 2 ++
> arch/arm/boot/dts/imx53.dtsi | 2 ++
> arch/arm/boot/dts/imx6qdl.dtsi | 2 ++
> arch/arm/boot/dts/imx6sl.dtsi | 2 ++
> arch/arm/boot/dts/imx6sx.dtsi | 2 ++
> arch/arm/boot/dts/imx6ul.dtsi | 2 ++
> arch/arm/boot/dts/imx7s.dtsi | 2 ++
> 15 files changed, 30 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx1.dtsi b/arch/arm/boot/dts/imx1.dtsi
> index dd3de38..7ef0d36 100644
> --- a/arch/arm/boot/dts/imx1.dtsi
> +++ b/arch/arm/boot/dts/imx1.dtsi
> @@ -18,6 +18,8 @@
> / {
> #address-cells = <1>;
> #size-cells = <1>;
> + chosen {};
> + memory { device_type = "memory"; reg = <0 0>; };
Would it be nice to add a comment about why this was added? Something to
prevent a cleanup like "remove empty nodes and invalid memory
configurations".
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* Re: [PATCH v1 2/2] arm: dts: mt2701: add nor flash node
From: Rob Herring @ 2017-01-19 14:18 UTC (permalink / raw)
To: Boris Brezillon
Cc: linux-arm-kernel@lists.infradead.org, Thomas Petazzoni,
Marek Vasut, Mark Rutland, devicetree@vger.kernel.org,
Guochun Mao, Richard Weinberger, Russell King,
linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org,
Matthias Brugger, linux-mediatek, Cyrille Pitchen, Brian Norris,
David Woodhouse
In-Reply-To: <20170119091428.598eb987@bbrezillon>
On Thu, Jan 19, 2017 at 2:14 AM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> Hi Rob,
>
> On Wed, 18 Jan 2017 20:51:08 -0600
> Rob Herring <robh@kernel.org> wrote:
>
>> On Wed, Jan 18, 2017 at 5:38 PM, Thomas Petazzoni
>> <thomas.petazzoni@free-electrons.com> wrote:
>> > Hello,
>> >
>> > On Wed, 18 Jan 2017 16:20:10 -0600, Rob Herring wrote:
>> >
>> >> > > Rob, Mark, any opinion?
>> >> >
>> >>
>> >> Sigh, is how to do compatibles really not yet understood?
>> >
>> > Well, it seems like not everyone necessarily understands what is the
>> > best strategy to adopt (me included).
>> >
>> >> > I agree that a clarification would be good. There are really two
>> >> > options:
>> >> >
>> >> > 1. Have two compatible strings in the DT, the one that matches the
>> >> > exact SoC where the IP is found (first compatible string) and the
>> >> > one that matches some other SoC where the same IP is found (second
>> >> > compatible string). Originally, Linux only supports the second
>> >> > compatible string in its device driver, but if it happens that a
>> >> > difference is found between two IPs that we thought were the same,
>> >> > we can add support for the first compatible string in the driver,
>> >> > with a slightly different behavior.
>> >>
>> >> This. And no wildcards in the compatible string.
>> >
>> > OK. So it means that today we do something like:
>> >
>> > compatible = "baz,foo-12", "baz,foo-00";
>> >
>> > and support only baz,foo-00 in the driver. If tomorrow we discover
>> > that there is in fact a difference between the two IP blocks, we can
>> > add support for baz,foo-12 in the driver, and handle the differences.
>> >
>> > But then, the DT still contains:
>> >
>> > compatible = "baz,foo-12", "baz,foo-00";
>> >
>> > and therefore pretends that the IP block is compatible with
>> > "baz,foo-00" which is in fact *not* the case. It was a mistake to
>> > consider it as compatible. So we keep living with a DT that has
>> > incorrect information.
>>
>> I wouldn't say it's a mistake necessarily. The old compatible would
>> probably work to some extent. I'd assume it was tested to some level.
>> Or it could be other changes exposing a difference.
>
> One last question and I'm done: is something like that acceptable?
>
> compatible = "<vendor>,<old-soc>","<vendor>,<new-soc>";
>
> This can happen when someone adds support for an unsupported feature
> on a brand new SoC, and then someone else use the same driver for an
> older SoC embedding the same IP but still wants to add a new compatible
> just in case these 2 IPs appear to be slightly different.
Yes, it's old and new compatible strings in this case and it's newest
compatible string first.
> Here the order of compat strings is no longer following a clear rule
> like 'most-specific compatible first' or 'newest IP/SoC version first',
> it's completely dependent on the order these IPs were supported in the
> OS (Linux). I'm perfectly fine with that BTW, just want to make sure
> this is authorized.
I guess we should say "newest compatible for IP first" instead. There
are some exceptions where we add fallbacks later on, but that falls
under the most-specific part.
It's order that the bindings are defined, not Linux support really,
but in practice those are the same.
Rob
^ permalink raw reply
* Re: [PATCH 1/3] ARM: dts: Add support for phyCORE-AM335x PCM-953 carrier board
From: Vladimir Zapolskiy @ 2017-01-19 14:24 UTC (permalink / raw)
To: Teresa Remmet, linux-omap-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Benoît Cousson, Tony Lindgren, Rob Herring, Mark Rutland,
Wadim Egorov
In-Reply-To: <1484831270-7251-1-git-send-email-t.remmet-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>
On 01/19/2017 03:07 PM, Teresa Remmet wrote:
> The phyCORE-AM335x development kit is a combination of the
> phyCORE-AM335x SoM and a PCM-953 carrier board. The features
> of the PCM-953 are:
> * ETH phy on carrier board: 1x RGMII
> * 1x CAN
> * Up to 4x UART
> * USB0 (otg)
> * USB1 (host)
> * SD slot
> * User gpio-keys
> * User LEDs
>
> Signed-off-by: Teresa Remmet <t.remmet-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>
> Reviewed-by: Wadim Egorov <w.egorov-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>
> ---
> .../devicetree/bindings/arm/omap/omap.txt | 3 +
> arch/arm/boot/dts/Makefile | 1 +
> arch/arm/boot/dts/am335x-pcm-953.dtsi | 303 +++++++++++++++++++++
> arch/arm/boot/dts/am335x-phycore-rdk.dts | 27 ++
> 4 files changed, 334 insertions(+)
> create mode 100644 arch/arm/boot/dts/am335x-pcm-953.dtsi
> create mode 100644 arch/arm/boot/dts/am335x-phycore-rdk.dts
>
> diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
> index 05f95c3..8219b2c 100644
> --- a/Documentation/devicetree/bindings/arm/omap/omap.txt
> +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
> @@ -151,6 +151,9 @@ Boards:
> - AM335X SBC-T335 : single board computer, built around the Sitara AM3352/4
> compatible = "compulab,sbc-t335", "compulab,cm-t335", "ti,am33xx"
>
> +- AM335X phyCORE-AM335x: Development kit
> + compatible = "phytec,am335x-pcm-953", "phytec,am335x-phycore-som", "ti,am33xx"
> +
> - OMAP5 EVM : Evaluation Module
> compatible = "ti,omap5-evm", "ti,omap5"
>
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 7327250..dd71afe 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -573,6 +573,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \
> am335x-lxm.dtb \
> am335x-nano.dtb \
> am335x-pepper.dtb \
> + am335x-phycore-rdk.dtb \
> am335x-shc.dtb \
> am335x-sbc-t335.dtb \
> am335x-sl50.dtb \
> diff --git a/arch/arm/boot/dts/am335x-pcm-953.dtsi b/arch/arm/boot/dts/am335x-pcm-953.dtsi
> new file mode 100644
> index 0000000..54a171d
> --- /dev/null
> +++ b/arch/arm/boot/dts/am335x-pcm-953.dtsi
> @@ -0,0 +1,303 @@
> +/*
> + * Copyright (C) 2014-2017 Phytec Messtechnik GmbH
> + * Author: Wadim Egorov <w.egorov-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>
> + * Teresa Remmet <t.remmet-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <dt-bindings/input/input.h>
> +
> +/ {
> + model = "Phytec AM335x PCM-953";
> + compatible = "phytec,am335x-pcm-953", "phytec,am335x-phycore-som", "ti,am33xx";
> +
> + user_leds: user_leds {
> + compatible = "gpio-leds";
> + };
> +
> + user_buttons: user_buttons {
> + compatible = "gpio-keys";
> + };
> +
> + regulators {
> + compatible = "simple-bus";
Please drop "simple-bus" compatible, see http://www.spinics.net/lists/linux-usb/msg101497.html
> +
> + vcc3v3: fixedregulator@1 {
> + compatible = "regulator-fixed";
> + };
> +
> + vcc1v8: fixedregulator@2 {
> + compatible = "regulator-fixed";
> + };
> + };
> +};
> +
> +/* CAN */
> +&am33xx_pinmux {
Which .dtsi file contains the referenced am33xx_pinmux device node?
You should include that file firstly, this is relevant to all other
references to device nodes used in this file.
> + dcan1_pins: pinmux_dcan1 {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x980, PIN_OUTPUT_PULLUP | MUX_MODE2) /* uart1_rxd.dcan1_tx_mux2 */
> + AM33XX_IOPAD(0x984, PIN_INPUT_PULLUP | MUX_MODE2) /* uart1_txd.dcan1_rx_mux2 */
> + >;
> + };
> +};
> +
> +&dcan1 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&dcan1_pins>;
> + status = "okay";
> +};
> +
> +/* Ethernet */
> +&am33xx_pinmux {
> + ethernet1_pins: pinmux_ethernet1 {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */
> + AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */
> + AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */
> + AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */
> + AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */
> + AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */
> + AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */
> + AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */
> + AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */
> + AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */
> + AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */
> + AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */
> + >;
> + };
> +};
> +
> +&cpsw_emac1 {
> + phy-handle = <&phy1>;
> + phy-mode = "rgmii-id";
> + dual_emac_res_vlan = <2>;
> + status = "okay";
> +};
> +
> +&davinci_mdio {
> + phy1: ethernet-phy@1 {
> + reg = <2>;
There is a mismatch between unit address and 'reg' property values.
> +
> + /* Register 260 (104h) – RGMII Clock and Control Pad Skew */
> + rxc-skew-ps = <1400>;
> + rxdv-skew-ps = <0>;
> + txc-skew-ps = <1400>;
> + txen-skew-ps = <0>;
> + /* Register 261 (105h) – RGMII RX Data Pad Skew */
> + rxd3-skew-ps = <0>;
> + rxd2-skew-ps = <0>;
> + rxd1-skew-ps = <0>;
> + rxd0-skew-ps = <0>;
> + /* Register 262 (106h) – RGMII TX Data Pad Skew */
> + txd3-skew-ps = <0>;
> + txd2-skew-ps = <0>;
> + txd1-skew-ps = <0>;
> + txd0-skew-ps = <0>;
> + };
> +};
> +
> +&mac {
> + slaves = <2>;
> + pinctrl-names = "default";
> + pinctrl-0 = <ðernet0_pins ðernet1_pins>;
> + dual_emac;
It seems that TI has properties with underscores in the names, acked.
> +};
> +
> +/* Misc */
> +&am33xx_pinmux {
> + pinctrl-names = "default";
> + pinctrl-0 = <&cb_gpio_pins>;
> +
> + cb_gpio_pins: pinmux_cb_gpio {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x968, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart0_ctsn.gpio1_8 */
> + AM33XX_IOPAD(0x96c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart0_rtsn.gpio1_9 */
> + >;
> + };
> +};
> +
> +/* MMC */
> +&am33xx_pinmux {
> + mmc1_pins: pinmux_mmc1_pins {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
> + AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
> + AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
> + AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
> + AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */
> + AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
> + AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE7) /* spi0_cs1.mmc0_sdcd */
> + >;
> + };
> +};
> +
> +&mmc1 {
> + vmmc-supply = <&vcc3v3>;
> + bus-width = <4>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc1_pins>;
> + cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
> + status = "okay";
> +};
> +
> +/* Power */
> +&vcc3v3 {
> + regulator-name = "vcc3v3";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-boot-on;
> +};
Please add properties directly into vcc3v3 device node.
> +
> +&vcc1v8 {
> + regulator-name = "vcc1v8";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + regulator-boot-on;
> +};
> +
Please add properties directly into vcc1v8 device node.
> +/* UARTs */
> +&am33xx_pinmux {
> + uart0_pins: pinmux_uart0 {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
> + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
> + >;
> + };
> +
> + uart1_pins: pinmux_uart1 {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_rxd.uart1_rxd */
> + AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */
> + AM33XX_IOPAD(0x978, PIN_INPUT | MUX_MODE0) /* uart1_ctsn.uart1_ctsn */
> + AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn.uart1_rtsn */
> + >;
> + };
> +
> + uart2_pins: pinmux_uart2 {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_tx_clk.uart2_rxd */
> + AM33XX_IOPAD(0x930, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_rx_clk.uart2_txd */
> + >;
> + };
> +
> + uart3_pins: pinmux_uart3 {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd3.uart3_rxd */
> + AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd2.uart3_txd */
> + >;
> + };
> +};
> +
> +&uart0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart0_pins>;
> + status = "okay";
> +};
> +
> +&uart1 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart1_pins>;
> +};
> +
> +&uart2 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart2_pins>;
> + status = "okay";
> +};
> +
> +&uart3 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart3_pins>;
> + status = "okay";
> +};
> +
> +/* USB */
> +&cppi41dma {
> + status = "okay";
> +};
> +
> +&usb_ctrl_mod {
> + status = "okay";
> +};
> +
> +&usb {
> + status = "okay";
> +};
> +
> +&usb0 {
> + status = "okay";
> +};
> +
> +&usb0_phy {
> + status = "okay";
> +};
> +
> +&usb1 {
> + status = "okay";
> + dr_mode = "host";
> +};
> +
> +&usb1_phy {
> + status = "okay";
> +};
> +
> +/* User IO */
> +&am33xx_pinmux {
> + user_buttons_pins: pinmux_user_buttons {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x9e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* emu0.gpio3_7 */
> + AM33XX_IOPAD(0x9e8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* emu1.gpio3_8 */
> + >;
> + };
> +
> + user_leds_pins: pinmux_user_leds {
> + pinctrl-single,pins = <
> + AM33XX_IOPAD(0x880, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn1.gpio1_30 */
> + AM33XX_IOPAD(0x884, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn2.gpio1_31 */
> + >;
> + };
> +};
> +
> +&user_buttons {
Please add properties directly into user_buttons device node.
> + pinctrl-names = "default";
> + pinctrl-0 = <&user_buttons_pins>;
> + status = "okay";
Please remove the redundant property above.
> +
> + button@0 {
> + label = "home";
> + linux,code = <KEY_HOME>;
> + gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>;
> + gpio-key,wakeup;
> + };
> +
> + button@1 {
> + label = "menu";
> + linux,code = <KEY_MENU>;
> + gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>;
> + gpio-key,wakeup;
> + };
> +};
> +
> +&user_leds {
Please add properties directly into user_leds device node.
> + pinctrl-names = "default";
> + pinctrl-0 = <&user_leds_pins>;
> + status = "okay";
Please remove the redundant property above.
> +
> + green {
> + label = "green:user";
> + gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
> + linux,default-trigger = "gpio";
> + default-state = "on";
> + };
> +
> + yellow {
> + label = "yellow:user";
> + gpios = <&gpio1 31 GPIO_ACTIVE_LOW>;
> + linux,default-trigger = "gpio";
> + default-state = "on";
> + };
> +};
> diff --git a/arch/arm/boot/dts/am335x-phycore-rdk.dts b/arch/arm/boot/dts/am335x-phycore-rdk.dts
> new file mode 100644
> index 0000000..305f0b3
> --- /dev/null
> +++ b/arch/arm/boot/dts/am335x-phycore-rdk.dts
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2014 PHYTEC Messtechnik GmbH
> + * Author: Wadim Egorov <w.egorov-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +/dts-v1/;
> +
> +#include "am335x-phycore-som.dtsi"
> +#include "am335x-pcm-953.dtsi"
> +
> +/* SoM */
> +&i2c_eeprom {
> + status = "okay";
> +};
> +
> +&i2c_rtc {
> + status = "okay";
> +};
> +
> +&serial_flash {
> + status = "okay";
> +
> +};
>
--
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