* [PATCH 4/7] Documentation: dt: iio: stm32-adc: optional dma support
From: Fabrice Gasnier @ 2017-01-19 13:34 UTC (permalink / raw)
To: linux-arm-kernel
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 at 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: linux-arm-kernel
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: linux-arm-kernel
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: linux-arm-kernel
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 at 0 {
+ status = "okay";
+ };
+};
+
+&timers3 {
+ status = "okay";
+
+ pwm {
+ pinctrl-0 = <&pwm3_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+ };
+
+ timer at 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: linux-arm-kernel
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
^ 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: linux-arm-kernel
In-Reply-To: <1484832916-7248-1-git-send-email-dingtianhong@huawei.com>
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@huawei.com>
Acked-by: Rob Herring <robh@kernel.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
^ 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: linux-arm-kernel
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: linux-arm-kernel
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: linux-arm-kernel
In-Reply-To: <1484832916-7248-1-git-send-email-dingtianhong@huawei.com>
Enable workaround for hisilicon erratum 161010101 on Hip05-d02 and Hip06-d03 board.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
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
^ permalink raw reply related
* [PATCH 0/4] Bluetooth support for GXBB/GXL/GXM based devices
From: Greg KH @ 2017-01-19 13:39 UTC (permalink / raw)
To: 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: 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: 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 at 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: 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 at 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 at 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: 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
* [PATCH v3 00/13] Move pad retention control to Exynos pin controller driver
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CGME20170119134902eucas1p24c04dc33bab06bd3d564f6aec2180b3b@eucas1p2.samsung.com>
Hello,
This patchset is a follow-up of my work on adding runtime PM support
to Exynos pin controller driver:
http://www.spinics.net/lists/arm-kernel/msg550161.html
Runtime PM support itself needs a bit more discussion, so lets first focus on
the prerequisites.
In case of Exynos pin controller driver it is a pad retention control. In
current code it was handled by machine and PMU code and had no relation to
what pin controller driver does. This patch series moves pad retention
control to pin controller driver. While implementing it, I also did a little
cleanup of both Exynos PMU and pin controller drivers. Exynos PMU driver
now provides a convenient function to get PMU regmap from other Exynos drivers.
Patch #1 provides a new interface to get Exynos PMU regmap, which is used
by the patch #11. Patches 2-10 are additional cleanups to the code I was
modyfying. Patches 10-12 implements the move of the retention control and
patch #13 is another cleanup, which is possible after removing dependency
to platform PM code.
Patches are based on linux-next from 2017.01.19 with Exynos4415 support
removal patch applied: https://lkml.org/lkml/2017/1/14/137
Changelog:
v3:
- fixed return value from exynos_get_pmu_regmap stub (pointed by Tomasz Figa)
- removed unnecessary regmap include in pmu.h
- fixed comments in retention control structure description
- simplified exynos_retention_disable function by moving samsung_retention_ctrl
structure to separate variable
- collected Acks
v2: https://www.spinics.net/lists/arm-kernel/msg555048.html
- reworked exynos_get_pmu_regmap() function and moved to Exynos PMU driver,
now it doesn't depend on driver probe order thus doesn't need to defer probing
of pinctrl driver if PMU has not yet been probed
- collected Acks, minor fixes according to review comments
v1: https://www.spinics.net/lists/arm-kernel/msg554487.html
- removed the need to add PMU phandles to all pin controller nodes, so old DTBs
are properly supported. This has been achieved by getting PMU regmap from
the "exynos-pmu" device of fixed name.
- more cleanup in Exynos pin controller driver: added missing entries in DT
documentation, removed "memory allocation failed" messages and added
initconst annotations.
- added support for s5pv210.
- reworked retention control code to be simpler and ready for adding Exynos5433
support.
v0: http://www.spinics.net/lists/arm-kernel/msg550161.html
- initial version
- part of "Runtime PM for Exynos pin controller driver" patchset
Patch summary:
Marek Szyprowski (13):
soc: samsung: pmu: Provide global function to get PMU regmap
soc: samsung: pmu: Use of_device_get_match_data helper
soc: samsung: pmu: Remove messages for failed memory allocation
pinctrl: samsung: Document Exynos3250 SoC support
pinctrl: samsung: Remove messages for failed memory allocation
pinctrl: samsung: Fix samsung_pinctrl_create_functions return value
pinctrl: samsung: Add missing initconst annotation
pinctrl: samsung: Remove dead code
pinctrl: samsung: Use generic of_device_get_match_data helper
pinctrl: samsung: Add infrastructure for pin-bank retention control
pinctrl: samsung: Move retention control from mach-exynos to the
pinctrl driver
pinctrl: samsung: Move retention control from mach-s5pv210 to the
pinctrl driver
pinctrl: samsung: Replace syscore ops with standard platform device
pm_ops
.../bindings/pinctrl/samsung-pinctrl.txt | 1 +
arch/arm/mach-exynos/suspend.c | 64 ------
arch/arm/mach-s5pv210/pm.c | 7 -
arch/arm/mach-s5pv210/regs-clock.h | 4 -
drivers/pinctrl/samsung/pinctrl-exynos.c | 231 +++++++++++++++++++--
drivers/pinctrl/samsung/pinctrl-s3c64xx.c | 12 +-
drivers/pinctrl/samsung/pinctrl-samsung.c | 123 ++++-------
drivers/pinctrl/samsung/pinctrl-samsung.h | 42 ++++
drivers/soc/samsung/exynos-pmu.c | 22 +-
include/linux/soc/samsung/exynos-pmu.h | 10 +
10 files changed, 322 insertions(+), 194 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v3 01/13] soc: samsung: pmu: Provide global function to get PMU regmap
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
PMU is something like a SoC wide service, so add a helper function to get
PMU regmap. This will be used by other Exynos device drivers. This way it
can be avoided to model this dependency in device tree (as phandles to PMU
node) for almost every device in the SoC.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Tomasz Figa <tomasz.figa@gmail.com>
---
drivers/soc/samsung/exynos-pmu.c | 11 +++++++++++
include/linux/soc/samsung/exynos-pmu.h | 10 ++++++++++
2 files changed, 21 insertions(+)
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index 0acdfd82e751..5c269bf23210 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
@@ -92,6 +93,16 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
{ /*sentinel*/ },
};
+struct regmap *exynos_get_pmu_regmap(void)
+{
+ struct device_node *np = of_find_matching_node(NULL,
+ exynos_pmu_of_device_ids);
+ if (np)
+ return syscon_node_to_regmap(np);
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap);
+
static int exynos_pmu_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
diff --git a/include/linux/soc/samsung/exynos-pmu.h b/include/linux/soc/samsung/exynos-pmu.h
index e2e9de1acc5b..e57eb4b6cc5a 100644
--- a/include/linux/soc/samsung/exynos-pmu.h
+++ b/include/linux/soc/samsung/exynos-pmu.h
@@ -12,6 +12,8 @@
#ifndef __LINUX_SOC_EXYNOS_PMU_H
#define __LINUX_SOC_EXYNOS_PMU_H
+struct regmap;
+
enum sys_powerdown {
SYS_AFTR,
SYS_LPA,
@@ -20,5 +22,13 @@ enum sys_powerdown {
};
extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
+#ifdef CONFIG_EXYNOS_PMU
+extern struct regmap *exynos_get_pmu_regmap(void);
+#else
+static inline struct regmap *exynos_get_pmu_regmap(void)
+{
+ return ERR_PTR(-ENODEV);
+}
+#endif
#endif /* __LINUX_SOC_EXYNOS_PMU_H */
--
1.9.1
^ permalink raw reply related
* [PATCH v3 02/13] soc: samsung: pmu: Use of_device_get_match_data helper
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
Replace custom code with generic helper to retrieve driver data.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Tomasz Figa <tomasz.figa@gmail.com>
---
drivers/soc/samsung/exynos-pmu.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index 5c269bf23210..1f914e63dcc6 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
@@ -105,7 +106,6 @@ struct regmap *exynos_get_pmu_regmap(void)
static int exynos_pmu_probe(struct platform_device *pdev)
{
- const struct of_device_id *match;
struct device *dev = &pdev->dev;
struct resource *res;
@@ -122,10 +122,7 @@ static int exynos_pmu_probe(struct platform_device *pdev)
return -ENOMEM;
}
pmu_context->dev = dev;
-
- match = of_match_node(exynos_pmu_of_device_ids, dev->of_node);
-
- pmu_context->pmu_data = match->data;
+ pmu_context->pmu_data = of_device_get_match_data(dev);
if (pmu_context->pmu_data->pmu_init)
pmu_context->pmu_data->pmu_init();
--
1.9.1
^ permalink raw reply related
* [PATCH v3 03/13] soc: samsung: pmu: Remove messages for failed memory allocation
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
Memory subsystem already prints message about failed memory
allocation, there is no need to do it in the driver.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Tomasz Figa <tomasz.figa@gmail.com>
---
drivers/soc/samsung/exynos-pmu.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index 1f914e63dcc6..813df6e7292d 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -117,10 +117,8 @@ static int exynos_pmu_probe(struct platform_device *pdev)
pmu_context = devm_kzalloc(&pdev->dev,
sizeof(struct exynos_pmu_context),
GFP_KERNEL);
- if (!pmu_context) {
- dev_err(dev, "Cannot allocate memory.\n");
+ if (!pmu_context)
return -ENOMEM;
- }
pmu_context->dev = dev;
pmu_context->pmu_data = of_device_get_match_data(dev);
--
1.9.1
^ permalink raw reply related
* [PATCH v3 04/13] pinctrl: samsung: Document Exynos3250 SoC support
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
Add missing compatible id for Exynos3250 SoC to device tree docs.
Exynos pin control driver supports it since commit d97f5b9804bfcdc1
("pinctrl: exynos: Add driver data for Exynos3250").
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Tomasz Figa <tomasz.figa@gmail.com>
---
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
index 1baf19eecabf..5e00a21de2bf 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -13,6 +13,7 @@ Required Properties:
- "samsung,s3c2450-pinctrl": for S3C2450-compatible pin-controller,
- "samsung,s3c64xx-pinctrl": for S3C64xx-compatible pin-controller,
- "samsung,s5pv210-pinctrl": for S5PV210-compatible pin-controller,
+ - "samsung,exynos3250-pinctrl": for Exynos3250 compatible pin-controller.
- "samsung,exynos4210-pinctrl": for Exynos4210 compatible pin-controller.
- "samsung,exynos4x12-pinctrl": for Exynos4x12 compatible pin-controller.
- "samsung,exynos5250-pinctrl": for Exynos5250 compatible pin-controller.
--
1.9.1
^ permalink raw reply related
* [PATCH v3 05/13] pinctrl: samsung: Remove messages for failed memory allocation
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
Memory subsystem already prints message about failed memory
allocation, there is no need to do it in the drivers.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Tomasz Figa <tomasz.figa@gmail.com>
---
drivers/pinctrl/samsung/pinctrl-exynos.c | 8 ++------
drivers/pinctrl/samsung/pinctrl-s3c64xx.c | 12 +++---------
drivers/pinctrl/samsung/pinctrl-samsung.c | 24 ++++++------------------
3 files changed, 11 insertions(+), 33 deletions(-)
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 24814db251a7..bf753a596209 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -528,10 +528,8 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
weint_data = devm_kzalloc(dev, bank->nr_pins
* sizeof(*weint_data), GFP_KERNEL);
- if (!weint_data) {
- dev_err(dev, "could not allocate memory for weint_data\n");
+ if (!weint_data)
return -ENOMEM;
- }
for (idx = 0; idx < bank->nr_pins; ++idx) {
irq = irq_of_parse_and_map(bank->of_node, idx);
@@ -559,10 +557,8 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
+ muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
- if (!muxed_data) {
- dev_err(dev, "could not allocate memory for muxed_data\n");
+ if (!muxed_data)
return -ENOMEM;
- }
irq_set_chained_handler_and_data(irq, exynos_irq_demux_eint16_31,
muxed_data);
diff --git a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
index 4c632812ccff..f17890aa6e25 100644
--- a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
@@ -489,10 +489,8 @@ static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
data = devm_kzalloc(dev, sizeof(*data)
+ nr_domains * sizeof(*data->domains), GFP_KERNEL);
- if (!data) {
- dev_err(dev, "failed to allocate handler data\n");
+ if (!data)
return -ENOMEM;
- }
data->drvdata = d;
bank = d->pin_banks;
@@ -715,10 +713,8 @@ static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
return -ENODEV;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_err(dev, "could not allocate memory for wkup eint data\n");
+ if (!data)
return -ENOMEM;
- }
data->drvdata = d;
for (i = 0; i < NUM_EINT0_IRQ; ++i) {
@@ -751,10 +747,8 @@ static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
ddata = devm_kzalloc(dev,
sizeof(*ddata) + nr_eints, GFP_KERNEL);
- if (!ddata) {
- dev_err(dev, "failed to allocate domain data\n");
+ if (!ddata)
return -ENOMEM;
- }
ddata->bank = bank;
bank->irq_domain = irq_domain_add_linear(bank->of_node,
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 3bc925f61b71..b11e67e85460 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -93,10 +93,8 @@ static int reserve_map(struct device *dev, struct pinctrl_map **map,
return 0;
new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
- if (!new_map) {
- dev_err(dev, "krealloc(map) failed\n");
+ if (!new_map)
return -ENOMEM;
- }
memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
@@ -133,10 +131,8 @@ static int add_map_configs(struct device *dev, struct pinctrl_map **map,
dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
GFP_KERNEL);
- if (!dup_configs) {
- dev_err(dev, "kmemdup(configs) failed\n");
+ if (!dup_configs)
return -ENOMEM;
- }
(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
(*map)[*num_maps].data.configs.group_or_pin = group;
@@ -156,10 +152,8 @@ static int add_config(struct device *dev, unsigned long **configs,
new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,
GFP_KERNEL);
- if (!new_configs) {
- dev_err(dev, "krealloc(configs) failed\n");
+ if (!new_configs)
return -ENOMEM;
- }
new_configs[old_num] = config;
@@ -756,10 +750,8 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions(
functions = devm_kzalloc(dev, func_cnt * sizeof(*functions),
GFP_KERNEL);
- if (!functions) {
- dev_err(dev, "failed to allocate memory for function list\n");
+ if (!functions)
return ERR_PTR(-EINVAL);
- }
func = functions;
/*
@@ -850,10 +842,8 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
drvdata->nr_pins, GFP_KERNEL);
- if (!pindesc) {
- dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
+ if (!pindesc)
return -ENOMEM;
- }
ctrldesc->pins = pindesc;
ctrldesc->npins = drvdata->nr_pins;
@@ -867,10 +857,8 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
*/
pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
drvdata->nr_pins, GFP_KERNEL);
- if (!pin_names) {
- dev_err(&pdev->dev, "mem alloc for pin names failed\n");
+ if (!pin_names)
return -ENOMEM;
- }
/* for each pin, the name of the pin is pin-bank name + pin number */
for (bank = 0; bank < drvdata->nr_banks; bank++) {
--
1.9.1
^ permalink raw reply related
* [PATCH v3 06/13] pinctrl: samsung: Fix samsung_pinctrl_create_functions return value
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
Return proper error code in case of memory allocation failure.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Tomasz Figa <tomasz.figa@gmail.com>
---
drivers/pinctrl/samsung/pinctrl-samsung.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index b11e67e85460..10b3fd826231 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -751,7 +751,7 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions(
functions = devm_kzalloc(dev, func_cnt * sizeof(*functions),
GFP_KERNEL);
if (!functions)
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ENOMEM);
func = functions;
/*
--
1.9.1
^ permalink raw reply related
* [PATCH v3 07/13] pinctrl: samsung: Add missing initconst annotation
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
Exynos5433 support has been added in parallel to adding initconst
annotation to most of the init data structures, so add those
annotations also to Exynos5433 structures.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Tomasz Figa <tomasz.figa@gmail.com>
---
drivers/pinctrl/samsung/pinctrl-exynos.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index bf753a596209..70b94ad10cc1 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -1266,7 +1266,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
};
/* pin banks of exynos5433 pin-controller - ALIVE */
-static const struct samsung_pin_bank_data exynos5433_pin_banks0[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks0[] __initconst = {
EXYNOS5433_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
EXYNOS5433_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
EXYNOS5433_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
@@ -1279,28 +1279,28 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
};
/* pin banks of exynos5433 pin-controller - AUD */
-static const struct samsung_pin_bank_data exynos5433_pin_banks1[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks1[] __initconst = {
EXYNOS5433_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
EXYNOS5433_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
};
/* pin banks of exynos5433 pin-controller - CPIF */
-static const struct samsung_pin_bank_data exynos5433_pin_banks2[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks2[] __initconst = {
EXYNOS5433_PIN_BANK_EINTG(2, 0x000, "gpv6", 0x00),
};
/* pin banks of exynos5433 pin-controller - eSE */
-static const struct samsung_pin_bank_data exynos5433_pin_banks3[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks3[] __initconst = {
EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj2", 0x00),
};
/* pin banks of exynos5433 pin-controller - FINGER */
-static const struct samsung_pin_bank_data exynos5433_pin_banks4[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks4[] __initconst = {
EXYNOS5433_PIN_BANK_EINTG(4, 0x000, "gpd5", 0x00),
};
/* pin banks of exynos5433 pin-controller - FSYS */
-static const struct samsung_pin_bank_data exynos5433_pin_banks5[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks5[] __initconst = {
EXYNOS5433_PIN_BANK_EINTG(6, 0x000, "gph1", 0x00),
EXYNOS5433_PIN_BANK_EINTG(7, 0x020, "gpr4", 0x04),
EXYNOS5433_PIN_BANK_EINTG(5, 0x040, "gpr0", 0x08),
@@ -1310,17 +1310,17 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
};
/* pin banks of exynos5433 pin-controller - IMEM */
-static const struct samsung_pin_bank_data exynos5433_pin_banks6[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks6[] __initconst = {
EXYNOS5433_PIN_BANK_EINTG(8, 0x000, "gpf0", 0x00),
};
/* pin banks of exynos5433 pin-controller - NFC */
-static const struct samsung_pin_bank_data exynos5433_pin_banks7[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks7[] __initconst = {
EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj0", 0x00),
};
/* pin banks of exynos5433 pin-controller - PERIC */
-static const struct samsung_pin_bank_data exynos5433_pin_banks8[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks8[] __initconst = {
EXYNOS5433_PIN_BANK_EINTG(6, 0x000, "gpv7", 0x00),
EXYNOS5433_PIN_BANK_EINTG(5, 0x020, "gpb0", 0x04),
EXYNOS5433_PIN_BANK_EINTG(8, 0x040, "gpc0", 0x08),
@@ -1341,7 +1341,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
};
/* pin banks of exynos5433 pin-controller - TOUCH */
-static const struct samsung_pin_bank_data exynos5433_pin_banks9[] = {
+static const struct samsung_pin_bank_data exynos5433_pin_banks9[] __initconst = {
EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj1", 0x00),
};
@@ -1349,7 +1349,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
* Samsung pinctrl driver data for Exynos5433 SoC. Exynos5433 SoC includes
* ten gpio/pin-mux/pinconfig controllers.
*/
-const struct samsung_pin_ctrl exynos5433_pin_ctrl[] = {
+const struct samsung_pin_ctrl exynos5433_pin_ctrl[] __initconst = {
{
/* pin-controller instance 0 data */
.pin_banks = exynos5433_pin_banks0,
--
1.9.1
^ permalink raw reply related
* [PATCH v3 08/13] pinctrl: samsung: Remove dead code
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
'enable' parameter has been removed a while ago, so all code for handling
it can be simply removed.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Tomasz Figa <tomasz.figa@gmail.com>
---
drivers/pinctrl/samsung/pinctrl-samsung.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 10b3fd826231..2803ae57f373 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -350,7 +350,7 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
/* enable or disable a pinmux function */
static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
- unsigned group, bool enable)
+ unsigned group)
{
struct samsung_pinctrl_drv_data *drvdata;
const struct samsung_pin_bank_type *type;
@@ -380,8 +380,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
data &= ~(mask << shift);
- if (enable)
- data |= func->val << shift;
+ data |= func->val << shift;
writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
spin_unlock_irqrestore(&bank->slock, flags);
@@ -392,7 +391,7 @@ static int samsung_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned selector,
unsigned group)
{
- samsung_pinmux_setup(pctldev, selector, group, true);
+ samsung_pinmux_setup(pctldev, selector, group);
return 0;
}
--
1.9.1
^ permalink raw reply related
* [PATCH v3 09/13] pinctrl: samsung: Use generic of_device_get_match_data helper
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
Replace custom code with generic helper.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Tomasz Figa <tomasz.figa@gmail.com>
---
drivers/pinctrl/samsung/pinctrl-samsung.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 2803ae57f373..59f99ea7e65b 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -27,6 +27,7 @@
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/irqdomain.h>
+#include <linux/of_device.h>
#include <linux/spinlock.h>
#include <linux/syscore_ops.h>
@@ -955,15 +956,12 @@ static int samsung_gpiolib_unregister(struct platform_device *pdev,
return 0;
}
-static const struct of_device_id samsung_pinctrl_dt_match[];
-
/* retrieve the soc specific data */
static const struct samsung_pin_ctrl *
samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
struct platform_device *pdev)
{
int id;
- const struct of_device_id *match;
struct device_node *node = pdev->dev.of_node;
struct device_node *np;
const struct samsung_pin_bank_data *bdata;
@@ -978,8 +976,8 @@ static int samsung_gpiolib_unregister(struct platform_device *pdev,
dev_err(&pdev->dev, "failed to get alias id\n");
return ERR_PTR(-ENOENT);
}
- match = of_match_node(samsung_pinctrl_dt_match, node);
- ctrl = (struct samsung_pin_ctrl *)match->data + id;
+ ctrl = of_device_get_match_data(&pdev->dev);
+ ctrl += id;
d->suspend = ctrl->suspend;
d->resume = ctrl->resume;
--
1.9.1
^ permalink raw reply related
* [PATCH v3 10/13] pinctrl: samsung: Add infrastructure for pin-bank retention control
From: Marek Szyprowski @ 2017-01-19 13:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484833733-16082-1-git-send-email-m.szyprowski@samsung.com>
Pad retention control after suspend/resume cycle should be done from pin
controller driver instead of PMU (power management unit) driver to avoid
possible ordering and logical dependencies. Till now it worked fine only
because PMU driver registered its sys_ops after pin controller.
This patch adds infrastructure to handle pad retention during pin control
driver resume.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Tomasz Figa <tomasz.figa@gmail.com>
---
drivers/pinctrl/samsung/pinctrl-samsung.c | 12 +++++++++
drivers/pinctrl/samsung/pinctrl-samsung.h | 42 +++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 59f99ea7e65b..021abd7221f8 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1060,6 +1060,13 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
if (res)
drvdata->irq = res->start;
+ if (ctrl->retention_data) {
+ drvdata->retention_ctrl = ctrl->retention_data->init(drvdata,
+ ctrl->retention_data);
+ if (IS_ERR(drvdata->retention_ctrl))
+ return PTR_ERR(drvdata->retention_ctrl);
+ }
+
ret = samsung_gpiolib_register(pdev, drvdata);
if (ret)
return ret;
@@ -1126,6 +1133,8 @@ static void samsung_pinctrl_suspend_dev(
if (drvdata->suspend)
drvdata->suspend(drvdata);
+ if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable)
+ drvdata->retention_ctrl->enable(drvdata);
}
/**
@@ -1173,6 +1182,9 @@ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
if (widths[type])
writel(bank->pm_save[type], reg + offs[type]);
}
+
+ if (drvdata->retention_ctrl && drvdata->retention_ctrl->disable)
+ drvdata->retention_ctrl->disable(drvdata);
}
/**
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index 6f7ce7539a00..515a61035e54 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -185,10 +185,48 @@ struct samsung_pin_bank {
};
/**
+ * struct samsung_retention_data: runtime pin-bank retention control data.
+ * @regs: array of PMU registers to control pad retention.
+ * @nr_regs: number of registers in @regs array.
+ * @value: value to store to registers to turn off retention.
+ * @refcnt: atomic counter if retention control affects more than one bank.
+ * @priv: retention control code private data
+ * @enable: platform specific callback to enter retention mode.
+ * @disable: platform specific callback to exit retention mode.
+ **/
+struct samsung_retention_ctrl {
+ const u32 *regs;
+ int nr_regs;
+ u32 value;
+ atomic_t *refcnt;
+ void *priv;
+ void (*enable)(struct samsung_pinctrl_drv_data *);
+ void (*disable)(struct samsung_pinctrl_drv_data *);
+};
+
+/**
+ * struct samsung_retention_data: represent a pin-bank retention control data.
+ * @regs: array of PMU registers to control pad retention.
+ * @nr_regs: number of registers in @regs array.
+ * @value: value to store to registers to turn off retention.
+ * @refcnt: atomic counter if retention control affects more than one bank.
+ * @init: platform specific callback to initialize retention control.
+ **/
+struct samsung_retention_data {
+ const u32 *regs;
+ int nr_regs;
+ u32 value;
+ atomic_t *refcnt;
+ struct samsung_retention_ctrl *(*init)(struct samsung_pinctrl_drv_data *,
+ const struct samsung_retention_data *);
+};
+
+/**
* struct samsung_pin_ctrl: represent a pin controller.
* @pin_banks: list of pin banks included in this controller.
* @nr_banks: number of pin banks.
* @nr_ext_resources: number of the extra base address for pin banks.
+ * @retention_data: configuration data for retention control.
* @eint_gpio_init: platform specific callback to setup the external gpio
* interrupts for the controller.
* @eint_wkup_init: platform specific callback to setup the external wakeup
@@ -198,6 +236,7 @@ struct samsung_pin_ctrl {
const struct samsung_pin_bank_data *pin_banks;
u32 nr_banks;
int nr_ext_resources;
+ const struct samsung_retention_data *retention_data;
int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
@@ -219,6 +258,7 @@ struct samsung_pin_ctrl {
* @nr_function: number of such pin functions.
* @pin_base: starting system wide pin number.
* @nr_pins: number of pins supported by the controller.
+ * @retention_ctrl: retention control runtime data.
*/
struct samsung_pinctrl_drv_data {
struct list_head node;
@@ -238,6 +278,8 @@ struct samsung_pinctrl_drv_data {
unsigned int pin_base;
unsigned int nr_pins;
+ struct samsung_retention_ctrl *retention_ctrl;
+
void (*suspend)(struct samsung_pinctrl_drv_data *);
void (*resume)(struct samsung_pinctrl_drv_data *);
};
--
1.9.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