* [PATCH] extcon: Split out the extcon APIs for extcon provider driver
From: Charles Keepax @ 2016-11-29 10:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480413743-13037-1-git-send-email-cw00.choi@samsung.com>
On Tue, Nov 29, 2016 at 07:02:23PM +0900, Chanwoo Choi wrote:
> This patchs split out the extcon APIs of extcon provider driver in order to
> prevent the direct access of struct extcon_dev by extcon consumer driver.
> The extcon consumer driver don't need to handle the extcon provider APIs.
>
> The extcon subsystem has two type of extcon drivers as following:
> - extcon provider driver
> : Detect the external connector and identify the state/property of
> each external connector. And it send the notification to synchronize
> the information between provider and consumer driver.
> - extcon consumer driver
> : Receive the notifcation from extcon provider driver. When receving the noti,
> it can get the both state and property of specific external connector.
>
> Cc: Myungjoo Ham <myungjoo.ham@samsung.com>
> Cc: Chen-Yu Tsai <wens@csie.org>
> Cc: Krzysztof Kozlowski <krzk@kernel.org>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Cc: Kishon Vijay Abraham I <kishon@ti.com>
> Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
> Cc: Felipe Balbi <balbi@kernel.org>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Chris Zhong <zyw@rock-chips.com>
> Cc: Roger Quadros <rogerq@ti.com>
> Cc: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
> Cc: patches at opensource.wolfsonmicro.com
> Cc: linux-renesas-soc at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-usb at vger.kernel.org
> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
> ---
> drivers/extcon/devres.c | 2 +-
> drivers/extcon/extcon-adc-jack.c | 2 +-
> drivers/extcon/extcon-arizona.c | 2 +-
For the Arizona bit:
Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Thanks,
Charles
^ permalink raw reply
* [PATCH v7 5/8] clk: sunxi-ng: define the PLL DE clock
From: Jean-Francois Moine @ 2016-11-29 10:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1480414715.git.moinejf@free.fr>
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
include/dt-bindings/clock/sun8i-h3-ccu.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/dt-bindings/clock/sun8i-h3-ccu.h b/include/dt-bindings/clock/sun8i-h3-ccu.h
index efb7ba2..7af57b7 100644
--- a/include/dt-bindings/clock/sun8i-h3-ccu.h
+++ b/include/dt-bindings/clock/sun8i-h3-ccu.h
@@ -44,6 +44,7 @@
#define _DT_BINDINGS_CLK_SUN8I_H3_H_
#define CLK_CPUX 14
+#define CLK_PLL_DE 13
#define CLK_BUS_CE 20
#define CLK_BUS_DMA 21
--
2.10.2
^ permalink raw reply related
* [PATCH v3 net-next 0/6] Support Armada 37xx SoC (ARMv8 64-bits) in mvneta driver
From: Gregory CLEMENT @ 2016-11-29 10:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.a09aeaf5ba62853d595153626b6121ef52a3e9b4.1480412215.git-series.gregory.clement@free-electrons.com>
Hi,
On mar., nov. 29 2016, Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> Hi,
>
> The Armada 37xx is a new ARMv8 SoC from Marvell using same network
> controller as the older Armada 370/38x/XP SoCs. This series adapts the
> driver in order to be able to use it on this new SoC. The main changes
> are:
>
> - 64-bits support: the first patches allow using the driver on a 64-bit
> architecture.
>
> - MBUS support: the mbus configuration is different on Armada 37xx
> from the older SoCs.
>
> - per cpu interrupt: Armada 37xx do not support per cpu interrupt for
> the NETA IP, the non-per-CPU behavior was added back.
>
> The first item is solved by patches 1 to 3.
> The 2 last items are solved by patch 4.
> In patch 5 the dt support is added.
>
> Beside Armada 37xx, the series have been tested on Armada XP and
> Armada 38x (with Hardware Buffer Management and with Software Buffer
> Managment).
>
> Thanks,
>
I forgot to commit my cover with git series, so it was the old one. It
should have been the following one:
Hi,
The Armada 37xx is a new ARMv8 SoC from Marvell using same network
controller as the older Armada 370/38x/XP SoCs. This series adapts the
driver in order to be able to use it on this new SoC. The main changes
are:
- 64-bits support: the first patches allow using the driver on a 64-bit
architecture.
- MBUS support: the mbus configuration is different on Armada 37xx
from the older SoCs.
- per cpu interrupt: Armada 37xx do not support per cpu interrupt for
the NETA IP, the non-per-CPU behavior was added back.
The first patch is an optimization in the rx path in swbm mode.
The first item is solved by patches 2 to 3.
The 2 last items are solved by patch 5.
In patch 6 the dt support is added.
Beside Armada 37xx, this new series have been again tested on Armada
XP and Armada 38x (with Hardware Buffer Management and with Software
Buffer Management).
This is the 3th version of the series:
- 1st version:
http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/469588.html
- 2nd version:
http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/470476.html
Changelog:
v2 -> v3:
- Adding patch 1 "Optimize rx path for small frame"
- Fix the kbuild error by moving the "phys_addr += pp->rx_offset_correction;"
line from patch 2 to patch 3 where rx_offset_correction is introduced.
- Move the memory allocation of the buf_virt_addr of the rxq to be
called by the probe function in order to avoid a memory leak.
> Gregory
>
> Gregory CLEMENT (4):
> net: mvneta: Optimize rx path for small frame
> net: mvneta: Use cacheable memory to store the rx buffer virtual address
> net: mvneta: Only disable mvneta_bm for 64-bits
> ARM64: dts: marvell: Add network support for Armada 3700
>
> Marcin Wojtas (2):
> net: mvneta: Convert to be 64 bits compatible
> net: mvneta: Add network support for Armada 3700 SoC
>
> Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt | 7 +-
> arch/arm64/boot/dts/marvell/armada-3720-db.dts | 23 ++++-
> arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 23 ++++-
> drivers/net/ethernet/marvell/Kconfig | 10 +-
> drivers/net/ethernet/marvell/mvneta.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
> 5 files changed, 361 insertions(+), 102 deletions(-)
>
> base-commit: 436accebb53021ef7c63535f60bda410aa87c136
> --
> git-series 0.8.10
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH] extcon: Split out the extcon APIs for extcon provider driver
From: Chanwoo Choi @ 2016-11-29 10:02 UTC (permalink / raw)
To: linux-arm-kernel
This patchs split out the extcon APIs of extcon provider driver in order to
prevent the direct access of struct extcon_dev by extcon consumer driver.
The extcon consumer driver don't need to handle the extcon provider APIs.
The extcon subsystem has two type of extcon drivers as following:
- extcon provider driver
: Detect the external connector and identify the state/property of
each external connector. And it send the notification to synchronize
the information between provider and consumer driver.
- extcon consumer driver
: Receive the notifcation from extcon provider driver. When receving the noti,
it can get the both state and property of specific external connector.
Cc: Myungjoo Ham <myungjoo.ham@samsung.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Felipe Balbi <balbi@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Chris Zhong <zyw@rock-chips.com>
Cc: Roger Quadros <rogerq@ti.com>
Cc: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Cc: patches at opensource.wolfsonmicro.com
Cc: linux-renesas-soc at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-usb at vger.kernel.org
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
---
drivers/extcon/devres.c | 2 +-
drivers/extcon/extcon-adc-jack.c | 2 +-
drivers/extcon/extcon-arizona.c | 2 +-
drivers/extcon/extcon-axp288.c | 2 +-
drivers/extcon/extcon-gpio.c | 2 +-
drivers/extcon/extcon-max14577.c | 2 +-
drivers/extcon/extcon-max3355.c | 2 +-
drivers/extcon/extcon-max77693.c | 2 +-
drivers/extcon/extcon-max77843.c | 2 +-
drivers/extcon/extcon-max8997.c | 2 +-
drivers/extcon/extcon-palmas.c | 1 +
drivers/extcon/extcon-qcom-spmi-misc.c | 2 +-
drivers/extcon/extcon-rt8973a.c | 2 +-
drivers/extcon/extcon-sm5502.c | 2 +-
drivers/extcon/extcon-usb-gpio.c | 2 +-
drivers/extcon/extcon.c | 2 +-
drivers/phy/phy-rcar-gen3-usb2.c | 2 +-
drivers/phy/phy-sun4i-usb.c | 2 +-
drivers/power/supply/qcom_smbb.c | 2 +-
drivers/usb/phy/phy-tahvo.c | 2 +-
include/linux/extcon-provider.h | 262 +++++++++++++++++++++++++++++++++
include/linux/extcon.h | 168 +--------------------
22 files changed, 286 insertions(+), 183 deletions(-)
create mode 100644 include/linux/extcon-provider.h
diff --git a/drivers/extcon/devres.c b/drivers/extcon/devres.c
index e686acd1c459..1b7dce13b21b 100644
--- a/drivers/extcon/devres.c
+++ b/drivers/extcon/devres.c
@@ -14,7 +14,7 @@
* GNU General Public License for more details.
*/
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
static int devm_extcon_dev_match(struct device *dev, void *res, void *data)
{
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index bc538708c753..0882813a95f9 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -26,7 +26,7 @@
#include <linux/workqueue.h>
#include <linux/iio/consumer.h>
#include <linux/extcon/extcon-adc-jack.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
/**
* struct adc_jack_data - internal data for adc_jack device driver
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index aeab47df9233..292878714ed9 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -27,7 +27,7 @@
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <sound/soc.h>
diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c
index 42f41e808292..f5b3687d29e8 100644
--- a/drivers/extcon/extcon-axp288.c
+++ b/drivers/extcon/extcon-axp288.c
@@ -23,7 +23,7 @@
#include <linux/property.h>
#include <linux/usb/phy.h>
#include <linux/notifier.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/regmap.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index ebed22f22d75..ab770adcca7e 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -17,7 +17,7 @@
* GNU General Public License for more details.
*/
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/extcon/extcon-gpio.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c
index 12e26c4e7763..9a7524ebf698 100644
--- a/drivers/extcon/extcon-max14577.c
+++ b/drivers/extcon/extcon-max14577.c
@@ -23,7 +23,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/max14577.h>
#include <linux/mfd/max14577-private.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#define DELAY_MS_DEFAULT 17000 /* unit: millisecond */
diff --git a/drivers/extcon/extcon-max3355.c b/drivers/extcon/extcon-max3355.c
index 533e16a952b8..0aa410836f4e 100644
--- a/drivers/extcon/extcon-max3355.c
+++ b/drivers/extcon/extcon-max3355.c
@@ -9,7 +9,7 @@
* may be copied, distributed, and modified under those terms.
*/
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 68dbcb814b2f..d49339591cb6 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -26,7 +26,7 @@
#include <linux/mfd/max77693.h>
#include <linux/mfd/max77693-common.h>
#include <linux/mfd/max77693-private.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/regmap.h>
#include <linux/irqdomain.h>
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c
index 5d11fdf36e94..ad288b6d475f 100644
--- a/drivers/extcon/extcon-max77843.c
+++ b/drivers/extcon/extcon-max77843.c
@@ -11,7 +11,7 @@
* (at your option) any later version.
*/
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 4a0612fb9c07..8152790d72e1 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -25,7 +25,7 @@
#include <linux/kobject.h>
#include <linux/mfd/max8997.h>
#include <linux/mfd/max8997-private.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/irqdomain.h>
#define DEV_NAME "max8997-muic"
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index 634ba70782de..a093fc2a56e8 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -25,6 +25,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/extcon-provider.h>
#include <linux/mfd/palmas.h>
#include <linux/of.h>
#include <linux/of_platform.h>
diff --git a/drivers/extcon/extcon-qcom-spmi-misc.c b/drivers/extcon/extcon-qcom-spmi-misc.c
index b8cde096a808..660bbf163bf5 100644
--- a/drivers/extcon/extcon-qcom-spmi-misc.c
+++ b/drivers/extcon/extcon-qcom-spmi-misc.c
@@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c
index 174c388739ea..64442f236855 100644
--- a/drivers/extcon/extcon-rt8973a.c
+++ b/drivers/extcon/extcon-rt8973a.c
@@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include "extcon-rt8973a.h"
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c
index b22325688503..9e2483e70533 100644
--- a/drivers/extcon/extcon-sm5502.c
+++ b/drivers/extcon/extcon-sm5502.c
@@ -19,7 +19,7 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include "extcon-sm5502.h"
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
index d589c5feff3d..98e5e3eb5317 100644
--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -14,7 +14,7 @@
* GNU General Public License for more details.
*/
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/init.h>
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index 78298460d168..6eaeffe8bd88 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -30,7 +30,7 @@
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/err.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c
index 3d97eadd247d..bd2430d7339c 100644
--- a/drivers/phy/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/phy-rcar-gen3-usb2.c
@@ -12,7 +12,7 @@
* published by the Free Software Foundation.
*/
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index fec34f5213c4..eeda5134c777 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -24,7 +24,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
diff --git a/drivers/power/supply/qcom_smbb.c b/drivers/power/supply/qcom_smbb.c
index b5896ba2a602..bb91a1c339bc 100644
--- a/drivers/power/supply/qcom_smbb.c
+++ b/drivers/power/supply/qcom_smbb.c
@@ -34,7 +34,7 @@
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#define SMBB_CHG_VMAX 0x040
#define SMBB_CHG_VSAFE 0x041
diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
index ab5d364f6e8c..1343bff004eb 100644
--- a/drivers/usb/phy/phy-tahvo.c
+++ b/drivers/usb/phy/phy-tahvo.c
@@ -23,7 +23,7 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/usb.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb/otg.h>
diff --git a/include/linux/extcon-provider.h b/include/linux/extcon-provider.h
new file mode 100644
index 000000000000..e91dc028184b
--- /dev/null
+++ b/include/linux/extcon-provider.h
@@ -0,0 +1,262 @@
+/*
+ * linux/include/linux/extcon-provider.h
+ *
+ * Copyright (C) 2016 Samsung Electronics
+ * Author: Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_EXTCON_PROVIDER_H__
+#define __LINUX_EXTCON_PROVIDER_H__
+
+#include <linux/extcon.h>
+
+/**
+ * struct extcon_dev - An extcon device represents one external connector.
+ * @name: The name of this extcon device. Parent device name is
+ * used if NULL.
+ * @supported_cable: Array of supported cable names ending with EXTCON_NONE.
+ * If supported_cable is NULL, cable name related APIs
+ * are disabled.
+ * @mutually_exclusive: Array of mutually exclusive set of cables that cannot
+ * be attached simultaneously. The array should be
+ * ending with NULL or be NULL (no mutually exclusive
+ * cables). For example, if it is { 0x7, 0x30, 0}, then,
+ * {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot
+ * be attached simulataneously. {0x7, 0} is equivalent to
+ * {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
+ * can be no simultaneous connections.
+ * @dev: Device of this extcon.
+ * @state: Attach/detach state of this extcon. Do not provide at
+ * register-time.
+ * @nh: Notifier for the state change events from this extcon
+ * @entry: To support list of extcon devices so that users can
+ * search for extcon devices based on the extcon name.
+ * @lock:
+ * @max_supported: Internal value to store the number of cables.
+ * @extcon_dev_type: Device_type struct to provide attribute_groups
+ * customized for each extcon device.
+ * @cables: Sysfs subdirectories. Each represents one cable.
+ *
+ * In most cases, users only need to provide "User initializing data" of
+ * this struct when registering an extcon. In some exceptional cases,
+ * optional callbacks may be needed. However, the values in "internal data"
+ * are overwritten by register function.
+ */
+struct extcon_dev {
+ /* Optional user initializing data */
+ const char *name;
+ const unsigned int *supported_cable;
+ const u32 *mutually_exclusive;
+
+ /* Internal data. Please do not set. */
+ struct device dev;
+ struct raw_notifier_head *nh;
+ struct list_head entry;
+ int max_supported;
+ spinlock_t lock; /* could be called by irq handler */
+ u32 state;
+
+ /* /sys/class/extcon/.../cable.n/... */
+ struct device_type extcon_dev_type;
+ struct extcon_cable *cables;
+
+ /* /sys/class/extcon/.../mutually_exclusive/... */
+ struct attribute_group attr_g_muex;
+ struct attribute **attrs_muex;
+ struct device_attribute *d_attrs_muex;
+};
+
+#if IS_ENABLED(CONFIG_EXTCON)
+
+/*
+ * Following APIs are for notifiers or configurations.
+ * Notifiers are the external port and connection devices.
+ */
+extern int extcon_dev_register(struct extcon_dev *edev);
+extern void extcon_dev_unregister(struct extcon_dev *edev);
+extern int devm_extcon_dev_register(struct device *dev,
+ struct extcon_dev *edev);
+extern void devm_extcon_dev_unregister(struct device *dev,
+ struct extcon_dev *edev);
+
+/*
+ * Following APIs control the memory of extcon device.
+ */
+extern struct extcon_dev *extcon_dev_allocate(const unsigned int *cable);
+extern void extcon_dev_free(struct extcon_dev *edev);
+extern struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
+ const unsigned int *cable);
+extern void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev);
+
+/*
+ * set_state access each bit of the 32b encoded state value.
+ * They are used to access the status of each cable based on the cable id.
+ */
+extern int extcon_set_state(struct extcon_dev *edev, unsigned int id,
+ bool cable_state);
+extern int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
+ bool cable_state);
+
+/*
+ * Synchronize the state and property data for a specific external connector.
+ */
+extern int extcon_sync(struct extcon_dev *edev, unsigned int id);
+
+/*
+ * set_property access the property value of each external connector.
+ * They are used to access the property of each cable based on the property id.
+ */
+extern int extcon_set_property(struct extcon_dev *edev, unsigned int id,
+ unsigned int prop,
+ union extcon_property_value prop_val);
+extern int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id,
+ unsigned int prop,
+ union extcon_property_value prop_val);
+
+/*
+ * set_property_capability set the capability of the property for each
+ * external connector. They are used to set the capability of the property
+ * of each external connector based on the id and property.
+ */
+extern int extcon_set_property_capability(struct extcon_dev *edev,
+ unsigned int id, unsigned int prop);
+
+/*
+ * Following APIs are to monitor every action of a notifier.
+ * Registrar gets notified for every external port of a connection device.
+ * Probably this could be used to debug an action of notifier; however,
+ * we do not recommend to use this for normal 'notifiee' device drivers who
+ * want to be notified by a specific external port of the notifier.
+ */
+extern int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
+ struct notifier_block *nb);
+extern int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
+ struct notifier_block *nb);
+extern int devm_extcon_register_notifier(struct device *dev,
+ struct extcon_dev *edev, unsigned int id,
+ struct notifier_block *nb);
+extern void devm_extcon_unregister_notifier(struct device *dev,
+ struct extcon_dev *edev, unsigned int id,
+ struct notifier_block *nb);
+
+/*
+ * Following API get the extcon device from devicetree.
+ * This function use phandle of devicetree to get extcon device directly.
+ */
+extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
+ int index);
+
+/* Following API to get information of extcon device */
+extern const char *extcon_get_edev_name(struct extcon_dev *edev);
+
+
+#else /* CONFIG_EXTCON */
+static inline int extcon_dev_register(struct extcon_dev *edev)
+{
+ return 0;
+}
+
+static inline void extcon_dev_unregister(struct extcon_dev *edev) { }
+
+static inline int devm_extcon_dev_register(struct device *dev,
+ struct extcon_dev *edev)
+{
+ return -EINVAL;
+}
+
+static inline void devm_extcon_dev_unregister(struct device *dev,
+ struct extcon_dev *edev) { }
+
+static inline struct extcon_dev *extcon_dev_allocate(const unsigned int *cable)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void extcon_dev_free(struct extcon_dev *edev) { }
+
+static inline struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
+ const unsigned int *cable)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void devm_extcon_dev_free(struct extcon_dev *edev) { }
+
+static inline int extcon_set_state(struct extcon_dev *edev, unsigned int id,
+ bool cable_state)
+{
+ return 0;
+}
+
+static inline int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
+ bool cable_state)
+{
+ return 0;
+}
+
+static inline int extcon_sync(struct extcon_dev *edev, unsigned int id)
+{
+ return 0;
+}
+
+static inline int extcon_set_property(struct extcon_dev *edev, unsigned int id,
+ unsigned int prop,
+ union extcon_property_value prop_val)
+{
+ return 0;
+}
+
+static inline int extcon_set_property_sync(struct extcon_dev *edev,
+ unsigned int id, unsigned int prop,
+ union extcon_property_value prop_val)
+{
+ return 0;
+}
+
+static inline int extcon_set_property_capability(struct extcon_dev *edev,
+ unsigned int id, unsigned int prop)
+{
+ return 0;
+}
+
+static inline int extcon_register_notifier(struct extcon_dev *edev,
+ unsigned int id,
+ struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int extcon_unregister_notifier(struct extcon_dev *edev,
+ unsigned int id,
+ struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int devm_extcon_register_notifier(struct device *dev,
+ struct extcon_dev *edev, unsigned int id,
+ struct notifier_block *nb)
+{
+ return -ENOSYS;
+}
+
+static inline void devm_extcon_unregister_notifier(struct device *dev,
+ struct extcon_dev *edev, unsigned int id,
+ struct notifier_block *nb) { }
+#endif /* CONFIG_EXTCON */
+
+/*
+ * Following API are deprecated. EXTCON remains the function definition
+ * to prevent the build break.
+ */
+static inline int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id,
+ bool cable_state)
+{
+ return extcon_set_state_sync(edev, id, cable_state);
+}
+#endif /* __LINUX_EXTCON_PROVIDER_H__ */
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index b871c0cb1f02..8cb2ef6dcbe0 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -160,62 +160,7 @@
};
struct extcon_cable;
-
-/**
- * struct extcon_dev - An extcon device represents one external connector.
- * @name: The name of this extcon device. Parent device name is
- * used if NULL.
- * @supported_cable: Array of supported cable names ending with EXTCON_NONE.
- * If supported_cable is NULL, cable name related APIs
- * are disabled.
- * @mutually_exclusive: Array of mutually exclusive set of cables that cannot
- * be attached simultaneously. The array should be
- * ending with NULL or be NULL (no mutually exclusive
- * cables). For example, if it is { 0x7, 0x30, 0}, then,
- * {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot
- * be attached simulataneously. {0x7, 0} is equivalent to
- * {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
- * can be no simultaneous connections.
- * @dev: Device of this extcon.
- * @state: Attach/detach state of this extcon. Do not provide at
- * register-time.
- * @nh: Notifier for the state change events from this extcon
- * @entry: To support list of extcon devices so that users can
- * search for extcon devices based on the extcon name.
- * @lock:
- * @max_supported: Internal value to store the number of cables.
- * @extcon_dev_type: Device_type struct to provide attribute_groups
- * customized for each extcon device.
- * @cables: Sysfs subdirectories. Each represents one cable.
- *
- * In most cases, users only need to provide "User initializing data" of
- * this struct when registering an extcon. In some exceptional cases,
- * optional callbacks may be needed. However, the values in "internal data"
- * are overwritten by register function.
- */
-struct extcon_dev {
- /* Optional user initializing data */
- const char *name;
- const unsigned int *supported_cable;
- const u32 *mutually_exclusive;
-
- /* Internal data. Please do not set. */
- struct device dev;
- struct raw_notifier_head *nh;
- struct list_head entry;
- int max_supported;
- spinlock_t lock; /* could be called by irq handler */
- u32 state;
-
- /* /sys/class/extcon/.../cable.n/... */
- struct device_type extcon_dev_type;
- struct extcon_cable *cables;
-
- /* /sys/class/extcon/.../mutually_exclusive/... */
- struct attribute_group attr_g_muex;
- struct attribute **attrs_muex;
- struct device_attribute *d_attrs_muex;
-};
+struct extcon_dev;
#if IS_ENABLED(CONFIG_EXTCON)
@@ -223,60 +168,29 @@ struct extcon_dev {
* Following APIs are for notifiers or configurations.
* Notifiers are the external port and connection devices.
*/
-extern int extcon_dev_register(struct extcon_dev *edev);
-extern void extcon_dev_unregister(struct extcon_dev *edev);
-extern int devm_extcon_dev_register(struct device *dev,
- struct extcon_dev *edev);
-extern void devm_extcon_dev_unregister(struct device *dev,
- struct extcon_dev *edev);
extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
/*
- * Following APIs control the memory of extcon device.
- */
-extern struct extcon_dev *extcon_dev_allocate(const unsigned int *cable);
-extern void extcon_dev_free(struct extcon_dev *edev);
-extern struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
- const unsigned int *cable);
-extern void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev);
-
-/*
- * get/set_state access each bit of the 32b encoded state value.
+ * get_state access each bit of the 32b encoded state value.
* They are used to access the status of each cable based on the cable id.
*/
extern int extcon_get_state(struct extcon_dev *edev, unsigned int id);
-extern int extcon_set_state(struct extcon_dev *edev, unsigned int id,
- bool cable_state);
-extern int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
- bool cable_state);
-/*
- * Synchronize the state and property data for a specific external connector.
- */
-extern int extcon_sync(struct extcon_dev *edev, unsigned int id);
/*
- * get/set_property access the property value of each external connector.
+ * get_property access the property value of each external connector.
* They are used to access the property of each cable based on the property id.
*/
extern int extcon_get_property(struct extcon_dev *edev, unsigned int id,
unsigned int prop,
union extcon_property_value *prop_val);
-extern int extcon_set_property(struct extcon_dev *edev, unsigned int id,
- unsigned int prop,
- union extcon_property_value prop_val);
-extern int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id,
- unsigned int prop,
- union extcon_property_value prop_val);
/*
- * get/set_property_capability set the capability of the property for each
+ * get_property_capability set the capability of the property for each
* external connector. They are used to set the capability of the property
* of each external connector based on the id and property.
*/
extern int extcon_get_property_capability(struct extcon_dev *edev,
unsigned int id, unsigned int prop);
-extern int extcon_set_property_capability(struct extcon_dev *edev,
- unsigned int id, unsigned int prop);
/*
* Following APIs are to monitor every action of a notifier.
@@ -306,81 +220,19 @@ extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
/* Following API to get information of extcon device */
extern const char *extcon_get_edev_name(struct extcon_dev *edev);
-
#else /* CONFIG_EXTCON */
-static inline int extcon_dev_register(struct extcon_dev *edev)
-{
- return 0;
-}
-
-static inline void extcon_dev_unregister(struct extcon_dev *edev) { }
-
-static inline int devm_extcon_dev_register(struct device *dev,
- struct extcon_dev *edev)
-{
- return -EINVAL;
-}
-
-static inline void devm_extcon_dev_unregister(struct device *dev,
- struct extcon_dev *edev) { }
-
-static inline struct extcon_dev *extcon_dev_allocate(const unsigned int *cable)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline void extcon_dev_free(struct extcon_dev *edev) { }
-
-static inline struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
- const unsigned int *cable)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline void devm_extcon_dev_free(struct extcon_dev *edev) { }
-
static inline int extcon_get_state(struct extcon_dev *edev, unsigned int id)
{
return 0;
}
-static inline int extcon_set_state(struct extcon_dev *edev, unsigned int id,
- bool cable_state)
-{
- return 0;
-}
-
-static inline int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
- bool cable_state)
-{
- return 0;
-}
-
-static inline int extcon_sync(struct extcon_dev *edev, unsigned int id)
-{
- return 0;
-}
-
static inline int extcon_get_property(struct extcon_dev *edev, unsigned int id,
unsigned int prop,
union extcon_property_value *prop_val)
{
return 0;
}
-static inline int extcon_set_property(struct extcon_dev *edev, unsigned int id,
- unsigned int prop,
- union extcon_property_value prop_val)
-{
- return 0;
-}
-
-static inline int extcon_set_property_sync(struct extcon_dev *edev,
- unsigned int id, unsigned int prop,
- union extcon_property_value prop_val)
-{
- return 0;
-}
static inline int extcon_get_property_capability(struct extcon_dev *edev,
unsigned int id, unsigned int prop)
@@ -388,12 +240,6 @@ static inline int extcon_get_property_capability(struct extcon_dev *edev,
return 0;
}
-static inline int extcon_set_property_capability(struct extcon_dev *edev,
- unsigned int id, unsigned int prop)
-{
- return 0;
-}
-
static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
{
return NULL;
@@ -459,10 +305,4 @@ static inline int extcon_get_cable_state_(struct extcon_dev *edev, unsigned int
{
return extcon_get_state(edev, id);
}
-
-static inline int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id,
- bool cable_state)
-{
- return extcon_set_state_sync(edev, id, cable_state);
-}
#endif /* __LINUX_EXTCON_H__ */
--
1.9.1
^ permalink raw reply related
* [PATCH v9 06/11] arm/arm64: vgic: Implement VGICv3 CPU interface access
From: Vijay Kilari @ 2016-11-29 10:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161129083747.GA9838@cbox>
On Tue, Nov 29, 2016 at 2:07 PM, Christoffer Dall
<christoffer.dall@linaro.org> wrote:
> On Tue, Nov 29, 2016 at 01:08:26PM +0530, Vijay Kilari wrote:
>> On Tue, Nov 29, 2016 at 1:09 AM, Christoffer Dall
>> <christoffer.dall@linaro.org> wrote:
>> > On Wed, Nov 23, 2016 at 06:31:53PM +0530, vijay.kilari at gmail.com wrote:
>> >> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>> >>
>> >> VGICv3 CPU interface registers are accessed using
>> >> KVM_DEV_ARM_VGIC_CPU_SYSREGS ioctl. These registers are accessed
>> >> as 64-bit. The cpu MPIDR value is passed along with register id.
>> >> is used to identify the cpu for registers access.
>> >>
>> >> The VM that supports SEIs expect it on destination machine to handle
>> >> guest aborts and hence checked for ICC_CTLR_EL1.SEIS compatibility.
>> >> Similarly, VM that supports Affinity Level 3 that is required for AArch64
>> >> mode, is required to be supported on destination machine. Hence checked
>> >> for ICC_CTLR_EL1.A3V compatibility.
>> >>
>> >> The CPU system register handling is spitted into two files
>> >
>> > spitted? Did you mean 'split into' ?
>> >
>> >> vgic-sys-reg-common.c and vgic-sys-reg-v3.c.
>> >> The vgic-sys-reg-common.c handles read and write of VGIC CPU registers
>> >
>> > So this is weird because everything in virt/kvm/arm/ is exactly supposed
>> > to be common between arm and arm64 already.
>> >
>> > I would rather that you had a copy of vgic-sys-reg-v3.c in arch/arm/kvm/
>> > and in arch/arm64/kvm/ each taking care of its own architecture.
>> >
>> > But note that I didn't actually require that you implemented support for
>> > GICv3 migration on AArch32 hosts for these patches, I just didn't want
>> > thigns to silently break.
>> >
>> > If we cannot test the AArch32 implementation, we should potentially just
>> > make sure that is not supported yet, return a proper error to userspace
>> > and get the AArch64 host implementation correct.
>> >
>> > I suggest you move your:
>> > virt/kvm/arm/vgic/vgic-sys-reg-v3.c to
>> > arch/arm64/kvm/vgic-sys-reg-v3.c
>> >
>> > and rename
>> > virt/kvm/arm/vgic/vgic-sys-reg-common.c to
>> > virt/kvm/arm/vgic/vgic-sys-reg-v3.c
>> >
>> > And then wait with the AArch32 host side for now, but just make sure it
>> > compiles and returns an error as opposed to crashing the system if
>> > someone tries to excercise this interface on an AArch32 host.
>>
>> I will add arch/arm/kvm/vgic-coproc-v3.c (pls check if file name is ok or not?)
>
> I would call it vgic-v3-coproc.c
>
>> and return -ENXIO as shown below and update document accordingly.
>>
>> int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
>> u64 *reg)
>> {
>> /*
>> * TODO: Implement for AArch32
>> */
>> return -ENXIO;
>> }
>>
>> int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
>> u64 *reg)
>> {
>> /*
>> * TODO: Implement for AArch32
>> */
>> return -ENXIO;
>> }
>
>
>>
>> >
>> >> for both AArch64 and AArch32 mode. The vgic-sys-reg-v3.c handles AArch64
>> >> mode and is compiled only for AArch64 mode.
>> >>
>> >> Updated arch/arm/include/uapi/asm/kvm.h with new definitions
>> >> required to compile for AArch32.
>> >>
>> >> The version of VGIC v3 specification is define here
>> >> Documentation/virtual/kvm/devices/arm-vgic-v3.txt
>> >>
>> >> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
>> >> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>> >> ---
>> [...]
>> >> +static bool access_gic_aprn(struct kvm_vcpu *vcpu, bool is_write, u8 apr,
>> >> + u8 idx, unsigned long *reg)
>> >> +{
>> >> + struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu;
>> >> +
>> >> + /* num_pri_bits are initialized with HW supported values.
>> >> + * We can rely safely on num_pri_bits even if VM has not
>> >> + * restored ICC_CTLR_EL1 before restoring APnR registers.
>> >> + */
>> >
>> > nit: commenting style
>> ok
>> >
>> >> + switch (vgic_v3_cpu->num_pri_bits) {
>> >> + case 7:
>> >> + vgic_v3_access_apr_reg(vcpu, is_write, apr, idx, reg);
>> >> + break;
>> >> + case 6:
>> >> + if (idx > 1)
>> >> + goto err;
>> >> + vgic_v3_access_apr_reg(vcpu, is_write, apr, idx, reg);
>> >> + break;
>> >> + default:
>> >> + if (idx > 0)
>> >> + goto err;
>> >> + vgic_v3_access_apr_reg(vcpu, is_write, apr, idx, reg);
>> >> + }
>> >
>> > It looks to me like userspace can then program active priorities with
>> > higher numbers than what it will program num_pri_bits to later. Is that
>> > not weird, or am I missing something?
>>
>> As long as it is within HW supported priorities it is safe.
>
> I know that it is safe on the hardware, but it is weird to define a VM
> with some max priority and still be able to set a higher active priority
> is it not?
In that case, we need to cache the highest active priorities updated
by a VM in a variable
when APnR is restored and later check against num_pri_bits when
ICC_CTLR_EL1 is updated.
If the value cached is greater than num_pri_bits restored then reject
ICC_CTLR_EL1 restore.
This variable should be initialized with value 5 ( min priority)
>
> On the other hand, if we cannot enforce this at runtime, it may not
> matter?
At VM runtime irrespective of VM's num_pri_bits all the APnR registers that
HW supports are saved and restored.
>
> Hint: I'd like for you to actually think about these constraints and
> make sure the sematics of the emulated VM environment remain intact
> across migrations.
>
>> >
>> >> +
>> >> + return true;
>> >> +err:
>> >> + if (!is_write)
>> >> + *reg = 0;
>> >> +
>> >> + return false;
>> >> +}
>> >> +
>> >> +bool access_gic_ap0r_reg(struct kvm_vcpu *vcpu, bool is_write, u8 idx,
>> >> + unsigned long *reg)
>> >> +{
>> >> + return access_gic_aprn(vcpu, is_write, 0, idx, reg);
>> >> +}
>> >> +
>> >> +bool access_gic_ap1r_reg(struct kvm_vcpu *vcpu, bool is_write, u8 idx,
>> >> + unsigned long *reg)
>> >> +{
>> >> + return access_gic_aprn(vcpu, is_write, 1, idx, reg);
>> >> +}
>> >> +
>> >> +bool access_gic_sre_reg(struct kvm_vcpu *vcpu, bool is_write,
>> >> + unsigned long *reg)
>> >> +{
>> >> + struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
>> >> +
>> >> + /* Validate SRE bit */
>> >> + if (is_write) {
>> >> + if (!(*reg & ICC_SRE_EL1_SRE))
>> >> + return false;
>> >> + } else {
>> >> + *reg = vgicv3->vgic_sre;
>> >> + }
>> >> +
>> >> + return true;
>> >> +}
>> >> diff --git a/virt/kvm/arm/vgic/vgic-sys-reg-v3.c b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
>> >> new file mode 100644
>> >> index 0000000..82c2f02
>> >> --- /dev/null
>> >> +++ b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
>> >> @@ -0,0 +1,142 @@
>> >> +/*
>> >> + * VGIC system registers handling functions
>> >> + *
>> >> + * This program is free software; you can redistribute it and/or modify
>> >> + * it under the terms of the GNU General Public License version 2 as
>> >> + * published by the Free Software Foundation.
>> >> + *
>> >> + * This program is distributed in the hope that it will be useful,
>> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> >> + * GNU General Public License for more details.
>> >> + */
>> >> +
>> >> +#include <linux/kvm.h>
>> >> +#include <linux/kvm_host.h>
>> >> +#include <asm/kvm_emulate.h>
>> >> +#include "vgic.h"
>> >> +#include "sys_regs.h"
>> >> +
>> >> +#define ACCESS_SYS_REG(REG) \
>> >> +static bool access_gic_##REG##_sys_reg(struct kvm_vcpu *vcpu, \
>> >> + struct sys_reg_params *p, \
>> >> + const struct sys_reg_desc *r) \
>> >> +{ \
>> >> + unsigned long tmp; \
>> >> + bool ret; \
>> >> + \
>> >> + if (p->is_write) \
>> >> + tmp = p->regval; \
>> >> + ret = access_gic_##REG##_reg(vcpu, p->is_write, &tmp); \
>> >> + if (!p->is_write) \
>> >> + p->regval = tmp; \
>> >> + \
>> >> + return ret; \
>> >> +}
>> >> +
>> >> +ACCESS_SYS_REG(ctlr)
>> >> +ACCESS_SYS_REG(pmr)
>> >> +ACCESS_SYS_REG(bpr0)
>> >> +ACCESS_SYS_REG(bpr1)
>> >> +ACCESS_SYS_REG(sre)
>> >> +ACCESS_SYS_REG(grpen0)
>> >> +ACCESS_SYS_REG(grpen1)
>> >> +
>> >> +#define ACCESS_APNR_SYS_REG(REG) \
>> >> +static bool access_gic_##REG##_sys_reg(struct kvm_vcpu *vcpu, \
>> >> + struct sys_reg_params *p, \
>> >> + const struct sys_reg_desc *r) \
>> >> +{ \
>> >> + unsigned long tmp; \
>> >> + u8 idx = p->Op2 & 3; \
>> >> + bool ret; \
>> >> + \
>> >> + if (p->is_write) \
>> >> + tmp = p->regval; \
>> >> + ret = access_gic_##REG##_reg(vcpu, p->is_write, idx, &tmp); \
>> >> + if (!p->is_write) \
>> >> + p->regval = tmp; \
>> >> + \
>> >> + return ret; \
>> >> +}
>> >> +
>> >> +ACCESS_APNR_SYS_REG(ap0r)
>> >> +ACCESS_APNR_SYS_REG(ap1r)
>> >
>> > I don't get these indirections. Why can't you call the functions
>> > directly?
>>
>> The code is same for accessing the registers hence added this indirection.
>>
>
> That's not answering my question.
>
> What is the benefit of adding this indirection as opposed to having the
> functions called directly?
In sys_reg_desc the access function is of type
bool (*access)(struct kvm_vcpu *,
struct sys_reg_params *,
const struct sys_reg_desc *);
Where as the each register access function is of type below to support
access to AArch32(later if not now).
bool access_gic_xxx(struct kvm_vcpu *vcpu, bool is_write, unsigned long *reg);
I can drop this macro and make function calls for each reg access.
>
> To make my point clear: I hate this kind of preprocessor macro fun, and
> I think it should only ever be used when there's a huge benefit in terms
> of code reuse or simplicity of some sort. I don't see anything like
> that in this case.
>
> Thanks,
> -Christoffer
^ permalink raw reply
* [PATCH v3 net-next 2/6] net: mvneta: Use cacheable memory to store the rx buffer virtual address
From: Marcin Wojtas @ 2016-11-29 9:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a010f2cde3de80132d82acb2812b82343ea54c95.1480412215.git-series.gregory.clement@free-electrons.com>
Hi Gregory,
Another remark below, sorry for noise.
2016-11-29 10:37 GMT+01:00 Gregory CLEMENT <gregory.clement@free-electrons.com>:
> Until now the virtual address of the received buffer were stored in the
> cookie field of the rx descriptor. However, this field is 32-bits only
> which prevents to use the driver on a 64-bits architecture.
>
> With this patch the virtual address is stored in an array not shared with
> the hardware (no more need to use the DMA API). Thanks to this, it is
> possible to use cache contrary to the access of the rx descriptor member.
>
> The change is done in the swbm path only because the hwbm uses the cookie
> field, this also means that currently the hwbm is not usable in 64-bits.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/net/ethernet/marvell/mvneta.c | 93 ++++++++++++++++++++++++----
> 1 file changed, 81 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> index 1b84f746d748..32b142d0e44e 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -561,6 +561,9 @@ struct mvneta_rx_queue {
> u32 pkts_coal;
> u32 time_coal;
>
> + /* Virtual address of the RX buffer */
> + void **buf_virt_addr;
> +
> /* Virtual address of the RX DMA descriptors array */
> struct mvneta_rx_desc *descs;
>
> @@ -1573,10 +1576,14 @@ static void mvneta_tx_done_pkts_coal_set(struct mvneta_port *pp,
>
> /* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
> static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
> - u32 phys_addr, u32 cookie)
> + u32 phys_addr, void *virt_addr,
> + struct mvneta_rx_queue *rxq)
> {
> - rx_desc->buf_cookie = cookie;
> + int i;
> +
> rx_desc->buf_phys_addr = phys_addr;
> + i = rx_desc - rxq->descs;
> + rxq->buf_virt_addr[i] = virt_addr;
> }
>
> /* Decrement sent descriptors counter */
> @@ -1781,7 +1788,8 @@ EXPORT_SYMBOL_GPL(mvneta_frag_free);
>
> /* Refill processing for SW buffer management */
> static int mvneta_rx_refill(struct mvneta_port *pp,
> - struct mvneta_rx_desc *rx_desc)
> + struct mvneta_rx_desc *rx_desc,
> + struct mvneta_rx_queue *rxq)
>
> {
> dma_addr_t phys_addr;
> @@ -1799,7 +1807,7 @@ static int mvneta_rx_refill(struct mvneta_port *pp,
> return -ENOMEM;
> }
>
> - mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)data);
> + mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
> return 0;
> }
>
> @@ -1861,7 +1869,12 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
>
> for (i = 0; i < rxq->size; i++) {
> struct mvneta_rx_desc *rx_desc = rxq->descs + i;
> - void *data = (void *)rx_desc->buf_cookie;
> + void *data;
> +
> + if (!pp->bm_priv)
> + data = rxq->buf_virt_addr[i];
> + else
> + data = (void *)(uintptr_t)rx_desc->buf_cookie;
Dropping packets for HWBM (in fact returning dropped buffers to the
pool) is done a couple of lines above. This point will never be
reached with HWBM enabled (and it's also incorrect).
Best regards,
Marcin
^ permalink raw reply
* [PATCH v3 net-next 2/6] net: mvneta: Use cacheable memory to store the rx buffer virtual address
From: Marcin Wojtas @ 2016-11-29 9:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a010f2cde3de80132d82acb2812b82343ea54c95.1480412215.git-series.gregory.clement@free-electrons.com>
Hi Gregory,
Apparently HWBM had a mistake in implementation, please see below.
2016-11-29 10:37 GMT+01:00 Gregory CLEMENT <gregory.clement@free-electrons.com>:
> Until now the virtual address of the received buffer were stored in the
> cookie field of the rx descriptor. However, this field is 32-bits only
> which prevents to use the driver on a 64-bits architecture.
>
> With this patch the virtual address is stored in an array not shared with
> the hardware (no more need to use the DMA API). Thanks to this, it is
> possible to use cache contrary to the access of the rx descriptor member.
>
> The change is done in the swbm path only because the hwbm uses the cookie
> field, this also means that currently the hwbm is not usable in 64-bits.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/net/ethernet/marvell/mvneta.c | 93 ++++++++++++++++++++++++----
> 1 file changed, 81 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> index 1b84f746d748..32b142d0e44e 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -561,6 +561,9 @@ struct mvneta_rx_queue {
> u32 pkts_coal;
> u32 time_coal;
>
> + /* Virtual address of the RX buffer */
> + void **buf_virt_addr;
> +
> /* Virtual address of the RX DMA descriptors array */
> struct mvneta_rx_desc *descs;
>
> @@ -1573,10 +1576,14 @@ static void mvneta_tx_done_pkts_coal_set(struct mvneta_port *pp,
>
> /* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
> static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
> - u32 phys_addr, u32 cookie)
> + u32 phys_addr, void *virt_addr,
> + struct mvneta_rx_queue *rxq)
> {
> - rx_desc->buf_cookie = cookie;
> + int i;
> +
> rx_desc->buf_phys_addr = phys_addr;
> + i = rx_desc - rxq->descs;
> + rxq->buf_virt_addr[i] = virt_addr;
> }
>
> /* Decrement sent descriptors counter */
> @@ -1781,7 +1788,8 @@ EXPORT_SYMBOL_GPL(mvneta_frag_free);
>
> /* Refill processing for SW buffer management */
> static int mvneta_rx_refill(struct mvneta_port *pp,
> - struct mvneta_rx_desc *rx_desc)
> + struct mvneta_rx_desc *rx_desc,
> + struct mvneta_rx_queue *rxq)
>
> {
> dma_addr_t phys_addr;
> @@ -1799,7 +1807,7 @@ static int mvneta_rx_refill(struct mvneta_port *pp,
> return -ENOMEM;
> }
>
> - mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)data);
> + mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
> return 0;
> }
>
> @@ -1861,7 +1869,12 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
>
> for (i = 0; i < rxq->size; i++) {
> struct mvneta_rx_desc *rx_desc = rxq->descs + i;
> - void *data = (void *)rx_desc->buf_cookie;
> + void *data;
> +
> + if (!pp->bm_priv)
> + data = rxq->buf_virt_addr[i];
> + else
> + data = (void *)(uintptr_t)rx_desc->buf_cookie;
>
> dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
> MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
> @@ -1894,12 +1907,13 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> unsigned char *data;
> dma_addr_t phys_addr;
> u32 rx_status, frag_size;
> - int rx_bytes, err;
> + int rx_bytes, err, index;
>
> rx_done++;
> rx_status = rx_desc->status;
> rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
> - data = (unsigned char *)rx_desc->buf_cookie;
> + index = rx_desc - rxq->descs;
> + data = (unsigned char *)rxq->buf_virt_addr[index];
> phys_addr = rx_desc->buf_phys_addr;
>
> if (!mvneta_rxq_desc_is_first_last(rx_status) ||
> @@ -1938,7 +1952,7 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> }
>
> /* Refill processing */
> - err = mvneta_rx_refill(pp, rx_desc);
> + err = mvneta_rx_refill(pp, rx_desc, rxq);
> if (err) {
> netdev_err(dev, "Linux processing - Can't refill\n");
> rxq->missed++;
> @@ -2020,7 +2034,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
> rx_done++;
> rx_status = rx_desc->status;
> rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
> - data = (unsigned char *)rx_desc->buf_cookie;
> + data = (u8 *)(uintptr_t)rx_desc->buf_cookie;
> phys_addr = rx_desc->buf_phys_addr;
> pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc);
> bm_pool = &pp->bm_priv->bm_pools[pool_id];
> @@ -2708,6 +2722,56 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
> return rx_done;
> }
>
> +/* Refill processing for HW buffer management */
> +static int mvneta_rx_hwbm_refill(struct mvneta_port *pp,
> + struct mvneta_rx_desc *rx_desc)
> +
> +{
> + dma_addr_t phys_addr;
> + void *data;
> +
> + data = mvneta_frag_alloc(pp->frag_size);
> + if (!data)
> + return -ENOMEM;
> +
> + phys_addr = dma_map_single(pp->dev->dev.parent, data,
> + MVNETA_RX_BUF_SIZE(pp->pkt_size),
> + DMA_FROM_DEVICE);
> + if (unlikely(dma_mapping_error(pp->dev->dev.parent, phys_addr))) {
> + mvneta_frag_free(pp->frag_size, data);
> + return -ENOMEM;
> + }
> +
> + rx_desc->buf_phys_addr = phys_addr;
> + rx_desc->buf_cookie = (uintptr_t)data;
> +
> + return 0;
> +}
> +
> +/* Handle rxq fill: allocates rxq skbs; called when initializing a port */
> +static int mvneta_rxq_bm_fill(struct mvneta_port *pp,
> + struct mvneta_rx_queue *rxq,
> + int num)
> +{
> + int i;
> +
> + for (i = 0; i < num; i++) {
> + memset(rxq->descs + i, 0, sizeof(struct mvneta_rx_desc));
> + if (mvneta_rx_hwbm_refill(pp, rxq->descs + i) != 0) {
> + netdev_err(pp->dev, "%s:rxq %d, %d of %d buffs filled\n",
> + __func__, rxq->id, i, num);
> + break;
> + }
> + }
> +
> + /* Add this number of RX descriptors as non occupied (ready to
> + * get packets)
> + */
> + mvneta_rxq_non_occup_desc_add(pp, rxq, i);
> +
> + return i;
> +}
> +
> /* Handle rxq fill: allocates rxq skbs; called when initializing a port */
> static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
> int num)
> @@ -2716,7 +2780,7 @@ static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
>
> for (i = 0; i < num; i++) {
> memset(rxq->descs + i, 0, sizeof(struct mvneta_rx_desc));
> - if (mvneta_rx_refill(pp, rxq->descs + i) != 0) {
> + if (mvneta_rx_refill(pp, rxq->descs + i, rxq) != 0) {
> netdev_err(pp->dev, "%s:rxq %d, %d of %d buffs filled\n",
> __func__, rxq->id, i, num);
> break;
> @@ -2784,14 +2848,14 @@ static int mvneta_rxq_init(struct mvneta_port *pp,
> mvneta_rxq_buf_size_set(pp, rxq,
> MVNETA_RX_BUF_SIZE(pp->pkt_size));
> mvneta_rxq_bm_disable(pp, rxq);
> + mvneta_rxq_fill(pp, rxq, rxq->size);
> } else {
> mvneta_rxq_bm_enable(pp, rxq);
> mvneta_rxq_long_pool_set(pp, rxq);
> mvneta_rxq_short_pool_set(pp, rxq);
> + mvneta_rxq_bm_fill(pp, rxq, rxq->size);
Manual filling descriptors with new buffers is redundant. For HWBM,
all buffers are allocated in mvneta_bm_construct() and in runtime they
are put into descriptors by hardware. I think it's enough to add here:
mvneta_rxq_non_occup_desc_add(pp, rxq, rxq->size);
And remove mvneta_rxq_bm_fill and mvneta_rx_hwbm_refill.
Best regards,
Marcin
^ permalink raw reply
* [PATCH v2 6/7] IIO: add STM32 IIO timer driver
From: Benjamin Gaignard @ 2016-11-29 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3e2bce3d-c607-d397-487f-2439a0ba7b0b@kernel.org>
2016-11-27 16:42 GMT+01:00 Jonathan Cameron <jic23@kernel.org>:
> I delved into the datasheet after trying to figure this out, so I think
> I now sort of understand your intent, but please do answer the questions
> inline.
>
> On 24/11/16 15:14, Benjamin Gaignard wrote:
>> Timers IPs can be used to generate triggers for other IPs like
>> DAC, ADC or other timers.
>> Each trigger may result of timer internals signals like counter enable,
>> reset or edge, this configuration could be done through "master_mode"
>> device attribute.
>>
>> A timer device could be triggered by other timers, we use the trigger
>> name and is_stm32_iio_timer_trigger() function to distinguish them
>> and configure IP input switch.
> The presence of an IIO device in here was a suprise.. What is it actually for?
IIO device is needed to be able to valid the input triggers, which
aren't the same than
those generated by the device.
Since I use triggers name to distinguish them I have introduced
is_stm32_iio_timer_trigger()
function to be sure that triggers are coming for a valid hardware and
not from a fake one
using the same name.
>
> I think this needs some examples of usage to make it clear what the aim is.
In the hardware block there is switch in input to select which trigger
will drive the IP.
For example that allow to start multiple pwm exactly that the same
time or to start/stop
it on master edges.
>
> I was basically expecting to see a driver instantiating one iio trigger
> per timer that can act as a trigger. Those would each have sampling frequency
> controls and basica enable / disable.
An hardware device could have up to 5 triggers: timX_trgo, timX_ch1, timX_ch2,
timX_ch3, timX_ch4.
Until now I have try to simplify the problem and just use timX_trgo trigger.
I have added a "sampling_frequency" attribute on the trigger to
control the frequence
and I use trigger set_state function to enable disable it.
>
> I'm seeing something much more complex here so additional explanation is
> needed.
>>
>> Timer may also decide on which event (edge, level) they could
>> be activated by a trigger, this configuration is done by writing in
>> "slave_mode" device attribute.
> Really? Sounds like magic numbers in sysfs which is never a good idea.
> Please document those attributes / or break them up into elements that
> don't require magic numbers.
I would like to use strings here, it is possible to use IIO_CONST_ATTR
to describe them ?
>>
>> Since triggers could also be used by DAC or ADC their names are defined
>> in include/dt-bindings/iio/timer/st,stm32-iio-timer.h so those IPs will be able
>> to configure themselves in valid_trigger function
>>
>> Trigger have a "sampling_frequency" attribute which allow to configure
>> timer sampling frequency without using pwm interface
>>
>> version 2:
>> - keep only one compatible
> Hmm. I'm not sure I like this as such. We are actually dealing with lots
> of instances of a hardware block with only a small amount of shared
> infrastrcuture (which is classic mfd teritory). So to my mind we
> should have a separate device for each.
Registers mapping and offset are the same, from triggers point of view
only the configuration of the input switch is different.
>
>> - use st,input-triggers-names and st,output-triggers-names
>> to know which triggers are accepted and/or create by the device
> I'm not following why we have this cascade setup?
>
> These are triggers, not devices in the IIO context. We need some detailed
> description of why you have it setup like this. This would include the
> ABI with examples of how you are using it.
I had put example of usage on the cover letter, I will duplicate them
in this commit
message.
>
> Basically I don't currently understand what you are doing :(
>
>
> Thanks,
>
> Jonathan
>>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
>> ---
>> drivers/iio/Kconfig | 2 +-
>> drivers/iio/Makefile | 1 +
>> drivers/iio/timer/Kconfig | 15 +
>> drivers/iio/timer/Makefile | 1 +
>> drivers/iio/timer/stm32-iio-timer.c | 448 +++++++++++++++++++++
>> drivers/iio/trigger/Kconfig | 1 -
>> include/dt-bindings/iio/timer/st,stm32-iio-timer.h | 23 ++
>> include/linux/iio/timer/stm32-iio-timers.h | 16 +
>> 8 files changed, 505 insertions(+), 2 deletions(-)
>> create mode 100644 drivers/iio/timer/Kconfig
>> create mode 100644 drivers/iio/timer/Makefile
>> create mode 100644 drivers/iio/timer/stm32-iio-timer.c
>> create mode 100644 include/dt-bindings/iio/timer/st,stm32-iio-timer.h
>> create mode 100644 include/linux/iio/timer/stm32-iio-timers.h
>>
>> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
>> index 6743b18..2de2a80 100644
>> --- a/drivers/iio/Kconfig
>> +++ b/drivers/iio/Kconfig
>> @@ -90,5 +90,5 @@ source "drivers/iio/potentiometer/Kconfig"
>> source "drivers/iio/pressure/Kconfig"
>> source "drivers/iio/proximity/Kconfig"
>> source "drivers/iio/temperature/Kconfig"
>> -
>> +source "drivers/iio/timer/Kconfig"
>> endif # IIO
>> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
>> index 87e4c43..b797c08 100644
>> --- a/drivers/iio/Makefile
>> +++ b/drivers/iio/Makefile
>> @@ -32,4 +32,5 @@ obj-y += potentiometer/
>> obj-y += pressure/
>> obj-y += proximity/
>> obj-y += temperature/
>> +obj-y += timer/
>> obj-y += trigger/
>> diff --git a/drivers/iio/timer/Kconfig b/drivers/iio/timer/Kconfig
>> new file mode 100644
>> index 0000000..7a73bc6
>> --- /dev/null
>> +++ b/drivers/iio/timer/Kconfig
>> @@ -0,0 +1,15 @@
>> +#
>> +# Timers drivers
>> +
>> +menu "Timers"
>> +
>> +config IIO_STM32_TIMER
>> + tristate "stm32 iio timer"
>> + depends on ARCH_STM32
>> + depends on OF
>> + select IIO_TRIGGERED_EVENT
>> + select MFD_STM32_GP_TIMER
>> + help
>> + Select this option to enable stm32 timers hardware IPs
>> +
>> +endmenu
>> diff --git a/drivers/iio/timer/Makefile b/drivers/iio/timer/Makefile
>> new file mode 100644
>> index 0000000..a360c9f
>> --- /dev/null
>> +++ b/drivers/iio/timer/Makefile
>> @@ -0,0 +1 @@
>> +obj-$(CONFIG_IIO_STM32_TIMER) += stm32-iio-timer.o
>> diff --git a/drivers/iio/timer/stm32-iio-timer.c b/drivers/iio/timer/stm32-iio-timer.c
>> new file mode 100644
>> index 0000000..35f2687
>> --- /dev/null
>> +++ b/drivers/iio/timer/stm32-iio-timer.c
>> @@ -0,0 +1,448 @@
>> +/*
>> + * stm32-iio-timer.c
>> + *
>> + * Copyright (C) STMicroelectronics 2016
>> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
>> + * License terms: GNU General Public License (GPL), version 2
>> + */
>> +
>> +#include <linux/iio/iio.h>
>> +#include <linux/iio/sysfs.h>
>> +#include <linux/iio/timer/stm32-iio-timers.h>
>> +#include <linux/iio/trigger.h>
>> +#include <linux/iio/triggered_event.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/mfd/stm32-gptimer.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +
>> +#define DRIVER_NAME "stm32-iio-timer"
>> +
>> +struct stm32_iio_timer_dev {
>> + struct device *dev;
>> + struct regmap *regmap;
>> + struct clk *clk;
>> + int irq;
>> + bool own_timer;
>> + unsigned int sampling_frequency;
>> + struct iio_trigger *active_trigger;
>> +};
>> +
>> +static ssize_t _store_frequency(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf, size_t len)
>> +{
>> + struct iio_trigger *trig = to_iio_trigger(dev);
>> + struct stm32_iio_timer_dev *stm32 = iio_trigger_get_drvdata(trig);
>> + unsigned int freq;
>> + int ret;
>> +
>> + ret = kstrtouint(buf, 10, &freq);
>> + if (ret)
>> + return ret;
>> +
>> + stm32->sampling_frequency = freq;
>> +
>> + return len;
>> +}
>> +
>> +static ssize_t _read_frequency(struct device *dev,
>> + struct device_attribute *attr, char *buf)
>> +{
>> + struct iio_trigger *trig = to_iio_trigger(dev);
>> + struct stm32_iio_timer_dev *stm32 = iio_trigger_get_drvdata(trig);
>> + unsigned long long freq = stm32->sampling_frequency;
>> + u32 psc, arr, cr1;
>> +
>> + regmap_read(stm32->regmap, TIM_CR1, &cr1);
>> + regmap_read(stm32->regmap, TIM_PSC, &psc);
>> + regmap_read(stm32->regmap, TIM_ARR, &arr);
>> +
>> + if (psc && arr && (cr1 & TIM_CR1_CEN)) {
>> + freq = (unsigned long long)clk_get_rate(stm32->clk);
>> + do_div(freq, psc);
>> + do_div(freq, arr);
>> + }
>> +
>> + return sprintf(buf, "%d\n", (unsigned int)freq);
>> +}
>> +
>> +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
>> + _read_frequency,
>> + _store_frequency);
>> +
>> +static struct attribute *stm32_trigger_attrs[] = {
>> + &iio_dev_attr_sampling_frequency.dev_attr.attr,
>> + NULL,
>> +};
>> +
>> +static const struct attribute_group stm32_trigger_attr_group = {
>> + .attrs = stm32_trigger_attrs,
>> +};
>> +
>> +static const struct attribute_group *stm32_trigger_attr_groups[] = {
>> + &stm32_trigger_attr_group,
>> + NULL,
>> +};
>> +
>> +static
>> +ssize_t _show_master_mode(struct device *dev,
>> + struct device_attribute *attr, char *buf)
>> +{
>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>> + struct stm32_iio_timer_dev *stm32 = iio_priv(indio_dev);
>> + u32 cr2;
>> +
>> + regmap_read(stm32->regmap, TIM_CR2, &cr2);
>> +
>> + return snprintf(buf, PAGE_SIZE, "%d\n", (cr2 >> 4) & 0x7);
>> +}
>> +
>> +static
>> +ssize_t _store_master_mode(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf, size_t len)
>> +{
>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>> + struct stm32_iio_timer_dev *stm32 = iio_priv(indio_dev);
>> + u8 mode;
>> + int ret;
>> +
>> + ret = kstrtou8(buf, 10, &mode);
>> + if (ret)
>> + return ret;
>> +
>> + if (mode > 0x7)
>> + return -EINVAL;
>> +
>> + regmap_update_bits(stm32->regmap, TIM_CR2, TIM_CR2_MMS, mode << 4);
>> +
>> + return len;
>> +}
>> +
>> +static IIO_DEVICE_ATTR(master_mode, S_IRUGO | S_IWUSR,
>> + _show_master_mode,
>> + _store_master_mode,
>> + 0);
>> +
>> +static
>> +ssize_t _show_slave_mode(struct device *dev,
>> + struct device_attribute *attr, char *buf)
>> +{
>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>> + struct stm32_iio_timer_dev *stm32 = iio_priv(indio_dev);
>> + u32 smcr;
>> +
>> + regmap_read(stm32->regmap, TIM_SMCR, &smcr);
>> +
>> + return snprintf(buf, PAGE_SIZE, "%d\n", smcr & 0x3);
>> +}
>> +
>> +static
>> +ssize_t _store_slave_mode(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf, size_t len)
>> +{
>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>> + struct stm32_iio_timer_dev *stm32 = iio_priv(indio_dev);
>> + u8 mode;
>> + int ret;
>> +
>> + ret = kstrtou8(buf, 10, &mode);
>> + if (ret)
>> + return ret;
>> +
>> + if (mode > 0x7)
>> + return -EINVAL;
> How is something called slave mode going to be fed a number between 0 and 7?
> Rule of thumb is no magic numbers in sysfs and right now this is looking
> rather cryptic to say the least!
I would like to use strings here, it is possible to use IIO_CONST_ATTR
to describe them ?
In documentation slave modes are describe that this:
000: Slave mode disabled - if CEN = ?1? then the prescaler is clocked
directly by the internal clock.
001: Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending
on TI1FP2 level.
010: Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending
on TI2FP1 level.
011: Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2
edges depending on the level of the other input.
100: Reset Mode - Rising edge of the selected trigger input (TRGI)
reinitializes the counter and generates an update of the registers.
101: Gated Mode - The counter clock is enabled when the trigger input
(TRGI) is high.
The counter stops (but is not reset) as soon as the trigger becomes low.
Both start and stop of the counter are controlled.
110: Trigger Mode - The counter starts at a rising edge of the trigger
TRGI (but it is notreset).
Only the start of the counter is controlled.
111: External Clock Mode 1 - Rising edges of the selected trigger
(TRGI) clock the counter.
>> +
>> + regmap_update_bits(stm32->regmap, TIM_SMCR, TIM_SMCR_SMS, mode);
>> +
>> + return len;
>> +}
>> +
>> +static IIO_DEVICE_ATTR(slave_mode, S_IRUGO | S_IWUSR,
> There is an iritating move (in terms of noise it's generating) to use values
> directly instead fo these defines. Still if you don't fix it here I'll only
> get a patch 'fixing' it soon after...
I will fix at in version 3
>
>> + _show_slave_mode,
>> + _store_slave_mode,
>> + 0);
>> +
>> +static struct attribute *stm32_timer_attrs[] = {
>> + &iio_dev_attr_master_mode.dev_attr.attr,
>> + &iio_dev_attr_slave_mode.dev_attr.attr,
> New ABI so must be documented under Documentation/ABI/testing/sysfs-bus-iio-*
OK
>> + NULL,
>> +};
>> +
>> +static const struct attribute_group stm32_timer_attr_group = {
>> + .attrs = stm32_timer_attrs,
>> +};
>> +
>> +static int stm32_timer_start(struct stm32_iio_timer_dev *stm32)
>> +{
>> + unsigned long long prd, div;
>> + int prescaler = 0;
>> + u32 max_arr = 0xFFFF, cr1;
>> +
>> + if (stm32->sampling_frequency == 0)
>> + return 0;
>> +
>> + /* Period and prescaler values depends of clock rate */
>> + div = (unsigned long long)clk_get_rate(stm32->clk);
>> +
>> + do_div(div, stm32->sampling_frequency);
>> +
>> + prd = div;
>> +
>> + while (div > max_arr) {
>> + prescaler++;
>> + div = prd;
>> + do_div(div, (prescaler + 1));
>> + }
>> + prd = div;
>> +
>> + if (prescaler > MAX_TIM_PSC) {
>> + dev_err(stm32->dev, "prescaler exceeds the maximum value\n");
>> + return -EINVAL;
>> + }
>> +
>> + /* Check that we own the timer */
>> + regmap_read(stm32->regmap, TIM_CR1, &cr1);
>> + if ((cr1 & TIM_CR1_CEN) && !stm32->own_timer)
>> + return -EBUSY;
>> +
>> + if (!stm32->own_timer) {
>> + stm32->own_timer = true;
>> + clk_enable(stm32->clk);
>> + }
>> +
>> + regmap_write(stm32->regmap, TIM_PSC, prescaler);
>> + regmap_write(stm32->regmap, TIM_ARR, prd - 1);
>> + regmap_update_bits(stm32->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE);
>> +
>> + /* Force master mode to update mode */
>> + regmap_update_bits(stm32->regmap, TIM_CR2, TIM_CR2_MMS, 0x20);
>> +
>> + /* Make sure that registers are updated */
>> + regmap_update_bits(stm32->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
>> +
>> + /* Enable interrupt */
>> + regmap_write(stm32->regmap, TIM_SR, 0);
>> + regmap_update_bits(stm32->regmap, TIM_DIER, TIM_DIER_UIE, TIM_DIER_UIE);
>> +
>> + /* Enable controller */
>> + regmap_update_bits(stm32->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN);
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_timer_stop(struct stm32_iio_timer_dev *stm32)
>> +{
>> + if (!stm32->own_timer)
>> + return 0;
>> +
>> + /* Stop timer */
>> + regmap_update_bits(stm32->regmap, TIM_DIER, TIM_DIER_UIE, 0);
>> + regmap_update_bits(stm32->regmap, TIM_CR1, TIM_CR1_CEN, 0);
>> + regmap_write(stm32->regmap, TIM_PSC, 0);
>> + regmap_write(stm32->regmap, TIM_ARR, 0);
>> +
>> + clk_disable(stm32->clk);
>> +
>> + stm32->own_timer = false;
>> + stm32->active_trigger = NULL;
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_set_trigger_state(struct iio_trigger *trig, bool state)
>> +{
>> + struct stm32_iio_timer_dev *stm32 = iio_trigger_get_drvdata(trig);
>> +
>> + stm32->active_trigger = trig;
>> +
>> + if (state)
>> + return stm32_timer_start(stm32);
>> + else
>> + return stm32_timer_stop(stm32);
>> +}
>> +
>> +static irqreturn_t stm32_timer_irq_handler(int irq, void *private)
>> +{
>> + struct stm32_iio_timer_dev *stm32 = private;
>> + u32 sr;
>> +
>> + regmap_read(stm32->regmap, TIM_SR, &sr);
>> + regmap_write(stm32->regmap, TIM_SR, 0);
>> +
>> + if ((sr & TIM_SR_UIF) && stm32->active_trigger)
>> + iio_trigger_poll(stm32->active_trigger);
> This is acting like a trigger cascading off another trigger?
Not only a trigger but ADC or DAC too.
>
> Normally this interrupt handler would be directly associated with the
> trigger hardware - in this case the timer.
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static const struct iio_trigger_ops timer_trigger_ops = {
>> + .owner = THIS_MODULE,
>> + .set_trigger_state = stm32_set_trigger_state,
>> +};
>> +
>> +static int stm32_setup_iio_triggers(struct stm32_iio_timer_dev *stm32)
>> +{
>> + int ret;
>> + struct property *p;
>> + const char *cur = NULL;
>> +
>> + p = of_find_property(stm32->dev->of_node,
>> + "st,output-triggers-names", NULL);
>> +
>> + while ((cur = of_prop_next_string(p, cur)) != NULL) {
>> + struct iio_trigger *trig;
>> +
>> + trig = devm_iio_trigger_alloc(stm32->dev, "%s", cur);
>> + if (!trig)
>> + return -ENOMEM;
>> +
>> + trig->dev.parent = stm32->dev->parent;
>> + trig->ops = &timer_trigger_ops;
>> + trig->dev.groups = stm32_trigger_attr_groups;
>> + iio_trigger_set_drvdata(trig, stm32);
>> +
>> + ret = devm_iio_trigger_register(stm32->dev, trig);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +/**
>> + * is_stm32_iio_timer_trigger
>> + * @trig: trigger to be checked
>> + *
>> + * return true if the trigger is a valid stm32 iio timer trigger
>> + * either return false
>> + */
>> +bool is_stm32_iio_timer_trigger(struct iio_trigger *trig)
>> +{
>> + return (trig->ops == &timer_trigger_ops);
>> +}
>> +EXPORT_SYMBOL(is_stm32_iio_timer_trigger);
>> +
>> +static int stm32_validate_trigger(struct iio_dev *indio_dev,
>> + struct iio_trigger *trig)
>> +{
>> + struct stm32_iio_timer_dev *dev = iio_priv(indio_dev);
>> + int ret;
>> +
>> + if (!is_stm32_iio_timer_trigger(trig))
>> + return -EINVAL;
>> +
>> + ret = of_property_match_string(dev->dev->of_node,
>> + "st,input-triggers-names",
>> + trig->name);
>> +
>> + if (ret < 0)
>> + return ret;
>> +
>> + regmap_update_bits(dev->regmap, TIM_SMCR, TIM_SMCR_TS, ret << 4);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct iio_info stm32_trigger_info = {
>> + .driver_module = THIS_MODULE,
>> + .validate_trigger = stm32_validate_trigger,
>> + .attrs = &stm32_timer_attr_group,
>> +};
>> +
>> +static struct stm32_iio_timer_dev *stm32_setup_iio_device(struct device *dev)
>> +{
>> + struct iio_dev *indio_dev;
>> + int ret;
>> +
>> + indio_dev = devm_iio_device_alloc(dev, sizeof(struct stm32_iio_timer_dev));
>> + if (!indio_dev)
>> + return NULL;
> This is 'unusual'. Why does a trigger driver need an iio_dev at all?
Trigger doesn't need it but for configuring the input switch when
validating the triggers I need a device
>> +
>> + indio_dev->name = dev_name(dev);
>> + indio_dev->dev.parent = dev;
>> + indio_dev->info = &stm32_trigger_info;
>> + indio_dev->modes = INDIO_EVENT_TRIGGERED;
>> + indio_dev->num_channels = 0;
>> + indio_dev->dev.of_node = dev->of_node;
>> +
>> + ret = iio_triggered_event_setup(indio_dev,
>> + NULL,
>> + stm32_timer_irq_handler);
> So the iio_dev exists to provide the ability to fire this interrupt from
> another trigger? Why do you want to do this?
I need interrupt because I use set_trigger_state() to enable/disable
the sampling frequency.
As far I understand and test set_trigger_state() is only called when
indio_dev->modes = INDIO_EVENT_TRIGGERED
and iio_triggered_event_setup have been called to create register an
irq handler.
I just need irq declaration for this last condition, I don't need the
irq to fire in kernel to drive other hardware block.
If I could use set_trigger_state() without calling using
iio_triggered_event_setup() I should remove all
irq code from the driver.
One possible solution would be to add calls to set_trigger_state() in
iio_trigger_write_current() function
at the same level than iio_trigger_detach_poll_func() or
iio_trigger_attach_poll_func() calls:
if (indio_dev->modes = INDIO_DIRECT_MODE && oldtrig->ops->set_trigger_state)
oldtrig->ops->set_trigger_state(oldtrig, false);
if (indio_dev->modes = INDIO_DIRECT_MODE &&
indio_dev->trig->ops->set_trigger_state)
indio_dev->trig->ops->set_trigger_state(indio_dev->trig, true);
I'm to new in IIO framework to understand if that it possible or not
>> + if (ret)
>> + return NULL;
>> +
>> + ret = devm_iio_device_register(dev, indio_dev);
>> + if (ret) {
>> + iio_triggered_event_cleanup(indio_dev);
>> + return NULL;
>> + }
>> +
>> + return iio_priv(indio_dev);
>> +}
>> +
>> +static int stm32_iio_timer_probe(struct platform_device *pdev)
>> +{
>> + struct device *dev = &pdev->dev;
>> + struct stm32_iio_timer_dev *stm32;
>> + struct stm32_gptimer_dev *mfd = dev_get_drvdata(pdev->dev.parent);
>> + int ret;
>> +
>> + stm32 = stm32_setup_iio_device(dev);
>> + if (!stm32)
>> + return -ENOMEM;
>> +
>> + stm32->dev = dev;
>> + stm32->regmap = mfd->regmap;
>> + stm32->clk = mfd->clk;
>> +
>> + stm32->irq = platform_get_irq(pdev, 0);
>> + if (stm32->irq < 0)
>> + return -EINVAL;
>> +
>> + ret = devm_request_irq(stm32->dev, stm32->irq,
>> + stm32_timer_irq_handler, IRQF_SHARED,
>> + "iiotimer_event", stm32);
>> + if (ret)
>> + return ret;
>> +
>> + ret = stm32_setup_iio_triggers(stm32);
>> + if (ret)
>> + return ret;
>> +
>> + platform_set_drvdata(pdev, stm32);
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_iio_timer_remove(struct platform_device *pdev)
>> +{
>> + struct stm32_iio_timer_dev *stm32 = platform_get_drvdata(pdev);
>> +
>> + iio_triggered_event_cleanup((struct iio_dev *)stm32);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct of_device_id stm32_trig_of_match[] = {
>> + {
>> + .compatible = "st,stm32-iio-timer",
>> + },
>> +};
>> +MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
>> +
>> +static struct platform_driver stm32_iio_timer_driver = {
>> + .probe = stm32_iio_timer_probe,
>> + .remove = stm32_iio_timer_remove,
>> + .driver = {
>> + .name = DRIVER_NAME,
>> + .of_match_table = stm32_trig_of_match,
>> + },
>> +};
>> +module_platform_driver(stm32_iio_timer_driver);
>> +
>> +MODULE_ALIAS("platform:" DRIVER_NAME);
>> +MODULE_DESCRIPTION("STMicroelectronics STM32 iio timer driver");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/iio/trigger/Kconfig b/drivers/iio/trigger/Kconfig
>> index 809b2e7..f2af4fe 100644
>> --- a/drivers/iio/trigger/Kconfig
>> +++ b/drivers/iio/trigger/Kconfig
>> @@ -46,5 +46,4 @@ config IIO_SYSFS_TRIGGER
>>
>> To compile this driver as a module, choose M here: the
>> module will be called iio-trig-sysfs.
>> -
> Clear this out...
>> endmenu
>> diff --git a/include/dt-bindings/iio/timer/st,stm32-iio-timer.h b/include/dt-bindings/iio/timer/st,stm32-iio-timer.h
>> new file mode 100644
>> index 0000000..d39bf16
>> --- /dev/null
>> +++ b/include/dt-bindings/iio/timer/st,stm32-iio-timer.h
>> @@ -0,0 +1,23 @@
>> +/*
>> + * st,stm32-iio-timer.h
>> + *
>> + * Copyright (C) STMicroelectronics 2016
>> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
>> + * License terms: GNU General Public License (GPL), version 2
>> + */
>> +
>> +#ifndef _DT_BINDINGS_IIO_TIMER_H_
>> +#define _DT_BINDINGS_IIO_TIMER_H_
>> +
>> +#define TIM1_TRGO "tim1_trgo"
>> +#define TIM2_TRGO "tim2_trgo"
>> +#define TIM3_TRGO "tim3_trgo"
>> +#define TIM4_TRGO "tim4_trgo"
>> +#define TIM5_TRGO "tim5_trgo"
>> +#define TIM6_TRGO "tim6_trgo"
>> +#define TIM7_TRGO "tim7_trgo"
>> +#define TIM8_TRGO "tim8_trgo"
>> +#define TIM9_TRGO "tim9_trgo"
>> +#define TIM12_TRGO "tim12_trgo"
>> +
>> +#endif
>> diff --git a/include/linux/iio/timer/stm32-iio-timers.h b/include/linux/iio/timer/stm32-iio-timers.h
>> new file mode 100644
>> index 0000000..5d1b86c
>> --- /dev/null
>> +++ b/include/linux/iio/timer/stm32-iio-timers.h
>> @@ -0,0 +1,16 @@
>> +/*
>> + * stm32-iio-timers.h
>> + *
>> + * Copyright (C) STMicroelectronics 2016
>> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
>> + * License terms: GNU General Public License (GPL), version 2
>> + */
>> +
>> +#ifndef _STM32_IIO_TIMERS_H_
>> +#define _STM32_IIO_TIMERS_H_
>> +
>> +#include <dt-bindings/iio/timer/st,stm32-iio-timer.h>
>> +
>> +bool is_stm32_iio_timer_trigger(struct iio_trigger *trig);
>> +
>> +#endif
>>
>
^ permalink raw reply
* [PATCH v3 net-next 6/6] ARM64: dts: marvell: Add network support for Armada 3700
From: Gregory CLEMENT @ 2016-11-29 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.a09aeaf5ba62853d595153626b6121ef52a3e9b4.1480412215.git-series.gregory.clement@free-electrons.com>
Add neta nodes for network support both in device tree for the SoC and
the board.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 23 +++++++++++++++++++-
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 23 +++++++++++++++++++-
2 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
index 1372e9a6aaa4..c8b82e4145de 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
@@ -81,3 +81,26 @@
&pcie0 {
status = "okay";
};
+
+&mdio {
+ status = "okay";
+ phy0: ethernet-phy at 0 {
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy at 1 {
+ reg = <1>;
+ };
+};
+
+ð0 {
+ phy-mode = "rgmii-id";
+ phy = <&phy0>;
+ status = "okay";
+};
+
+ð1 {
+ phy-mode = "rgmii-id";
+ phy = <&phy1>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index e9bd58793464..3b8eb45bdc76 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -140,6 +140,29 @@
};
};
+ eth0: ethernet at 30000 {
+ compatible = "marvell,armada-3700-neta";
+ reg = <0x30000 0x4000>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sb_periph_clk 8>;
+ status = "disabled";
+ };
+
+ mdio: mdio at 32004 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "marvell,orion-mdio";
+ reg = <0x32004 0x4>;
+ };
+
+ eth1: ethernet at 40000 {
+ compatible = "marvell,armada-3700-neta";
+ reg = <0x40000 0x4000>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sb_periph_clk 7>;
+ status = "disabled";
+ };
+
usb3: usb at 58000 {
compatible = "marvell,armada3700-xhci",
"generic-xhci";
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v3 net-next 5/6] net: mvneta: Add network support for Armada 3700 SoC
From: Gregory CLEMENT @ 2016-11-29 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.a09aeaf5ba62853d595153626b6121ef52a3e9b4.1480412215.git-series.gregory.clement@free-electrons.com>
From: Marcin Wojtas <mw@semihalf.com>
Armada 3700 is a new ARMv8 SoC from Marvell using same network controller
as older Armada 370/38x/XP. There are however some differences that
needed taking into account when adding support for it:
* open default MBUS window to 4GB of DRAM - Armada 3700 SoC's Mbus
configuration for network controller has to be done on two levels:
global and per-port. The first one is inherited from the
bootloader. The latter can be opened in a default way, leaving
arbitration to the bus controller. Hence filled mbus_dram_target_info
structure is not needed
* make per-CPU operation optional - Recent patches adding RSS and XPS
support for Armada 38x/XP enabled per-CPU operation of the controller
by default. Contrary to older SoC's Armada 3700 SoC's network
controller is not capable of per-CPU processing due to interrupt lines'
connectivity. This patch restores non-per-CPU operation, which is now
optional and depends on neta_armada3700 flag value in mvneta_port
structure. In order not to complicate the code, separate interrupt
subroutine is implemented.
For now, on the Armada 3700, RSS is disabled as the current
implementation depend on the per cpu interrupts.
[gregory.clement at free-electrons.com: extract from a larger patch, replace
some ifdef and port to net-next for v4.10]
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt | 7 +-
drivers/net/ethernet/marvell/Kconfig | 7 +-
drivers/net/ethernet/marvell/mvneta.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 214 insertions(+), 87 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
index 73be8970815e..7aa840c8768d 100644
--- a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
+++ b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
@@ -1,7 +1,10 @@
-* Marvell Armada 370 / Armada XP Ethernet Controller (NETA)
+* Marvell Armada 370 / Armada XP / Armada 3700 Ethernet Controller (NETA)
Required properties:
-- compatible: "marvell,armada-370-neta" or "marvell,armada-xp-neta".
+- compatible: could be one of the followings
+ "marvell,armada-370-neta"
+ "marvell,armada-xp-neta"
+ "marvell,armada-3700-neta"
- reg: address and length of the register set for the device.
- interrupts: interrupt for the device
- phy: See ethernet.txt file in the same directory.
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index 2ccea9dd9248..3b8f11fe5e13 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -56,14 +56,15 @@ config MVNETA_BM_ENABLE
buffer management.
config MVNETA
- tristate "Marvell Armada 370/38x/XP network interface support"
- depends on PLAT_ORION || COMPILE_TEST
+ tristate "Marvell Armada 370/38x/XP/37xx network interface support"
+ depends on ARCH_MVEBU || COMPILE_TEST
depends on HAS_DMA
select MVMDIO
select FIXED_PHY
---help---
This driver supports the network interface units in the
- Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family.
+ Marvell ARMADA XP, ARMADA 370, ARMADA 38x and
+ ARMADA 37xx SoC family.
Note that this driver is distinct from the mv643xx_eth
driver, which should be used for the older Marvell SoCs
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index a8bd0d83028f..99cee88d5052 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -397,6 +397,9 @@ struct mvneta_port {
spinlock_t lock;
bool is_stopped;
+ u32 cause_rx_tx;
+ struct napi_struct napi;
+
/* Core clock */
struct clk *clk;
/* AXI clock */
@@ -422,6 +425,9 @@ struct mvneta_port {
u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
+
+ /* Flags for special SoC configurations */
+ bool neta_armada3700;
u16 rx_offset_correction;
};
@@ -965,14 +971,9 @@ static int mvneta_mbus_io_win_set(struct mvneta_port *pp, u32 base, u32 wsize,
return 0;
}
-/* Assign and initialize pools for port. In case of fail
- * buffer manager will remain disabled for current port.
- */
-static int mvneta_bm_port_init(struct platform_device *pdev,
- struct mvneta_port *pp)
+static int mvneta_bm_port_mbus_init(struct mvneta_port *pp)
{
- struct device_node *dn = pdev->dev.of_node;
- u32 long_pool_id, short_pool_id, wsize;
+ u32 wsize;
u8 target, attr;
int err;
@@ -991,6 +992,25 @@ static int mvneta_bm_port_init(struct platform_device *pdev,
netdev_info(pp->dev, "fail to configure mbus window to BM\n");
return err;
}
+ return 0;
+}
+
+/* Assign and initialize pools for port. In case of fail
+ * buffer manager will remain disabled for current port.
+ */
+static int mvneta_bm_port_init(struct platform_device *pdev,
+ struct mvneta_port *pp)
+{
+ struct device_node *dn = pdev->dev.of_node;
+ u32 long_pool_id, short_pool_id;
+
+ if (!pp->neta_armada3700) {
+ int ret;
+
+ ret = mvneta_bm_port_mbus_init(pp);
+ if (ret)
+ return ret;
+ }
if (of_property_read_u32(dn, "bm,pool-long", &long_pool_id)) {
netdev_info(pp->dev, "missing long pool id\n");
@@ -1359,22 +1379,27 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
for_each_present_cpu(cpu) {
int rxq_map = 0, txq_map = 0;
int rxq, txq;
+ if (!pp->neta_armada3700) {
+ for (rxq = 0; rxq < rxq_number; rxq++)
+ if ((rxq % max_cpu) == cpu)
+ rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
+
+ for (txq = 0; txq < txq_number; txq++)
+ if ((txq % max_cpu) == cpu)
+ txq_map |= MVNETA_CPU_TXQ_ACCESS(txq);
+
+ /* With only one TX queue we configure a special case
+ * which will allow to get all the irq on a single
+ * CPU
+ */
+ if (txq_number == 1)
+ txq_map = (cpu == pp->rxq_def) ?
+ MVNETA_CPU_TXQ_ACCESS(1) : 0;
- for (rxq = 0; rxq < rxq_number; rxq++)
- if ((rxq % max_cpu) == cpu)
- rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
-
- for (txq = 0; txq < txq_number; txq++)
- if ((txq % max_cpu) == cpu)
- txq_map |= MVNETA_CPU_TXQ_ACCESS(txq);
-
- /* With only one TX queue we configure a special case
- * which will allow to get all the irq on a single
- * CPU
- */
- if (txq_number == 1)
- txq_map = (cpu == pp->rxq_def) ?
- MVNETA_CPU_TXQ_ACCESS(1) : 0;
+ } else {
+ txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
+ rxq_map = MVNETA_CPU_RXQ_ACCESS_ALL_MASK;
+ }
mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map);
}
@@ -2632,6 +2657,17 @@ static void mvneta_set_rx_mode(struct net_device *dev)
/* Interrupt handling - the callback for request_irq() */
static irqreturn_t mvneta_isr(int irq, void *dev_id)
{
+ struct mvneta_port *pp = (struct mvneta_port *)dev_id;
+
+ mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+ napi_schedule(&pp->napi);
+
+ return IRQ_HANDLED;
+}
+
+/* Interrupt handling - the callback for request_percpu_irq() */
+static irqreturn_t mvneta_percpu_isr(int irq, void *dev_id)
+{
struct mvneta_pcpu_port *port = (struct mvneta_pcpu_port *)dev_id;
disable_percpu_irq(port->pp->dev->irq);
@@ -2679,7 +2715,7 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
if (!netif_running(pp->dev)) {
- napi_complete(&port->napi);
+ napi_complete(napi);
return rx_done;
}
@@ -2708,7 +2744,8 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
*/
rx_queue = fls(((cause_rx_tx >> 8) & 0xff));
- cause_rx_tx |= port->cause_rx_tx;
+ cause_rx_tx |= pp->neta_armada3700 ? pp->cause_rx_tx :
+ port->cause_rx_tx;
if (rx_queue) {
rx_queue = rx_queue - 1;
@@ -2722,11 +2759,27 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
if (budget > 0) {
cause_rx_tx = 0;
- napi_complete(&port->napi);
- enable_percpu_irq(pp->dev->irq, 0);
+ napi_complete(napi);
+
+ if (pp->neta_armada3700) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mvreg_write(pp, MVNETA_INTR_NEW_MASK,
+ MVNETA_RX_INTR_MASK(rxq_number) |
+ MVNETA_TX_INTR_MASK(txq_number) |
+ MVNETA_MISCINTR_INTR_MASK);
+ local_irq_restore(flags);
+ } else {
+ enable_percpu_irq(pp->dev->irq, 0);
+ }
}
- port->cause_rx_tx = cause_rx_tx;
+ if (pp->neta_armada3700)
+ pp->cause_rx_tx = cause_rx_tx;
+ else
+ port->cause_rx_tx = cause_rx_tx;
+
return rx_done;
}
@@ -3047,11 +3100,16 @@ static void mvneta_start_dev(struct mvneta_port *pp)
/* start the Rx/Tx activity */
mvneta_port_enable(pp);
- /* Enable polling on the port */
- for_each_online_cpu(cpu) {
- struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+ if (!pp->neta_armada3700) {
+ /* Enable polling on the port */
+ for_each_online_cpu(cpu) {
+ struct mvneta_pcpu_port *port =
+ per_cpu_ptr(pp->ports, cpu);
- napi_enable(&port->napi);
+ napi_enable(&port->napi);
+ }
+ } else {
+ napi_enable(&pp->napi);
}
/* Unmask interrupts. It has to be done from each CPU */
@@ -3073,10 +3131,15 @@ static void mvneta_stop_dev(struct mvneta_port *pp)
phy_stop(ndev->phydev);
- for_each_online_cpu(cpu) {
- struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+ if (!pp->neta_armada3700) {
+ for_each_online_cpu(cpu) {
+ struct mvneta_pcpu_port *port =
+ per_cpu_ptr(pp->ports, cpu);
- napi_disable(&port->napi);
+ napi_disable(&port->napi);
+ }
+ } else {
+ napi_disable(&pp->napi);
}
netif_carrier_off(pp->dev);
@@ -3486,31 +3549,37 @@ static int mvneta_open(struct net_device *dev)
goto err_cleanup_rxqs;
/* Connect to port interrupt line */
- ret = request_percpu_irq(pp->dev->irq, mvneta_isr,
- MVNETA_DRIVER_NAME, pp->ports);
+ if (pp->neta_armada3700)
+ ret = request_irq(pp->dev->irq, mvneta_isr, 0,
+ dev->name, pp);
+ else
+ ret = request_percpu_irq(pp->dev->irq, mvneta_percpu_isr,
+ dev->name, pp->ports);
if (ret) {
netdev_err(pp->dev, "cannot request irq %d\n", pp->dev->irq);
goto err_cleanup_txqs;
}
- /* Enable per-CPU interrupt on all the CPU to handle our RX
- * queue interrupts
- */
- on_each_cpu(mvneta_percpu_enable, pp, true);
+ if (!pp->neta_armada3700) {
+ /* Enable per-CPU interrupt on all the CPU to handle our RX
+ * queue interrupts
+ */
+ on_each_cpu(mvneta_percpu_enable, pp, true);
- pp->is_stopped = false;
- /* Register a CPU notifier to handle the case where our CPU
- * might be taken offline.
- */
- ret = cpuhp_state_add_instance_nocalls(online_hpstate,
- &pp->node_online);
- if (ret)
- goto err_free_irq;
+ pp->is_stopped = false;
+ /* Register a CPU notifier to handle the case where our CPU
+ * might be taken offline.
+ */
+ ret = cpuhp_state_add_instance_nocalls(online_hpstate,
+ &pp->node_online);
+ if (ret)
+ goto err_free_irq;
- ret = cpuhp_state_add_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
- &pp->node_dead);
- if (ret)
- goto err_free_online_hp;
+ ret = cpuhp_state_add_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
+ &pp->node_dead);
+ if (ret)
+ goto err_free_online_hp;
+ }
/* In default link is down */
netif_carrier_off(pp->dev);
@@ -3526,13 +3595,20 @@ static int mvneta_open(struct net_device *dev)
return 0;
err_free_dead_hp:
- cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
- &pp->node_dead);
+ if (!pp->neta_armada3700)
+ cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
+ &pp->node_dead);
err_free_online_hp:
- cpuhp_state_remove_instance_nocalls(online_hpstate, &pp->node_online);
+ if (!pp->neta_armada3700)
+ cpuhp_state_remove_instance_nocalls(online_hpstate,
+ &pp->node_online);
err_free_irq:
- on_each_cpu(mvneta_percpu_disable, pp, true);
- free_percpu_irq(pp->dev->irq, pp->ports);
+ if (pp->neta_armada3700) {
+ free_irq(pp->dev->irq, pp);
+ } else {
+ on_each_cpu(mvneta_percpu_disable, pp, true);
+ free_percpu_irq(pp->dev->irq, pp->ports);
+ }
err_cleanup_txqs:
mvneta_cleanup_txqs(pp);
err_cleanup_rxqs:
@@ -3545,23 +3621,30 @@ static int mvneta_stop(struct net_device *dev)
{
struct mvneta_port *pp = netdev_priv(dev);
- /* Inform that we are stopping so we don't want to setup the
- * driver for new CPUs in the notifiers. The code of the
- * notifier for CPU online is protected by the same spinlock,
- * so when we get the lock, the notifer work is done.
- */
- spin_lock(&pp->lock);
- pp->is_stopped = true;
- spin_unlock(&pp->lock);
+ if (!pp->neta_armada3700) {
+ /* Inform that we are stopping so we don't want to setup the
+ * driver for new CPUs in the notifiers. The code of the
+ * notifier for CPU online is protected by the same spinlock,
+ * so when we get the lock, the notifer work is done.
+ */
+ spin_lock(&pp->lock);
+ pp->is_stopped = true;
+ spin_unlock(&pp->lock);
- mvneta_stop_dev(pp);
- mvneta_mdio_remove(pp);
+ mvneta_stop_dev(pp);
+ mvneta_mdio_remove(pp);
cpuhp_state_remove_instance_nocalls(online_hpstate, &pp->node_online);
cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
&pp->node_dead);
- on_each_cpu(mvneta_percpu_disable, pp, true);
- free_percpu_irq(dev->irq, pp->ports);
+ on_each_cpu(mvneta_percpu_disable, pp, true);
+ free_percpu_irq(dev->irq, pp->ports);
+ } else {
+ mvneta_stop_dev(pp);
+ mvneta_mdio_remove(pp);
+ free_irq(dev->irq, pp);
+ }
+
mvneta_cleanup_rxqs(pp);
mvneta_cleanup_txqs(pp);
@@ -3840,6 +3923,11 @@ static int mvneta_ethtool_set_rxfh(struct net_device *dev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
struct mvneta_port *pp = netdev_priv(dev);
+
+ /* Current code for Armada 3700 doesn't support RSS features yet */
+ if (pp->neta_armada3700)
+ return -EOPNOTSUPP;
+
/* We require at least one supported parameter to be changed
* and no change in any of the unsupported parameters
*/
@@ -3860,6 +3948,10 @@ static int mvneta_ethtool_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
{
struct mvneta_port *pp = netdev_priv(dev);
+ /* Current code for Armada 3700 doesn't support RSS features yet */
+ if (pp->neta_armada3700)
+ return -EOPNOTSUPP;
+
if (hfunc)
*hfunc = ETH_RSS_HASH_TOP;
@@ -3967,16 +4059,29 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp,
win_enable = 0x3f;
win_protect = 0;
- for (i = 0; i < dram->num_cs; i++) {
- const struct mbus_dram_window *cs = dram->cs + i;
- mvreg_write(pp, MVNETA_WIN_BASE(i), (cs->base & 0xffff0000) |
- (cs->mbus_attr << 8) | dram->mbus_dram_target_id);
+ if (dram) {
+ for (i = 0; i < dram->num_cs; i++) {
+ const struct mbus_dram_window *cs = dram->cs + i;
+
+ mvreg_write(pp, MVNETA_WIN_BASE(i),
+ (cs->base & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ dram->mbus_dram_target_id);
- mvreg_write(pp, MVNETA_WIN_SIZE(i),
- (cs->size - 1) & 0xffff0000);
+ mvreg_write(pp, MVNETA_WIN_SIZE(i),
+ (cs->size - 1) & 0xffff0000);
- win_enable &= ~(1 << i);
- win_protect |= 3 << (2 * i);
+ win_enable &= ~(1 << i);
+ win_protect |= 3 << (2 * i);
+ }
+ } else {
+ /* For Armada3700 open default 4GB Mbus window, leaving
+ * arbitration of target/attribute to a different layer
+ * of configuration.
+ */
+ mvreg_write(pp, MVNETA_WIN_SIZE(0), 0xffff0000);
+ win_enable &= ~BIT(0);
+ win_protect = 3;
}
mvreg_write(pp, MVNETA_BASE_ADDR_ENABLE, win_enable);
@@ -4106,6 +4211,10 @@ static int mvneta_probe(struct platform_device *pdev)
pp->indir[0] = rxq_def;
+ /* Get special SoC configurations */
+ if (of_device_is_compatible(dn, "marvell,armada-3700-neta"))
+ pp->neta_armada3700 = true;
+
pp->clk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(pp->clk))
pp->clk = devm_clk_get(&pdev->dev, NULL);
@@ -4173,7 +4282,11 @@ static int mvneta_probe(struct platform_device *pdev)
pp->tx_csum_limit = tx_csum_limit;
dram_target_info = mv_mbus_dram_info();
- if (dram_target_info)
+ /* Armada3700 requires setting default configuration of Mbus
+ * windows, however without using filled mbus_dram_target_info
+ * structure.
+ */
+ if (dram_target_info || pp->neta_armada3700)
mvneta_conf_mbus_windows(pp, dram_target_info);
pp->tx_ring_size = MVNETA_MAX_TXD;
@@ -4206,11 +4319,20 @@ static int mvneta_probe(struct platform_device *pdev)
goto err_netdev;
}
- for_each_present_cpu(cpu) {
- struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+ /* Armada3700 network controller does not support per-cpu
+ * operation, so only single NAPI should be initialized.
+ */
+ if (pp->neta_armada3700) {
+ netif_napi_add(dev, &pp->napi, mvneta_poll, NAPI_POLL_WEIGHT);
+ } else {
+ for_each_present_cpu(cpu) {
+ struct mvneta_pcpu_port *port =
+ per_cpu_ptr(pp->ports, cpu);
- netif_napi_add(dev, &port->napi, mvneta_poll, NAPI_POLL_WEIGHT);
- port->pp = pp;
+ netif_napi_add(dev, &port->napi, mvneta_poll,
+ NAPI_POLL_WEIGHT);
+ port->pp = pp;
+ }
}
dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
@@ -4295,6 +4417,7 @@ static int mvneta_remove(struct platform_device *pdev)
static const struct of_device_id mvneta_match[] = {
{ .compatible = "marvell,armada-370-neta" },
{ .compatible = "marvell,armada-xp-neta" },
+ { .compatible = "marvell,armada-3700-neta" },
{ }
};
MODULE_DEVICE_TABLE(of, mvneta_match);
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v3 net-next 4/6] net: mvneta: Only disable mvneta_bm for 64-bits
From: Gregory CLEMENT @ 2016-11-29 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.a09aeaf5ba62853d595153626b6121ef52a3e9b4.1480412215.git-series.gregory.clement@free-electrons.com>
Actually only the mvneta_bm support is not 64-bits compatible.
The mvneta code itself can run on 64-bits architecture.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/net/ethernet/marvell/Kconfig | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index 66fd9dbb2ca7..2ccea9dd9248 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -44,6 +44,7 @@ config MVMDIO
config MVNETA_BM_ENABLE
tristate "Marvell Armada 38x/XP network interface BM support"
depends on MVNETA
+ depends on !64BIT
---help---
This driver supports auxiliary block of the network
interface units in the Marvell ARMADA XP and ARMADA 38x SoC
@@ -58,7 +59,6 @@ config MVNETA
tristate "Marvell Armada 370/38x/XP network interface support"
depends on PLAT_ORION || COMPILE_TEST
depends on HAS_DMA
- depends on !64BIT
select MVMDIO
select FIXED_PHY
---help---
@@ -71,6 +71,7 @@ config MVNETA
config MVNETA_BM
tristate
+ depends on !64BIT
default y if MVNETA=y && MVNETA_BM_ENABLE!=n
default MVNETA_BM_ENABLE
select HWBM
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v3 net-next 3/6] net: mvneta: Convert to be 64 bits compatible
From: Gregory CLEMENT @ 2016-11-29 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.a09aeaf5ba62853d595153626b6121ef52a3e9b4.1480412215.git-series.gregory.clement@free-electrons.com>
From: Marcin Wojtas <mw@semihalf.com>
Prepare the mvneta driver in order to be usable on the 64 bits platform
such as the Armada 3700.
[gregory.clement at free-electrons.com]: this patch was extract from a larger
one to ease review and maintenance.
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/net/ethernet/marvell/mvneta.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 32b142d0e44e..a8bd0d83028f 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -296,6 +296,12 @@
/* descriptor aligned size */
#define MVNETA_DESC_ALIGNED_SIZE 32
+/* Number of bytes to be taken into account by HW when putting incoming data
+ * to the buffers. It is needed in case NET_SKB_PAD exceeds maximum packet
+ * offset supported in MVNETA_RXQ_CONFIG_REG(q) registers.
+ */
+#define MVNETA_RX_PKT_OFFSET_CORRECTION 64
+
#define MVNETA_RX_PKT_SIZE(mtu) \
ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \
ETH_HLEN + ETH_FCS_LEN, \
@@ -416,6 +422,7 @@ struct mvneta_port {
u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
+ u16 rx_offset_correction;
};
/* The mvneta_tx_desc and mvneta_rx_desc structures describe the
@@ -1807,6 +1814,7 @@ static int mvneta_rx_refill(struct mvneta_port *pp,
return -ENOMEM;
}
+ phys_addr += pp->rx_offset_correction;
mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
return 0;
}
@@ -2742,6 +2750,7 @@ static int mvneta_rx_hwbm_refill(struct mvneta_port *pp,
return -ENOMEM;
}
+ phys_addr += pp->rx_offset_correction;
rx_desc->buf_phys_addr = phys_addr;
rx_desc->buf_cookie = (uintptr_t)data;
@@ -2837,7 +2846,7 @@ static int mvneta_rxq_init(struct mvneta_port *pp,
mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), rxq->size);
/* Set Offset */
- mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD);
+ mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD - pp->rx_offset_correction);
/* Set coalescing pkts and time */
mvneta_rx_pkts_coal_set(pp, rxq, rxq->pkts_coal);
@@ -4088,6 +4097,13 @@ static int mvneta_probe(struct platform_device *pdev)
pp->rxq_def = rxq_def;
+ /* Set RX packet offset correction for platforms, whose
+ * NET_SKB_PAD, exceeds 64B. It should be 64B for 64-bit
+ * platforms and 0B for 32-bit ones.
+ */
+ pp->rx_offset_correction =
+ max(0, NET_SKB_PAD - MVNETA_RX_PKT_OFFSET_CORRECTION);
+
pp->indir[0] = rxq_def;
pp->clk = devm_clk_get(&pdev->dev, "core");
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v3 net-next 2/6] net: mvneta: Use cacheable memory to store the rx buffer virtual address
From: Gregory CLEMENT @ 2016-11-29 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.a09aeaf5ba62853d595153626b6121ef52a3e9b4.1480412215.git-series.gregory.clement@free-electrons.com>
Until now the virtual address of the received buffer were stored in the
cookie field of the rx descriptor. However, this field is 32-bits only
which prevents to use the driver on a 64-bits architecture.
With this patch the virtual address is stored in an array not shared with
the hardware (no more need to use the DMA API). Thanks to this, it is
possible to use cache contrary to the access of the rx descriptor member.
The change is done in the swbm path only because the hwbm uses the cookie
field, this also means that currently the hwbm is not usable in 64-bits.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/net/ethernet/marvell/mvneta.c | 93 ++++++++++++++++++++++++----
1 file changed, 81 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 1b84f746d748..32b142d0e44e 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -561,6 +561,9 @@ struct mvneta_rx_queue {
u32 pkts_coal;
u32 time_coal;
+ /* Virtual address of the RX buffer */
+ void **buf_virt_addr;
+
/* Virtual address of the RX DMA descriptors array */
struct mvneta_rx_desc *descs;
@@ -1573,10 +1576,14 @@ static void mvneta_tx_done_pkts_coal_set(struct mvneta_port *pp,
/* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
- u32 phys_addr, u32 cookie)
+ u32 phys_addr, void *virt_addr,
+ struct mvneta_rx_queue *rxq)
{
- rx_desc->buf_cookie = cookie;
+ int i;
+
rx_desc->buf_phys_addr = phys_addr;
+ i = rx_desc - rxq->descs;
+ rxq->buf_virt_addr[i] = virt_addr;
}
/* Decrement sent descriptors counter */
@@ -1781,7 +1788,8 @@ EXPORT_SYMBOL_GPL(mvneta_frag_free);
/* Refill processing for SW buffer management */
static int mvneta_rx_refill(struct mvneta_port *pp,
- struct mvneta_rx_desc *rx_desc)
+ struct mvneta_rx_desc *rx_desc,
+ struct mvneta_rx_queue *rxq)
{
dma_addr_t phys_addr;
@@ -1799,7 +1807,7 @@ static int mvneta_rx_refill(struct mvneta_port *pp,
return -ENOMEM;
}
- mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)data);
+ mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
return 0;
}
@@ -1861,7 +1869,12 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
for (i = 0; i < rxq->size; i++) {
struct mvneta_rx_desc *rx_desc = rxq->descs + i;
- void *data = (void *)rx_desc->buf_cookie;
+ void *data;
+
+ if (!pp->bm_priv)
+ data = rxq->buf_virt_addr[i];
+ else
+ data = (void *)(uintptr_t)rx_desc->buf_cookie;
dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
@@ -1894,12 +1907,13 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
unsigned char *data;
dma_addr_t phys_addr;
u32 rx_status, frag_size;
- int rx_bytes, err;
+ int rx_bytes, err, index;
rx_done++;
rx_status = rx_desc->status;
rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
- data = (unsigned char *)rx_desc->buf_cookie;
+ index = rx_desc - rxq->descs;
+ data = (unsigned char *)rxq->buf_virt_addr[index];
phys_addr = rx_desc->buf_phys_addr;
if (!mvneta_rxq_desc_is_first_last(rx_status) ||
@@ -1938,7 +1952,7 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
}
/* Refill processing */
- err = mvneta_rx_refill(pp, rx_desc);
+ err = mvneta_rx_refill(pp, rx_desc, rxq);
if (err) {
netdev_err(dev, "Linux processing - Can't refill\n");
rxq->missed++;
@@ -2020,7 +2034,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
rx_done++;
rx_status = rx_desc->status;
rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
- data = (unsigned char *)rx_desc->buf_cookie;
+ data = (u8 *)(uintptr_t)rx_desc->buf_cookie;
phys_addr = rx_desc->buf_phys_addr;
pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc);
bm_pool = &pp->bm_priv->bm_pools[pool_id];
@@ -2708,6 +2722,56 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
return rx_done;
}
+/* Refill processing for HW buffer management */
+static int mvneta_rx_hwbm_refill(struct mvneta_port *pp,
+ struct mvneta_rx_desc *rx_desc)
+
+{
+ dma_addr_t phys_addr;
+ void *data;
+
+ data = mvneta_frag_alloc(pp->frag_size);
+ if (!data)
+ return -ENOMEM;
+
+ phys_addr = dma_map_single(pp->dev->dev.parent, data,
+ MVNETA_RX_BUF_SIZE(pp->pkt_size),
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(pp->dev->dev.parent, phys_addr))) {
+ mvneta_frag_free(pp->frag_size, data);
+ return -ENOMEM;
+ }
+
+ rx_desc->buf_phys_addr = phys_addr;
+ rx_desc->buf_cookie = (uintptr_t)data;
+
+ return 0;
+}
+
+/* Handle rxq fill: allocates rxq skbs; called when initializing a port */
+static int mvneta_rxq_bm_fill(struct mvneta_port *pp,
+ struct mvneta_rx_queue *rxq,
+ int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ memset(rxq->descs + i, 0, sizeof(struct mvneta_rx_desc));
+ if (mvneta_rx_hwbm_refill(pp, rxq->descs + i) != 0) {
+ netdev_err(pp->dev, "%s:rxq %d, %d of %d buffs filled\n",
+ __func__, rxq->id, i, num);
+ break;
+ }
+ }
+
+ /* Add this number of RX descriptors as non occupied (ready to
+ * get packets)
+ */
+ mvneta_rxq_non_occup_desc_add(pp, rxq, i);
+
+ return i;
+}
+
/* Handle rxq fill: allocates rxq skbs; called when initializing a port */
static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
int num)
@@ -2716,7 +2780,7 @@ static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
for (i = 0; i < num; i++) {
memset(rxq->descs + i, 0, sizeof(struct mvneta_rx_desc));
- if (mvneta_rx_refill(pp, rxq->descs + i) != 0) {
+ if (mvneta_rx_refill(pp, rxq->descs + i, rxq) != 0) {
netdev_err(pp->dev, "%s:rxq %d, %d of %d buffs filled\n",
__func__, rxq->id, i, num);
break;
@@ -2784,14 +2848,14 @@ static int mvneta_rxq_init(struct mvneta_port *pp,
mvneta_rxq_buf_size_set(pp, rxq,
MVNETA_RX_BUF_SIZE(pp->pkt_size));
mvneta_rxq_bm_disable(pp, rxq);
+ mvneta_rxq_fill(pp, rxq, rxq->size);
} else {
mvneta_rxq_bm_enable(pp, rxq);
mvneta_rxq_long_pool_set(pp, rxq);
mvneta_rxq_short_pool_set(pp, rxq);
+ mvneta_rxq_bm_fill(pp, rxq, rxq->size);
}
- mvneta_rxq_fill(pp, rxq, rxq->size);
-
return 0;
}
@@ -3865,6 +3929,11 @@ static int mvneta_init(struct device *dev, struct mvneta_port *pp)
rxq->size = pp->rx_ring_size;
rxq->pkts_coal = MVNETA_RX_COAL_PKTS;
rxq->time_coal = MVNETA_RX_COAL_USEC;
+ rxq->buf_virt_addr = devm_kmalloc(pp->dev->dev.parent,
+ rxq->size * sizeof(void *),
+ GFP_KERNEL);
+ if (!rxq->buf_virt_addr)
+ return -ENOMEM;
}
return 0;
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v3 net-next 1/6] net: mvneta: Optimize rx path for small frame
From: Gregory CLEMENT @ 2016-11-29 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.a09aeaf5ba62853d595153626b6121ef52a3e9b4.1480412215.git-series.gregory.clement@free-electrons.com>
For small frame reuse the phys_addr variable instead of accessing the
uncacheable value in the rx descriptor.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/net/ethernet/marvell/mvneta.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 87274d4ab102..1b84f746d748 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1918,7 +1918,7 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
goto err_drop_frame;
dma_sync_single_range_for_cpu(dev->dev.parent,
- rx_desc->buf_phys_addr,
+ phys_addr,
MVNETA_MH_SIZE + NET_SKB_PAD,
rx_bytes,
DMA_FROM_DEVICE);
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v3 net-next 0/6] Support Armada 37xx SoC (ARMv8 64-bits) in mvneta driver
From: Gregory CLEMENT @ 2016-11-29 9:37 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
The Armada 37xx is a new ARMv8 SoC from Marvell using same network
controller as the older Armada 370/38x/XP SoCs. This series adapts the
driver in order to be able to use it on this new SoC. The main changes
are:
- 64-bits support: the first patches allow using the driver on a 64-bit
architecture.
- MBUS support: the mbus configuration is different on Armada 37xx
from the older SoCs.
- per cpu interrupt: Armada 37xx do not support per cpu interrupt for
the NETA IP, the non-per-CPU behavior was added back.
The first item is solved by patches 1 to 3.
The 2 last items are solved by patch 4.
In patch 5 the dt support is added.
Beside Armada 37xx, the series have been tested on Armada XP and
Armada 38x (with Hardware Buffer Management and with Software Buffer
Managment).
Thanks,
Gregory
Gregory CLEMENT (4):
net: mvneta: Optimize rx path for small frame
net: mvneta: Use cacheable memory to store the rx buffer virtual address
net: mvneta: Only disable mvneta_bm for 64-bits
ARM64: dts: marvell: Add network support for Armada 3700
Marcin Wojtas (2):
net: mvneta: Convert to be 64 bits compatible
net: mvneta: Add network support for Armada 3700 SoC
Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt | 7 +-
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 23 ++++-
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 23 ++++-
drivers/net/ethernet/marvell/Kconfig | 10 +-
drivers/net/ethernet/marvell/mvneta.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
5 files changed, 361 insertions(+), 102 deletions(-)
base-commit: 436accebb53021ef7c63535f60bda410aa87c136
--
git-series 0.8.10
^ permalink raw reply
* [PATCH] KVM: arm/arm64: Access CNTHCTL_EL2 bit fields correctly
From: Marc Zyngier @ 2016-11-29 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161128194221.GG18170@cbox>
On 28/11/16 19:42, Christoffer Dall wrote:
> On Mon, Nov 28, 2016 at 06:39:04PM +0000, Marc Zyngier wrote:
>> On 28/11/16 17:43, Marc Zyngier wrote:
>>> Hi Jintack,
>>>
>>> On 28/11/16 16:46, Jintack Lim wrote:
>>>> Bit positions of CNTHCTL_EL2 are changing depending on HCR_EL2.E2H bit.
>>>> EL1PCEN and EL1PCTEN are 1st and 0th bits when E2H is not set, but they
>>>> are 11th and 10th bits respectively when E2H is set. Current code is
>>>> unintentionally setting wrong bits to CNTHCTL_EL2 with E2H set, which
>>>> may allow guest OS to access physical timer. So, fix it.
>>>>
>>>> Signed-off-by: Jintack Lim <jintack@cs.columbia.edu>
>>>> ---
>>>> arch/arm/include/asm/kvm_timer.h | 33 +++++++++++++++++++
>>>> arch/arm64/include/asm/kvm_timer.h | 62 ++++++++++++++++++++++++++++++++++++
>>>> include/clocksource/arm_arch_timer.h | 6 ++--
>>>> virt/kvm/arm/hyp/timer-sr.c | 8 ++---
>>>> 4 files changed, 103 insertions(+), 6 deletions(-)
>>>> create mode 100644 arch/arm/include/asm/kvm_timer.h
>>>> create mode 100644 arch/arm64/include/asm/kvm_timer.h
>>>>
>>
>> [...]
>>
>>> We could make it nicer (read "faster") by introducing a
>>> hyp_alternate_select construct that only returns a value instead
>>> of calling a function. I remember writing something like that
>>> at some point, and dropping it...
>>
>> So here's what this could look like (warning, wacky code ahead,
>> though I fixed a stupid bug that was present in the previous patch).
>> The generated code is quite nice (no branch, only an extra mov
>> instruction on the default path)... Of course, completely untested!
>
> Isn't this all about determining which bitmask to use, statically, once,
> after the system has booted?
>
> How about a good old fashioned static variable, or global struct like
> the global one we use for the VGIC, which sets the proper mit mask
> during kvm init, and the world-switch code just uses a variable?
We could indeed do that (I've been carried away with my tendency for
weird and wonderful hacks).
But as Jintack mentioned, there is a much better approach, which is to
do nothing at all on the VHE path (we can set the permission bits once
and for all). cntvoff_el2 also falls into the same category of things we
should be able to only restore and not bother resetting (as it doesn't
affect the EL2 virtual counter).
Thoughts?
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH] KVM: arm/arm64: Access CNTHCTL_EL2 bit fields correctly
From: Marc Zyngier @ 2016-11-29 9:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHyh4xhXoFWsbnNNePthWp2-ZAOtCuUVmLn-JKRe4sc=nqrYNw@mail.gmail.com>
On 29/11/16 03:28, Jintack Lim wrote:
> On Mon, Nov 28, 2016 at 1:39 PM, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> On 28/11/16 17:43, Marc Zyngier wrote:
>>> Hi Jintack,
>
> Hi Marc,
>
>>>
>>> On 28/11/16 16:46, Jintack Lim wrote:
>>>> Bit positions of CNTHCTL_EL2 are changing depending on HCR_EL2.E2H bit.
>>>> EL1PCEN and EL1PCTEN are 1st and 0th bits when E2H is not set, but they
>>>> are 11th and 10th bits respectively when E2H is set. Current code is
>>>> unintentionally setting wrong bits to CNTHCTL_EL2 with E2H set, which
>>>> may allow guest OS to access physical timer. So, fix it.
>>>>
>>>> Signed-off-by: Jintack Lim <jintack@cs.columbia.edu>
>>>> ---
>>>> arch/arm/include/asm/kvm_timer.h | 33 +++++++++++++++++++
>>>> arch/arm64/include/asm/kvm_timer.h | 62 ++++++++++++++++++++++++++++++++++++
>>>> include/clocksource/arm_arch_timer.h | 6 ++--
>>>> virt/kvm/arm/hyp/timer-sr.c | 8 ++---
>>>> 4 files changed, 103 insertions(+), 6 deletions(-)
>>>> create mode 100644 arch/arm/include/asm/kvm_timer.h
>>>> create mode 100644 arch/arm64/include/asm/kvm_timer.h
>>>>
>>
>> [...]
>>
>>> We could make it nicer (read "faster") by introducing a
>>> hyp_alternate_select construct that only returns a value instead
>>> of calling a function. I remember writing something like that
>>> at some point, and dropping it...
>>
>> So here's what this could look like (warning, wacky code ahead,
>> though I fixed a stupid bug that was present in the previous patch).
>> The generated code is quite nice (no branch, only an extra mov
>> instruction on the default path)... Of course, completely untested!
>
> This looks much cleaner than my patch.
> While we are at it, is it worth to consider that we just need to set
> those bits once for VHE case, not for every world switch as an
> optimization?
Ah! That's a much better idea indeed! And we could stop messing with
cntvoff_el2 as well, as it doesn't need to be restored to zero on exit.
Could you try and respin something along those lines?
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH 2/2] ARM: dts: dra7-evm: add pinmux configuration for mmc1/2
From: Sekhar Nori @ 2016-11-29 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1480411308.git.nsekhar@ti.com>
From: Kishon Vijay Abraham I <kishon@ti.com>
Add pinmux configuration for SD card slot and eMMC device
found on TI's DRA74x EVM.
Only the default modes are supported. For higher speed modes
(UHS and HS200) to function, we need full fledged IODelay support
in kernel. IODelay support is yet to be added.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
[nsekhar at ti.com: rebase to mainline/master, use IOPAD() macro,
update commit message]
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
---
arch/arm/boot/dts/dra7-evm.dts | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index a1efd4efed6d..1fc29ed636c9 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -164,6 +164,33 @@
DRA7XX_CORE_IOPAD(0x3818, MUX_MODE15 | PULL_UP) /* wakeup0.off */
>;
};
+
+ mmc1_pins_default: mmc1_pins_default {
+ pinctrl-single,pins = <
+ DRA7XX_CORE_IOPAD(0x376c, PIN_INPUT | MUX_MODE14) /* mmc1sdcd.gpio219 */
+ DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
+ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
+ DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
+ DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
+ DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
+ DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
+ >;
+ };
+
+ mmc2_pins_default: mmc2_pins_default {
+ pinctrl-single,pins = <
+ DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
+ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
+ DRA7XX_CORE_IOPAD(0x34a0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
+ DRA7XX_CORE_IOPAD(0x34a4, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
+ DRA7XX_CORE_IOPAD(0x34a8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
+ DRA7XX_CORE_IOPAD(0x34ac, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
+ DRA7XX_CORE_IOPAD(0x348c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
+ DRA7XX_CORE_IOPAD(0x3490, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
+ DRA7XX_CORE_IOPAD(0x3494, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
+ DRA7XX_CORE_IOPAD(0x3498, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
+ >;
+ };
};
&i2c1 {
@@ -402,6 +429,8 @@
&mmc1 {
status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins_default>;
vmmc-supply = <&evm_3v3_sd>;
vmmc_aux-supply = <&ldo1_reg>;
bus-width = <4>;
@@ -414,6 +443,8 @@
&mmc2 {
status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins_default>;
vmmc-supply = <&evm_3v3_sw>;
bus-width = <8>;
};
--
2.9.0
^ permalink raw reply related
* [PATCH 1/2] ARM: dts: dra7-evm: Remove pinmux configurations for erratum i869
From: Sekhar Nori @ 2016-11-29 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1480411308.git.nsekhar@ti.com>
Pinmuxing for DRA7x/AM57x family of processors need to be done in IO
isolation as part of initial bootloader executed from SRAM. This is
done as part of iodelay configuration sequence and is required due
to the limitations introduced by erratum ID: i869[1] (IO Glitches
can occur when changing IO settings) and elaborated in the Technical
Reference Manual[2] 18.4.6.1.7 Isolation Requirements.
Only peripheral that is permitted for dynamic pin mux configuration
is MMC and DCAN. MMC is permitted to change to accommodate the
requirements for varied speeds (which require IO-delay support in
kernel as well). DCAN is a result of i893[1] (DCAN initialization
sequence).
DCAN pinmux is retained in this patch. MMC pinmux is missing from
the dra7-evm.dts file and the board is relying on configuration done
by bootloader. A subsequent patch will add MMC pinmux configuration.
A side-effect of this patch is that NAND support is removed. NAND
pins clash with VOUT3 on DRA7-EVM. U-Boot selects VOUT3 over NAND
as per TI EVM application needs.
[1] http://www.ti.com/lit/pdf/sprz429
[2] http://www.ti.com/lit/pdf/sprui30
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
---
arch/arm/boot/dts/dra7-evm.dts | 260 -----------------------------------------
1 file changed, 260 deletions(-)
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index 132f2be10889..a1efd4efed6d 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -151,204 +151,6 @@
};
&dra7_pmx_core {
- pinctrl-names = "default";
- pinctrl-0 = <&vtt_pin>;
-
- vtt_pin: pinmux_vtt_pin {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x37b4, PIN_OUTPUT | MUX_MODE14) /* spi1_cs1.gpio7_11 */
- >;
- };
-
- i2c1_pins: pinmux_i2c1_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3800, PIN_INPUT | MUX_MODE0) /* i2c1_sda */
- DRA7XX_CORE_IOPAD(0x3804, PIN_INPUT | MUX_MODE0) /* i2c1_scl */
- >;
- };
-
- i2c2_pins: pinmux_i2c2_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE0) /* i2c2_sda */
- DRA7XX_CORE_IOPAD(0x380c, PIN_INPUT | MUX_MODE0) /* i2c2_scl */
- >;
- };
-
- i2c3_pins: pinmux_i2c3_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3688, PIN_INPUT | MUX_MODE9) /* gpio6_14.i2c3_sda */
- DRA7XX_CORE_IOPAD(0x368c, PIN_INPUT | MUX_MODE9) /* gpio6_15.i2c3_scl */
- >;
- };
-
- mcspi1_pins: pinmux_mcspi1_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x37a4, PIN_INPUT | MUX_MODE0) /* spi1_sclk */
- DRA7XX_CORE_IOPAD(0x37a8, PIN_INPUT | MUX_MODE0) /* spi1_d1 */
- DRA7XX_CORE_IOPAD(0x37ac, PIN_INPUT | MUX_MODE0) /* spi1_d0 */
- DRA7XX_CORE_IOPAD(0x37b0, PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs0 */
- DRA7XX_CORE_IOPAD(0x37b8, PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs2.hdmi1_hpd */
- DRA7XX_CORE_IOPAD(0x37bc, PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs3.hdmi1_cec */
- >;
- };
-
- mcspi2_pins: pinmux_mcspi2_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x37c0, PIN_INPUT | MUX_MODE0) /* spi2_sclk */
- DRA7XX_CORE_IOPAD(0x37c4, PIN_INPUT_SLEW | MUX_MODE0) /* spi2_d1 */
- DRA7XX_CORE_IOPAD(0x37c8, PIN_INPUT_SLEW | MUX_MODE0) /* spi2_d1 */
- DRA7XX_CORE_IOPAD(0x37cc, PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */
- >;
- };
-
- uart1_pins: pinmux_uart1_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x37e0, PIN_INPUT_SLEW | MUX_MODE0) /* uart1_rxd */
- DRA7XX_CORE_IOPAD(0x37e4, PIN_INPUT_SLEW | MUX_MODE0) /* uart1_txd */
- DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT | MUX_MODE3) /* uart1_ctsn */
- DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT | MUX_MODE3) /* uart1_rtsn */
- >;
- };
-
- uart2_pins: pinmux_uart2_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x37f0, PIN_INPUT | MUX_MODE0) /* uart2_rxd */
- DRA7XX_CORE_IOPAD(0x37f4, PIN_INPUT | MUX_MODE0) /* uart2_txd */
- DRA7XX_CORE_IOPAD(0x37f8, PIN_INPUT | MUX_MODE0) /* uart2_ctsn */
- DRA7XX_CORE_IOPAD(0x37fc, PIN_INPUT | MUX_MODE0) /* uart2_rtsn */
- >;
- };
-
- uart3_pins: pinmux_uart3_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3648, PIN_INPUT_SLEW | MUX_MODE0) /* uart3_rxd */
- DRA7XX_CORE_IOPAD(0x364c, PIN_INPUT_SLEW | MUX_MODE0) /* uart3_txd */
- >;
- };
-
- usb1_pins: pinmux_usb1_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */
- >;
- };
-
- usb2_pins: pinmux_usb2_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3684, PIN_INPUT_SLEW | MUX_MODE0) /* usb2_drvvbus */
- >;
- };
-
- nand_flash_x16: nand_flash_x16 {
- /* On DRA7 EVM, GPMC_WPN and NAND_BOOTn comes from DIP switch
- * So NAND flash requires following switch settings:
- * SW5.1 (NAND_BOOTn) = ON (LOW)
- * SW5.9 (GPMC_WPN) = OFF (HIGH)
- */
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3400, PIN_INPUT | MUX_MODE0) /* gpmc_ad0 */
- DRA7XX_CORE_IOPAD(0x3404, PIN_INPUT | MUX_MODE0) /* gpmc_ad1 */
- DRA7XX_CORE_IOPAD(0x3408, PIN_INPUT | MUX_MODE0) /* gpmc_ad2 */
- DRA7XX_CORE_IOPAD(0x340c, PIN_INPUT | MUX_MODE0) /* gpmc_ad3 */
- DRA7XX_CORE_IOPAD(0x3410, PIN_INPUT | MUX_MODE0) /* gpmc_ad4 */
- DRA7XX_CORE_IOPAD(0x3414, PIN_INPUT | MUX_MODE0) /* gpmc_ad5 */
- DRA7XX_CORE_IOPAD(0x3418, PIN_INPUT | MUX_MODE0) /* gpmc_ad6 */
- DRA7XX_CORE_IOPAD(0x341c, PIN_INPUT | MUX_MODE0) /* gpmc_ad7 */
- DRA7XX_CORE_IOPAD(0x3420, PIN_INPUT | MUX_MODE0) /* gpmc_ad8 */
- DRA7XX_CORE_IOPAD(0x3424, PIN_INPUT | MUX_MODE0) /* gpmc_ad9 */
- DRA7XX_CORE_IOPAD(0x3428, PIN_INPUT | MUX_MODE0) /* gpmc_ad10 */
- DRA7XX_CORE_IOPAD(0x342c, PIN_INPUT | MUX_MODE0) /* gpmc_ad11 */
- DRA7XX_CORE_IOPAD(0x3430, PIN_INPUT | MUX_MODE0) /* gpmc_ad12 */
- DRA7XX_CORE_IOPAD(0x3434, PIN_INPUT | MUX_MODE0) /* gpmc_ad13 */
- DRA7XX_CORE_IOPAD(0x3438, PIN_INPUT | MUX_MODE0) /* gpmc_ad14 */
- DRA7XX_CORE_IOPAD(0x343c, PIN_INPUT | MUX_MODE0) /* gpmc_ad15 */
- DRA7XX_CORE_IOPAD(0x34d8, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0 */
- DRA7XX_CORE_IOPAD(0x34cc, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen */
- DRA7XX_CORE_IOPAD(0x34b4, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_csn0 */
- DRA7XX_CORE_IOPAD(0x34c4, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale */
- DRA7XX_CORE_IOPAD(0x34c8, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren */
- DRA7XX_CORE_IOPAD(0x34d0, PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle */
- >;
- };
-
- cpsw_default: cpsw_default {
- pinctrl-single,pins = <
- /* Slave 1 */
- DRA7XX_CORE_IOPAD(0x3650, PIN_OUTPUT | MUX_MODE0) /* rgmii0_txc.rgmii0_txc */
- DRA7XX_CORE_IOPAD(0x3654, PIN_OUTPUT | MUX_MODE0) /* rgmii0_txctl.rgmii0_txctl */
- DRA7XX_CORE_IOPAD(0x3658, PIN_OUTPUT | MUX_MODE0) /* rgmii0_td3.rgmii0_txd3 */
- DRA7XX_CORE_IOPAD(0x365c, PIN_OUTPUT | MUX_MODE0) /* rgmii0_txd2.rgmii0_txd2 */
- DRA7XX_CORE_IOPAD(0x3660, PIN_OUTPUT | MUX_MODE0) /* rgmii0_txd1.rgmii0_txd1 */
- DRA7XX_CORE_IOPAD(0x3664, PIN_OUTPUT | MUX_MODE0) /* rgmii0_txd0.rgmii0_txd0 */
- DRA7XX_CORE_IOPAD(0x3668, PIN_INPUT | MUX_MODE0) /* rgmii0_rxc.rgmii0_rxc */
- DRA7XX_CORE_IOPAD(0x366c, PIN_INPUT | MUX_MODE0) /* rgmii0_rxctl.rgmii0_rxctl */
- DRA7XX_CORE_IOPAD(0x3670, PIN_INPUT | MUX_MODE0) /* rgmii0_rxd3.rgmii0_rxd3 */
- DRA7XX_CORE_IOPAD(0x3674, PIN_INPUT | MUX_MODE0) /* rgmii0_rxd2.rgmii0_rxd2 */
- DRA7XX_CORE_IOPAD(0x3678, PIN_INPUT | MUX_MODE0) /* rgmii0_rxd1.rgmii0_rxd1 */
- DRA7XX_CORE_IOPAD(0x367c, PIN_INPUT | MUX_MODE0) /* rgmii0_rxd0.rgmii0_rxd0 */
-
- /* Slave 2 */
- DRA7XX_CORE_IOPAD(0x3598, PIN_OUTPUT | MUX_MODE3) /* vin2a_d12.rgmii1_txc */
- DRA7XX_CORE_IOPAD(0x359c, PIN_OUTPUT | MUX_MODE3) /* vin2a_d13.rgmii1_tctl */
- DRA7XX_CORE_IOPAD(0x35a0, PIN_OUTPUT | MUX_MODE3) /* vin2a_d14.rgmii1_td3 */
- DRA7XX_CORE_IOPAD(0x35a4, PIN_OUTPUT | MUX_MODE3) /* vin2a_d15.rgmii1_td2 */
- DRA7XX_CORE_IOPAD(0x35a8, PIN_OUTPUT | MUX_MODE3) /* vin2a_d16.rgmii1_td1 */
- DRA7XX_CORE_IOPAD(0x35ac, PIN_OUTPUT | MUX_MODE3) /* vin2a_d17.rgmii1_td0 */
- DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT | MUX_MODE3) /* vin2a_d18.rgmii1_rclk */
- DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT | MUX_MODE3) /* vin2a_d19.rgmii1_rctl */
- DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT | MUX_MODE3) /* vin2a_d20.rgmii1_rd3 */
- DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT | MUX_MODE3) /* vin2a_d21.rgmii1_rd2 */
- DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT | MUX_MODE3) /* vin2a_d22.rgmii1_rd1 */
- DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT | MUX_MODE3) /* vin2a_d23.rgmii1_rd0 */
- >;
-
- };
-
- cpsw_sleep: cpsw_sleep {
- pinctrl-single,pins = <
- /* Slave 1 */
- DRA7XX_CORE_IOPAD(0x3650, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3654, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3658, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x365c, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3660, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3664, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3668, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x366c, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3670, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3674, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3678, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x367c, MUX_MODE15)
-
- /* Slave 2 */
- DRA7XX_CORE_IOPAD(0x3598, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x359c, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35a0, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35a4, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35a8, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35ac, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35b0, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35b4, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35b8, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35bc, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35c0, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x35c4, MUX_MODE15)
- >;
- };
-
- davinci_mdio_default: davinci_mdio_default {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x363c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_d.mdio_d */
- DRA7XX_CORE_IOPAD(0x3640, PIN_INPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
- >;
- };
-
- davinci_mdio_sleep: davinci_mdio_sleep {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x363c, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3640, MUX_MODE15)
- >;
- };
-
dcan1_pins_default: dcan1_pins_default {
pinctrl-single,pins = <
DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */
@@ -362,37 +164,10 @@
DRA7XX_CORE_IOPAD(0x3818, MUX_MODE15 | PULL_UP) /* wakeup0.off */
>;
};
-
- atl_pins: pinmux_atl_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3698, PIN_OUTPUT | MUX_MODE5) /* xref_clk1.atl_clk1 */
- DRA7XX_CORE_IOPAD(0x369c, PIN_OUTPUT | MUX_MODE5) /* xref_clk2.atl_clk2 */
- >;
- };
-
- mcasp3_pins: pinmux_mcasp3_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3724, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_aclkx */
- DRA7XX_CORE_IOPAD(0x3728, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_fsx */
- DRA7XX_CORE_IOPAD(0x372c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr0 */
- DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr1 */
- >;
- };
-
- mcasp3_sleep_pins: pinmux_mcasp3_sleep_pins {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3724, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3728, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x372c, MUX_MODE15)
- DRA7XX_CORE_IOPAD(0x3730, MUX_MODE15)
- >;
- };
};
&i2c1 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&i2c1_pins>;
clock-frequency = <400000>;
tps659038: tps659038 at 58 {
@@ -581,8 +356,6 @@
&i2c2 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&i2c2_pins>;
clock-frequency = <400000>;
pcf_hdmi: gpio at 26 {
@@ -602,41 +375,29 @@
&i2c3 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&i2c3_pins>;
clock-frequency = <400000>;
};
&mcspi1 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mcspi1_pins>;
};
&mcspi2 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mcspi2_pins>;
};
&uart1 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&uart1_pins>;
interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
<&dra7_pmx_core 0x3e0>;
};
&uart2 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&uart2_pins>;
};
&uart3 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&uart3_pins>;
};
&mmc1 {
@@ -732,14 +493,10 @@
&usb1 {
dr_mode = "peripheral";
- pinctrl-names = "default";
- pinctrl-0 = <&usb1_pins>;
};
&usb2 {
dr_mode = "host";
- pinctrl-names = "default";
- pinctrl-0 = <&usb2_pins>;
};
&elm {
@@ -748,8 +505,6 @@
&gpmc {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&nand_flash_x16>;
ranges = <0 0 0x08000000 0x01000000>; /* minimum GPMC partition = 16MB */
nand at 0,0 {
compatible = "ti,omap2-nand";
@@ -845,9 +600,6 @@
&mac {
status = "okay";
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&cpsw_default>;
- pinctrl-1 = <&cpsw_sleep>;
dual_emac;
};
@@ -863,12 +615,6 @@
dual_emac_res_vlan = <2>;
};
-&davinci_mdio {
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&davinci_mdio_default>;
- pinctrl-1 = <&davinci_mdio_sleep>;
-};
-
&dcan1 {
status = "ok";
pinctrl-names = "default", "sleep", "active";
@@ -878,9 +624,6 @@
};
&atl {
- pinctrl-names = "default";
- pinctrl-0 = <&atl_pins>;
-
assigned-clocks = <&abe_dpll_sys_clk_mux>,
<&atl_gfclk_mux>,
<&dpll_abe_ck>,
@@ -899,9 +642,6 @@
&mcasp3 {
#sound-dai-cells = <0>;
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&mcasp3_pins>;
- pinctrl-1 = <&mcasp3_sleep_pins>;
assigned-clocks = <&mcasp3_ahclkx_mux>;
assigned-clock-parents = <&atl_clkin2_ck>;
--
2.9.0
^ permalink raw reply related
* [PATCH 0/2] ARM: dts: dra7-evm: pinmuxing updates
From: Sekhar Nori @ 2016-11-29 9:24 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This patch series drops most of the pinmuxing from dra7-evm
to satisfy erratum i869 and adds missing eMMC and SD card pinmuxing.
The patches apply to latest linux-next. Tested on DRA74x EVM Rev H
using U-Boot 2016.11. Boot tested using NFS and basic testing carried
out on SD card, eMMC, Audio capture and playback.
Kishon Vijay Abraham I (1):
ARM: dts: dra7-evm: add pinmux configuration for mmc1/2
Sekhar Nori (1):
ARM: dts: dra7-evm: Remove pinmux configurations for erratum i869
arch/arm/boot/dts/dra7-evm.dts | 275 ++++-------------------------------------
1 file changed, 23 insertions(+), 252 deletions(-)
--
2.9.0
^ permalink raw reply
* [PATCH v2] drm: tilcdc: fix parsing of some DT properties
From: Jyri Sarha @ 2016-11-29 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480333043-1292-1-git-send-email-bgolaszewski@baylibre.com>
On 11/28/16 13:37, Bartosz Golaszewski wrote:
> The DT binding for tildc is not consistent with the driver code: there
> are two options - 'max-width' and 'max-pixelclock' specified in the
> documentation which are parsed as 'ti,max-width' and
> 'ti'max-pixelclock' respectively.
>
> Make the driver code consistent with the binding.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Reviewed-by: Jyri Sarha <jsarha@ti.com>
I'll pick this up for a pull request that I'll send shortly.
> ---
> v1 -> v2:
> - fix max-pixelclock too
>
> drivers/gpu/drm/tilcdc/tilcdc_drv.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> index 5efb369..bd0a3bd 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> @@ -296,12 +296,12 @@ static int tilcdc_init(struct drm_driver *ddrv, struct device *dev)
>
> DBG("Maximum Bandwidth Value %d", priv->max_bandwidth);
>
> - if (of_property_read_u32(node, "ti,max-width", &priv->max_width))
> + if (of_property_read_u32(node, "max-width", &priv->max_width))
> priv->max_width = TILCDC_DEFAULT_MAX_WIDTH;
>
> DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width);
>
> - if (of_property_read_u32(node, "ti,max-pixelclock",
> + if (of_property_read_u32(node, "max-pixelclock",
> &priv->max_pixelclock))
> priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK;
>
>
^ permalink raw reply
* [PATCH v5 8/8] iommu/rockchip: Enable Rockchip IOMMU on ARM64
From: Heiko Stübner @ 2016-11-29 9:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161129004225.GA109697@google.com>
Am Montag, 28. November 2016, 16:42:27 schrieb Brian Norris:
> Hi,
>
> On Fri, Jun 24, 2016 at 10:13:33AM +0800, Shunqian Zheng wrote:
> > From: Simon Xue <xxm@rock-chips.com>
> >
> > This patch makes it possible to compile the rockchip-iommu driver on
> > ARM64, so that it can be used with 64-bit SoCs equipped with this type
> > of IOMMU.
> >
> > Signed-off-by: Simon Xue <xxm@rock-chips.com>
> > Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
> > Signed-off-by: Tomasz Figa <tfiga@chromium.org>
> > ---
> >
> > drivers/iommu/Kconfig | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> > index ad08603..5572621 100644
> > --- a/drivers/iommu/Kconfig
> > +++ b/drivers/iommu/Kconfig
> > @@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
> >
> > config ROCKCHIP_IOMMU
> >
> > bool "Rockchip IOMMU Support"
> >
> > - depends on ARM
> > + depends on ARM || ARM64
> >
> > depends on ARCH_ROCKCHIP || COMPILE_TEST
> > select IOMMU_API
> > select ARM_DMA_USE_IOMMU
>
> Whatever happened with the rest of this series? Some of the IOMMU bits
> made it, but the DRM fixes never did, and so this didn't get applied.
> This leaves the whole DRM stack unusable on ARM64 Rockchip systems.
>
> The patch context has changed a bit on patch 7 (and maybe 6?), so
> somebody will need to refresh those on the latest upstream.
I've tried forward-porting these when going through Caesars VOP dts patches,
but was somewhat unsucessful in my small attempt at the time - see [0].
Heiko
[0] https://lkml.org/lkml/2016/11/14/519
^ permalink raw reply
* [PATCH] arm64: dts: Add symlinks for cros-ec-keyboard and cros-ec-sbs
From: Heiko Stübner @ 2016-11-29 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161128235132.GA71295@google.com>
Am Montag, 28. November 2016, 15:51:35 schrieb Brian Norris:
> Hi Olof, Arnd,
>
> On Thu, May 12, 2016 at 03:02:10PM -0700, Doug Anderson wrote:
> > We'd like to be able to use the cros-ec-keyboard.dtsi and
> > cros-ec-sbs.dtsi snippets for arm64 devices. Currently those files live
> > in the arm/boot/dts directory.
> >
> > Let's follow the convention set by commit 8ee57b8182c4 ("ARM64: dts:
> > vexpress: Use a symlink to vexpress-v2m-rs1.dtsi from arch=arm") and use
> > a symlink. Note that in this case we put the files in a new
> > "include/common" directory since these snippets may need to be
> > referenced by dts files in many different subdirectories.
> >
> > Signed-off-by: Douglas Anderson <dianders@chromium.org>
> > ---
> > Note that, as of right now, there are no users of this. However, given
> > development happening it is almost 100% certain that users will arrive
> > soon. If we need to wait for the first user before landing this we can
> > leave this on the back burner. If it's OK to have no users (yet), let's
> > land.
>
> This may not fit your definition of "soon", but I'm looking to start
> using these files in arch/arm64/. I'll probably carry along this patch
> and resend when I'm ready, but it'd be just as well if you'd merge it
> now (or express a preference for a different directory structure).
Till now I was expecting to just pick up this patch as well once the first
(rk3399-)users arrived. But of course it could also be picked up separately.
> > arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi | 1 +
> > arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi | 1 +
> > 2 files changed, 2 insertions(+)
> > create mode 120000
> > arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi
> > create mode 120000 arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi
> >
> > \ No newline at end of file
> >
> > diff --git a/arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi
> > b/arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi new file mode
> > 120000
> > index 000000000000..1c1889f0a791
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi
> > @@ -0,0 +1 @@
> > +../../../../../arm/boot/dts/cros-ec-keyboard.dtsi
> > \ No newline at end of file
> > diff --git a/arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi
> > b/arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi new file mode
> > 120000
> > index 000000000000..3d7ae9c88bcd
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi
> > @@ -0,0 +1 @@
> > +../../../../../arm/boot/dts/cros-ec-sbs.dtsi
>
> FWIW:
>
> Reviewed-by: Brian Norris <briannorris@chromium.org>
I'm also running with this on my rk3399-gru and it sucessfully enables the
cros-ec keyboard :-) ,so if anyone picks it up before me they can add
Reviewed-by: Heiko Stueber <heiko@sntech.de>
Tested-by: Heiko Stuebner <heiko@sntech.de>
^ permalink raw reply
* [PATCH v7 4/8] drm/sunxi: Add DT bindings documentation of Allwinner HDMI
From: Jean-Francois Moine @ 2016-11-29 9:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1480414715.git.moinejf@free.fr>
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
.../devicetree/bindings/display/sunxi/hdmi.txt | 56 ++++++++++++++++++++++
1 file changed, 56 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/sunxi/hdmi.txt
diff --git a/Documentation/devicetree/bindings/display/sunxi/hdmi.txt b/Documentation/devicetree/bindings/display/sunxi/hdmi.txt
new file mode 100644
index 0000000..1e107cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/sunxi/hdmi.txt
@@ -0,0 +1,56 @@
+Allwinner HDMI Transmitter
+==========================
+
+The Allwinner HDMI transmitters are included in the SoCs.
+They support audio and video.
+
+Required properties:
+ - compatible : should be one of
+ "allwinner,sun8i-a83t-hdmi"
+ "allwinner,sun8i-h3-hdmi"
+ - reg: base address and size of the I/O memory
+ - clocks : phandles to the HDMI clocks as described in
+ Documentation/devicetree/bindings/clock/clock-bindings.txt
+ - clock-names : must be
+ "bus" : bus gate
+ "clock" : streaming clock
+ "ddc-clock" : DDC clock
+ - resets : One or two phandles to the HDMI resets
+ - reset-names : when 2 phandles, must be
+ "hdmi0" and "hdmi1"
+ - #address-cells : should be <1>
+ - #size-cells : should be <0>
+
+Required nodes:
+ - port: Audio and video input port nodes with endpoint definitions
+ as defined in Documentation/devicetree/bindings/graph.txt.
+ port at 0 is video and port at 1 is audio.
+
+Example:
+
+ hdmi: hdmi at 01ee0000 {
+ compatible = "allwinner,sun8i-a83t-hdmi";
+ reg = <0x01ee0000 0x20000>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI>,
+ <&ccu CLK_HDMI_DDC>;
+ clock-names = "bus", "clock", "ddc-clock";
+ resets = <&ccu RST_HDMI0>, <&ccu RST_HDMI1>;
+ reset-names = "hdmi0", "hdmi1";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_pins_a>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port at 0 { /* video */
+ reg = <0>;
+ hdmi_tcon1: endpoint {
+ remote-endpoint = <&tcon1_hdmi>;
+ };
+ };
+ port at 1 { /* audio */
+ reg = <1>;
+ hdmi_i2s2: endpoint {
+ remote-endpoint = <&i2s2_hdmi>;
+ };
+ };
+ };
--
2.10.2
^ permalink raw reply related
* [PATCH v2 0/6] mm: fix the "counter.sh" failure for libhugetlbfs
From: Huang Shijie @ 2016-11-29 9:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6b83ea5d-a465-7582-a215-51a21fb4ce2e@suse.cz>
On Mon, Nov 28, 2016 at 03:20:05PM +0100, Vlastimil Babka wrote:
> > Huang Shijie (6):
> > mm: hugetlb: rename some allocation functions
> > mm: hugetlb: add a new parameter for some functions
> > mm: hugetlb: change the return type for alloc_fresh_gigantic_page
> > mm: mempolicy: intruduce a helper huge_nodemask()
> > mm: hugetlb: add a new function to allocate a new gigantic page
> > mm: hugetlb: support gigantic surplus pages
> >
> > include/linux/mempolicy.h | 8 +++
> > mm/hugetlb.c | 128 ++++++++++++++++++++++++++++++++++++----------
> > mm/mempolicy.c | 20 ++++++++
> > 3 files changed, 130 insertions(+), 26 deletions(-)
>
> Can't say I'm entirely happy with the continued direction of maze of
> functions for huge page allocation :( Feels like path of least resistance to
> basically copy/paste the missing parts here. Is there no way to consolidate
> the code more?
Ok, I will spend some time to read the code and think about it.
If you have interest, please do it too. :)
Thanks
Huang Shijie
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox