* [PATCH v9 10/13] IIO: ADC: add stm32 DFSDM support for PDM microphone
From: Jonathan Cameron @ 2017-12-17 12:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513241885-32079-11-git-send-email-arnaud.pouliquen@st.com>
On Thu, 14 Dec 2017 09:58:02 +0100
Arnaud Pouliquen <arnaud.pouliquen@st.com> wrote:
> This code offers a way to handle PDM audio microphones in
> ASOC framework. Audio driver should use consumer API.
> A specific management is implemented for DMA, with a
> callback, to allows to handle audio buffers efficiently.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Looks good ;)
> ---
> V8 to V9
> - Create stm32_dfsdm_dma_request
> - Replace devm_of_platform_populate by of_platform_populate.
> - Reorder probe and remove sequences.
>
> .../ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 | 16 +
> drivers/iio/adc/stm32-dfsdm-adc.c | 502 ++++++++++++++++++++-
> include/linux/iio/adc/stm32-dfsdm-adc.h | 18 +
> 3 files changed, 529 insertions(+), 7 deletions(-)
> create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32
> create mode 100644 include/linux/iio/adc/stm32-dfsdm-adc.h
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32
> new file mode 100644
> index 0000000..da98223
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32
> @@ -0,0 +1,16 @@
> +What: /sys/bus/iio/devices/iio:deviceX/in_voltage_spi_clk_freq
> +KernelVersion: 4.14
> +Contact: arnaud.pouliquen at st.com
> +Description:
> + For audio purpose only.
> + Used by audio driver to set/get the spi input frequency.
> + This is mandatory if DFSDM is slave on SPI bus, to
> + provide information on the SPI clock frequency during runtime
> + Notice that the SPI frequency should be a multiple of sample
> + frequency to ensure the precision.
> + if DFSDM input is SPI master
> + Reading SPI clkout frequency,
> + error on writing
> + If DFSDM input is SPI Slave:
> + Reading returns value previously set.
> + Writing value before starting conversions.
> \ No newline at end of file
> diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
> index 68b5920..b03ca3f 100644
> --- a/drivers/iio/adc/stm32-dfsdm-adc.c
> +++ b/drivers/iio/adc/stm32-dfsdm-adc.c
> @@ -6,19 +6,23 @@
> * Author: Arnaud Pouliquen <arnaud.pouliquen@st.com>.
> */
>
> +#include <linux/dmaengine.h>
> +#include <linux/dma-mapping.h>
> #include <linux/interrupt.h>
> #include <linux/iio/buffer.h>
> #include <linux/iio/hw-consumer.h>
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
> #include <linux/module.h>
> -#include <linux/of.h>
> +#include <linux/of_device.h>
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
> #include <linux/slab.h>
>
> #include "stm32-dfsdm.h"
>
> +#define DFSDM_DMA_BUFFER_SIZE (4 * PAGE_SIZE)
> +
> /* Conversion timeout */
> #define DFSDM_TIMEOUT_US 100000
> #define DFSDM_TIMEOUT (msecs_to_jiffies(DFSDM_TIMEOUT_US / 1000))
> @@ -58,6 +62,18 @@ struct stm32_dfsdm_adc {
> struct completion completion;
> u32 *buffer;
>
> + /* Audio specific */
> + unsigned int spi_freq; /* SPI bus clock frequency */
> + unsigned int sample_freq; /* Sample frequency after filter decimation */
> + int (*cb)(const void *data, size_t size, void *cb_priv);
> + void *cb_priv;
> +
> + /* DMA */
> + u8 *rx_buf;
> + unsigned int bufi; /* Buffer current position */
> + unsigned int buf_sz; /* Buffer size */
> + struct dma_chan *dma_chan;
> + dma_addr_t dma_buf;
> };
>
> struct stm32_dfsdm_str2field {
> @@ -351,10 +367,63 @@ int stm32_dfsdm_channel_parse_of(struct stm32_dfsdm *dfsdm,
> return 0;
> }
>
> +static ssize_t dfsdm_adc_audio_get_spiclk(struct iio_dev *indio_dev,
> + uintptr_t priv,
> + const struct iio_chan_spec *chan,
> + char *buf)
> +{
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> +
> + return snprintf(buf, PAGE_SIZE, "%d\n", adc->spi_freq);
> +}
> +
> +static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev,
> + uintptr_t priv,
> + const struct iio_chan_spec *chan,
> + const char *buf, size_t len)
> +{
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> + struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
> + struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[adc->ch_id];
> + unsigned int sample_freq = adc->sample_freq;
> + unsigned int spi_freq;
> + int ret;
> +
> + dev_err(&indio_dev->dev, "enter %s\n", __func__);
> + /* If DFSDM is master on SPI, SPI freq can not be updated */
> + if (ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL)
> + return -EPERM;
> +
> + ret = kstrtoint(buf, 0, &spi_freq);
> + if (ret)
> + return ret;
> +
> + if (!spi_freq)
> + return -EINVAL;
> +
> + if (sample_freq) {
> + if (spi_freq % sample_freq)
> + dev_warn(&indio_dev->dev,
> + "Sampling rate not accurate (%d)\n",
> + spi_freq / (spi_freq / sample_freq));
> +
> + ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / sample_freq));
> + if (ret < 0) {
> + dev_err(&indio_dev->dev,
> + "No filter parameters that match!\n");
> + return ret;
> + }
> + }
> + adc->spi_freq = spi_freq;
> +
> + return len;
> +}
> +
> static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, bool dma)
> {
> struct regmap *regmap = adc->dfsdm->regmap;
> int ret;
> + unsigned int dma_en = 0, cont_en = 0;
>
> ret = stm32_dfsdm_start_channel(adc->dfsdm, adc->ch_id);
> if (ret < 0)
> @@ -365,6 +434,24 @@ static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, bool dma)
> if (ret < 0)
> goto stop_channels;
>
> + if (dma) {
> + /* Enable DMA transfer*/
> + dma_en = DFSDM_CR1_RDMAEN(1);
> + /* Enable conversion triggered by SPI clock*/
> + cont_en = DFSDM_CR1_RCONT(1);
> + }
> + /* Enable DMA transfer*/
> + ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
> + DFSDM_CR1_RDMAEN_MASK, dma_en);
> + if (ret < 0)
> + goto stop_channels;
> +
> + /* Enable conversion triggered by SPI clock*/
> + ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
> + DFSDM_CR1_RCONT_MASK, cont_en);
> + if (ret < 0)
> + goto stop_channels;
> +
> ret = stm32_dfsdm_start_filter(adc->dfsdm, adc->fl_id);
> if (ret < 0)
> goto stop_channels;
> @@ -398,6 +485,231 @@ static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc)
> stm32_dfsdm_stop_channel(adc->dfsdm, adc->ch_id);
> }
>
> +static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev,
> + unsigned int val)
> +{
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> + unsigned int watermark = DFSDM_DMA_BUFFER_SIZE / 2;
> +
> + /*
> + * DMA cyclic transfers are used, buffer is split into two periods.
> + * There should be :
> + * - always one buffer (period) DMA is working on
> + * - one buffer (period) driver pushed to ASoC side.
> + */
> + watermark = min(watermark, val * (unsigned int)(sizeof(u32)));
> + adc->buf_sz = watermark * 2;
> +
> + return 0;
> +}
> +
> +static unsigned int stm32_dfsdm_adc_dma_residue(struct stm32_dfsdm_adc *adc)
> +{
> + struct dma_tx_state state;
> + enum dma_status status;
> +
> + 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 */
> + unsigned int i = adc->buf_sz - state.residue;
> + unsigned int size;
> +
> + /* Return available bytes */
> + if (i >= adc->bufi)
> + size = i - adc->bufi;
> + else
> + size = adc->buf_sz + i - adc->bufi;
> +
> + return size;
> + }
> +
> + return 0;
> +}
> +
> +static void stm32_dfsdm_audio_dma_buffer_done(void *data)
> +{
> + struct iio_dev *indio_dev = data;
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> + int available = stm32_dfsdm_adc_dma_residue(adc);
> + size_t old_pos;
> +
> + /*
> + * FIXME: In Kernel interface does not support cyclic DMA buffer,and
> + * offers only an interface to push data samples per samples.
> + * For this reason IIO buffer interface is not used and interface is
> + * bypassed using a private callback registered by ASoC.
> + * This should be a temporary solution waiting a cyclic DMA engine
> + * support in IIO.
> + */
> +
> + dev_dbg(&indio_dev->dev, "%s: pos = %d, available = %d\n", __func__,
> + adc->bufi, available);
> + old_pos = adc->bufi;
> +
> + while (available >= indio_dev->scan_bytes) {
> + u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi];
> +
> + /* Mask 8 LSB that contains the channel ID */
> + *buffer = (*buffer & 0xFFFFFF00) << 8;
> + available -= indio_dev->scan_bytes;
> + adc->bufi += indio_dev->scan_bytes;
> + if (adc->bufi >= adc->buf_sz) {
> + if (adc->cb)
> + adc->cb(&adc->rx_buf[old_pos],
> + adc->buf_sz - old_pos, adc->cb_priv);
> + adc->bufi = 0;
> + old_pos = 0;
> + }
> + }
> + if (adc->cb)
> + adc->cb(&adc->rx_buf[old_pos], adc->bufi - old_pos,
> + adc->cb_priv);
> +}
> +
> +static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev)
> +{
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> + struct dma_async_tx_descriptor *desc;
> + dma_cookie_t cookie;
> + int ret;
> +
> + if (!adc->dma_chan)
> + return -EINVAL;
> +
> + dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__,
> + adc->buf_sz, adc->buf_sz / 2);
> +
> + /* Prepare a DMA cyclic transaction */
> + desc = dmaengine_prep_dma_cyclic(adc->dma_chan,
> + adc->dma_buf,
> + adc->buf_sz, adc->buf_sz / 2,
> + DMA_DEV_TO_MEM,
> + DMA_PREP_INTERRUPT);
> + if (!desc)
> + return -EBUSY;
> +
> + desc->callback = stm32_dfsdm_audio_dma_buffer_done;
> + desc->callback_param = indio_dev;
> +
> + cookie = dmaengine_submit(desc);
> + ret = dma_submit_error(cookie);
> + if (ret) {
> + dmaengine_terminate_all(adc->dma_chan);
> + return ret;
> + }
> +
> + /* Issue pending DMA requests */
> + dma_async_issue_pending(adc->dma_chan);
> +
> + return 0;
> +}
> +
> +static int stm32_dfsdm_postenable(struct iio_dev *indio_dev)
> +{
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> + int ret;
> +
> + /* Reset adc buffer index */
> + adc->bufi = 0;
> +
> + ret = stm32_dfsdm_start_dfsdm(adc->dfsdm);
> + if (ret < 0)
> + return ret;
> +
> + ret = stm32_dfsdm_start_conv(adc, true);
> + if (ret) {
> + dev_err(&indio_dev->dev, "Can't start conversion\n");
> + goto stop_dfsdm;
> + }
> +
> + if (adc->dma_chan) {
> + ret = stm32_dfsdm_adc_dma_start(indio_dev);
> + if (ret) {
> + dev_err(&indio_dev->dev, "Can't start DMA\n");
> + goto err_stop_conv;
> + }
> + }
> +
> + return 0;
> +
> +err_stop_conv:
> + stm32_dfsdm_stop_conv(adc);
> +stop_dfsdm:
> + stm32_dfsdm_stop_dfsdm(adc->dfsdm);
> +
> + return ret;
> +}
> +
> +static int stm32_dfsdm_predisable(struct iio_dev *indio_dev)
> +{
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> +
> + if (adc->dma_chan)
> + dmaengine_terminate_all(adc->dma_chan);
> +
> + stm32_dfsdm_stop_conv(adc);
> +
> + stm32_dfsdm_stop_dfsdm(adc->dfsdm);
> +
> + return 0;
> +}
> +
> +static const struct iio_buffer_setup_ops stm32_dfsdm_buffer_setup_ops = {
> + .postenable = &stm32_dfsdm_postenable,
> + .predisable = &stm32_dfsdm_predisable,
> +};
> +
> +/**
> + * stm32_dfsdm_get_buff_cb() - register a callback that will be called when
> + * DMA transfer period is achieved.
> + *
> + * @iio_dev: Handle to IIO device.
> + * @cb: Pointer to callback function:
> + * - data: pointer to data buffer
> + * - size: size in byte of the data buffer
> + * - private: pointer to consumer private structure.
> + * @private: Pointer to consumer private structure.
> + */
> +int stm32_dfsdm_get_buff_cb(struct iio_dev *iio_dev,
> + int (*cb)(const void *data, size_t size,
> + void *private),
> + void *private)
> +{
> + struct stm32_dfsdm_adc *adc;
> +
> + if (!iio_dev)
> + return -EINVAL;
> + adc = iio_priv(iio_dev);
> +
> + adc->cb = cb;
> + adc->cb_priv = private;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(stm32_dfsdm_get_buff_cb);
> +
> +/**
> + * stm32_dfsdm_release_buff_cb - unregister buffer callback
> + *
> + * @iio_dev: Handle to IIO device.
> + */
> +int stm32_dfsdm_release_buff_cb(struct iio_dev *iio_dev)
> +{
> + struct stm32_dfsdm_adc *adc;
> +
> + if (!iio_dev)
> + return -EINVAL;
> + adc = iio_priv(iio_dev);
> +
> + adc->cb = NULL;
> + adc->cb_priv = NULL;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(stm32_dfsdm_release_buff_cb);
> +
> static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev,
> const struct iio_chan_spec *chan, int *res)
> {
> @@ -453,15 +765,41 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
> {
> struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
> + struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[adc->ch_id];
> + unsigned int spi_freq = adc->spi_freq;
> int ret = -EINVAL;
>
> - if (mask == IIO_CHAN_INFO_OVERSAMPLING_RATIO) {
> + switch (mask) {
> + case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> ret = stm32_dfsdm_set_osrs(fl, 0, val);
> if (!ret)
> adc->oversamp = val;
> +
> + return ret;
> +
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + if (!val)
> + return -EINVAL;
> + if (ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL)
> + spi_freq = adc->dfsdm->spi_master_freq;
> +
> + if (spi_freq % val)
> + dev_warn(&indio_dev->dev,
> + "Sampling rate not accurate (%d)\n",
> + spi_freq / (spi_freq / val));
> +
> + ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / val));
> + if (ret < 0) {
> + dev_err(&indio_dev->dev,
> + "Not able to find parameter that match!\n");
> + return ret;
> + }
> + adc->sample_freq = val;
> +
> + return 0;
> }
>
> - return ret;
> + return -EINVAL;
> }
>
> static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
> @@ -494,11 +832,22 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
> *val = adc->oversamp;
>
> return IIO_VAL_INT;
> +
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + *val = adc->sample_freq;
> +
> + return IIO_VAL_INT;
> }
>
> return -EINVAL;
> }
>
> +static const struct iio_info stm32_dfsdm_info_audio = {
> + .hwfifo_set_watermark = stm32_dfsdm_set_watermark,
> + .read_raw = stm32_dfsdm_read_raw,
> + .write_raw = stm32_dfsdm_write_raw,
> +};
> +
> static const struct iio_info stm32_dfsdm_info_adc = {
> .read_raw = stm32_dfsdm_read_raw,
> .write_raw = stm32_dfsdm_write_raw,
> @@ -531,6 +880,70 @@ static irqreturn_t stm32_dfsdm_irq(int irq, void *arg)
> return IRQ_HANDLED;
> }
>
> +/*
> + * Define external info for SPI Frequency and audio sampling rate that can be
> + * configured by ASoC driver through consumer.h API
> + */
> +static const struct iio_chan_spec_ext_info dfsdm_adc_audio_ext_info[] = {
> + /* spi_clk_freq : clock freq on SPI/manchester bus used by channel */
> + {
> + .name = "spi_clk_freq",
> + .shared = IIO_SHARED_BY_TYPE,
> + .read = dfsdm_adc_audio_get_spiclk,
> + .write = dfsdm_adc_audio_set_spiclk,
> + },
> + {},
> +};
> +
> +static void stm32_dfsdm_dma_release(struct iio_dev *indio_dev)
> +{
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> +
> + if (adc->dma_chan) {
> + dma_free_coherent(adc->dma_chan->device->dev,
> + DFSDM_DMA_BUFFER_SIZE,
> + adc->rx_buf, adc->dma_buf);
> + dma_release_channel(adc->dma_chan);
> + }
> +}
> +
> +static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev)
> +{
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> + struct dma_slave_config config = {
> + .src_addr = (dma_addr_t)adc->dfsdm->phys_base +
> + DFSDM_RDATAR(adc->fl_id),
> + .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
> + };
> + int ret;
> +
> + adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx");
> + if (!adc->dma_chan)
> + return -EINVAL;
> +
> + adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev,
> + DFSDM_DMA_BUFFER_SIZE,
> + &adc->dma_buf, GFP_KERNEL);
> + if (!adc->rx_buf) {
> + ret = -ENOMEM;
> + goto err_release;
> + }
> +
> + ret = dmaengine_slave_config(adc->dma_chan, &config);
> + if (ret)
> + goto err_free;
> +
> + return 0;
> +
> +err_free:
> + dma_free_coherent(adc->dma_chan->device->dev, DFSDM_DMA_BUFFER_SIZE,
> + adc->rx_buf, adc->dma_buf);
> +err_release:
> + dma_release_channel(adc->dma_chan);
> +
> + return ret;
> +}
> +
> static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
> struct iio_chan_spec *ch)
> {
> @@ -551,7 +964,12 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
> ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
> ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
>
> - ch->scan_type.sign = 'u';
> + if (adc->dev_data->type == DFSDM_AUDIO) {
> + ch->scan_type.sign = 's';
> + ch->ext_info = dfsdm_adc_audio_ext_info;
> + } else {
> + ch->scan_type.sign = 'u';
> + }
> ch->scan_type.realbits = 24;
> ch->scan_type.storagebits = 32;
> adc->ch_id = ch->channel;
> @@ -560,6 +978,39 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
> &adc->dfsdm->ch_list[ch->channel]);
> }
>
> +static int stm32_dfsdm_audio_init(struct iio_dev *indio_dev)
> +{
> + struct iio_chan_spec *ch;
> + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> + struct stm32_dfsdm_channel *d_ch;
> + int ret;
> +
> + indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
> + indio_dev->setup_ops = &stm32_dfsdm_buffer_setup_ops;
> +
> + ch = devm_kzalloc(&indio_dev->dev, sizeof(*ch), GFP_KERNEL);
> + if (!ch)
> + return -ENOMEM;
> +
> + ch->scan_index = 0;
> +
> + ret = stm32_dfsdm_adc_chan_init_one(indio_dev, ch);
> + if (ret < 0) {
> + dev_err(&indio_dev->dev, "Channels init failed\n");
> + return ret;
> + }
> + ch->info_mask_separate = BIT(IIO_CHAN_INFO_SAMP_FREQ);
> +
> + d_ch = &adc->dfsdm->ch_list[adc->ch_id];
> + if (d_ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL)
> + adc->spi_freq = adc->dfsdm->spi_master_freq;
> +
> + indio_dev->num_channels = 1;
> + indio_dev->channels = ch;
> +
> + return stm32_dfsdm_dma_request(indio_dev);
> +}
> +
> static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
> {
> struct iio_chan_spec *ch;
> @@ -612,11 +1063,20 @@ static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_adc_data = {
> .init = stm32_dfsdm_adc_init,
> };
>
> +static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_audio_data = {
> + .type = DFSDM_AUDIO,
> + .init = stm32_dfsdm_audio_init,
> +};
> +
> static const struct of_device_id stm32_dfsdm_adc_match[] = {
> {
> .compatible = "st,stm32-dfsdm-adc",
> .data = &stm32h7_dfsdm_adc_data,
> },
> + {
> + .compatible = "st,stm32-dfsdm-dmic",
> + .data = &stm32h7_dfsdm_audio_data,
> + },
> {}
> };
>
> @@ -667,8 +1127,13 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
> name = devm_kzalloc(dev, sizeof("dfsdm-adc0"), GFP_KERNEL);
> if (!name)
> return -ENOMEM;
> - iio->info = &stm32_dfsdm_info_adc;
> - snprintf(name, sizeof("dfsdm-adc0"), "dfsdm-adc%d", adc->fl_id);
> + if (dev_data->type == DFSDM_AUDIO) {
> + iio->info = &stm32_dfsdm_info_audio;
> + snprintf(name, sizeof("dfsdm-pdm0"), "dfsdm-pdm%d", adc->fl_id);
> + } else {
> + iio->info = &stm32_dfsdm_info_adc;
> + snprintf(name, sizeof("dfsdm-adc0"), "dfsdm-adc%d", adc->fl_id);
> + }
> iio->name = name;
>
> /*
> @@ -700,7 +1165,27 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
> if (ret < 0)
> return ret;
>
> - return iio_device_register(iio);
> + ret = iio_device_register(iio);
> + if (ret < 0)
> + goto err_cleanup;
> +
> + dev_err(dev, "of_platform_populate\n");
> + if (dev_data->type == DFSDM_AUDIO) {
> + ret = of_platform_populate(np, NULL, NULL, dev);
> + if (ret < 0) {
> + dev_err(dev, "Failed to find an audio DAI\n");
> + goto err_unregister;
> + }
> + }
> +
> + return 0;
> +
> +err_unregister:
> + iio_device_unregister(iio);
> +err_cleanup:
> + stm32_dfsdm_dma_release(iio);
> +
> + return ret;
> }
>
> static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
> @@ -708,7 +1193,10 @@ static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
> struct stm32_dfsdm_adc *adc = platform_get_drvdata(pdev);
> struct iio_dev *indio_dev = iio_priv_to_dev(adc);
>
> + if (adc->dev_data->type == DFSDM_AUDIO)
> + of_platform_depopulate(&pdev->dev);
> iio_device_unregister(indio_dev);
> + stm32_dfsdm_dma_release(indio_dev);
>
> return 0;
> }
> diff --git a/include/linux/iio/adc/stm32-dfsdm-adc.h b/include/linux/iio/adc/stm32-dfsdm-adc.h
> new file mode 100644
> index 0000000..e7dc7a5
> --- /dev/null
> +++ b/include/linux/iio/adc/stm32-dfsdm-adc.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * This file discribe the STM32 DFSDM IIO driver API for audio part
> + *
> + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
> + * Author(s): Arnaud Pouliquen <arnaud.pouliquen@st.com>.
> + */
> +
> +#ifndef STM32_DFSDM_ADC_H
> +#define STM32_DFSDM_ADC_H
> +
> +int stm32_dfsdm_get_buff_cb(struct iio_dev *iio_dev,
> + int (*cb)(const void *data, size_t size,
> + void *private),
> + void *private);
> +int stm32_dfsdm_release_buff_cb(struct iio_dev *iio_dev);
> +
> +#endif
^ permalink raw reply
* [PATCH v9 13/13] ASoC: stm32: add DFSDM DAI support
From: Jonathan Cameron @ 2017-12-17 12:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513241885-32079-14-git-send-email-arnaud.pouliquen@st.com>
On Thu, 14 Dec 2017 09:58:05 +0100
Arnaud Pouliquen <arnaud.pouliquen@st.com> wrote:
> Add driver to handle DAI interface for PDM microphones connected
> to Digital Filter for Sigma Delta Modulators IP.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
For the IIO parts (I'm not knowledgeable enough about the sound side to
offer a proper review!)
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
So Mark, over to you. I'm happy if you want to do the immutable branch
once any issue you find are fixed, or I can do it. I'm just looking
for acks or a pull request now.
Jonathan
> ---
> sound/soc/stm/Kconfig | 11 ++
> sound/soc/stm/Makefile | 3 +
> sound/soc/stm/stm32_adfsdm.c | 347 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 361 insertions(+)
> create mode 100644 sound/soc/stm/stm32_adfsdm.c
>
> diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
> index 3398e6c..a78f770 100644
> --- a/sound/soc/stm/Kconfig
> +++ b/sound/soc/stm/Kconfig
> @@ -28,4 +28,15 @@ config SND_SOC_STM32_SPDIFRX
> help
> Say Y if you want to enable S/PDIF capture for STM32
>
> +config SND_SOC_STM32_DFSDM
> + tristate "SoC Audio support for STM32 DFSDM"
> + depends on (ARCH_STM32 && OF && STM32_DFSDM_ADC) || COMPILE_TEST
> + depends on SND_SOC
> + select SND_SOC_GENERIC_DMAENGINE_PCM
> + select SND_SOC_DMIC
> + select IIO_BUFFER_CB
> + help
> + Select this option to enable the STM32 Digital Filter
> + for Sigma Delta Modulators (DFSDM) driver used
> + in various STM32 series for digital microphone capture.
> endmenu
> diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
> index 4ed22e6..53e90e6 100644
> --- a/sound/soc/stm/Makefile
> +++ b/sound/soc/stm/Makefile
> @@ -12,3 +12,6 @@ obj-$(CONFIG_SND_SOC_STM32_I2S) += snd-soc-stm32-i2s.o
> # SPDIFRX
> snd-soc-stm32-spdifrx-objs := stm32_spdifrx.o
> obj-$(CONFIG_SND_SOC_STM32_SPDIFRX) += snd-soc-stm32-spdifrx.o
> +
> +#DFSDM
> +obj-$(CONFIG_SND_SOC_STM32_DFSDM) += stm32_adfsdm.o
> diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c
> new file mode 100644
> index 0000000..af50891
> --- /dev/null
> +++ b/sound/soc/stm/stm32_adfsdm.c
> @@ -0,0 +1,347 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * This file is part of STM32 DFSDM ASoC DAI driver
> + *
> + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
> + * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com>
> + * Olivier Moysan <olivier.moysan@st.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/consumer.h>
> +#include <linux/iio/adc/stm32-dfsdm-adc.h>
> +
> +#include <sound/pcm.h>
> +#include <sound/soc.h>
> +
> +#define STM32_ADFSDM_DRV_NAME "stm32-adfsdm"
> +
> +#define DFSDM_MAX_PERIOD_SIZE (PAGE_SIZE / 2)
> +#define DFSDM_MAX_PERIODS 6
> +
> +struct stm32_adfsdm_priv {
> + struct snd_soc_dai_driver dai_drv;
> + struct snd_pcm_substream *substream;
> + struct device *dev;
> +
> + /* IIO */
> + struct iio_channel *iio_ch;
> + struct iio_cb_buffer *iio_cb;
> + bool iio_active;
> +
> + /* PCM buffer */
> + unsigned char *pcm_buff;
> + unsigned int pos;
> +};
> +
> +static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = {
> + .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
> + SNDRV_PCM_INFO_PAUSE,
> + .formats = SNDRV_PCM_FMTBIT_S32_LE,
> +
> + .rate_min = 8000,
> + .rate_max = 32000,
> +
> + .channels_min = 1,
> + .channels_max = 1,
> +
> + .periods_min = 2,
> + .periods_max = DFSDM_MAX_PERIODS,
> +
> + .period_bytes_max = DFSDM_MAX_PERIOD_SIZE,
> + .buffer_bytes_max = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE
> +};
> +
> +static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream,
> + struct snd_soc_dai *dai)
> +{
> + struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
> +
> + if (priv->iio_active) {
> + iio_channel_stop_all_cb(priv->iio_cb);
> + priv->iio_active = false;
> + }
> +}
> +
> +static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
> + struct snd_soc_dai *dai)
> +{
> + struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
> + int ret;
> +
> + ret = iio_write_channel_attribute(priv->iio_ch,
> + substream->runtime->rate, 0,
> + IIO_CHAN_INFO_SAMP_FREQ);
> + if (ret < 0) {
> + dev_err(dai->dev, "%s: Failed to set %d sampling rate\n",
> + __func__, substream->runtime->rate);
> + return ret;
> + }
> +
> + if (!priv->iio_active) {
> + ret = iio_channel_start_all_cb(priv->iio_cb);
> + if (!ret)
> + priv->iio_active = true;
> + else
> + dev_err(dai->dev, "%s: IIO channel start failed (%d)\n",
> + __func__, ret);
> + }
> +
> + return ret;
> +}
> +
> +static int stm32_adfsdm_set_sysclk(struct snd_soc_dai *dai, int clk_id,
> + unsigned int freq, int dir)
> +{
> + struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
> + ssize_t size;
> + char str_freq[10];
> +
> + dev_dbg(dai->dev, "%s: Enter for freq %d\n", __func__, freq);
> +
> + /* Set IIO frequency if CODEC is master as clock comes from SPI_IN */
> +
> + snprintf(str_freq, sizeof(str_freq), "%d\n", freq);
> + size = iio_write_channel_ext_info(priv->iio_ch, "spi_clk_freq",
> + str_freq, sizeof(str_freq));
> + if (size != sizeof(str_freq)) {
> + dev_err(dai->dev, "%s: Failed to set SPI clock\n",
> + __func__);
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> +static const struct snd_soc_dai_ops stm32_adfsdm_dai_ops = {
> + .shutdown = stm32_adfsdm_shutdown,
> + .prepare = stm32_adfsdm_dai_prepare,
> + .set_sysclk = stm32_adfsdm_set_sysclk,
> +};
> +
> +static const struct snd_soc_dai_driver stm32_adfsdm_dai = {
> + .capture = {
> + .channels_min = 1,
> + .channels_max = 1,
> + .formats = SNDRV_PCM_FMTBIT_S32_LE,
> + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
> + SNDRV_PCM_RATE_32000),
> + },
> + .ops = &stm32_adfsdm_dai_ops,
> +};
> +
> +static const struct snd_soc_component_driver stm32_adfsdm_dai_component = {
> + .name = "stm32_dfsdm_audio",
> +};
> +
> +static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private)
> +{
> + struct stm32_adfsdm_priv *priv = private;
> + struct snd_soc_pcm_runtime *rtd = priv->substream->private_data;
> + u8 *pcm_buff = priv->pcm_buff;
> + u8 *src_buff = (u8 *)data;
> + unsigned int buff_size = snd_pcm_lib_buffer_bytes(priv->substream);
> + unsigned int period_size = snd_pcm_lib_period_bytes(priv->substream);
> + unsigned int old_pos = priv->pos;
> + unsigned int cur_size = size;
> +
> + dev_dbg(rtd->dev, "%s: buff_add :%p, pos = %d, size = %zu\n",
> + __func__, &pcm_buff[priv->pos], priv->pos, size);
> +
> + if ((priv->pos + size) > buff_size) {
> + memcpy(&pcm_buff[priv->pos], src_buff, buff_size - priv->pos);
> + cur_size -= buff_size - priv->pos;
> + priv->pos = 0;
> + }
> +
> + memcpy(&pcm_buff[priv->pos], &src_buff[size - cur_size], cur_size);
> + priv->pos = (priv->pos + cur_size) % buff_size;
> +
> + if (cur_size != size || (old_pos && (old_pos % period_size < size)))
> + snd_pcm_period_elapsed(priv->substream);
> +
> + return 0;
> +}
> +
> +static int stm32_adfsdm_trigger(struct snd_pcm_substream *substream, int cmd)
> +{
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct stm32_adfsdm_priv *priv =
> + snd_soc_dai_get_drvdata(rtd->cpu_dai);
> +
> + switch (cmd) {
> + case SNDRV_PCM_TRIGGER_START:
> + case SNDRV_PCM_TRIGGER_RESUME:
> + priv->pos = 0;
> + return stm32_dfsdm_get_buff_cb(priv->iio_ch->indio_dev,
> + stm32_afsdm_pcm_cb, priv);
> + case SNDRV_PCM_TRIGGER_SUSPEND:
> + case SNDRV_PCM_TRIGGER_STOP:
> + return stm32_dfsdm_release_buff_cb(priv->iio_ch->indio_dev);
> + }
> +
> + return -EINVAL;
> +}
> +
> +static int stm32_adfsdm_pcm_open(struct snd_pcm_substream *substream)
> +{
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
> + int ret;
> +
> + ret = snd_soc_set_runtime_hwparams(substream, &stm32_adfsdm_pcm_hw);
> + if (!ret)
> + priv->substream = substream;
> +
> + return ret;
> +}
> +
> +static int stm32_adfsdm_pcm_close(struct snd_pcm_substream *substream)
> +{
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct stm32_adfsdm_priv *priv =
> + snd_soc_dai_get_drvdata(rtd->cpu_dai);
> +
> + snd_pcm_lib_free_pages(substream);
> + priv->substream = NULL;
> +
> + return 0;
> +}
> +
> +static snd_pcm_uframes_t stm32_adfsdm_pcm_pointer(
> + struct snd_pcm_substream *substream)
> +{
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct stm32_adfsdm_priv *priv =
> + snd_soc_dai_get_drvdata(rtd->cpu_dai);
> +
> + return bytes_to_frames(substream->runtime, priv->pos);
> +}
> +
> +static int stm32_adfsdm_pcm_hw_params(struct snd_pcm_substream *substream,
> + struct snd_pcm_hw_params *params)
> +{
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct stm32_adfsdm_priv *priv =
> + snd_soc_dai_get_drvdata(rtd->cpu_dai);
> + int ret;
> +
> + ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
> + if (ret < 0)
> + return ret;
> + priv->pcm_buff = substream->runtime->dma_area;
> +
> + return iio_channel_cb_set_buffer_watermark(priv->iio_cb,
> + params_period_size(params));
> +}
> +
> +static int stm32_adfsdm_pcm_hw_free(struct snd_pcm_substream *substream)
> +{
> + snd_pcm_lib_free_pages(substream);
> +
> + return 0;
> +}
> +
> +static struct snd_pcm_ops stm32_adfsdm_pcm_ops = {
> + .open = stm32_adfsdm_pcm_open,
> + .close = stm32_adfsdm_pcm_close,
> + .hw_params = stm32_adfsdm_pcm_hw_params,
> + .hw_free = stm32_adfsdm_pcm_hw_free,
> + .trigger = stm32_adfsdm_trigger,
> + .pointer = stm32_adfsdm_pcm_pointer,
> +};
> +
> +static int stm32_adfsdm_pcm_new(struct snd_soc_pcm_runtime *rtd)
> +{
> + struct snd_pcm *pcm = rtd->pcm;
> + struct stm32_adfsdm_priv *priv =
> + snd_soc_dai_get_drvdata(rtd->cpu_dai);
> + unsigned int size = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE;
> +
> + return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
> + priv->dev, size, size);
> +}
> +
> +static void stm32_adfsdm_pcm_free(struct snd_pcm *pcm)
> +{
> + struct snd_pcm_substream *substream;
> + struct snd_soc_pcm_runtime *rtd;
> + struct stm32_adfsdm_priv *priv;
> +
> + substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
> + if (substream) {
> + rtd = substream->private_data;
> + priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
> +
> + snd_pcm_lib_preallocate_free_for_all(pcm);
> + }
> +}
> +
> +static struct snd_soc_platform_driver stm32_adfsdm_soc_platform = {
> + .ops = &stm32_adfsdm_pcm_ops,
> + .pcm_new = stm32_adfsdm_pcm_new,
> + .pcm_free = stm32_adfsdm_pcm_free,
> +};
> +
> +static const struct of_device_id stm32_adfsdm_of_match[] = {
> + {.compatible = "st,stm32h7-dfsdm-dai"},
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, stm32_adfsdm_of_match);
> +
> +static int stm32_adfsdm_probe(struct platform_device *pdev)
> +{
> + struct stm32_adfsdm_priv *priv;
> + int ret;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->dev = &pdev->dev;
> + priv->dai_drv = stm32_adfsdm_dai;
> +
> + dev_set_drvdata(&pdev->dev, priv);
> +
> + ret = devm_snd_soc_register_component(&pdev->dev,
> + &stm32_adfsdm_dai_component,
> + &priv->dai_drv, 1);
> + if (ret < 0)
> + return ret;
> +
> + /* Associate iio channel */
> + priv->iio_ch = devm_iio_channel_get_all(&pdev->dev);
> + if (IS_ERR(priv->iio_ch))
> + return PTR_ERR(priv->iio_ch);
> +
> + priv->iio_cb = iio_channel_get_all_cb(&pdev->dev, NULL, NULL);
> + if (IS_ERR(priv->iio_cb))
> + return PTR_ERR(priv->iio_ch);
> +
> + ret = devm_snd_soc_register_platform(&pdev->dev,
> + &stm32_adfsdm_soc_platform);
> + if (ret < 0)
> + dev_err(&pdev->dev, "%s: Failed to register PCM platform\n",
> + __func__);
> +
> + return ret;
> +}
> +
> +static struct platform_driver stm32_adfsdm_driver = {
> + .driver = {
> + .name = STM32_ADFSDM_DRV_NAME,
> + .of_match_table = stm32_adfsdm_of_match,
> + },
> + .probe = stm32_adfsdm_probe,
> +};
> +
> +module_platform_driver(stm32_adfsdm_driver);
> +
> +MODULE_DESCRIPTION("stm32 DFSDM DAI driver");
> +MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:" STM32_ADFSDM_DRV_NAME);
^ permalink raw reply
* pxa3xx_nand times out in 4.14 with JFFS2
From: Willy Tarreau @ 2017-12-17 13:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171217133355.618e5f92@bbrezillon>
Hi Boris!
On Sun, Dec 17, 2017 at 01:33:55PM +0100, Boris Brezillon wrote:
> You should have a look at this thread [1], and in case you don't want
> to read everything,
I've read it entirely, it was very instructive!
> you can just test the solution proposed here [2].
>
> [1]http://linux-mtd.infradead.narkive.com/Rd5UaRPO/bug-pxa3xx-wait-time-out-when-scanning-for-bb
> [2]http://patchwork.ozlabs.org/patch/847411/
Well done for such a quick reply! I can confirm that your proposed
patch below does fix it for me! Now I understand why only jffs2 was
triggering the issue if it only affects OOB, and I guess I would have
faced it as well with nanddump had I thought about testing it.
I'm queuing this one here to continue to progress on my machine, feel
free to add my tested-by if the patch gets merged, or to ping me to
test any other option you'd like to confirm!
Thanks!
Willy
---
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 321a90c..adb9fd8 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -950,6 +950,7 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
switch (command) {
case NAND_CMD_READ0:
+ case NAND_CMD_READOOB:
case NAND_CMD_PAGEPROG:
info->use_ecc = 1;
break;
^ permalink raw reply related
* pxa3xx_nand times out in 4.14 with JFFS2
From: Ezequiel Garcia @ 2017-12-17 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171217131705.GA30726@1wt.eu>
On 17 December 2017 at 10:17, Willy Tarreau <w@1wt.eu> wrote:
> Hi Boris!
>
> On Sun, Dec 17, 2017 at 01:33:55PM +0100, Boris Brezillon wrote:
>> You should have a look at this thread [1], and in case you don't want
>> to read everything,
>
> I've read it entirely, it was very instructive!
>
>> you can just test the solution proposed here [2].
>>
>> [1]http://linux-mtd.infradead.narkive.com/Rd5UaRPO/bug-pxa3xx-wait-time-out-when-scanning-for-bb
>> [2]http://patchwork.ozlabs.org/patch/847411/
>
> Well done for such a quick reply! I can confirm that your proposed
> patch below does fix it for me! Now I understand why only jffs2 was
> triggering the issue if it only affects OOB, and I guess I would have
> faced it as well with nanddump had I thought about testing it.
>
> I'm queuing this one here to continue to progress on my machine, feel
> free to add my tested-by if the patch gets merged, or to ping me to
> test any other option you'd like to confirm!
>
> Thanks!
> Willy
>
> ---
>
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 321a90c..adb9fd8 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -950,6 +950,7 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
>
> switch (command) {
> case NAND_CMD_READ0:
> + case NAND_CMD_READOOB:
> case NAND_CMD_PAGEPROG:
> info->use_ecc = 1;
> break;
>
>
If we can confirm that with this patch, bad block markers can be read
without issues, then it's good to go.
Willy, think you could try to test that?
--
Ezequiel Garc?a, VanguardiaSur
www.vanguardiasur.com.ar
^ permalink raw reply
* pxa3xx_nand times out in 4.14 with JFFS2
From: Ezequiel Garcia @ 2017-12-17 14:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171217120503.GA3323@1wt.eu>
On 17 December 2017 at 09:05, Willy Tarreau <w@1wt.eu> wrote:
> Hello,
>
> I recently bought a Linksys WRT1900ACS which hosts an Armada 385 and a
> NAND flash. While I could get OpenWRT to work flawlessly on it using
> kernel 4.4, mainline 4.14.6 fails with a lot of such messages :
>
> pxa3xx-nand f10d0000.flash: Wait time out!!!
>
Boris,
Any idea why this issue is on v4.14, but not observed on v4.4?
Also, is this somehow related to Armada 385 only?
--
Ezequiel Garc?a, VanguardiaSur
www.vanguardiasur.com.ar
^ permalink raw reply
* pxa3xx_nand times out in 4.14 with JFFS2
From: Boris Brezillon @ 2017-12-17 14:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAAEAJfBUyhvi68A6QEJRywq9hxMBYuJ4m+O6ogBtV1nkeBR_og@mail.gmail.com>
On Sun, 17 Dec 2017 11:27:51 -0300
Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> wrote:
> On 17 December 2017 at 09:05, Willy Tarreau <w@1wt.eu> wrote:
> > Hello,
> >
> > I recently bought a Linksys WRT1900ACS which hosts an Armada 385 and a
> > NAND flash. While I could get OpenWRT to work flawlessly on it using
> > kernel 4.4, mainline 4.14.6 fails with a lot of such messages :
> >
> > pxa3xx-nand f10d0000.flash: Wait time out!!!
> >
>
> Boris,
>
> Any idea why this issue is on v4.14, but not observed on v4.4?
I have absolutely no idea.
>
> Also, is this somehow related to Armada 385 only?
I doubt it. My guess is that almost nobody uses JFFS2 these days, which
may explain why this problem has not been detected before.
^ permalink raw reply
* pxa3xx_nand times out in 4.14 with JFFS2
From: Willy Tarreau @ 2017-12-17 15:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171217155305.16c5bb4f@bbrezillon>
On Sun, Dec 17, 2017 at 03:53:05PM +0100, Boris Brezillon wrote:
> On Sun, 17 Dec 2017 11:27:51 -0300
> Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> wrote:
>
> > On 17 December 2017 at 09:05, Willy Tarreau <w@1wt.eu> wrote:
> > > Hello,
> > >
> > > I recently bought a Linksys WRT1900ACS which hosts an Armada 385 and a
> > > NAND flash. While I could get OpenWRT to work flawlessly on it using
> > > kernel 4.4, mainline 4.14.6 fails with a lot of such messages :
> > >
> > > pxa3xx-nand f10d0000.flash: Wait time out!!!
> > >
> >
> > Boris,
> >
> > Any idea why this issue is on v4.14, but not observed on v4.4?
>
> I have absolutely no idea.
Warning, the 4.4 in openwrt very likely is heavily patched! That's also
why I'm moving to mainline instead (to know what I'm using). I've seen
some nand timeout changes in the patches. I don't know if anything else
is applied to the driver (it's always a pain to find where to dig, as
there is no unified list of all patches for a given architecture).
> > Also, is this somehow related to Armada 385 only?
>
> I doubt it. My guess is that almost nobody uses JFFS2 these days, which
> may explain why this problem has not been detected before.
That's very likely indeed.
Ezequiel, to answer your question about dumping bad blocks, this flash
doesn't report any bad blocks yet (cool) however I could issue "nanddump
--oob --bb=dumpbad" on all MTD devices without issues. The last one has
8 BBT blocks. I didn't find any bad block, but I could confirm that
dumping oob apparently worked as it returned data that differs from the
non-oob dump on the last partition (the one containing the oob blocks),
so I guess we're fine :
# cmp -l raw oob
40822793 377 61
40822794 377 164
40822795 377 142
40822796 377 102
40822797 377 126
40822798 377 115
40822799 377 1
40957961 377 115
40957962 377 126
40957963 377 102
40957964 377 142
40957965 377 164
40957966 377 60
40957967 377 1
Hoping this helps,
Willy
^ permalink raw reply
* pxa3xx_nand times out in 4.14 with JFFS2
From: Willy Tarreau @ 2017-12-17 15:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171217150043.GA1403@1wt.eu>
On Sun, Dec 17, 2017 at 04:00:43PM +0100, Willy Tarreau wrote:
> > > Any idea why this issue is on v4.14, but not observed on v4.4?
> >
> > I have absolutely no idea.
>
> Warning, the 4.4 in openwrt very likely is heavily patched! That's also
> why I'm moving to mainline instead (to know what I'm using). I've seen
> some nand timeout changes in the patches. I don't know if anything else
> is applied to the driver (it's always a pain to find where to dig, as
> there is no unified list of all patches for a given architecture).
Given the description here, I suspect this is how they got rid of the
problem there :
https://github.com/lede-project/source/blob/lede-17.01/target/linux/mvebu/patches-4.4/110-pxa3xxx_revert_irq_thread.patch
---
Revert "mtd: pxa3xx-nand: handle PIO in threaded interrupt"
This reverts commit 24542257a3b987025d4b998ec2d15e556c98ad3f
This upstream change has been causing spurious timeouts on accesses
to the NAND flash if something else on the system is causing
significant latency.
Nothing guarantees that the thread will run in time, so the
usual timeout is unreliable.
---
Willy
^ permalink raw reply
* [PATCH net-next 2/2 v8] net: ethernet: Add a driver for Gemini gigabit ethernet
From: Linus Walleij @ 2017-12-17 15:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171211.141651.2190843744682664766.davem@davemloft.net>
On Mon, Dec 11, 2017 at 8:16 PM, David Miller <davem@davemloft.net> wrote:
> From: Linus Walleij <linus.walleij@linaro.org>
>> +if NET_VENDOR_CORTINA
>> +
>> +config GEMINI_ETHERNET
>> + tristate "Gemini Gigabit Ethernet support"
>> + depends on ARCH_GEMINI
>> + depends on OF
>> + select PHYLIB
>> + select CRC32
>> + ---help---
>> + This driver supports StorLink SL351x (Gemini) dual Gigabit Ethernet.
>
> Make this driver buildable anywhere, you don't use any platform architecture
> specific features.
I pushed the recent v9 set where I remove the dep on ARCH_GEMINI
and the autobuilders complain a lot about the use of dma_to_pfn()
which turns out to be a ARM thing from <asm/dma-mapping.h>
included from <linux/dma-mapping.h>.
I will try switching to functions from the generic dma-mapping API
and fix it up and send a v10.
Yours,
Linus Walleij
^ permalink raw reply
* pxa3xx_nand times out in 4.14 with JFFS2
From: Ezequiel Garcia @ 2017-12-17 15:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171217150043.GA1403@1wt.eu>
On 17 December 2017 at 12:00, Willy Tarreau <w@1wt.eu> wrote:
> On Sun, Dec 17, 2017 at 03:53:05PM +0100, Boris Brezillon wrote:
>> On Sun, 17 Dec 2017 11:27:51 -0300
>> Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> wrote:
>>
>> > On 17 December 2017 at 09:05, Willy Tarreau <w@1wt.eu> wrote:
>> > > Hello,
>> > >
>> > > I recently bought a Linksys WRT1900ACS which hosts an Armada 385 and a
>> > > NAND flash. While I could get OpenWRT to work flawlessly on it using
>> > > kernel 4.4, mainline 4.14.6 fails with a lot of such messages :
>> > >
>> > > pxa3xx-nand f10d0000.flash: Wait time out!!!
>> > >
>> >
>> > Boris,
>> >
>> > Any idea why this issue is on v4.14, but not observed on v4.4?
>>
>> I have absolutely no idea.
>
> Warning, the 4.4 in openwrt very likely is heavily patched! That's also
> why I'm moving to mainline instead (to know what I'm using). I've seen
> some nand timeout changes in the patches. I don't know if anything else
> is applied to the driver (it's always a pain to find where to dig, as
> there is no unified list of all patches for a given architecture).
>
>> > Also, is this somehow related to Armada 385 only?
>>
>> I doubt it. My guess is that almost nobody uses JFFS2 these days, which
>> may explain why this problem has not been detected before.
>
> That's very likely indeed.
>
> Ezequiel, to answer your question about dumping bad blocks, this flash
> doesn't report any bad blocks yet (cool) however I could issue "nanddump
> --oob --bb=dumpbad" on all MTD devices without issues. The last one has
> 8 BBT blocks. I didn't find any bad block, but I could confirm that
> dumping oob apparently worked as it returned data that differs from the
> non-oob dump on the last partition (the one containing the oob blocks),
> so I guess we're fine :
>
If not too much to ask, this is the test that I believe is needed.
You seem to have a setup ready, hence why I'm asking you, if
possible, to give it a shot.
(1) Scrub the BBT from the NAND. Or scrub the whole NAND.
You cannot do this from the kernel, it needs to be done from the bootloader.
(2) Mark a couple blocks as bad using the OOB -- AFAICR, there
was a command to do this in the bootloader.
(3) Boot, let Linux create the BBT and see if it catches the bad blocks.
This would guarantee that devices with factory bad blocks,
(and no BBT), would be OK with this patch.
--
Ezequiel Garc?a, VanguardiaSur
www.vanguardiasur.com.ar
^ permalink raw reply
* pxa3xx_nand times out in 4.14 with JFFS2
From: Willy Tarreau @ 2017-12-17 16:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAAEAJfD47bGTSppEqcRszjAgBUjiCevmdYLKfsQTPYMcVu8VDA@mail.gmail.com>
On Sun, Dec 17, 2017 at 12:53:36PM -0300, Ezequiel Garcia wrote:
> If not too much to ask, this is the test that I believe is needed.
> You seem to have a setup ready, hence why I'm asking you, if
> possible, to give it a shot.
>
> (1) Scrub the BBT from the NAND. Or scrub the whole NAND.
> You cannot do this from the kernel, it needs to be done from the bootloader.
>
> (2) Mark a couple blocks as bad using the OOB -- AFAICR, there
> was a command to do this in the bootloader.
>
> (3) Boot, let Linux create the BBT and see if it catches the bad blocks.
Are the current boot loaders safe regarding the scrub operation ? I'm
asking because that's how I bricked my mirabox a few years ago when
trying to mark a bad block from u-boot :-/ If someone has a good
knowledge of these commands to limit the risk and helps me only playing
with a small part at the end of the flash (or in the unused area) I'd
prefer it :-)
> This would guarantee that devices with factory bad blocks,
> (and no BBT), would be OK with this patch.
I see. I'm fine with trying provided I have reasonably good assurance
that I won't have to go through the kwboot pain again :-/
Cheers,
Willy
^ permalink raw reply
* [PATCH v2] PM / Domains: Remove obsolete "samsung, power-domain" check
From: Rafael J. Wysocki @ 2017-12-17 17:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512042868-23017-1-git-send-email-geert+renesas@glider.be>
On Thursday, November 30, 2017 12:54:28 PM CET Geert Uytterhoeven wrote:
> Currently the generic PM Domain code code checks for the presence of
> both (generic) "power-domains" and (Samsung Exynos legacy)
> "samsung,power-domain" properties in all device tree nodes representing
> devices.
>
> There are two issues with this:
> 1. This imposes a small boot-time penalty on all platforms using DT,
> 2. Platform-specific checks do not really belong in core framework
> code.
>
> Remove the platform-specific check, as the last user of
> "samsung,power-domain" was removed in commit 46dcf0ff0de35da8 ("ARM:
> dts: exynos: Remove exynos4415.dtsi"). All other users were converted
> before in commit 0da6587041363033 ("ARM: dts: convert to generic power
> domain bindings for exynos DT").
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> This is v2 of 'PM / Domains: Restrict "samsung,power-domain" checks to
> ARCH_EXYNOS'.
>
> "samsung,power-domain" was only ever used in:
> - arch/arm/boot/dts/exynos4415.dtsi: Removed
> - arch/arm/boot/dts/exynos3250.dtsi: CONFIG_ARCH_EXYNOS3
> - arch/arm/boot/dts/exynos4.dtsi: CONFIG_ARCH_EXYNOS4
> - arch/arm/boot/dts/exynos4x12.dtsi: CONFIG_ARCH_EXYNOS4
> - arch/arm/boot/dts/exynos5250.dtsi: CONFIG_ARCH_EXYNOS5
> - arch/arm/boot/dts/exynos5420.dtsi: CONFIG_ARCH_EXYNOS5
>
> v2:
> - Remove the check completely instead of restricting it to
> ARCH_EXYNOS, as suggested Javier Martinez Canillas one year ago
> ("Removing the support for the deprecated property sound sensible to me",
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-October/462868.html).
> ---
> drivers/base/power/domain.c | 16 ++--------------
> 1 file changed, 2 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
> index 0c80bea05bcb92be..f9dcc981b6b9328c 100644
> --- a/drivers/base/power/domain.c
> +++ b/drivers/base/power/domain.c
> @@ -2199,20 +2199,8 @@ int genpd_dev_pm_attach(struct device *dev)
>
> ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
> "#power-domain-cells", 0, &pd_args);
> - if (ret < 0) {
> - if (ret != -ENOENT)
> - return ret;
> -
> - /*
> - * Try legacy Samsung-specific bindings
> - * (for backwards compatibility of DT ABI)
> - */
> - pd_args.args_count = 0;
> - pd_args.np = of_parse_phandle(dev->of_node,
> - "samsung,power-domain", 0);
> - if (!pd_args.np)
> - return -ENOENT;
> - }
> + if (ret < 0)
> + return ret;
>
> mutex_lock(&gpd_list_lock);
> pd = genpd_get_from_provider(&pd_args);
>
Applied, thanks!
^ permalink raw reply
* [PATCH] bus: simple-pm-bus: convert bool SIMPLE_PM_BUS to tristate
From: Rafael J. Wysocki @ 2017-12-17 18:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171201070232.v4uilgo5cydaoyqa@verge.net.au>
On Friday, December 1, 2017 8:02:33 AM CET Simon Horman wrote:
> On Thu, Nov 30, 2017 at 12:57:00PM +0100, Geert Uytterhoeven wrote:
> > From: Paul Gortmaker <paul.gortmaker@windriver.com>
> >
> > The Kconfig currently controlling compilation of this code is:
> >
> > config SIMPLE_PM_BUS
> > bool "Simple Power-Managed Bus Driver"
> >
> > ...meaning that it currently is not being built as a module by anyone.
> >
> > In removing the orphaned modular support in a previous patch set,
> > Geert indicated he'd rather see this code converted to tristate.
> >
> > I normally don't do that because it extends functionality that I
> > can't easily run time test or even know if the use case makes sense,
> > but since in this case the author has nominated it as such, we do
> > the conversion here.
> >
> > Note that doesn't change the lack of run time testing ; this change
> > is only tested for sucessful compile and modpost.
> >
> > [geert: Ethernet is probed successfully on sh73a0/kzm9g after
> > insmodding simple-pm-bus.ko]
> >
> > Cc: Kevin Hilman <khilman@linaro.org>
> > Cc: Simon Horman <horms+renesas@verge.net.au>
> > Cc: linux-arm-kernel at lists.infradead.org
> > Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
> > Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
> > Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
>
> Acked-by: Simon Horman <horms+renesas@verge.net.au>
Applied, thanks!
^ permalink raw reply
* [PATCH v1 4/4] arm64: dts: mediatek: add mt2712 cpufreq related device nodes
From: Rafael J. Wysocki @ 2017-12-17 18:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a68c5382-2a9c-6c3c-ea67-99db46bdff1a@gmail.com>
On Tuesday, December 12, 2017 10:34:42 AM CET Matthias Brugger wrote:
> Hi,
>
> On 12/12/2017 08:26 AM, Viresh Kumar wrote:
> > On 12-12-17, 02:17, Rafael J. Wysocki wrote:
> >> On Monday, December 11, 2017 8:57:19 AM CET Viresh Kumar wrote:
> >>> On 08-12-17, 14:07, Andrew-sh Cheng wrote:
> >>>> Add opp v2 information,
> >>>> and also add clocks, regulators and opp information into cpu nodes
> >>>>
> >>>> Signed-off-by: Andrew-sh Cheng <andrew-sh.cheng@mediatek.com>
> >>>> ---
> >>>> arch/arm64/boot/dts/mediatek/mt2712-evb.dts | 27 ++++++++++++++
> >>>> arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 57 +++++++++++++++++++++++++++++
> >>>> 2 files changed, 84 insertions(+)
> >>>
> >>> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> >>
> >> Of course, DT bindings require ACKs from DT maintainers to be applied.
> >
> > I didn't knew that we need Acks from DT maintainers for dts files as well? Yeah,
> > its very much required while defining new bindings for sure.
> >
>
> I will take the dts parts through the Mediatek SoC tree, so you don't have to
> worry about them.
>
> Please let me know when you take patch 1 and 2.
Applied now, thanks!
Do you need the branch containing them to be exposed?
Thanks,
Rafael
^ permalink raw reply
* pxa3xx_nand times out in 4.14 with JFFS2
From: Boris Brezillon @ 2017-12-17 18:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171217162342.GA1833@1wt.eu>
On Sun, 17 Dec 2017 17:23:42 +0100
Willy Tarreau <w@1wt.eu> wrote:
> On Sun, Dec 17, 2017 at 12:53:36PM -0300, Ezequiel Garcia wrote:
> > If not too much to ask, this is the test that I believe is needed.
> > You seem to have a setup ready, hence why I'm asking you, if
> > possible, to give it a shot.
> >
> > (1) Scrub the BBT from the NAND. Or scrub the whole NAND.
> > You cannot do this from the kernel, it needs to be done from the bootloader.
> >
> > (2) Mark a couple blocks as bad using the OOB -- AFAICR, there
> > was a command to do this in the bootloader.
> >
> > (3) Boot, let Linux create the BBT and see if it catches the bad blocks.
>
> Are the current boot loaders safe regarding the scrub operation ? I'm
> asking because that's how I bricked my mirabox a few years ago when
> trying to mark a bad block from u-boot :-/ If someone has a good
> knowledge of these commands to limit the risk and helps me only playing
> with a small part at the end of the flash (or in the unused area) I'd
> prefer it :-)
>
> > This would guarantee that devices with factory bad blocks,
> > (and no BBT), would be OK with this patch.
>
> I see. I'm fine with trying provided I have reasonably good assurance
> that I won't have to go through the kwboot pain again :-/
There's a easy test you can do without scrubing the NAND:
1/ comment the nand-on-flash-bbt property in your DT (this will trigger
a full scan)
2/ from u-boot (before booting the kernel), erase a block that you know
contains nothing important
3/ during the kernel scan, make sure this block is not reported as bad
^ permalink raw reply
* [PATCH v4 3/4] cpufreq: Add DVFS support for Armada 37xx
From: Rafael J. Wysocki @ 2017-12-17 18:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214153631.GZ3322@vireshk-i7>
On Thursday, December 14, 2017 4:36:31 PM CET Viresh Kumar wrote:
> On 14-12-17, 16:00, Gregory CLEMENT wrote:
> > This patch adds DVFS support for the Armada 37xx SoCs
> >
> > There are up to four CPU frequency loads for Armada 37xx controlled by
> > the hardware.
> >
> > This driver associates the CPU load level to a frequency, then the
> > hardware will switch while selecting a load level.
> >
> > The hardware also can associate a voltage for each level (AVS support)
> > but it is not yet supported
> >
> > Tested-by: Andre Heider <a.heider@gmail.com>
> > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> > ---
> > drivers/cpufreq/Kconfig.arm | 7 +
> > drivers/cpufreq/Makefile | 1 +
> > drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
> > 3 files changed, 249 insertions(+)
> > create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
>
> Thanks for taking care of very minor review comments I had. All the
> patches look good now to me :)
All applied, thanks!
^ permalink raw reply
* [PATCH v2 0/2] cpufreq: Sort Kconfig and Makefile
From: Rafael J. Wysocki @ 2017-12-17 18:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213170536.28238-1-gregory.clement@free-electrons.com>
On Wednesday, December 13, 2017 6:05:34 PM CET Gregory CLEMENT wrote:
> Hi,
>
> The patch of this series was originally part of the series "Add CPU
> Frequency scaling support on Armada 37xx" [1].
>
> As requested by Rafael J. Wysocki, these 2 patches are extracted in a
> independent series, in the meantime, Viresh Kumar gave his acked-by
> that I added to the patches.
>
> In this second version only the 1st patch had been modified, see the
> changelog for the details.
>
> Thanks,
>
> Gregory
>
> [1]: http://lists.infradead.org/pipermail/linux-arm-kernel/2017-December/546709.html
>
> Changelog:
> v1 -> v2:
>
> - Fixed tab vs space issue in KConfig, suggested by Randy Dunlap
> - Removed unneeded "default n" in KConfig, suggested by Randy Dunlap
>
> Gregory CLEMENT (2):
> cpufreq: ARM: sort the Kconfig menu
> cpufreq: sort the drivers in ARM part
>
> drivers/cpufreq/Kconfig.arm | 81 ++++++++++++++++++++++-----------------------
> drivers/cpufreq/Makefile | 8 ++---
> 2 files changed, 44 insertions(+), 45 deletions(-)
>
>
Both applied, thanks!
^ permalink raw reply
* [PATCH 0/2] cpufreq: few fix on mvebu driver
From: Rafael J. Wysocki @ 2017-12-17 18:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213172914.6148-1-gregory.clement@free-electrons.com>
On Wednesday, December 13, 2017 6:29:12 PM CET Gregory CLEMENT wrote:
> Hi,
>
> The second patch of this series was originally part of the series "Add CPU
> Frequency scaling support on Armada 37xx" [1].
>
> As requested by Viresh Kumar, it is extracted in a independent series.
> In the meantime, Thomas Petazzoni pointed an issue on the first
> version that I fixed in this series.
>
> While I was on this driver I found an aother issue that I fixed with
> the first patch.
>
> Thanks,
>
> Gregory
>
> [1]: http://lists.infradead.org/pipermail/linux-arm-kernel/2017-December/547650.html
>
> Gregory CLEMENT (2):
> cpufreq: mvebu: Free the clock reference in the normal path
> cpufreq: mvebu: Free opp if registering failed
>
> drivers/cpufreq/mvebu-cpufreq.c | 16 +++++++++-------
> 1 file changed, 9 insertions(+), 7 deletions(-)
>
>
Both applied, thanks!
^ permalink raw reply
* [PATCH v4 3/4] cpufreq: Add DVFS support for Armada 37xx
From: Rafael J. Wysocki @ 2017-12-17 18:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2201504.Sp2n0UgIp2@aspire.rjw.lan>
On Sunday, December 17, 2017 7:08:53 PM CET Rafael J. Wysocki wrote:
> On Thursday, December 14, 2017 4:36:31 PM CET Viresh Kumar wrote:
> > On 14-12-17, 16:00, Gregory CLEMENT wrote:
> > > This patch adds DVFS support for the Armada 37xx SoCs
> > >
> > > There are up to four CPU frequency loads for Armada 37xx controlled by
> > > the hardware.
> > >
> > > This driver associates the CPU load level to a frequency, then the
> > > hardware will switch while selecting a load level.
> > >
> > > The hardware also can associate a voltage for each level (AVS support)
> > > but it is not yet supported
> > >
> > > Tested-by: Andre Heider <a.heider@gmail.com>
> > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > > Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> > > ---
> > > drivers/cpufreq/Kconfig.arm | 7 +
> > > drivers/cpufreq/Makefile | 1 +
> > > drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
> > > 3 files changed, 249 insertions(+)
> > > create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
> >
> > Thanks for taking care of very minor review comments I had. All the
> > patches look good now to me :)
>
> All applied, thanks!
>
Actually, all except for the [4/4] as you applied it earlier.
Thanks!
^ permalink raw reply
* pxa3xx_nand times out in 4.14 with JFFS2
From: Willy Tarreau @ 2017-12-17 19:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171217190746.2a61232c@bbrezillon>
On Sun, Dec 17, 2017 at 07:07:46PM +0100, Boris Brezillon wrote:
> > > This would guarantee that devices with factory bad blocks,
> > > (and no BBT), would be OK with this patch.
> >
> > I see. I'm fine with trying provided I have reasonably good assurance
> > that I won't have to go through the kwboot pain again :-/
>
> There's a easy test you can do without scrubing the NAND:
> 1/ comment the nand-on-flash-bbt property in your DT (this will trigger
> a full scan)
> 2/ from u-boot (before booting the kernel), erase a block that you know
> contains nothing important
> 3/ during the kernel scan, make sure this block is not reported as bad
OK so I tried and never faced any error. Thus I also attempted to mark
a bad block in u-boot, it appeared in the bad blocks table, then I had
to scrub the whole table to get rid of it. Each time when I booted I
saw the message "Scanning device for bad blocks" but no error ever
happened. So I hope it's OK.
Please find a summary of my tests below.
Marvell>> nand erase 280000 1000
NAND erase: device 0 offset 0x280000, size 0x1000
Erasing at 0x280000 -- 100% complete.
OK
Marvell>> nand dump 280000
Page 00280000 dump:
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
...
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
OOB:
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
Boot....
# nanddump -c --oob --bb=dumpbad /dev/mtd8 >/tmp/dump-mtd8.txt
=> only ff everywhere
# dmesg
...
pxa3xx-nand f10d0000.flash: This platform can't do DMA on this device
nand: device found, Manufacturer ID: 0x01, Chip ID: 0xf1
nand: AMD/Spansion S34ML01G2
nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
pxa3xx-nand f10d0000.flash: ECC strength 16, ECC step size 2048
Scanning device for bad blocks
...
Marvell>> nand markbad 280000
Bad block table written to 0x000007fe0000, version 0x02
Bad block table written to 0x000007fc0000, version 0x02
>>> orion_nfc_wait_for_completion_timeout command timed out!, status (0x100)
command 19 execution timed out (CS -1, NDCR=0x8104bfff, NDSR=0x100).
block 0x00280000 successfully marked as bad
Marvell>>
Marvell>> nand bad
Device 0 bad blocks:
280000
7f00000
7f20000
7f40000
7f60000
7f80000
7fa0000
7fc0000
7fe0000
Boot...
# dmesg
...
[ 0.875117] pxa3xx-nand f10d0000.flash: This platform can't do DMA on this device
[ 0.881627] nand: device found, Manufacturer ID: 0x01, Chip ID: 0xf1
[ 0.886697] nand: AMD/Spansion S34ML01G2
[ 0.889326] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
[ 0.895628] pxa3xx-nand f10d0000.flash: ECC strength 16, ECC step size 2048
[ 0.901316] Scanning device for bad blocks
...
Marvell>> nand scrub 7f00000 100000
Erasing at 0x7fe0000 -- 100% complete.
Bad block table not found for chip 0
Bad block table not found for chip 0
Bad block table written to 0x000007fe0000, version 0x01
Bad block table written to 0x000007fc0000, version 0x01
OK
Marvell>> nand bad
Device 0 bad blocks:
7f00000
7f20000
7f40000
7f60000
7f80000
7fa0000
7fc0000
7fe0000
Boot...
# dmesg
...
[ 0.875322] pxa3xx-nand f10d0000.flash: This platform can't do DMA on this device
[ 0.881834] nand: device found, Manufacturer ID: 0x01, Chip ID: 0xf1
[ 0.886904] nand: AMD/Spansion S34ML01G2
[ 0.889533] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
[ 0.895835] pxa3xx-nand f10d0000.flash: ECC strength 16, ECC step size 2048
[ 0.901524] Scanning device for bad blocks
[ 1.202116] ata2: SATA link down (SStatus 0 SControl 300)
[ 1.206245] ata1: SATA link down (SStatus 0 SControl 300)
[ 1.244449] 10 ofpart partitions found on MTD device pxa3xx_nand-0
[ 1.249345] Creating 10 MTD partitions on "pxa3xx_nand-0":
[ 1.253551] 0x000000000000-0x000000200000 : "u-boot"
[ 1.257523] 0x000000200000-0x000000240000 : "u_env"
[ 1.261372] 0x000000240000-0x000000280000 : "s_env"
[ 1.265217] 0x000000900000-0x000000a00000 : "devinfo"
[ 1.269229] 0x000000a00000-0x000003200000 : "kernel1"
[ 1.273326] 0x000001000000-0x000003200000 : "rootfs1"
[ 1.277407] 0x000003200000-0x000005a00000 : "kernel2"
[ 1.281509] 0x000003800000-0x000005a00000 : "rootfs2"
[ 1.285591] 0x000005a00000-0x000008000000 : "syscfg"
[ 1.289596] 0x000000280000-0x000000900000 : "unused_area"
...
Willy
^ permalink raw reply
* [PATCH v5 0/4] ARM: ep93xx: ts72xx: Add support for BK3 board
From: Lukasz Majewski @ 2017-12-17 19:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAK8P3a2jEVQXKXJXp27ft5oaD8Jbo6g1fB-t_aduJWhC2dtJ0g@mail.gmail.com>
Hi Arnd,
> On Wed, Dec 13, 2017 at 9:26 AM, Alexander Sverdlin
> <alexander.sverdlin@gmail.com> wrote:
> > On Wed Dec 13 08:34:22 2017 Linus Walleij
> > <linus.walleij@linaro.org> wrote:
> >> Arnd has been nudging me to do DT conversion for EP93xx
> >> so if there are many active industrial users of these
> >> I should prioritize it, because these things have 20+ years
> >> support cycles.
> >
> > I'm not sure how important or necessary at all is to change
> > anything in these legacy platforms.
>
> I suspect that at several points in the next 5 to 10 years, we will
> remove additional platforms or CPU types, as we tend to do when a
> platform becomes a maintenance burden and is clearly not used by
> anyone.
I suppose that at least the last argument is not the case here :-).
>
> It's hard to predict in advance what triggers the removal, but as the
> number of platforms that are not using DT or ARCH_MULTIPLATFORM
> goes down to a small number, there will be increased interested in
> either removing or converting the remaining ones. This is not an
> immediate danger at the moment, since we still have 14 platforms that
> are not using ARCH_MULTIPLATFORM, and 23 that have remaining
> board files, but you don't want to be the last user of the last
> platform after the other ones are done ;-)
:-)
>
> >> We also need to think about upholding support in GCC for
> >> ARMv4(t) for the foreseeable future if there is a big web of
> >> random deeply embedded systems out there that will need
> >> updates.
> >
> > But we should definitely preserve at least what we have.
>
> Plain ARMv4 (and earlier) support in gcc is already marked
> 'deprecated' and will likely be gone in gcc-8 (it's still there as of
> last week). ARMv4T is going to be around for a while, and you can
> even keep building for ARMv4 using "-march=armv4t -marm" when linking
> with 'ld --fix-v4bx'.
I think that we shall start complaining on the gcc-devel mailing list
now.
I would be hard to wake up in 2 years time and realise that we don't
have a modern compiler.
>
> Debian recently did a survey to find out whether there were still
> users on ARMv4 or ARMv4T, and the result was that probably everyone is
> on ARMv5E or ARMv6 for the ARM port (which is separate from the
> ARMHF port that is ARMv7+). See also
> https://lists.debian.org/debian-user/2017/11/msg00379.html
> and let them know quickly if you use Debian stable releases and
> plan to update to Debian 10 (Buster) in the future.
>
> Arnd
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171217/56d4973a/attachment.sig>
^ permalink raw reply
* [PATCH] ARM: pxa/lubbock: add GPIO driver for LUB_MISC_WR register
From: Robert Jarzmik @ 2017-12-17 20:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171212232405.GG10595@n2100.armlinux.org.uk>
Russell King - ARM Linux <linux@armlinux.org.uk> writes:
> On Tue, Dec 12, 2017 at 09:27:34PM +0100, Robert Jarzmik wrote:
>> Russell King <rmk+kernel@armlinux.org.uk> writes:
>>
>> > Add a gpio driver for the lubbock miscellaneous write IO register so we
>> > can take advantage of subsystems modelled around gpiolib, rather than
>> > having to provide platform specific callbacks.
>> >
>> > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
>>
>> Hi Russell and Linux,
>>
>> It looks certainly good to me. It's unfortunate in the current status of
>> linux-next I have, gpio-reg.c seems broken (that one is for Linus in [1] and
>> [2]), and therefore I can't test it live.
>
> It won't do much on its own without some patches to make use of the new
> GPIOs... but it will be used as the direct register write becomes a
> call to gpio-reg's ->set_multiple() method.
Applied to pxa/for-next, thanks.
Cheers.
--
Robert
^ permalink raw reply
* [PATCH 2/9] ARM: dts: imx7-colibri: make sure multiplexed pins are not active
From: Stefan Agner @ 2017-12-17 20:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5AD6bDEMStEWY8hRG_8gh0RAD_66zboTsKd-cFkPtiLKg@mail.gmail.com>
On 2017-12-16 15:01, Fabio Estevam wrote:
> On Wed, Dec 6, 2017 at 1:29 PM, Stefan Agner <stefan@agner.ch> wrote:
>> The Colibri pins PWM<A> and <D> are multiplexed on the module, make
>> sure the secondary SoC pin is not active.
>>
>> Signed-off-by: Stefan Agner <stefan@agner.ch>
>
> I haven't really understood the commit message, but this is probably
> because I don't have access to the schematics.
It means that the modules pins are connected to two SoC pads. It is also
mentioned in the Colibri iMX7 datasheet.
This allows to use the module pin for a different purpose, but we mux it
such that it is usable for the primary purpose (which is PWM).
>
> Anyway:
>
> Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
Thanks!
--
Stefan
^ permalink raw reply
* [PATCH v5 0/4] ARM: ep93xx: ts72xx: Add support for BK3 board
From: Arnd Bergmann @ 2017-12-17 20:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171217204122.0a10a5e1@jawa>
On Sun, Dec 17, 2017 at 8:41 PM, Lukasz Majewski <lukma@denx.de> wrote:
>> >> We also need to think about upholding support in GCC for
>> >> ARMv4(t) for the foreseeable future if there is a big web of
>> >> random deeply embedded systems out there that will need
>> >> updates.
>> >
>> > But we should definitely preserve at least what we have.
>>
>> Plain ARMv4 (and earlier) support in gcc is already marked
>> 'deprecated' and will likely be gone in gcc-8 (it's still there as of
>> last week). ARMv4T is going to be around for a while, and you can
>> even keep building for ARMv4 using "-march=armv4t -marm" when linking
>> with 'ld --fix-v4bx'.
>
> I think that we shall start complaining on the gcc-devel mailing list
> now.
>
> I would be hard to wake up in 2 years time and realise that we don't
> have a modern compiler.
What distro or build system are you using? It would also be helpful
to test whether the -march=armv4t/--fix-v4bx workaround produces
working binaries for you, in that case you could report to the gcc
developers that the removal of armv4 can continue but that
the --fix-v4bx option in ld needs to stay around.
Arnd
^ permalink raw reply
* [PATCH v2 1/9] ARM: dts: imx7-colibri: move and rename USB Host power regulator
From: Stefan Agner @ 2017-12-17 20:37 UTC (permalink / raw)
To: linux-arm-kernel
The Colibri default which enables USB Host power is not necessarily
tied to the OTG2 controller, some carrier board use the pin to
control USB power for both controllers. Hence name the pinctrl
group more generic.
Also move the regulator to the generic eval-v3 device tree since
the regulator is always on the carrier board. In the Colibri iMX7S
case the regulator is just not used. This allows to reuse the
regulator in a upcoming SKU Colibri iMX7D 1GB with eMMC.
Signed-off-by: Stefan Agner <stefan@agner.ch>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
---
arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi | 11 +++++++++++
arch/arm/boot/dts/imx7-colibri.dtsi | 2 +-
arch/arm/boot/dts/imx7d-colibri-eval-v3.dts | 13 +------------
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
index 18bebd6d8d47..5ecb3a858c5a 100644
--- a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
@@ -70,6 +70,17 @@
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
+
+ reg_usbh_vbus: regulator-usbh-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh_reg>;
+ regulator-name = "VCC_USB[1-4]";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 7 GPIO_ACTIVE_LOW>;
+ vin-supply = <®_5v0>;
+ };
};
&bl {
diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi
index bb5bf94f1a32..60ea7557d8c9 100644
--- a/arch/arm/boot/dts/imx7-colibri.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri.dtsi
@@ -559,7 +559,7 @@
>;
};
- pinctrl_usbotg2_reg: gpio-usbotg2-vbus {
+ pinctrl_usbh_reg: gpio-usbh-vbus {
fsl,pins = <
MX7D_PAD_UART3_CTS_B__GPIO4_IO7 0x14 /* SODIMM 129 USBH PEN */
>;
diff --git a/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts b/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts
index a608a14d8c85..136e11ab4893 100644
--- a/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts
@@ -48,20 +48,9 @@
model = "Toradex Colibri iMX7D on Colibri Evaluation Board V3";
compatible = "toradex,colibri-imx7d-eval-v3", "toradex,colibri-imx7d",
"fsl,imx7d";
-
- reg_usb_otg2_vbus: regulator-usb-otg2-vbus {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usbotg2_reg>;
- regulator-name = "VCC_USB[1-4]";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- gpio = <&gpio4 7 GPIO_ACTIVE_LOW>;
- vin-supply = <®_5v0>;
- };
};
&usbotg2 {
- vbus-supply = <®_usb_otg2_vbus>;
+ vbus-supply = <®_usbh_vbus>;
status = "okay";
};
--
2.15.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox