* [PATCH v2 02/11] mfd: axp20x: add volatile and writeable reg ranges for VBUS power supply driver
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
The X-Powers AXP20X and AXP22X PMICs allow to choose the maximum voltage
and minimum current delivered by the VBUS power supply.
This adds the register used by the VBUS power supply driver to the range
of volatile and writeable regs ranges.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
added in v2
drivers/mfd/axp20x.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index ba130be..6ee2cc6 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -65,12 +65,14 @@ static const struct regmap_access_table axp152_volatile_table = {
static const struct regmap_range axp20x_writeable_ranges[] = {
regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+ regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_VBUS_IPSOUT_MGMT),
regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
regmap_reg_range(AXP20X_RDC_H, AXP20X_OCV(AXP20X_OCV_MAX)),
};
static const struct regmap_range axp20x_volatile_ranges[] = {
regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_USB_OTG_STATUS),
+ regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_VBUS_IPSOUT_MGMT),
regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL2),
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
@@ -91,11 +93,13 @@ static const struct regmap_access_table axp20x_volatile_table = {
/* AXP22x ranges are shared with the AXP809, as they cover the same range */
static const struct regmap_range axp22x_writeable_ranges[] = {
regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+ regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_VBUS_IPSOUT_MGMT),
regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
};
static const struct regmap_range axp22x_volatile_ranges[] = {
regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
+ regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_VBUS_IPSOUT_MGMT),
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
--
2.9.3
^ permalink raw reply related
* [PATCH v2 03/11] power: supply: axp20x_usb_power: set min voltage and max current from sysfs
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
AXP20X and AXP22X PMICs allow setting the min voltage and max current of
VBUS power supply. This adds entries in sysfs to allow to do so.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
v2:
- moving defines from header mfd/axp20x.h to the driver,
- adding two functions to reduce indentation in axp20x_usb_power_set_property,
- adding new define for VBUS register VHOLD bits offset,
- switching return values in case of invalid value from 0 to -EINVAL,
drivers/power/supply/axp20x_usb_power.c | 81 +++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index 8985646..9e3f4ae 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -31,6 +31,8 @@
#define AXP20X_USB_STATUS_VBUS_VALID BIT(2)
#define AXP20X_VBUS_VHOLD_uV(b) (4000000 + (((b) >> 3) & 7) * 100000)
+#define AXP20X_VBUS_VHOLD_MASK GENMASK(5, 3)
+#define AXP20X_VBUS_VHOLD_OFFSET 3
#define AXP20X_VBUS_CLIMIT_MASK 3
#define AXP20X_VBUC_CLIMIT_900mA 0
#define AXP20X_VBUC_CLIMIT_500mA 1
@@ -155,6 +157,81 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
return 0;
}
+static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
+ int intval)
+{
+ int val;
+
+ switch (intval) {
+ case 4000000:
+ case 4100000:
+ case 4200000:
+ case 4300000:
+ case 4400000:
+ case 4500000:
+ case 4600000:
+ case 4700000:
+ val = (intval - 4000000) / 100000;
+ return regmap_update_bits(power->regmap,
+ AXP20X_VBUS_IPSOUT_MGMT,
+ AXP20X_VBUS_VHOLD_MASK,
+ val << AXP20X_VBUS_VHOLD_OFFSET);
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
+static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power,
+ int intval)
+{
+ int val;
+
+ switch (intval) {
+ case 100000:
+ if (power->axp20x_id == AXP221_ID)
+ return -EINVAL;
+ case 500000:
+ case 900000:
+ val = (900000 - intval) / 400000;
+ return regmap_update_bits(power->regmap,
+ AXP20X_VBUS_IPSOUT_MGMT,
+ AXP20X_VBUS_CLIMIT_MASK, val);
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
+static int axp20x_usb_power_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ return axp20x_usb_power_set_voltage_min(power, val->intval);
+
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ return axp20x_usb_power_set_current_max(power, val->intval);
+
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
+static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
+ psp == POWER_SUPPLY_PROP_CURRENT_MAX;
+}
+
static enum power_supply_property axp20x_usb_power_properties[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
@@ -178,7 +255,9 @@ static const struct power_supply_desc axp20x_usb_power_desc = {
.type = POWER_SUPPLY_TYPE_USB,
.properties = axp20x_usb_power_properties,
.num_properties = ARRAY_SIZE(axp20x_usb_power_properties),
+ .property_is_writeable = axp20x_usb_power_prop_writeable,
.get_property = axp20x_usb_power_get_property,
+ .set_property = axp20x_usb_power_set_property,
};
static const struct power_supply_desc axp22x_usb_power_desc = {
@@ -186,7 +265,9 @@ static const struct power_supply_desc axp22x_usb_power_desc = {
.type = POWER_SUPPLY_TYPE_USB,
.properties = axp22x_usb_power_properties,
.num_properties = ARRAY_SIZE(axp22x_usb_power_properties),
+ .property_is_writeable = axp20x_usb_power_prop_writeable,
.get_property = axp20x_usb_power_get_property,
+ .set_property = axp20x_usb_power_set_property,
};
static int axp20x_usb_power_probe(struct platform_device *pdev)
--
2.9.3
^ permalink raw reply related
* [PATCH v2 04/11] Documentation: DT: binding: axp20x_usb_power: add axp223 compatible
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
This adds the "x-powers,axp223-usb-power-supply" to the list of
compatibles for AXP20X VBUS power supply driver.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
v2:
- adding small explanation on AXP223 variation compared to the AXP221,
Documentation/devicetree/bindings/power/supply/axp20x_usb_power.txt | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/power/supply/axp20x_usb_power.txt b/Documentation/devicetree/bindings/power/supply/axp20x_usb_power.txt
index f1d7bee..ba8d35f 100644
--- a/Documentation/devicetree/bindings/power/supply/axp20x_usb_power.txt
+++ b/Documentation/devicetree/bindings/power/supply/axp20x_usb_power.txt
@@ -3,6 +3,11 @@ AXP20x USB power supply
Required Properties:
-compatible: One of: "x-powers,axp202-usb-power-supply"
"x-powers,axp221-usb-power-supply"
+ "x-powers,axp223-usb-power-supply"
+
+The AXP223 PMIC shares most of its behaviour with the AXP221 but has slight
+variations such as the former being able to set the VBUS power supply max
+current to 100mA, unlike the latter.
This node is a subnode of the axp20x PMIC.
--
2.9.3
^ permalink raw reply related
* [PATCH v2 05/11] power: supply: axp20x_usb_power: add 100mA max current limit for AXP223
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
The X-Powers AXP223 shares most of its behaviour with the AXP221 PMIC
but allows the VBUS power supply max current to be set to 100mA (like
the AXP209 PMIC).
This basically adds a new compatible to the VBUS power supply driver and
adds a check on the compatible when setting current max limit.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/power/supply/axp20x_usb_power.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index 9e3f4ae..1bcb025 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -90,11 +90,10 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
switch (v & AXP20X_VBUS_CLIMIT_MASK) {
case AXP20X_VBUC_CLIMIT_100mA:
- if (power->axp20x_id == AXP202_ID) {
- val->intval = 100000;
- } else {
+ if (power->axp20x_id == AXP221_ID)
val->intval = -1; /* No 100mA limit */
- }
+ else
+ val->intval = 100000;
break;
case AXP20X_VBUC_CLIMIT_500mA:
val->intval = 500000;
@@ -317,7 +316,8 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
usb_power_desc = &axp20x_usb_power_desc;
irq_names = axp20x_irq_names;
- } else if (power->axp20x_id == AXP221_ID) {
+ } else if (power->axp20x_id == AXP221_ID ||
+ power->axp20x_id == AXP223_ID) {
usb_power_desc = &axp22x_usb_power_desc;
irq_names = axp22x_irq_names;
} else {
@@ -360,6 +360,9 @@ static const struct of_device_id axp20x_usb_power_match[] = {
}, {
.compatible = "x-powers,axp221-usb-power-supply",
.data = (void *)AXP221_ID,
+ }, {
+ .compatible = "x-powers,axp223-usb-power-supply",
+ .data = (void *)AXP223_ID,
}, { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, axp20x_usb_power_match);
--
2.9.3
^ permalink raw reply related
* [PATCH v2 06/11] mfd: axp20x: add separate MFD cell for AXP223
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
The AXP223 shares most of its logic with the AXP221 but has some
differences for the VBUS power supply driver. Thus, to probe the driver
with the correct compatible, the AXP221 and the AXP223 now have separate
MFD cells.
AXP221 MFD cells are renamed from axp22x_cells to axp221_cells to avoid
confusion.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
v2:
- correct indentation,
- renaming axp22x_cells to axp221_cells to avoid confusion between axp22x,
axp221 and axp223
drivers/mfd/axp20x.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 6ee2cc6..b31f123 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -591,7 +591,22 @@ static struct mfd_cell axp20x_cells[] = {
},
};
-static struct mfd_cell axp22x_cells[] = {
+static struct mfd_cell axp221_cells[] = {
+ {
+ .name = "axp20x-pek",
+ .num_resources = ARRAY_SIZE(axp22x_pek_resources),
+ .resources = axp22x_pek_resources,
+ }, {
+ .name = "axp20x-regulator",
+ }, {
+ .name = "axp20x-usb-power-supply",
+ .of_compatible = "x-powers,axp221-usb-power-supply",
+ .num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources),
+ .resources = axp22x_usb_power_supply_resources,
+ },
+};
+
+static struct mfd_cell axp223_cells[] = {
{
.name = "axp20x-pek",
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
@@ -600,7 +615,7 @@ static struct mfd_cell axp22x_cells[] = {
.name = "axp20x-regulator",
}, {
.name = "axp20x-usb-power-supply",
- .of_compatible = "x-powers,axp221-usb-power-supply",
+ .of_compatible = "x-powers,axp223-usb-power-supply",
.num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources),
.resources = axp22x_usb_power_supply_resources,
},
@@ -793,9 +808,14 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
break;
case AXP221_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp221_cells);
+ axp20x->cells = axp221_cells;
+ axp20x->regmap_cfg = &axp22x_regmap_config;
+ axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip;
+ break;
case AXP223_ID:
- axp20x->nr_cells = ARRAY_SIZE(axp22x_cells);
- axp20x->cells = axp22x_cells;
+ axp20x->nr_cells = ARRAY_SIZE(axp223_cells);
+ axp20x->cells = axp223_cells;
axp20x->regmap_cfg = &axp22x_regmap_config;
axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip;
break;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 07/11] ARM: dtsi: add DTSI for AXP223
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
The AXP223 shares most of its logic with the AXP221 but it has some
differences for the VBUS driver.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
v2:
- adding small explanation of AXP223 variation compared to AXP221,
arch/arm/boot/dts/axp223.dtsi | 58 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 arch/arm/boot/dts/axp223.dtsi
diff --git a/arch/arm/boot/dts/axp223.dtsi b/arch/arm/boot/dts/axp223.dtsi
new file mode 100644
index 0000000..b91b6c1
--- /dev/null
+++ b/arch/arm/boot/dts/axp223.dtsi
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 Free Electrons
+ *
+ * Quentin Schulz <quentin.schulz@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * AXP223 Integrated Power Management Chip
+ * http://www.x-powers.com/product/AXP22X.php
+ * http://dl.linux-sunxi.org/AXP/AXP223-en.pdf
+ *
+ * The AXP223 shares most of its logic with the AXP221 but it has some
+ * differences, for the VBUS driver for example.
+ */
+
+#include "axp22x.dtsi"
+
+&usb_power_supply {
+ compatible = "x-powers,axp223-usb-power-supply";
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 08/11] ARM: dts: sun8i-a33-olinuxino: use AXP223 DTSI
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
Previously, the Olimex A33-OlinuXino used everything declared in AXP221
DTSI while it has an AXP223 PMIC.
This corrects that so the Olimex A33-OlinuXino can get some features the
AXP223 has (at the moment, ability to have 100mA as maximal current on
VBUS power supply).
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-a33-olinuxino.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/sun8i-a33-olinuxino.dts b/arch/arm/boot/dts/sun8i-a33-olinuxino.dts
index 9ea637e..3e8f2ec 100644
--- a/arch/arm/boot/dts/sun8i-a33-olinuxino.dts
+++ b/arch/arm/boot/dts/sun8i-a33-olinuxino.dts
@@ -126,7 +126,7 @@
};
};
-#include "axp22x.dtsi"
+#include "axp223.dtsi"
®_aldo1 {
regulator-always-on;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 09/11] ARM: dts: sun8i-a33-sinlinx-sina33: use AXP223 DTSI
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
Previously, the Sinlinx SinA33 used everything declared in AXP221 DTSI
while it has an AXP223 PMIC.
This corrects that so the Sinlinx SinA33 can get some features the
AXP223 has (at the moment, ability to have 100mA as maximal current on
VBUS power supply).
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts b/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
index fef6abc..1fc459c 100644
--- a/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
+++ b/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
@@ -145,7 +145,7 @@
};
};
-#include "axp22x.dtsi"
+#include "axp223.dtsi"
®_aldo1 {
regulator-always-on;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 10/11] ARM: dts: sun8i-r16-parrot: use AXP223 DTSI
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
Previously, the Allwinner Parrot R16 used everything declared in AXP221
DTSI while it has an AXP223 PMIC.
This corrects that so the Allwinner Parrot R16 can get some features the
AXP223 has (at the moment, ability to have 100mA as maximal current on
VBUS power supply).
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-r16-parrot.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/sun8i-r16-parrot.dts b/arch/arm/boot/dts/sun8i-r16-parrot.dts
index 47553e5..6afdba3 100644
--- a/arch/arm/boot/dts/sun8i-r16-parrot.dts
+++ b/arch/arm/boot/dts/sun8i-r16-parrot.dts
@@ -209,7 +209,7 @@
};
};
-#include "axp22x.dtsi"
+#include "axp223.dtsi"
®_aldo1 {
regulator-always-on;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 11/11] ARM: dtsi: sun8i-reference-design-tablet: use AXP223 DTSI
From: Quentin Schulz @ 2016-12-09 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209110419.28981-1-quentin.schulz@free-electrons.com>
Previously, the sun8i tablets used everything declared in AXP221 DTSI
while they have an AXP223 PMIC.
This corrects that so the sun8i tablets can get some features the AXP223
has (at the moment, ability to have 100mA as maximal current on VBUS
power supply).
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
index 08cd001..ea79c33 100644
--- a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
+++ b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
@@ -136,7 +136,7 @@
};
};
-#include "axp22x.dtsi"
+#include "axp223.dtsi"
®_aldo1 {
regulator-always-on;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 1/2] mfd: axp20x: Add address extension registers for AXP806 regmap
From: Lee Jones @ 2016-12-09 11:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161123031616.10114-2-wens@csie.org>
On Wed, 23 Nov 2016, Chen-Yu Tsai wrote:
> The AXP806 supports either master/standalone or slave mode.
> Slave mode allows sharing the serial bus, even with multiple
> AXP806 which all have the same hardware address.
>
> This is done with extra "serial interface address extension",
> or AXP806_BUS_ADDR_EXT, and "register address extension", or
> AXP806_REG_ADDR_EXT, registers. The former is read-only, with
> 1 bit customizable at the factory, and 1 bit depending on the
> state of an external pin. The latter is writable. Only when
> the these device addressing bits (in the upper 4 bits of the
> registers) match, will the device respond to operations on
> its other registers.
>
> Add these 2 registers to the regmap so we can access them.
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
> drivers/mfd/axp20x.c | 3 ++-
> include/linux/mfd/axp20x.h | 2 ++
> 2 files changed, 4 insertions(+), 1 deletion(-)
Applied for v4.11, thanks.
> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index ba130be32e61..cdaeb34a9a38 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -135,6 +135,7 @@ static const struct regmap_range axp806_writeable_ranges[] = {
> regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
> regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ2_EN),
> regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
> + regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT),
> };
>
> static const struct regmap_range axp806_volatile_ranges[] = {
> @@ -305,7 +306,7 @@ static const struct regmap_config axp806_regmap_config = {
> .val_bits = 8,
> .wr_table = &axp806_writeable_table,
> .volatile_table = &axp806_volatile_table,
> - .max_register = AXP806_VREF_TEMP_WARN_L,
> + .max_register = AXP806_REG_ADDR_EXT,
> .cache_type = REGCACHE_RBTREE,
> };
>
> diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
> index fec597fb34cb..7e85ececcedf 100644
> --- a/include/linux/mfd/axp20x.h
> +++ b/include/linux/mfd/axp20x.h
> @@ -115,6 +115,8 @@ enum {
> #define AXP806_CLDO2_V_CTRL 0x25
> #define AXP806_CLDO3_V_CTRL 0x26
> #define AXP806_VREF_TEMP_WARN_L 0xf3
> +#define AXP806_BUS_ADDR_EXT 0xfe
> +#define AXP806_REG_ADDR_EXT 0xff
>
> /* Interrupt */
> #define AXP152_IRQ1_EN 0x40
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH v2 2/2] mfd: axp20x: Fix AXP806 access errors on cold boot
From: Lee Jones @ 2016-12-09 11:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161123031616.10114-3-wens@csie.org>
Mark,
Is the following valid/necessary?
On Wed, 23 Nov 2016, Chen-Yu Tsai wrote:
> The AXP806 supports either master/standalone or slave mode.
> Slave mode allows sharing the serial bus, even with multiple
> AXP806 which all have the same hardware address.
>
> This is done with extra "serial interface address extension",
> or AXP806_BUS_ADDR_EXT, and "register address extension", or
> AXP806_REG_ADDR_EXT, registers. The former is read-only, with
> 1 bit customizable at the factory, and 1 bit depending on the
> state of an external pin. The latter is writable. Only when
> the these device addressing bits (in the upper 4 bits of the
> registers) match, will the device respond to operations on
> its other registers.
>
> The AXP806_REG_ADDR_EXT was previously configured by Allwinner's
> bootloader. Work on U-boot SPL support now allows us to switch
> to mainline U-boot, which doesn't do this for us. There might
> be other bare minimum bootloaders out there which don't to this
> either. It's best to handle this in the kernel.
>
> This patch sets AXP806_REG_ADDR_EXT to 0x10, which is what we
> know to be the proper value for a standard AXP806 in slave mode.
> Afterwards it will reinitialize the regmap cache, to purge any
> invalid stale values.
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
> drivers/mfd/axp20x.c | 38 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index cdaeb34a9a38..a0166c667656 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -31,6 +31,8 @@
>
> #define AXP20X_OFF 0x80
>
> +#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE BIT(4)
> +
> static const char * const axp20x_model_names[] = {
> "AXP152",
> "AXP202",
> @@ -829,6 +831,42 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
> {
> int ret;
>
> + /*
> + * The AXP806 supports either master/standalone or slave mode.
> + * Slave mode allows sharing the serial bus, even with multiple
> + * AXP806 which all have the same hardware address.
> + *
> + * This is done with extra "serial interface address extension",
> + * or AXP806_BUS_ADDR_EXT, and "register address extension", or
> + * AXP806_REG_ADDR_EXT, registers. The former is read-only, with
> + * 1 bit customizable at the factory, and 1 bit depending on the
> + * state of an external pin. The latter is writable. Only when
> + * the these device addressing bits (in the upper 4 bits of the
> + * registers) match, will the device respond to operations on its
> + * other registers.
> + *
> + * Since we only support an AXP806 chained to an AXP809 in slave
> + * mode, and there isn't any existing hardware which uses AXP806
> + * in master mode, or has 2 AXP806s in the same system, we can
> + * just program the register address extension to the slave mode
> + * address.
> + */
> + if (axp20x->variant == AXP806_ID) {
> + /* Write to the register address extension register */
> + regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
> + AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
> +
> + /* Make sure the write hits the device */
> + regcache_sync_region(axp20x->regmap, AXP806_REG_ADDR_EXT,
> + AXP806_REG_ADDR_EXT);
> +
> + /*
> + * Reinitialize the regmap cache in case the device didn't
> + * properly respond to our reads before.
> + */
> + regmap_reinit_cache(axp20x->regmap, axp20x->regmap_cfg);
> + }
> +
> ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
> IRQF_ONESHOT | IRQF_SHARED, -1,
> axp20x->regmap_irq_chip,
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH v2 1/8] mfd: sun6i-prcm: Add codec analog controls sub-device for Allwinner A23
From: Lee Jones @ 2016-12-09 11:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161125123442.28410-2-wens@csie.org>
On Fri, 25 Nov 2016, Chen-Yu Tsai wrote:
> The PRCM block on the A23 contains a message box like interface to
> the registers for the analog path controls of the internal codec.
>
> Add a sub-device for it.
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
> drivers/mfd/sun6i-prcm.c | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
Applied for v4.11, thanks.
> diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c
> index 011fcc555945..2b658bed47db 100644
> --- a/drivers/mfd/sun6i-prcm.c
> +++ b/drivers/mfd/sun6i-prcm.c
> @@ -12,6 +12,9 @@
> #include <linux/init.h>
> #include <linux/of.h>
>
> +#define SUN8I_CODEC_ANALOG_BASE 0x1c0
> +#define SUN8I_CODEC_ANALOG_SIZE 0x4
> +
> struct prcm_data {
> int nsubdevs;
> const struct mfd_cell *subdevs;
> @@ -57,6 +60,10 @@ static const struct resource sun6i_a31_apb0_rstc_res[] = {
> },
> };
>
> +static const struct resource sun8i_codec_analog_res[] = {
> + DEFINE_RES_MEM(SUN8I_CODEC_ANALOG_BASE, SUN8I_CODEC_ANALOG_SIZE),
> +};
> +
> static const struct mfd_cell sun6i_a31_prcm_subdevs[] = {
> {
> .name = "sun6i-a31-ar100-clk",
> @@ -109,6 +116,12 @@ static const struct mfd_cell sun8i_a23_prcm_subdevs[] = {
> .num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
> .resources = sun6i_a31_apb0_rstc_res,
> },
> + {
> + .name = "sun8i-codec-analog",
> + .of_compatible = "allwinner,sun8i-a23-codec-analog",
> + .num_resources = ARRAY_SIZE(sun8i_codec_analog_res),
> + .resources = sun8i_codec_analog_res,
> + },
> };
>
> static const struct prcm_data sun6i_a31_prcm_data = {
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Tearing down DMA transfer setup after DMA client has finished
From: Måns Rullgård @ 2016-12-09 11:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6ce1ea97-1d68-2203-c7b4-73315e801655@laposte.net>
Sebastian Frias <sf84@laposte.net> writes:
> On 09/12/16 07:59, Vinod Koul wrote:
>> On Thu, Dec 08, 2016 at 04:48:18PM +0000, M?ns Rullg?rd wrote:
>>> Vinod Koul <vinod.koul@intel.com> writes:
>>>
>>>> To make it efficient, disregarding your Sbox HW issue, the solution is
>>>> virtual channels. You can delink physical channels and virtual channels. If
>>>> one has SW controlled MUX then a channel can service any client. For few
>>>> controllers request lines are hard wired so they cant use any channel. But
>>>> if you dont have this restriction then driver can queue up many transactions
>>>> from different controllers.
>>>
>>> Have you been paying attention at all? This exactly what the driver
>>> ALREADY DOES.
>>
>> And have you read what the question was?
I wrote the driver. I think I know what Mason and I are asking.
> I think many people appreciate the quick turn around time and
> responsiveness of knowledgeable people making constructive remarks in
> this thread, but it looks we are slowly drifting away from the main
> problem.
>
> If we had to sum up the discussion, the current DMA API/framework in
> Linux seems to lack a way to properly handle this HW (or if it has a
> way, the information got lost somewhere).
>
> What concrete solution do you propose?
>
> Alternatively, one can think of the current issue (i.e.: the fact that
> the IRQ arrives "too soon") in a different way. Instead of thinking
> the IRQ indicates "transfer complete", it is indicating "ready to
> accept another command", which in practice (and with proper API
> support) can translate into efficient queuing of DMA operations.
For multiple back to back transfers to the same peripheral, it is indeed
a slight optimisation. What's apparently lacking is some way of doing a
full flush
--
M?ns Rullg?rd
^ permalink raw reply
* Tearing down DMA transfer setup after DMA client has finished
From: 1Måns Rullgård @ 2016-12-09 11:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6ce1ea97-1d68-2203-c7b4-73315e801655@laposte.net>
Sebastian Frias <sf84@laposte.net> writes:
> On 09/12/16 07:59, Vinod Koul wrote:
>> On Thu, Dec 08, 2016 at 04:48:18PM +0000, M?ns Rullg?rd wrote:
>>> Vinod Koul <vinod.koul@intel.com> writes:
>>>
>>>> To make it efficient, disregarding your Sbox HW issue, the solution is
>>>> virtual channels. You can delink physical channels and virtual channels. If
>>>> one has SW controlled MUX then a channel can service any client. For few
>>>> controllers request lines are hard wired so they cant use any channel. But
>>>> if you dont have this restriction then driver can queue up many transactions
>>>> from different controllers.
>>>
>>> Have you been paying attention at all? This exactly what the driver
>>> ALREADY DOES.
>>
>> And have you read what the question was?
I wrote the driver. I think I know what Mason and I are asking.
> I think many people appreciate the quick turn around time and
> responsiveness of knowledgeable people making constructive remarks in
> this thread, but it looks we are slowly drifting away from the main
> problem.
>
> If we had to sum up the discussion, the current DMA API/framework in
> Linux seems to lack a way to properly handle this HW (or if it has a
> way, the information got lost somewhere).
>
> What concrete solution do you propose?
>
> Alternatively, one can think of the current issue (i.e.: the fact that
> the IRQ arrives "too soon") in a different way. Instead of thinking
> the IRQ indicates "transfer complete", it is indicating "ready to
> accept another command", which in practice (and with proper API
> support) can translate into efficient queuing of DMA operations.
For multiple back to back transfers to the same peripheral, it is indeed
a slight optimisation. What's apparently lacking is some way of doing a
full flush at the end of a series of transfers, before switching the
channel to another device.
--
M?ns Rullg?rd
^ permalink raw reply
* [PATCH 02/12] ARM: dts: imx6qdl: rename ipu client nodes
From: Philipp Zabel @ 2016-12-09 11:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481158673-15937-3-git-send-email-steve_longerbeam@mentor.com>
Hi Steve,
Am Mittwoch, den 07.12.2016, 16:57 -0800 schrieb Steve Longerbeam:
> To allow for IPU client devices that are composed of more than one
> port for input and output (SMFC and IC), change the nodes from being
> a single port node to nodes that can contain multiple ports. Rename
> the nodes to use the following format: "ipu<id>_<subunit>".
Don't do this. These are not IPU client device nodes, they are input and
output port nodes according to the of graph bindings, as described in
Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt.
They happen to match to the CSI0/1 and DI0/1 modules, but really what is
described here are the external connections of the IPU. The IPU
internals are not described in the device tree at all.
regards
Philipp
> The IPUv3 driver will then need to lookup the client nodes by name
> rather than by port id.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> arch/arm/boot/dts/imx6q.dtsi | 12 ++++++------
> arch/arm/boot/dts/imx6qdl.dtsi | 12 ++++++------
> 2 files changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
> index e9a5d0b..2b261ba 100644
> --- a/arch/arm/boot/dts/imx6q.dtsi
> +++ b/arch/arm/boot/dts/imx6q.dtsi
> @@ -141,18 +141,18 @@
> clock-names = "bus", "di0", "di1";
> resets = <&src 4>;
>
> - ipu2_csi0: port at 0 {
> + ipu2_csi0: ipu2_csi at 0 {
> reg = <0>;
> };
>
> - ipu2_csi1: port at 1 {
> + ipu2_csi1: ipu2_csi at 1 {
> reg = <1>;
> };
>
> - ipu2_di0: port at 2 {
> + ipu2_di0: ipu2_di at 0 {
> #address-cells = <1>;
> #size-cells = <0>;
> - reg = <2>;
> + reg = <0>;
>
> ipu2_di0_disp0: disp0-endpoint {
> };
> @@ -174,10 +174,10 @@
> };
> };
>
> - ipu2_di1: port at 3 {
> + ipu2_di1: ipu2_di at 1 {
> #address-cells = <1>;
> #size-cells = <0>;
> - reg = <3>;
> + reg = <1>;
>
> ipu2_di1_hdmi: hdmi-endpoint {
> remote-endpoint = <&hdmi_mux_3>;
> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
> index e01e5d5..2465187 100644
> --- a/arch/arm/boot/dts/imx6qdl.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
> @@ -1226,18 +1226,18 @@
> clock-names = "bus", "di0", "di1";
> resets = <&src 2>;
>
> - ipu1_csi0: port at 0 {
> + ipu1_csi0: ipu1_csi at 0 {
> reg = <0>;
> };
>
> - ipu1_csi1: port at 1 {
> + ipu1_csi1: ipu1_csi at 1 {
> reg = <1>;
> };
>
> - ipu1_di0: port at 2 {
> + ipu1_di0: ipu1_di at 0 {
> #address-cells = <1>;
> #size-cells = <0>;
> - reg = <2>;
> + reg = <0>;
>
> ipu1_di0_disp0: disp0-endpoint {
> };
> @@ -1259,10 +1259,10 @@
> };
> };
>
> - ipu1_di1: port at 3 {
> + ipu1_di1: ipu1_di at 1 {
> #address-cells = <1>;
> #size-cells = <0>;
> - reg = <3>;
> + reg = <1>;
>
> ipu1_di1_disp1: disp1-endpoint {
> };
^ permalink raw reply
* [PATCH v8 01/16] FDT: introduce global phandle allocation
From: Marc Zyngier @ 2016-12-09 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-2-andre.przywara@arm.com>
Hi Andre,
On 04/11/16 17:31, Andre Przywara wrote:
> Allocating an FDT phandle (a unique identifier) using a static
> variable in a static inline function defined in a header file works
> only if all users are in the same source file. So trying to allocate
> a handle from two different compilation units fails.
> Introduce global phandle allocation and reference code to properly
> allocate unique phandles.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> Makefile | 1 +
> arm/fdt.c | 2 +-
> arm/gic.c | 2 +-
> include/kvm/fdt.h | 10 +++++-----
> kvm-fdt.c | 26 ++++++++++++++++++++++++++
> 5 files changed, 34 insertions(+), 7 deletions(-)
> create mode 100644 kvm-fdt.c
>
> diff --git a/Makefile b/Makefile
> index 1f0196f..e4a4002 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -98,6 +98,7 @@ OBJS += kvm-ipc.o
> OBJS += builtin-sandbox.o
> OBJS += virtio/mmio.o
> OBJS += hw/i8042.o
> +OBJS += kvm-fdt.o
>
> # Translate uname -m into ARCH string
> ARCH ?= $(shell uname -m | sed -e s/i.86/i386/ -e s/ppc.*/powerpc/ \
> diff --git a/arm/fdt.c b/arm/fdt.c
> index 381d48f..8bcfffb 100644
> --- a/arm/fdt.c
> +++ b/arm/fdt.c
> @@ -114,7 +114,7 @@ static int setup_fdt(struct kvm *kvm)
> {
> struct device_header *dev_hdr;
> u8 staging_fdt[FDT_MAX_SIZE];
> - u32 gic_phandle = fdt__alloc_phandle();
> + u32 gic_phandle = fdt__get_phandle(PHANDLE_GIC);
> u64 mem_reg_prop[] = {
> cpu_to_fdt64(kvm->arch.memory_guest_start),
> cpu_to_fdt64(kvm->ram_size),
> diff --git a/arm/gic.c b/arm/gic.c
> index d6d6dd0..b60437e 100644
> --- a/arm/gic.c
> +++ b/arm/gic.c
> @@ -222,7 +222,7 @@ void gic__generate_fdt_nodes(void *fdt, u32 phandle, enum irqchip_type type)
> _FDT(fdt_property_cell(fdt, "#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS));
> _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
> _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
> - _FDT(fdt_property_cell(fdt, "phandle", phandle));
> + _FDT(fdt_property_cell(fdt, "phandle", fdt__get_phandle(PHANDLE_GIC)));
> _FDT(fdt_end_node(fdt));
> }
>
> diff --git a/include/kvm/fdt.h b/include/kvm/fdt.h
> index 53d85a4..cd2bb72 100644
> --- a/include/kvm/fdt.h
> +++ b/include/kvm/fdt.h
> @@ -8,6 +8,10 @@
> #include <linux/types.h>
>
> #define FDT_MAX_SIZE 0x10000
> +#define FDT_INVALID_PHANDLE 0
> +#define FDT_IS_VALID_PHANDLE(phandle) ((phandle) != FDT_INVALID_PHANDLE)
> +
> +enum phandles {PHANDLE_GIC, PHANDLES_MAX};
>
> /* Those definitions are generic FDT values for specifying IRQ
> * types and are used in the Linux kernel internally as well as in
> @@ -33,10 +37,6 @@ enum irq_type {
> } \
> } while (0)
>
> -static inline u32 fdt__alloc_phandle(void)
> -{
> - static u32 phandle = 0;
> - return ++phandle;
> -}
> +u32 fdt__get_phandle(enum phandles phandle);
>
> #endif /* KVM__FDT_H */
> diff --git a/kvm-fdt.c b/kvm-fdt.c
> new file mode 100644
> index 0000000..d05f3fe
> --- /dev/null
> +++ b/kvm-fdt.c
> @@ -0,0 +1,26 @@
> +/*
> + * Commonly used FDT functions.
> + */
> +
> +#include <stdio.h>
> +#include "kvm/fdt.h"
> +#include "kvm/util.h"
> +
> +u32 phandles[PHANDLES_MAX] = {};
It is a bit weird that you're initializing this to zero...
> +u32 next_phandle = 1;
> +
> +u32 fdt__get_phandle(enum phandles phandle)
> +{
> + u32 ret;
> +
> + if (phandle >= PHANDLES_MAX)
> + return FDT_INVALID_PHANDLE;
> +
> + ret = phandles[phandle];
> + if (ret == FDT_INVALID_PHANDLE) {
and yet test against a #define that isn't the initializer.
Also, given that fdt__get_phandle() can now fail by returning
FDT_INVALID_HANDLE, maybe we should abort instead of returning something
that is definitely wrong and use it blindly (which is going to be fun to
debug...).
> + ret = next_phandle++;
> + phandles[phandle] = ret;
> + }
> +
> + return ret;
> +}
>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v8 01/16] FDT: introduce global phandle allocation
From: Marc Zyngier @ 2016-12-09 12:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-2-andre.przywara@arm.com>
On 04/11/16 17:31, Andre Przywara wrote:
> Allocating an FDT phandle (a unique identifier) using a static
> variable in a static inline function defined in a header file works
> only if all users are in the same source file. So trying to allocate
> a handle from two different compilation units fails.
> Introduce global phandle allocation and reference code to properly
> allocate unique phandles.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> Makefile | 1 +
> arm/fdt.c | 2 +-
> arm/gic.c | 2 +-
> include/kvm/fdt.h | 10 +++++-----
> kvm-fdt.c | 26 ++++++++++++++++++++++++++
> 5 files changed, 34 insertions(+), 7 deletions(-)
> create mode 100644 kvm-fdt.c
>
> diff --git a/Makefile b/Makefile
> index 1f0196f..e4a4002 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -98,6 +98,7 @@ OBJS += kvm-ipc.o
> OBJS += builtin-sandbox.o
> OBJS += virtio/mmio.o
> OBJS += hw/i8042.o
> +OBJS += kvm-fdt.o
>
> # Translate uname -m into ARCH string
> ARCH ?= $(shell uname -m | sed -e s/i.86/i386/ -e s/ppc.*/powerpc/ \
> diff --git a/arm/fdt.c b/arm/fdt.c
> index 381d48f..8bcfffb 100644
> --- a/arm/fdt.c
> +++ b/arm/fdt.c
> @@ -114,7 +114,7 @@ static int setup_fdt(struct kvm *kvm)
> {
> struct device_header *dev_hdr;
> u8 staging_fdt[FDT_MAX_SIZE];
> - u32 gic_phandle = fdt__alloc_phandle();
> + u32 gic_phandle = fdt__get_phandle(PHANDLE_GIC);
> u64 mem_reg_prop[] = {
> cpu_to_fdt64(kvm->arch.memory_guest_start),
> cpu_to_fdt64(kvm->ram_size),
> diff --git a/arm/gic.c b/arm/gic.c
> index d6d6dd0..b60437e 100644
> --- a/arm/gic.c
> +++ b/arm/gic.c
> @@ -222,7 +222,7 @@ void gic__generate_fdt_nodes(void *fdt, u32 phandle, enum irqchip_type type)
> _FDT(fdt_property_cell(fdt, "#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS));
> _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
> _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
> - _FDT(fdt_property_cell(fdt, "phandle", phandle));
> + _FDT(fdt_property_cell(fdt, "phandle", fdt__get_phandle(PHANDLE_GIC)));
> _FDT(fdt_end_node(fdt));
> }
>
> diff --git a/include/kvm/fdt.h b/include/kvm/fdt.h
> index 53d85a4..cd2bb72 100644
> --- a/include/kvm/fdt.h
> +++ b/include/kvm/fdt.h
> @@ -8,6 +8,10 @@
> #include <linux/types.h>
>
> #define FDT_MAX_SIZE 0x10000
> +#define FDT_INVALID_PHANDLE 0
> +#define FDT_IS_VALID_PHANDLE(phandle) ((phandle) != FDT_INVALID_PHANDLE)
> +
> +enum phandles {PHANDLE_GIC, PHANDLES_MAX};
Another nit here: PHANDLE_GIC is pretty much ARM-specific, while FDT is
supposed to be generic. Can't we move the enum to be architecture
specific and not put this in an architecture agnostic one?
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v2] arm64: mm: Fix memmap to be initialized for the entire section
From: Yisheng Xie @ 2016-12-09 12:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480530091-1092-1-git-send-email-rrichter@cavium.com>
Hi Robert,
We have merged your patch to 4.9.0-rc8, however we still meet the similar problem
on our D05 board:
Thanks,
Yisheng Xie
-----------------
[ 5.081971] ------------[ cut here ]------------
[ 5.086668] kernel BUG at mm/page_alloc.c:1863!
[ 5.091281] Internal error: Oops - BUG: 0 [#1] SMP
[ 5.096159] Modules linked in:
[ 5.099265] CPU: 61 PID: 1 Comm: swapper/0 Not tainted 4.9.0-rc8+ #58
[ 5.105822] Hardware name: Huawei Taishan 2280 /D05, BIOS Hisilicon D05 UEFI 16.08 RC1 12/08/2016
[ 5.114860] task: fffffe13f23d7400 task.stack: fffffe13f66f8000
[ 5.120903] PC is at move_freepages+0x170/0x180
[ 5.125514] LR is at move_freepages_block+0xa8/0xb8
[ 5.130479] pc : [<fffffc00081e9588>] lr : [<fffffc00081e9640>] pstate: 200000c5
[ 5.138008] sp : fffffe13f66fb910
[ 5.141375] x29: fffffe13f66fb910 x28: 00000000ffffff80
[ 5.146784] x27: fffffdff800b0000 x26: fffffe13fbf62b90
[ 5.152193] x25: 000000000000000a x24: fffffdff800b0020
[ 5.157598] x23: 0000000000000000 x22: fffffdff800b0000
[ 5.163006] x21: fffffdff800fffc0 x20: fffffe13fbf62680
[ 5.168412] x19: fffffdff80080000 x18: 000000004c4d6d26
[ 5.173820] x17: 0000000000000000 x16: 0000000000000000
[ 5.179226] x15: 000000005c589429 x14: 0000000000000000
[ 5.184634] x13: 0000000000000000 x12: 00000000fe2ce6e0
[ 5.190039] x11: 00000000bb5b525b x10: 00000000bb48417b
[ 5.195446] x9 : 0000000000000068 x8 : 0000000000000000
[ 5.200854] x7 : fffffe13fbff2680 x6 : 0000000000000001
[ 5.206260] x5 : fffffc0008e12328 x4 : 0000000000000000
[ 5.211667] x3 : fffffe13fbf62680 x2 : 0000000000000000
[ 5.217073] x1 : fffffe13fbff2680 x0 : fffffe13fbf62680
[...]
[ 5.768991] [<fffffc00081e9588>] move_freepages+0x170/0x180
[ 5.774664] [<fffffc00081e9640>] move_freepages_block+0xa8/0xb8
[ 5.780691] [<fffffc00081e9bbc>] __rmqueue+0x494/0x5f0
[ 5.785921] [<fffffc00081eb10c>] get_page_from_freelist+0x5ec/0xb58
[ 5.792302] [<fffffc00081ebc4c>] __alloc_pages_nodemask+0x144/0xd08
[ 5.798687] [<fffffc0008240514>] alloc_page_interleave+0x64/0xc0
[ 5.804801] [<fffffc0008240b20>] alloc_pages_current+0x108/0x168
[ 5.810920] [<fffffc0008c75410>] atomic_pool_init+0x78/0x1cc
[ 5.816680] [<fffffc0008c755a0>] arm64_dma_init+0x3c/0x44
[ 5.822180] [<fffffc0008082d94>] do_one_initcall+0x44/0x138
[ 5.827853] [<fffffc0008c70d54>] kernel_init_freeable+0x1ec/0x28c
[ 5.834060] [<fffffc00088a79f0>] kernel_init+0x18/0x110
[ 5.839378] [<fffffc0008082b30>] ret_from_fork+0x10/0x20
[ 5.844785] Code: 9108a021 9400afc5 d4210000 d503201f (d4210000)
[ 5.851024] ---[ end trace 3382df1ae82057db ]---
On 2016/12/1 2:21, Robert Richter wrote:
> On ThunderX systems with certain memory configurations we see the
> following BUG_ON():
>
> kernel BUG at mm/page_alloc.c:1848!
>
> This happens for some configs with 64k page size enabled. The BUG_ON()
> checks if start and end page of a memmap range belongs to the same
> zone.
>
> The BUG_ON() check fails if a memory zone contains NOMAP regions. In
> this case the node information of those pages is not initialized. This
> causes an inconsistency of the page links with wrong zone and node
> information for that pages. NOMAP pages from node 1 still point to the
> mem zone from node 0 and have the wrong nid assigned.
>
> The reason for the mis-configuration is a change in pfn_valid() which
> reports pages marked NOMAP as invalid:
>
> 68709f45385a arm64: only consider memblocks with NOMAP cleared for linear mapping
>
> This causes pages marked as nomap being no long reassigned to the new
> zone in memmap_init_zone() by calling __init_single_pfn().
>
> Fixing this by restoring the old behavior of pfn_valid() to use
> memblock_is_memory(). Also changing users of pfn_valid() in arm64 code
> to use memblock_is_map_memory() where necessary. This only affects
> code in ioremap.c. The code in mmu.c still can use the new version of
> pfn_valid().
>
> As a consequence, pfn_valid() can not be used to check if a physical
> page is RAM. It just checks if there is an underlying memmap with a
> valid struct page. Moreover, for performance reasons the whole memmap
> (with pageblock_nr_pages number of pages) has valid pfns (SPARSEMEM
> config). The memory range is extended to fit the alignment of the
> memmap. Thus, pfn_valid() may return true for pfns that do not map to
> physical memory. Those pages are simply not reported to the mm, they
> are not marked reserved nor added to the list of free pages. Other
> functions such a page_is_ram() or memblock_is_map_ memory() must be
> used to check for memory and if the page can be mapped with the linear
> mapping.
>
> Since NOMAP mem ranges may need to be mapped with different mem
> attributes (e.g. read-only or non-caching) we can not use linear
> mapping here. The use of memblock_is_memory() in pfn_valid() may not
> break this behaviour. Since commit:
>
> e7cd190385d1 arm64: mark reserved memblock regions explicitly in iomem
>
> NOMAP mem resources are no longer marked as system RAM (IORESOURCE_
> SYSTEM_RAM). Now page_is_ram() and region_intersects() (see
> memremap()) do not detect NOMAP mem as system ram and NOMAP mem is not
> added to the linear mapping as system RAM is.
>
> v2:
>
> * Added Ack
> * updated description to reflect the discussion
>
> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Signed-off-by: Robert Richter <rrichter@cavium.com>
> ---
> arch/arm64/mm/init.c | 2 +-
> arch/arm64/mm/ioremap.c | 5 +++--
> 2 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> index 212c4d1e2f26..166911f4a2e6 100644
> --- a/arch/arm64/mm/init.c
> +++ b/arch/arm64/mm/init.c
> @@ -147,7 +147,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
> #ifdef CONFIG_HAVE_ARCH_PFN_VALID
> int pfn_valid(unsigned long pfn)
> {
> - return memblock_is_map_memory(pfn << PAGE_SHIFT);
> + return memblock_is_memory(pfn << PAGE_SHIFT);
> }
> EXPORT_SYMBOL(pfn_valid);
> #endif
> diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
> index 01e88c8bcab0..c17c220b0c48 100644
> --- a/arch/arm64/mm/ioremap.c
> +++ b/arch/arm64/mm/ioremap.c
> @@ -21,6 +21,7 @@
> */
>
> #include <linux/export.h>
> +#include <linux/memblock.h>
> #include <linux/mm.h>
> #include <linux/vmalloc.h>
> #include <linux/io.h>
> @@ -55,7 +56,7 @@ static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
> /*
> * Don't allow RAM to be mapped.
> */
> - if (WARN_ON(pfn_valid(__phys_to_pfn(phys_addr))))
> + if (WARN_ON(memblock_is_map_memory(phys_addr)))
> return NULL;
>
> area = get_vm_area_caller(size, VM_IOREMAP, caller);
> @@ -96,7 +97,7 @@ EXPORT_SYMBOL(__iounmap);
> void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
> {
> /* For normal memory we already have a cacheable mapping. */
> - if (pfn_valid(__phys_to_pfn(phys_addr)))
> + if (memblock_is_map_memory(phys_addr))
> return (void __iomem *)__phys_to_virt(phys_addr);
>
> return __ioremap_caller(phys_addr, size, __pgprot(PROT_NORMAL),
>
^ permalink raw reply
* [PATCH v2] arm64: mm: Fix memmap to be initialized for the entire section
From: Ard Biesheuvel @ 2016-12-09 12:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <bc099ca6-d927-3eb6-438c-291a66ecf5f9@huawei.com>
On 9 December 2016 at 12:14, Yisheng Xie <xieyisheng1@huawei.com> wrote:
> Hi Robert,
> We have merged your patch to 4.9.0-rc8, however we still meet the similar problem
> on our D05 board:
>
To be clear: does this issue also occur on D05 *without* the patch?
> -----------------
> [ 5.081971] ------------[ cut here ]------------
> [ 5.086668] kernel BUG at mm/page_alloc.c:1863!
> [ 5.091281] Internal error: Oops - BUG: 0 [#1] SMP
> [ 5.096159] Modules linked in:
> [ 5.099265] CPU: 61 PID: 1 Comm: swapper/0 Not tainted 4.9.0-rc8+ #58
> [ 5.105822] Hardware name: Huawei Taishan 2280 /D05, BIOS Hisilicon D05 UEFI 16.08 RC1 12/08/2016
> [ 5.114860] task: fffffe13f23d7400 task.stack: fffffe13f66f8000
> [ 5.120903] PC is at move_freepages+0x170/0x180
> [ 5.125514] LR is at move_freepages_block+0xa8/0xb8
> [ 5.130479] pc : [<fffffc00081e9588>] lr : [<fffffc00081e9640>] pstate: 200000c5
> [ 5.138008] sp : fffffe13f66fb910
> [ 5.141375] x29: fffffe13f66fb910 x28: 00000000ffffff80
> [ 5.146784] x27: fffffdff800b0000 x26: fffffe13fbf62b90
> [ 5.152193] x25: 000000000000000a x24: fffffdff800b0020
> [ 5.157598] x23: 0000000000000000 x22: fffffdff800b0000
> [ 5.163006] x21: fffffdff800fffc0 x20: fffffe13fbf62680
> [ 5.168412] x19: fffffdff80080000 x18: 000000004c4d6d26
> [ 5.173820] x17: 0000000000000000 x16: 0000000000000000
> [ 5.179226] x15: 000000005c589429 x14: 0000000000000000
> [ 5.184634] x13: 0000000000000000 x12: 00000000fe2ce6e0
> [ 5.190039] x11: 00000000bb5b525b x10: 00000000bb48417b
> [ 5.195446] x9 : 0000000000000068 x8 : 0000000000000000
> [ 5.200854] x7 : fffffe13fbff2680 x6 : 0000000000000001
> [ 5.206260] x5 : fffffc0008e12328 x4 : 0000000000000000
> [ 5.211667] x3 : fffffe13fbf62680 x2 : 0000000000000000
> [ 5.217073] x1 : fffffe13fbff2680 x0 : fffffe13fbf62680
> [...]
> [ 5.768991] [<fffffc00081e9588>] move_freepages+0x170/0x180
> [ 5.774664] [<fffffc00081e9640>] move_freepages_block+0xa8/0xb8
> [ 5.780691] [<fffffc00081e9bbc>] __rmqueue+0x494/0x5f0
> [ 5.785921] [<fffffc00081eb10c>] get_page_from_freelist+0x5ec/0xb58
> [ 5.792302] [<fffffc00081ebc4c>] __alloc_pages_nodemask+0x144/0xd08
> [ 5.798687] [<fffffc0008240514>] alloc_page_interleave+0x64/0xc0
> [ 5.804801] [<fffffc0008240b20>] alloc_pages_current+0x108/0x168
> [ 5.810920] [<fffffc0008c75410>] atomic_pool_init+0x78/0x1cc
> [ 5.816680] [<fffffc0008c755a0>] arm64_dma_init+0x3c/0x44
> [ 5.822180] [<fffffc0008082d94>] do_one_initcall+0x44/0x138
> [ 5.827853] [<fffffc0008c70d54>] kernel_init_freeable+0x1ec/0x28c
> [ 5.834060] [<fffffc00088a79f0>] kernel_init+0x18/0x110
> [ 5.839378] [<fffffc0008082b30>] ret_from_fork+0x10/0x20
> [ 5.844785] Code: 9108a021 9400afc5 d4210000 d503201f (d4210000)
> [ 5.851024] ---[ end trace 3382df1ae82057db ]---
>
>
> On 2016/12/1 2:21, Robert Richter wrote:
>> On ThunderX systems with certain memory configurations we see the
>> following BUG_ON():
>>
>> kernel BUG at mm/page_alloc.c:1848!
>>
>> This happens for some configs with 64k page size enabled. The BUG_ON()
>> checks if start and end page of a memmap range belongs to the same
>> zone.
>>
>> The BUG_ON() check fails if a memory zone contains NOMAP regions. In
>> this case the node information of those pages is not initialized. This
>> causes an inconsistency of the page links with wrong zone and node
>> information for that pages. NOMAP pages from node 1 still point to the
>> mem zone from node 0 and have the wrong nid assigned.
>>
>> The reason for the mis-configuration is a change in pfn_valid() which
>> reports pages marked NOMAP as invalid:
>>
>> 68709f45385a arm64: only consider memblocks with NOMAP cleared for linear mapping
>>
>> This causes pages marked as nomap being no long reassigned to the new
>> zone in memmap_init_zone() by calling __init_single_pfn().
>>
>> Fixing this by restoring the old behavior of pfn_valid() to use
>> memblock_is_memory(). Also changing users of pfn_valid() in arm64 code
>> to use memblock_is_map_memory() where necessary. This only affects
>> code in ioremap.c. The code in mmu.c still can use the new version of
>> pfn_valid().
>>
>> As a consequence, pfn_valid() can not be used to check if a physical
>> page is RAM. It just checks if there is an underlying memmap with a
>> valid struct page. Moreover, for performance reasons the whole memmap
>> (with pageblock_nr_pages number of pages) has valid pfns (SPARSEMEM
>> config). The memory range is extended to fit the alignment of the
>> memmap. Thus, pfn_valid() may return true for pfns that do not map to
>> physical memory. Those pages are simply not reported to the mm, they
>> are not marked reserved nor added to the list of free pages. Other
>> functions such a page_is_ram() or memblock_is_map_ memory() must be
>> used to check for memory and if the page can be mapped with the linear
>> mapping.
>>
>> Since NOMAP mem ranges may need to be mapped with different mem
>> attributes (e.g. read-only or non-caching) we can not use linear
>> mapping here. The use of memblock_is_memory() in pfn_valid() may not
>> break this behaviour. Since commit:
>>
>> e7cd190385d1 arm64: mark reserved memblock regions explicitly in iomem
>>
>> NOMAP mem resources are no longer marked as system RAM (IORESOURCE_
>> SYSTEM_RAM). Now page_is_ram() and region_intersects() (see
>> memremap()) do not detect NOMAP mem as system ram and NOMAP mem is not
>> added to the linear mapping as system RAM is.
>>
>> v2:
>>
>> * Added Ack
>> * updated description to reflect the discussion
>>
>> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Signed-off-by: Robert Richter <rrichter@cavium.com>
>> ---
>> arch/arm64/mm/init.c | 2 +-
>> arch/arm64/mm/ioremap.c | 5 +++--
>> 2 files changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
>> index 212c4d1e2f26..166911f4a2e6 100644
>> --- a/arch/arm64/mm/init.c
>> +++ b/arch/arm64/mm/init.c
>> @@ -147,7 +147,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
>> #ifdef CONFIG_HAVE_ARCH_PFN_VALID
>> int pfn_valid(unsigned long pfn)
>> {
>> - return memblock_is_map_memory(pfn << PAGE_SHIFT);
>> + return memblock_is_memory(pfn << PAGE_SHIFT);
>> }
>> EXPORT_SYMBOL(pfn_valid);
>> #endif
>> diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
>> index 01e88c8bcab0..c17c220b0c48 100644
>> --- a/arch/arm64/mm/ioremap.c
>> +++ b/arch/arm64/mm/ioremap.c
>> @@ -21,6 +21,7 @@
>> */
>>
>> #include <linux/export.h>
>> +#include <linux/memblock.h>
>> #include <linux/mm.h>
>> #include <linux/vmalloc.h>
>> #include <linux/io.h>
>> @@ -55,7 +56,7 @@ static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
>> /*
>> * Don't allow RAM to be mapped.
>> */
>> - if (WARN_ON(pfn_valid(__phys_to_pfn(phys_addr))))
>> + if (WARN_ON(memblock_is_map_memory(phys_addr)))
>> return NULL;
>>
>> area = get_vm_area_caller(size, VM_IOREMAP, caller);
>> @@ -96,7 +97,7 @@ EXPORT_SYMBOL(__iounmap);
>> void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
>> {
>> /* For normal memory we already have a cacheable mapping. */
>> - if (pfn_valid(__phys_to_pfn(phys_addr)))
>> + if (memblock_is_map_memory(phys_addr))
>> return (void __iomem *)__phys_to_virt(phys_addr);
>>
>> return __ioremap_caller(phys_addr, size, __pgprot(PROT_NORMAL),
>>
>
^ permalink raw reply
* [PATCH v3] arm64: fpsimd: improve stacking logic in non-interruptible context
From: Dave Martin @ 2016-12-09 12:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481215779-23432-1-git-send-email-ard.biesheuvel@linaro.org>
On Thu, Dec 08, 2016 at 04:49:39PM +0000, Ard Biesheuvel wrote:
> Currently, we allow kernel mode NEON in softirq or hardirq context by
> stacking and unstacking a slice of the NEON register file for each call
> to kernel_neon_begin() and kernel_neon_end(), respectively.
>
> Given that
> a) a CPU typically spends most of its time in userland, during which time
> no kernel mode NEON in process context is in progress,
> b) a CPU spends most of its time in the kernel doing other things than
> kernel mode NEON when it gets interrupted to perform kernel mode NEON
> in softirq context
>
> the stacking and subsequent unstacking is only necessary if we are
> interrupting a thread while it is performing kernel mode NEON in process
> context, which means that in all other cases, we can simply preserve the
> userland FPSIMD state once, and only restore it upon return to userland,
> even if we are being invoked from softirq or hardirq context.
>
> So instead of checking whether we are running in interrupt context, keep
> track of the level of nested kernel mode NEON calls in progress, and only
> perform the eager stack/unstack if the level exceeds 1.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> v3:
> - avoid corruption by concurrent invocations of kernel_neon_begin()/_end()
>
> v2:
> - BUG() on unexpected values of the nesting level
> - relax the BUG() on num_regs>32 to a WARN, given that nothing actually
> breaks in that case
>
> arch/arm64/kernel/fpsimd.c | 47 ++++++++++++++------
> 1 file changed, 33 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 394c61db5566..536ddab9316d 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -220,20 +220,35 @@ void fpsimd_flush_task_state(struct task_struct *t)
>
> #ifdef CONFIG_KERNEL_MODE_NEON
>
> -static DEFINE_PER_CPU(struct fpsimd_partial_state, hardirq_fpsimdstate);
> -static DEFINE_PER_CPU(struct fpsimd_partial_state, softirq_fpsimdstate);
> +/*
> + * Although unlikely, it is possible for three kernel mode NEON contexts to
> + * be live at the same time: process context, softirq context and hardirq
> + * context. So while the userland context is stashed in the thread's fpsimd
> + * state structure, we need two additional levels of storage.
> + */
> +static DEFINE_PER_CPU(struct fpsimd_partial_state, nested_fpsimdstate[2]);
> +static DEFINE_PER_CPU(atomic_t, kernel_neon_nesting_level);
Come to think of it, should we use this_cpu_{read,add}() etc?
I'm not sure why we need the barrier semantics of atomic_t ops here.
[...]
Cheers
---Dave
^ permalink raw reply
* [PATCH v2] arm64: mm: Fix memmap to be initialized for the entire section
From: Hanjun Guo @ 2016-12-09 12:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu_XsKU6godiQC7wVDmCUC9bZL=kv0RarTOTATuQ5EZp2Q@mail.gmail.com>
On 12/09/2016 08:19 PM, Ard Biesheuvel wrote:
> On 9 December 2016 at 12:14, Yisheng Xie <xieyisheng1@huawei.com> wrote:
>> Hi Robert,
>> We have merged your patch to 4.9.0-rc8, however we still meet the similar problem
>> on our D05 board:
>>
>
> To be clear: does this issue also occur on D05 *without* the patch?
It boots ok on D05 without this patch.
But I think the problem Robert described in the commit message is
still there, just not triggered in the boot. we met this problem
when having LTP stress memory test and hit the same BUG_ON.
Thanks
Hanjun
^ permalink raw reply
* [PATCH v3] arm64: fpsimd: improve stacking logic in non-interruptible context
From: Ard Biesheuvel @ 2016-12-09 12:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209122021.GA1574@e103592.cambridge.arm.com>
On 9 December 2016 at 12:20, Dave Martin <Dave.Martin@arm.com> wrote:
> On Thu, Dec 08, 2016 at 04:49:39PM +0000, Ard Biesheuvel wrote:
>> Currently, we allow kernel mode NEON in softirq or hardirq context by
>> stacking and unstacking a slice of the NEON register file for each call
>> to kernel_neon_begin() and kernel_neon_end(), respectively.
>>
>> Given that
>> a) a CPU typically spends most of its time in userland, during which time
>> no kernel mode NEON in process context is in progress,
>> b) a CPU spends most of its time in the kernel doing other things than
>> kernel mode NEON when it gets interrupted to perform kernel mode NEON
>> in softirq context
>>
>> the stacking and subsequent unstacking is only necessary if we are
>> interrupting a thread while it is performing kernel mode NEON in process
>> context, which means that in all other cases, we can simply preserve the
>> userland FPSIMD state once, and only restore it upon return to userland,
>> even if we are being invoked from softirq or hardirq context.
>>
>> So instead of checking whether we are running in interrupt context, keep
>> track of the level of nested kernel mode NEON calls in progress, and only
>> perform the eager stack/unstack if the level exceeds 1.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>> v3:
>> - avoid corruption by concurrent invocations of kernel_neon_begin()/_end()
>>
>> v2:
>> - BUG() on unexpected values of the nesting level
>> - relax the BUG() on num_regs>32 to a WARN, given that nothing actually
>> breaks in that case
>>
>> arch/arm64/kernel/fpsimd.c | 47 ++++++++++++++------
>> 1 file changed, 33 insertions(+), 14 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
>> index 394c61db5566..536ddab9316d 100644
>> --- a/arch/arm64/kernel/fpsimd.c
>> +++ b/arch/arm64/kernel/fpsimd.c
>> @@ -220,20 +220,35 @@ void fpsimd_flush_task_state(struct task_struct *t)
>>
>> #ifdef CONFIG_KERNEL_MODE_NEON
>>
>> -static DEFINE_PER_CPU(struct fpsimd_partial_state, hardirq_fpsimdstate);
>> -static DEFINE_PER_CPU(struct fpsimd_partial_state, softirq_fpsimdstate);
>> +/*
>> + * Although unlikely, it is possible for three kernel mode NEON contexts to
>> + * be live at the same time: process context, softirq context and hardirq
>> + * context. So while the userland context is stashed in the thread's fpsimd
>> + * state structure, we need two additional levels of storage.
>> + */
>> +static DEFINE_PER_CPU(struct fpsimd_partial_state, nested_fpsimdstate[2]);
>> +static DEFINE_PER_CPU(atomic_t, kernel_neon_nesting_level);
>
> Come to think of it, should we use this_cpu_{read,add}() etc?
>
I wasn't aware those existed ...
> I'm not sure why we need the barrier semantics of atomic_t ops here.
>
I don't think we do. We only need the atomic increment/decrement, afaict
^ permalink raw reply
* [PATCH v3] arm64: fpsimd: improve stacking logic in non-interruptible context
From: Dave Martin @ 2016-12-09 12:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu-P6ReNVVyyuwF8mE3S7U+X3uK6A=qKmmzU7vQy_SgXWQ@mail.gmail.com>
On Fri, Dec 09, 2016 at 12:24:03PM +0000, Ard Biesheuvel wrote:
> On 9 December 2016 at 12:20, Dave Martin <Dave.Martin@arm.com> wrote:
> > On Thu, Dec 08, 2016 at 04:49:39PM +0000, Ard Biesheuvel wrote:
> >> Currently, we allow kernel mode NEON in softirq or hardirq context by
> >> stacking and unstacking a slice of the NEON register file for each call
> >> to kernel_neon_begin() and kernel_neon_end(), respectively.
> >>
> >> Given that
> >> a) a CPU typically spends most of its time in userland, during which time
> >> no kernel mode NEON in process context is in progress,
> >> b) a CPU spends most of its time in the kernel doing other things than
> >> kernel mode NEON when it gets interrupted to perform kernel mode NEON
> >> in softirq context
> >>
> >> the stacking and subsequent unstacking is only necessary if we are
> >> interrupting a thread while it is performing kernel mode NEON in process
> >> context, which means that in all other cases, we can simply preserve the
> >> userland FPSIMD state once, and only restore it upon return to userland,
> >> even if we are being invoked from softirq or hardirq context.
> >>
> >> So instead of checking whether we are running in interrupt context, keep
> >> track of the level of nested kernel mode NEON calls in progress, and only
> >> perform the eager stack/unstack if the level exceeds 1.
> >>
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> ---
> >> v3:
> >> - avoid corruption by concurrent invocations of kernel_neon_begin()/_end()
> >>
> >> v2:
> >> - BUG() on unexpected values of the nesting level
> >> - relax the BUG() on num_regs>32 to a WARN, given that nothing actually
> >> breaks in that case
> >>
> >> arch/arm64/kernel/fpsimd.c | 47 ++++++++++++++------
> >> 1 file changed, 33 insertions(+), 14 deletions(-)
> >>
> >> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> >> index 394c61db5566..536ddab9316d 100644
> >> --- a/arch/arm64/kernel/fpsimd.c
> >> +++ b/arch/arm64/kernel/fpsimd.c
> >> @@ -220,20 +220,35 @@ void fpsimd_flush_task_state(struct task_struct *t)
[...]
> >> + * state structure, we need two additional levels of storage.
> >> + */
> >> +static DEFINE_PER_CPU(struct fpsimd_partial_state, nested_fpsimdstate[2]);
> >> +static DEFINE_PER_CPU(atomic_t, kernel_neon_nesting_level);
> >
> > Come to think of it, should we use this_cpu_{read,add}() etc?
> >
>
> I wasn't aware those existed ...
Actually, nor was I ... I asked Will about local atomics and he
suggested to use those ... then he remembered about the this_cpu_
variants.
The local atomic might still have some barrier semantics, apparently.
For arm64, they're just implemented using the non-local atomics anyway.
>
> > I'm not sure why we need the barrier semantics of atomic_t ops here.
> >
>
> I don't think we do. We only need the atomic increment/decrement, afaict
That's what I was thinking.
Otherwise, the patch looked reasonable to me, but I'll take another look
if you wanted to twiddle the atomics.
Cheers
---Dave
^ permalink raw reply
* [PATCH v5 1/7] MFD: add bindings for STM32 General Purpose Timer driver
From: Benjamin Gaignard @ 2016-12-09 12:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161209085331.GB3625@dell.home>
2016-12-09 9:53 GMT+01:00 Lee Jones <lee.jones@linaro.org>:
> Sorry to do this Ben. Not much to do now though!
>
>> Add bindings information for STM32 General Purpose Timer
>>
>> version 2:
>> - rename stm32-mfd-timer to stm32-gptimer
>> - only keep one compatible string
>>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
>> ---
>> .../bindings/mfd/stm32-general-purpose-timer.txt | 39 ++++++++++++++++++++++
>> 1 file changed, 39 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt b/Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt
>> new file mode 100644
>> index 0000000..ce67755
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt
>> @@ -0,0 +1,39 @@
>> +STM32 General Purpose Timer driver bindings
>
> This is a great place to describe what we're *actually* trying to
> achieve with this driver, and the worst place to use the term "general
> purpose", since this IP is so much more than that.
>
>
> "STM32 Timers
>
> This IP provides 3 types of timer along with PWM functionality.
>
> [...]"
>
> ... then go on to explain what the 3 types are and how they can be
> used.
>
>> +Required parameters:
>> +- compatible: must be "st,stm32-gptimer"
>
> I vehemently disagree that this entire IP is a GP Timer. It contains
> GP timers, sure, but it also contains Advanced and Basic timers.
>
> IMHO this compatible should be "st,stm32-timers".
>
> And the file name of both this and the *.c file should reflect that
> too.
I will do those name changes in v6.
>
> Remainder looks nice.
>
>> +- reg: Physical base address and length of the controller's
>> + registers.
>> +- clock-names: Set to "clk_int".
>> +- clocks: Phandle to the clock used by the timer module.
>> + For Clk properties, please refer to ../clock/clock-bindings.txt
>> +
>> +Optional parameters:
>> +- resets: Phandle to the parent reset controller.
>> + See ../reset/st,stm32-rcc.txt
>> +
>> +Optional subnodes:
>> +- pwm: See ../pwm/pwm-stm32.txt
>> +- timer: See ../iio/timer/stm32-timer-trigger.txt
>> +
>> +Example:
>> + timers at 40010000 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + compatible = "st,stm32-gptimer";
>> + reg = <0x40010000 0x400>;
>> + clocks = <&rcc 0 160>;
>> + clock-names = "clk_int";
>> +
>> + pwm at 0 {
>
> Out of interest, do you use the "@0", "@1" for anything now?
No I don't use them so I will remove them in v6
>
>> + compatible = "st,stm32-pwm";
>> + pinctrl-0 = <&pwm1_pins>;
>> + pinctrl-names = "default";
>> + };
>> +
>> + timer at 0 {
>> + compatible = "st,stm32-timer-trigger";
>> + reg = <0>;
>> + };
>> + };
>
> --
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org ? Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
--
Benjamin Gaignard
Graphic Study Group
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ 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