* [PATCH v1 2/2] arm64: dts: rockchip: Add PX5 Evaluation board
From: Andy Yan @ 2016-09-10 17:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473529249-6151-1-git-send-email-andy.yan@rock-chips.com>
PX5 EVB is designed by Rockchip for automotive field,
which intergrated with CVBS(TP2825)/MIPI DSI/CSI/LVDS
HDMI video input/output interface, audio codec ES8396,
WIFI/BT(on RTL8723BS), Gsensor BMA250E and light&proximity
sensor STK3410.
Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
---
Changes in v1:
- board rename
- add vendor prefix for i2c interfaced devices
Documentation/devicetree/bindings/arm/rockchip.txt | 4 +
arch/arm64/boot/dts/rockchip/Makefile | 1 +
arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts | 304 +++++++++++++++++++++
3 files changed, 309 insertions(+)
create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts
diff --git a/Documentation/devicetree/bindings/arm/rockchip.txt b/Documentation/devicetree/bindings/arm/rockchip.txt
index 6da3881..b6f92d6 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.txt
+++ b/Documentation/devicetree/bindings/arm/rockchip.txt
@@ -107,6 +107,10 @@ Rockchip platforms device tree bindings
Required root node properties:
- compatible = "rockchip,r88", "rockchip,rk3368";
+- Rockchip PX5 Evaluation board:
+ Required root node properties:
+ - compatible = "rockchip,px5-evb", "rockchip,px5", "rockchip,rk3368";
+
- Rockchip RK3228 Evaluation board:
Required root node properties:
- compatible = "rockchip,rk3228-evb", "rockchip,rk3228";
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index 7037a16..86c74b2 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -1,6 +1,7 @@
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-geekbox.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-r88.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-px5-evb.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-evb.dtb
always := $(dtb-y)
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts
new file mode 100644
index 0000000..be0e915
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "rk3368.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Rockchip PX5 EVB";
+ compatible = "rockchip,px5-evb", "rockchip,px5", "rockchip,rk3368";
+
+ chosen {
+ stdout-path = "serial4:115200n8";
+ };
+
+ memory at 0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x80000000>;
+ };
+
+ keys: gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwr_key>;
+
+ power {
+ gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+ label = "GPIO Power";
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+ };
+
+ vcc_sys: vcc-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&emmc {
+ status = "okay";
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ clock-frequency = <150000000>;
+ disable-wp;
+ keep-power-in-suspend;
+ non-removable;
+ num-slots = <1>;
+ vmmc-supply = <&vcc_io>;
+ vqmmc-supply = <&vcc18_flash>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_bus8>;
+};
+
+&i2c0 {
+ status = "okay";
+
+ rk808: pmic at 1b {
+ compatible = "rockchip,rk808";
+ reg = <0x1b>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int>, <&pmic_sleep>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+ rockchip,system-power-controller;
+ vcc1-supply = <&vcc_sys>;
+ vcc2-supply = <&vcc_sys>;
+ vcc3-supply = <&vcc_sys>;
+ vcc4-supply = <&vcc_sys>;
+ vcc6-supply = <&vcc_sys>;
+ vcc7-supply = <&vcc_sys>;
+ vcc8-supply = <&vcc_io>;
+ vcc9-supply = <&vcc_sys>;
+ vcc10-supply = <&vcc_sys>;
+ vcc11-supply = <&vcc_sys>;
+ vcc12-supply = <&vcc_io>;
+ clock-output-names = "xin32k", "rk808-clkout2";
+ #clock-cells = <1>;
+
+ regulators {
+ vdd_cpu: DCDC_REG1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-name = "vdd_cpu";
+ };
+
+ vdd_log: DCDC_REG2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-name = "vdd_log";
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vcc_ddr";
+ };
+
+ vcc_io: DCDC_REG4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc_io";
+ };
+
+ vcc18_flash: LDO_REG1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc18_flash";
+ };
+
+ vcca_33: LDO_REG2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcca_33";
+ };
+
+ vdd_10: LDO_REG3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-name = "vdd_10";
+ };
+
+ avdd_33: LDO_REG4 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "avdd_33";
+ };
+
+ vccio_sd: LDO_REG5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vccio_sd";
+ };
+
+ vdd10_lcd: LDO_REG6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-name = "vdd10_lcd";
+ };
+
+ vcc_18: LDO_REG7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc_18";
+ };
+
+ vcc18_lcd: LDO_REG8 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc18_lcd";
+ };
+
+ vcc_sd: SWITCH_REG1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vcc_sd";
+ };
+
+ vcc33_lcd: SWITCH_REG2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vcc33_lcd";
+ };
+ };
+ };
+};
+
+&i2c1 {
+ status = "okay";
+
+ /* Accelerometer */
+ bma250 at 18 {
+ compatible = "bosch,bma250";
+ reg = <0x18>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ stk3410 at 48 {
+ compatible = "sensortek,STK3310";
+ reg = <0x48>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ gsl1680: touchscreen at 40 {
+ compatible = "silead,gsl1680";
+ reg = <0x40>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
+ power-gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>;
+ touchscreen-size-x = <800>;
+ touchscreen-size-y = <1280>;
+ silead,max-fingers = <5>;
+ };
+};
+
+&pinctrl {
+
+ keys {
+ pwr_key: pwr-key {
+ rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_sleep: pmic-sleep {
+ rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
+ };
+
+ pmic_int: pmic-int {
+ rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+ rockchip,hw-tshut-mode = <0>; /* CRU */
+ rockchip,hw-tshut-polarity = <1>; /* high */
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_otg {
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
--
2.7.4
^ permalink raw reply related
* [linux-sunxi] Re: [RFC] misc: Add Allwinner Q8 tablet hardware manager
From: Hans de Goede @ 2016-09-10 18:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL_JsqLGS23JQxtdtUqNhkhDiV4mnKSBpMjdo4fx0=wuq_ydeg@mail.gmail.com>
Hi,
On 09-09-16 23:41, Rob Herring wrote:
> On Thu, Sep 1, 2016 at 2:08 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets
>> of which a new batch is produced every few weeks. Each batch uses a
>> different mix of touchscreen, accelerometer and wifi peripherals.
>>
>> Given that each batch is different creating a devicetree for each variant
>> is not desirable. This commit adds a Q8 tablet hardware manager which
>> auto-detects the touchscreen and accelerometer so that a single generic
>> dts can be used for these tablets.
>>
>> The wifi is connected to a discoverable bus (sdio or usb) and will be
>> autodetected by the mmc resp. usb subsystems.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>> .../misc/allwinner,sunxi-q8-hardwaremgr.txt | 52 +++
>> drivers/misc/Kconfig | 12 +
>> drivers/misc/Makefile | 1 +
>> drivers/misc/q8-hardwaremgr.c | 512 +++++++++++++++++++++
>> 4 files changed, 577 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
>> create mode 100644 drivers/misc/q8-hardwaremgr.c
>>
>> diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
>> new file mode 100644
>> index 0000000..f428bf5
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
>> @@ -0,0 +1,52 @@
>> +Q8 tablet hardware manager
>> +--------------------------
>> +
>> +Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets of
>> +which a new batch is produced every few weeks. Each batch uses a different
>> +mix of touchscreen, accelerometer and wifi peripherals.
>> +
>> +Given that each batch is different creating a devicetree for each variant is
>> +not desirable. The Q8 tablet hardware manager bindings are bindings for an os
>> +module which auto-detects the touchscreen so that a single
>> +generic dts can be used for these tablets.
>> +
>> +The wifi is connected to a discoverable bus and will be autodetected by the os.
>> +
>> +Required properties:
>> + - compatible : "allwinner,sunxi-q8-hardwaremgr"
>> + - touchscreen : phandle of a template touchscreen node, this must be a
>> + child node of the touchscreen i2c bus
>> +
>> +Optional properties:
>> + - touchscreen-supply : regulator phandle for the touchscreen vdd supply
>
> While I said I think you should be using overlays here, you could also
> do it without.
Good, because I believe that doing things without overlays will
be much easier. If you look at the actual implementation you will
see that it sets a lot of properties (touchscreen width, height,
inversion, axis-swapping, firmware-name) based on various sources,
the explosion of possible overlays from this is huge, and if
we're going to runtime patch the overlays then why use them at all
and not just runtime generate all the info ?
> However, this node has to go. It is not h/w, and you
> are putting it here purely to instantiate a driver.
With "this" in "this node has to go", do you mean the node
with the "allwinner,sunxi-q8-hardwaremgr" compatible, or
do you mean the touchscreen template node ?
> For the
> touchscreen property, surely you know where the touchscreen is located
> in the DT?
Nope q8 tablets come with A13, A23 or A33 SoCs, A23/A33 are pin
compatible with each other, but the A13 is not, this leads to
the touchscreen being on a different i2c bus, so I cannot hardcode
things, likewise the power-gpios and interrupt found in the
touchscreen node differ between the A13 vs A23/A33.
I actually had a touchscreen-i2c-bus property containing a
phandle to the i2c controller for the bus which has the
touchscreen in an earlier revision + touchscreen-gpios
and touchscreen-supply properties, I can switch to that
if you prefer that over having a touchscreen template node.
> If not, of_find_node_by_name()?
Still a bit confused about what you do not like,
(touchscreen template node vs q8-hardwaremgr node).
I guess (based on context) you do not want the
q8-hardwaremgr node ?
So the q8-hardwaremgr code should activate based on
the machine compatible I presume? How does that
work with module autoloading ?
If you do not want the q8-hardwaremgr node and thus
no touchscreen property them yes I can use
of_find_node_by_name(), but I thought that was
generally frowned up on?
> For touchscreen-supply, I
> assume this is to turn on the supply so you can talk to the touch
> controller. There's no reason the supply can't just be in the
> touchscreen node itself.
Only a few q8 tablets actually use the regulator, so
the hardwaremgr first tries detecting the touchscreen
without it, and only if it does not find anything then
tries with it, and adds a property to the touchscreen
node for it, but I guess I can do this other way
around and have it be present in the (incomplete /
template) touchscreen node and delete it from it if
not necessary.
That + using of_find_node_by_name() should indeed allow
me to remove the q8-hardwaremgr node. Assuming there is
an answer to the module auto loading, as I expect most
distros to build this as a module.
Regards,
Hans
>
>> +
>> +touschreen node required properties:
>> + - interrupt-parent : phandle pointing to the interrupt controller
>> + serving the touchscreen interrupt
>> + - interrupts : interrupt specification for the touchscreen interrupt
>> + - power-gpios : Specification for the pin connected to the touchscreen's
>> + enable / wake pin. This needs to be driven high to
>> + enable the touchscreen controller
>> +
>> +Example:
>> +
>> +/ {
>> + hwmgr {
>> + compatible = "allwinner,sunxi-q8-hardwaremgr";
>> + touchscreen = <&touchscreen>;
>> + touchscreen-supply = <®_ldo_io1>;
>> + };
>> +};
>> +
>> +&i2c0 {
>> + touchscreen: touchscreen at 0 {
>> + interrupt-parent = <&pio>;
>> + interrupts = <1 5 IRQ_TYPE_EDGE_FALLING>; /* PB5 */
>> + power-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>> + /*
>> + * Enabled by sunxi-q8-hardwaremgr if it detects a
>> + * known model touchscreen.
>> + */
>> + status = "disabled";
>> + };
>> +};
^ permalink raw reply
* [linux-sunxi] Re: [RFC] misc: Add Allwinner Q8 tablet hardware manager
From: Hans de Goede @ 2016-09-10 18:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <9E68DE9D-31CE-4F2D-9852-684A8B28A181@konsulko.com>
Hi,
On 09-09-16 21:13, Pantelis Antoniou wrote:
> Hi Hans,
>
>> On Sep 1, 2016, at 22:08 , Hans de Goede <hdegoede@redhat.com> wrote:
>>
>> Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets
>> of which a new batch is produced every few weeks. Each batch uses a
>> different mix of touchscreen, accelerometer and wifi peripherals.
>>
>> Given that each batch is different creating a devicetree for each variant
>> is not desirable. This commit adds a Q8 tablet hardware manager which
>> auto-detects the touchscreen and accelerometer so that a single generic
>> dts can be used for these tablets.
>>
>> The wifi is connected to a discoverable bus (sdio or usb) and will be
>> autodetected by the mmc resp. usb subsystems.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>> .../misc/allwinner,sunxi-q8-hardwaremgr.txt | 52 +++
>> drivers/misc/Kconfig | 12 +
>> drivers/misc/Makefile | 1 +
>> drivers/misc/q8-hardwaremgr.c | 512 +++++++++++++++++++++
>> 4 files changed, 577 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
>> create mode 100644 drivers/misc/q8-hardwaremgr.c
>>
>> diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
>> new file mode 100644
>> index 0000000..f428bf5
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
>> @@ -0,0 +1,52 @@
>> +Q8 tablet hardware manager
>> +--------------------------
>> +
>> +Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets of
>> +which a new batch is produced every few weeks. Each batch uses a different
>> +mix of touchscreen, accelerometer and wifi peripherals.
>> +
>> +Given that each batch is different creating a devicetree for each variant is
>> +not desirable. The Q8 tablet hardware manager bindings are bindings for an os
>> +module which auto-detects the touchscreen so that a single
>> +generic dts can be used for these tablets.
>> +
>> +The wifi is connected to a discoverable bus and will be autodetected by the os.
>> +
>> +Required properties:
>> + - compatible : "allwinner,sunxi-q8-hardwaremgr"
>> + - touchscreen : phandle of a template touchscreen node, this must be a
>> + child node of the touchscreen i2c bus
>> +
>> +Optional properties:
>> + - touchscreen-supply : regulator phandle for the touchscreen vdd supply
>> +
>> +touschreen node required properties:
>> + - interrupt-parent : phandle pointing to the interrupt controller
>> + serving the touchscreen interrupt
>> + - interrupts : interrupt specification for the touchscreen interrupt
>> + - power-gpios : Specification for the pin connected to the touchscreen's
>> + enable / wake pin. This needs to be driven high to
>> + enable the touchscreen controller
>> +
>> +Example:
>> +
>> +/ {
>> + hwmgr {
>> + compatible = "allwinner,sunxi-q8-hardwaremgr";
>> + touchscreen = <&touchscreen>;
>> + touchscreen-supply = <®_ldo_io1>;
>> + };
>> +};
>> +
>> +&i2c0 {
>> + touchscreen: touchscreen at 0 {
>> + interrupt-parent = <&pio>;
>> + interrupts = <1 5 IRQ_TYPE_EDGE_FALLING>; /* PB5 */
>> + power-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>> + /*
>> + * Enabled by sunxi-q8-hardwaremgr if it detects a
>> + * known model touchscreen.
>> + */
>> + status = "disabled";
>> + };
>> +};
>> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
>> index a216b46..c3e7772 100644
>> --- a/drivers/misc/Kconfig
>> +++ b/drivers/misc/Kconfig
>> @@ -804,6 +804,18 @@ config PANEL_BOOT_MESSAGE
>> An empty message will only clear the display at driver init time. Any other
>> printf()-formatted message is valid with newline and escape codes.
>>
>> +config Q8_HARDWAREMGR
>> + tristate "Allwinner Q8 tablet hardware manager"
>> + depends on GPIOLIB || COMPILE_TEST
>> + depends on I2C
>> + depends on OF
>> + default n
>> + help
>> + This option enables support for autodetecting the touchscreen
>> + on Allwinner Q8 tablets.
>> +
>> + If unsure, say N.
>> +
>> source "drivers/misc/c2port/Kconfig"
>> source "drivers/misc/eeprom/Kconfig"
>> source "drivers/misc/cb710/Kconfig"
>> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
>> index 7410c6d..cac76b7 100644
>> --- a/drivers/misc/Makefile
>> +++ b/drivers/misc/Makefile
>> @@ -57,6 +57,7 @@ obj-$(CONFIG_ECHO) += echo/
>> obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
>> obj-$(CONFIG_CXL_BASE) += cxl/
>> obj-$(CONFIG_PANEL) += panel.o
>> +obj-$(CONFIG_Q8_HARDWAREMGR) += q8-hardwaremgr.o
>>
>> lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
>> lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o
>> diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
>> new file mode 100644
>> index 0000000..e75625e
>> --- /dev/null
>> +++ b/drivers/misc/q8-hardwaremgr.c
>> @@ -0,0 +1,512 @@
>> +/*
>> + * Allwinner q8 formfactor tablet hardware manager
>> + *
>> + * Copyright (C) 2016 Hans de Goede <hdegoede@redhat.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <asm/unaligned.h>
>> +#include <linux/delay.h>
>> +#include <linux/err.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/i2c.h>
>> +#include <linux/module.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/slab.h>
>> +
>> +/*
>> + * We can detect which touchscreen controller is used automatically,
>> + * but some controllers can be wired up differently depending on the
>> + * q8 PCB variant used, so they need different firmware files / settings.
>> + *
>> + * We allow the user to specify a firmware_variant to select a config
>> + * from a list of known configs. We also allow overriding each setting
>> + * individually.
>> + */
>> +
>> +static int touchscreen_variant = -1;
>> +module_param(touchscreen_variant, int, 0444);
>> +MODULE_PARM_DESC(touchscreen_variant, "Touchscreen variant 0-x, -1 for auto");
>> +
>> +static int touchscreen_width = -1;
>> +module_param(touchscreen_width, int, 0444);
>> +MODULE_PARM_DESC(touchscreen_width, "Touchscreen width, -1 for auto");
>> +
>> +static int touchscreen_height = -1;
>> +module_param(touchscreen_height, int, 0444);
>> +MODULE_PARM_DESC(touchscreen_height, "Touchscreen height, -1 for auto");
>> +
>> +static int touchscreen_invert_x = -1;
>> +module_param(touchscreen_invert_x, int, 0444);
>> +MODULE_PARM_DESC(touchscreen_invert_x, "Touchscreen invert x, -1 for auto");
>> +
>> +static int touchscreen_invert_y = -1;
>> +module_param(touchscreen_invert_y, int, 0444);
>> +MODULE_PARM_DESC(touchscreen_invert_y, "Touchscreen invert y, -1 for auto");
>> +
>> +static int touchscreen_swap_x_y = -1;
>> +module_param(touchscreen_swap_x_y, int, 0444);
>> +MODULE_PARM_DESC(touchscreen_swap_x_y, "Touchscreen swap x y, -1 for auto");
>> +
>> +static char *touchscreen_fw_name;
>> +module_param(touchscreen_fw_name, charp, 0444);
>> +MODULE_PARM_DESC(touchscreen_fw_name, "Touchscreen firmware filename");
>> +
>> +#define TOUCHSCREEN_POWER_ON_DELAY 20
>> +#define SILEAD_REG_ID 0xFC
>> +#define EKTF2127_RESPONSE 0x52
>> +#define EKTF2127_REQUEST 0x53
>> +#define EKTF2127_WIDTH 0x63
>> +
>> +enum touchscreen_model {
>> + touchscreen_unknown,
>> + gsl1680_a082,
>> + gsl1680_b482,
>> + ektf2127,
>> + zet6251,
>> +};
>> +
>> +struct q8_hardwaremgr_data {
>> + struct device *dev;
>> + bool touchscreen_needs_regulator;
>> + enum touchscreen_model touchscreen_model;
>> + int touchscreen_addr;
>> + int touchscreen_variant;
>> + int touchscreen_width;
>> + int touchscreen_height;
>> + int touchscreen_invert_x;
>> + int touchscreen_invert_y;
>> + int touchscreen_swap_x_y;
>> + const char *touchscreen_compatible;
>> + const char *touchscreen_fw_name;
>> +};
>> +
>> +typedef int (*probe_func)(struct q8_hardwaremgr_data *data,
>> + struct i2c_adapter *adap);
>> +
>> +#if 0
>> + ret = i2c_smbus_xfer(adap, 0x40, 0, I2C_SMBUS_WRITE, 0,
>> + I2C_SMBUS_QUICK, NULL);
>> + if (ret < 0)
>> + return -ENODEV;
>> +
>> +#endif
>> +
>
> ^^^ crud?
Yes, please ignore.
>> +static int q8_hardwaremgr_probe_touchscreen(struct q8_hardwaremgr_data *data,
>> + struct i2c_adapter *adap)
>> +{
>> + struct i2c_client *client;
>> + unsigned char buff[24];
>> + __le32 chip_id;
>> + int ret;
>> +
>> + msleep(TOUCHSCREEN_POWER_ON_DELAY);
>> +
>> + /* Check for silead touchsceen at addr 0x40 */
>> + client = i2c_new_dummy(adap, 0x40);
>> + if (!client)
>> + return -ENOMEM;
>> +
>> + ret = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_ID,
>> + sizeof(chip_id), (u8 *)&chip_id);
>> + if (ret == sizeof(chip_id)) {
>> + switch (le32_to_cpu(chip_id)) {
>> + case 0xa0820000:
>> + data->touchscreen_addr = 0x40;
>> + data->touchscreen_compatible = "silead,gsl1680";
>> + data->touchscreen_model = gsl1680_a082;
>> + dev_info(data->dev, "Found Silead touchscreen ID: 0xa0820000\n");
>> + break;
>> + case 0xb4820000:
>> + data->touchscreen_addr = 0x40;
>> + data->touchscreen_compatible = "silead,gsl1680";
>> + data->touchscreen_model = gsl1680_b482;
>> + dev_info(data->dev, "Found Silead touchscreen ID: 0xb4820000\n");
>> + break;
>
>> + default:
>> + dev_warn(data->dev, "Found Silead touchscreen with unknown ID: 0x%08x\n",
>> + le32_to_cpu(chip_id));
>> + }
>> + ret = 0;
>> + }
>> + i2c_unregister_device(client);
>> + if (ret == 0 || ret == -ETIMEDOUT /* Bus stuck bail immediately */)
>> + return ret;
>> +
>> + /* Check for Elan eKTF2127 touchsceen at addr 0x15 */
>> + client = i2c_new_dummy(adap, 0x15);
>> + if (!client)
>> + return -ENOMEM;
>> +
>> + do {
>> + /* Read hello, ignore data, depends on initial power state */
>> + ret = i2c_master_recv(client, buff, 4);
>> + if (ret != 4)
>> + break;
>> +
>> + /* Request width */
>> + buff[0] = EKTF2127_REQUEST;
>> + buff[1] = EKTF2127_WIDTH;
>> + buff[2] = 0x00;
>> + buff[3] = 0x00;
>> + ret = i2c_master_send(client, buff, 4);
>> + if (ret != 4)
>> + break;
>> +
>> + msleep(20);
>> +
>> + /* Read response */
>> + ret = i2c_master_recv(client, buff, 4);
>> + if (ret != 4)
>> + break;
>> +
>> + if (buff[0] == EKTF2127_RESPONSE && buff[1] == EKTF2127_WIDTH) {
>> + data->touchscreen_addr = 0x15;
>> + data->touchscreen_compatible = "elan,ektf2127";
>> + data->touchscreen_model = ektf2127;
>> + dev_info(data->dev, "Found Elan eKTF2127 touchscreen\n");
>> + ret = 0;
>> + }
>> + } while (0);
>> + i2c_unregister_device(client);
>> + if (ret == 0 || ret == -ETIMEDOUT /* Bus stuck bail immediately */)
>> + return ret;
>> +
>> + /* Check for Zeitec zet6251 touchsceen at addr 0x76 */
>> + client = i2c_new_dummy(adap, 0x76);
>> + if (!client)
>> + return -ENOMEM;
>> +
>> + /*
>> + * We only do a simple read finger data packet test, because some
>> + * versions require firmware to be loaded. If not firmware is loaded
>> + * the buffer will be filed with 0xff, so we ignore the contents.
>> + */
>> + ret = i2c_master_recv(client, buff, 24);
>> + if (ret == 24) {
>> + data->touchscreen_addr = 0x76;
>> + data->touchscreen_compatible = "zeitec,zet6251";
>> + data->touchscreen_model = zet6251;
>> + dev_info(data->dev, "Found Zeitec zet6251 touchscreen\n");
>> + ret = 0;
>> + }
>
> I can understand having a switch here since it?s quite complicated but it would be better to
> have a structure that defines them i.e.
>
> struct touchscreen_detect_data {
> u32 chip_id;
> int addr;
> const char *compatible;
> enum touchscreen_model model;
>
> };
Having a chip-d in there will only work for the gsl1680,
not for the ektf not for the zeitec. I could use
an array of structs addressed by enum touchscreen_model
holding some of the other data, but that would boil
down to only addr and compatible. and adding that
kinda indirection does not make the code more readable
IMHO.
> static const struct touchscreen_detect_data ts_detect_data[] = {
> {
> .chip_id = 0xa0820000,
> .addr = 0x40,
> .compatible = ?silead,gsl1680?,
> .model = gsl1680_a082,
> }, ...
> };
>
> And so on, and restructuring by having different paths by touchscreen model type.
>
>
>> + i2c_unregister_device(client);
>> + if (ret == 0 || ret == -ETIMEDOUT /* Bus stuck bail immediately */)
>> + return ret;
>> +
>> + return -ENODEV;
>> +}
>> +
>> +static int q8_hardwaremgr_do_probe(struct q8_hardwaremgr_data *data,
>> + const char *prefix, probe_func func)
>> +{
>> + struct device *dev = data->dev;
>> + struct device_node *np;
>> + struct i2c_adapter *adap;
>> + struct regulator *reg;
>> + struct gpio_desc *gpio;
>> + int ret = 0;
>> +
>> + np = of_parse_phandle(dev->of_node, prefix, 0);
>> + if (!np) {
>> + dev_err(dev, "Error %s not set\n", prefix);
>> + return -EINVAL;
>> + }
>> +
>> + adap = of_get_i2c_adapter_by_node(np->parent);
>> + if (!adap) {
>> + ret = -EPROBE_DEFER;
>> + goto put_node;
>> + }
>> +
>> + reg = regulator_get_optional(dev, prefix);
>> + if (IS_ERR(reg)) {
>> + ret = PTR_ERR(reg);
>> + if (ret == -EPROBE_DEFER)
>> + goto put_adapter;
>> + reg = NULL;
>> + }
>> +
>> + gpio = fwnode_get_named_gpiod(&np->fwnode, "power-gpios");
>> + if (IS_ERR(gpio)) {
>> + ret = PTR_ERR(gpio);
>> + if (ret == -EPROBE_DEFER)
>> + goto put_reg;
>> + gpio = NULL;
>> + }
>> +
>> + /* First try with only the power gpio driven high */
>> + if (gpio) {
>> + ret = gpiod_direction_output(gpio, 1);
>> + if (ret)
>> + goto put_gpio;
>> + }
>> +
>> + dev_info(dev, "Looking for %s without a regulator\n", prefix);
>> + ret = func(data, adap);
>> + if (ret != 0 && reg) {
>> + /* Second try, also enable the regulator */
>> + ret = regulator_enable(reg);
>> + if (ret)
>> + goto restore_gpio;
>> +
>> + dev_info(dev, "Looking for %s with a regulator\n", prefix);
>> + ret = func(data, adap);
>> + if (ret == 0)
>> + data->touchscreen_needs_regulator = true;
>> +
>> + regulator_disable(reg);
>> + }
>> + ret = 0; /* Not finding a device is not an error */
>> +
>> +restore_gpio:
>> + if (gpio)
>> + gpiod_direction_output(gpio, 0);
>> +put_gpio:
>> + if (gpio)
>> + gpiod_put(gpio);
>> +put_reg:
>> + if (reg)
>> + regulator_put(reg);
>> +put_adapter:
>> + i2c_put_adapter(adap);
>> +
>> +put_node:
>> + of_node_put(np);
>> +
>> + return ret;
>> +}
>> +
>> +static void q8_hardwaremgr_apply_gsl1680_a082_variant(
>> + struct q8_hardwaremgr_data *data)
>> +{
>> + if (touchscreen_variant != -1) {
>> + data->touchscreen_variant = touchscreen_variant;
>> + } else {
>> + if (of_machine_is_compatible("allwinner,sun8i-a33"))
>> + data->touchscreen_variant = 1;
>> + else
>> + data->touchscreen_variant = 0;
>> + }
>> +
>> + switch (data->touchscreen_variant) {
>> + default:
>> + dev_warn(data->dev, "Error unknown touchscreen_variant %d using 0\n",
>> + touchscreen_variant);
>> + /* Fall through */
>> + case 0:
>> + data->touchscreen_width = 1024;
>> + data->touchscreen_height = 600;
>> + data->touchscreen_fw_name = "gsl1680-a082-q8-700.fw";
>> + break;
>> + case 1:
>> + data->touchscreen_width = 480;
>> + data->touchscreen_height = 800;
>> + data->touchscreen_swap_x_y = 1;
>> + data->touchscreen_fw_name = "gsl1680-a082-q8-a70.fw";
>> + break;
>> + }
>> +}
>> +
>> +static void q8_hardwaremgr_apply_gsl1680_b482_variant(
>> + struct q8_hardwaremgr_data *data)
>> +{
>> + if (touchscreen_variant != -1)
>> + data->touchscreen_variant = touchscreen_variant;
>> +
>> + switch (data->touchscreen_variant) {
>> + default:
>> + dev_warn(data->dev, "Error unknown touchscreen_variant %d using 0\n",
>> + touchscreen_variant);
>> + /* Fall through */
>> + case 0:
>> + data->touchscreen_width = 960;
>> + data->touchscreen_height = 640;
>> + data->touchscreen_fw_name = "gsl1680-b482-q8-d702.fw";
>> + break;
>> + case 1:
>> + data->touchscreen_width = 960;
>> + data->touchscreen_height = 640;
>> + data->touchscreen_fw_name = "gsl1680-b482-q8-a70.fw";
>> + break;
>> + }
>> +}
>> +
>> +static void q8_hardwaremgr_issue_gsl1680_warning(
>> + struct q8_hardwaremgr_data *data)
>> +{
>> + dev_warn(data->dev, "gsl1680 touchscreen may require kernel cmdline parameters to function properly\n");
>> + dev_warn(data->dev, "Try q8_hardwaremgr.touchscreen_invert_x=1 if x coordinates are inverted\n");
>> + dev_warn(data->dev, "Try q8_hardwaremgr.touchscreen_variant=%d if coordinates are all over the place\n",
>> + !data->touchscreen_variant);
>> +
>> +#define show(x) \
>> + dev_info(data->dev, #x " %d (%s)\n", data->x, \
>> + (x == -1) ? "auto" : "user supplied")
>> +
>> + show(touchscreen_variant);
>> + show(touchscreen_width);
>> + show(touchscreen_height);
>> + show(touchscreen_invert_x);
>> + show(touchscreen_invert_y);
>> + show(touchscreen_swap_x_y);
>> + dev_info(data->dev, "touchscreen_fw_name %s (%s)\n",
>> + data->touchscreen_fw_name,
>> + (touchscreen_fw_name == NULL) ? "auto" : "user supplied");
>> +#undef show
>> +}
>> +
>> +static void q8_hardwaremgr_apply_touchscreen(struct q8_hardwaremgr_data *data)
>> +{
>> + struct device *dev = data->dev;
>> + struct of_changeset cset;
>> + struct device_node *np;
>> +
>> + switch (data->touchscreen_model) {
>> + case touchscreen_unknown:
>> + return;
>> + case gsl1680_a082:
>> + q8_hardwaremgr_apply_gsl1680_a082_variant(data);
>> + break;
>> + case gsl1680_b482:
>> + q8_hardwaremgr_apply_gsl1680_b482_variant(data);
>> + break;
>> + case ektf2127:
>> + case zet6251:
>> + /* These have only 1 variant */
>> + break;
>> + }
>> +
>> + if (touchscreen_width != -1)
>> + data->touchscreen_width = touchscreen_width;
>> +
>> + if (touchscreen_height != -1)
>> + data->touchscreen_height = touchscreen_height;
>> +
>> + if (touchscreen_invert_x != -1)
>> + data->touchscreen_invert_x = touchscreen_invert_x;
>> +
>> + if (touchscreen_invert_y != -1)
>> + data->touchscreen_invert_y = touchscreen_invert_y;
>> +
>> + if (touchscreen_swap_x_y != -1)
>> + data->touchscreen_swap_x_y = touchscreen_swap_x_y;
>> +
>> + if (touchscreen_fw_name)
>> + data->touchscreen_fw_name = touchscreen_fw_name;
>> +
>> + if (data->touchscreen_model == gsl1680_a082 ||
>> + data->touchscreen_model == gsl1680_b482)
>> + q8_hardwaremgr_issue_gsl1680_warning(data);
>> +
>> + np = of_parse_phandle(data->dev->of_node, "touchscreen", 0);
>> + /* Never happens already checked in q8_hardwaremgr_do_probe() */
>> + if (WARN_ON(!np))
>> + return;
>> +
>> + of_changeset_init(&cset);
>> + of_changeset_add_property_u32(&cset, np, "reg", data->touchscreen_addr);
>> + of_changeset_add_property_string(&cset, np, "compatible",
>> + data->touchscreen_compatible);
>> +
>> + if (data->touchscreen_width)
>> + of_changeset_add_property_u32(&cset, np, "touchscreen-size-x",
>> + data->touchscreen_width);
>> + if (data->touchscreen_height)
>> + of_changeset_add_property_u32(&cset, np, "touchscreen-size-y",
>> + data->touchscreen_height);
>> + if (data->touchscreen_invert_x)
>> + of_changeset_add_property_bool(&cset, np,
>> + "touchscreen-inverted-x");
>> + if (data->touchscreen_invert_y)
>> + of_changeset_add_property_bool(&cset, np,
>> + "touchscreen-inverted-y");
>> + if (data->touchscreen_swap_x_y)
>> + of_changeset_add_property_bool(&cset, np,
>> + "touchscreen-swapped-x-y");
>> + if (data->touchscreen_fw_name)
>> + of_changeset_add_property_string(&cset, np, "firmware-name",
>> + data->touchscreen_fw_name);
>> + if (data->touchscreen_needs_regulator) {
>> + struct property *p;
>> +
>> + p = of_find_property(dev->of_node, "touchscreen-supply", NULL);
>> + /* Never happens already checked in q8_hardwaremgr_do_probe() */
>> + if (WARN_ON(!p))
>> + return;
>> +
>> + of_changeset_add_property_copy(&cset, np, "vddio-supply",
>> + p->value, p->length);
>> + }
>> +
>> + of_changeset_update_property_string(&cset, np, "status", "okay");
>> + of_changeset_apply(&cset);
>> +
>> + of_node_put(np);
>> +}
>> +
>> +static int q8_hardwaremgr_probe(struct platform_device *pdev)
>> +{
>> + struct device *dev = &pdev->dev;
>> + struct q8_hardwaremgr_data *data;
>> + int ret = 0;
>> +
>> + data = kzalloc(sizeof(*data), GFP_KERNEL);
>> + if (!data)
>> + return -ENOMEM;
>> +
>> + data->dev = &pdev->dev;
>> +
>> + ret = q8_hardwaremgr_do_probe(data, "touchscreen",
>> + q8_hardwaremgr_probe_touchscreen);
>> + if (ret)
>> + goto error;
>> +
>> + /*
>> + * Our pinctrl may conflict with the pinctrl of the detected devices
>> + * we're adding, so remove it before adding detected devices.
>> + */
>> + if (dev->pins) {
>> + devm_pinctrl_put(dev->pins->p);
>> + devm_kfree(dev, dev->pins);
>> + dev->pins = NULL;
>> + }
>> +
>
> Hmm, that?s weird for sure. How can it happen?
Nope, not weird. The touchscreen's power-gpios needs to
have the right drive-strength / pull-up setting, both
during q8_hardwaremgr_probe and when the actual driver
is using it. So the dt node for both contains a
phandle to a pinctrl for the power-gpio, as soon as
we start applying the dt changes, the touchscreen's
probe method will get called and just before that
the device-core will try to set the default pinctrl
for the touchscreen dt node/platform dev, which will
fail because the pins in there are owned by the
q8-hardwaremgr dt node/platform dev, which causes
an error in the kernel log (don't remember if it
also caused the touchscreen driver to not load or
not).
Note that with Rob's suggestion to not have
a q8-hardwaremgr node at all (*), the q8-hardwaremgr
code will need to do the pinctrl setting itself
and then it also doing the releasing later on
will feel more natural / will be expected.
Regards,
Hans
*) Assuming I've understood Rob correctly
wrt this.
^ permalink raw reply
* [PATCH 0/8] ARM: dts: rockchip: Remove skeleton.dtsi usage and fix memory node DTC warnings
From: Heiko Stuebner @ 2016-09-10 21:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473429669-6185-1-git-send-email-javier@osg.samsung.com>
Hi Javier,
Am Freitag, 9. September 2016, 10:01:01 CEST schrieb Javier Martinez Canillas:
> This series removes the inclusion of the skeleton.dtsi in all the Rockchip
> dts, which allows to get rid of the DTC warnings about a mismatch between
> the memory nodes' unit names and reg properties.
>
> Patches are pretty trivial and shouldn't cause functional changes AFAIK,
> but were only built tested and dtbs compared with scripts/dtc/dtx_diff.
applied all 8 to my dts branch (for 4.9 but might get delayed to 4.10 ... not
sure yet)
Thanks
Heiko
^ permalink raw reply
* [RFD] hix5hd2 datasheet?
From: Marty Plummer @ 2016-09-11 0:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <57D2740C.10000@hisilicon.com>
On 09/09/2016 03:34 AM, Wei Xu wrote:
> Hi Marty,
>
> On 08/09/2016 23:58, Marty Plummer wrote:
>> Hello,
>>
>> I'm currently working to get the ethernet interface for the
>> hi3520 SoC to work, and I think (emphasis on think) the hix5hd2-gmac
>> driver is compatible, or nearly so, as checking the sdk source code
>> for the interface has a fairly large amount of similar code (well, as
>> similar as 2.6.24 vs 4.8-rc4 code can be) and identical register
>> definitions to the very bit, so I was hoping to compare the datasheets
>> and see how far the commonality goes. Plus, having the datasheets
>> readily available will be of assistance to anyone else looking to
>> contribute.
>
> +Jiancheng into this mail group.
> Maybe you could get the hix5hd2 datasheets from him.
> Thanks!
>
> Best Regards,
> Wei
>
>>
>> Thanks,
>> Marty
>>
>>
>
In additon, I'm wondering how the second reg property for the
hix5hd2-gmac devicetree is determined (in fact, that is my main concern),
as I'm pretty sure it will work with the gmac on hi3520, but I can't
find a register in the hi3520 datasheet that I could 100% say is the
right one, and adding the driver to the initrd causes a kernel panic
(I'm assuming this is because of wrong reg values unless otherwise
proven) on an otherwise mostly working kernel.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160910/39d7b739/attachment.sig>
^ permalink raw reply
* [PATCH] atomic64: No need for CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
From: kbuild test robot @ 2016-09-11 4:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473352098-5822-1-git-send-email-vgupta@synopsys.com>
Hi Vineet,
[auto build test ERROR on arm64/for-next/core]
[cannot apply to linus/master linux/master v4.8-rc5 next-20160909]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]
url: https://github.com/0day-ci/linux/commits/Vineet-Gupta/atomic64-No-need-for-CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE/20160909-013936
base: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 4.9.0
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=ia64
All errors (new ones prefixed by >>):
lib/atomic64_test.c: In function 'test_atomic64':
>> lib/atomic64_test.c:217:2: error: implicit declaration of function 'atomic64_dec_if_positive' [-Werror=implicit-function-declaration]
BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
^
cc1: some warnings being treated as errors
vim +/atomic64_dec_if_positive +217 lib/atomic64_test.c
86a89380 Luca Barbieri 2010-02-24 211 INIT(v0);
9efbcd59 Luca Barbieri 2010-03-01 212 BUG_ON(!atomic64_add_unless(&v, one, v1));
86a89380 Luca Barbieri 2010-02-24 213 r += one;
86a89380 Luca Barbieri 2010-02-24 214 BUG_ON(v.counter != r);
86a89380 Luca Barbieri 2010-02-24 215
86a89380 Luca Barbieri 2010-02-24 216 INIT(onestwos);
86a89380 Luca Barbieri 2010-02-24 @217 BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
86a89380 Luca Barbieri 2010-02-24 218 r -= one;
86a89380 Luca Barbieri 2010-02-24 219 BUG_ON(v.counter != r);
86a89380 Luca Barbieri 2010-02-24 220
:::::: The code at line 217 was first introduced by commit
:::::: 86a8938078a8bb518c5376de493e348c7490d506 lib: Add self-test for atomic64_t
:::::: TO: Luca Barbieri <luca@luca-barbieri.com>
:::::: CC: H. Peter Anvin <hpa@zytor.com>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 44278 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160911/f694dbce/attachment-0001.obj>
^ permalink raw reply
* [PATCH v4 4/5] arm/arm64: vgic-new: Implement VGICv3 CPU interface access
From: Marc Zyngier @ 2016-09-11 7:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473510138-4719-5-git-send-email-vijay.kilari@gmail.com>
On Sat, 10 Sep 2016 17:52:17 +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 version of VGIC v3 specification is define here
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/445611.html
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> ---
> arch/arm64/include/uapi/asm/kvm.h | 3 +
> arch/arm64/kvm/Makefile | 1 +
> include/linux/irqchip/arm-gic-v3.h | 32 ++++-
> virt/kvm/arm/vgic/vgic-kvm-device.c | 27 ++++
> virt/kvm/arm/vgic/vgic-mmio-v2.c | 16 ---
> virt/kvm/arm/vgic/vgic-mmio-v3.c | 18 +++
> virt/kvm/arm/vgic/vgic-mmio.c | 16 +++
> virt/kvm/arm/vgic/vgic-sys-reg-v3.c | 261 ++++++++++++++++++++++++++++++++++++
> virt/kvm/arm/vgic/vgic-v3.c | 4 +
> virt/kvm/arm/vgic/vgic.h | 15 +++
> 10 files changed, 376 insertions(+), 17 deletions(-)
>
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 56dc08d..91c7137 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -206,9 +206,12 @@ struct kvm_arch_memory_slot {
> (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
> #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
> #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
> +#define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
> #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
> #define KVM_DEV_ARM_VGIC_GRP_CTRL 4
> #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
> +#define KVM_DEV_ARM_VGIC_CPU_SYSREGS 6
> +
> #define KVM_DEV_ARM_VGIC_CTRL_INIT 0
>
> /* Device Control API on vcpu fd */
> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> index d50a82a..1a14e29 100644
> --- a/arch/arm64/kvm/Makefile
> +++ b/arch/arm64/kvm/Makefile
> @@ -32,5 +32,6 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
> +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-sys-reg-v3.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
> kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 99ac022..22ec183 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -354,6 +354,24 @@
> */
> #define ICC_CTLR_EL1_EOImode_drop_dir (0U << 1)
> #define ICC_CTLR_EL1_EOImode_drop (1U << 1)
> +#define ICC_CTLR_EL1_CBPR_SHIFT (0)
> +#define ICC_CTLR_EL1_CBPR_MASK (1 << ICC_CTLR_EL1_CBPR_SHIFT)
> +#define ICC_CTLR_EL1_EOImode_SHIFT (1)
Since you're adding this, please rewrite the two existing EOImode
macros to use this new define.
> +#define ICC_CTLR_EL1_EOImode_MASK (1 << ICC_CTLR_EL1_EOImode_SHIFT)
> +#define ICC_CTLR_EL1_PRI_BITS_SHIFT (8)
> +#define ICC_CTLR_EL1_PRI_BITS_MASK (0x7 << ICC_CTLR_EL1_PRI_BITS_SHIFT)
> +#define ICC_CTLR_EL1_ID_BITS_SHIFT (11)
> +#define ICC_CTLR_EL1_ID_BITS_MASK (0x7 << ICC_CTLR_EL1_ID_BITS_SHIFT)
> +#define ICC_PMR_EL1_SHIFT (0)
> +#define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT)
> +#define ICC_BPR0_EL1_SHIFT (0)
> +#define ICC_BPR0_EL1_MASK (0x7 << ICC_PMR_EL1_SHIFT)
> +#define ICC_BPR1_EL1_SHIFT (0)
> +#define ICC_BPR1_EL1_MASK (0x7 << ICC_PMR_EL1_SHIFT)
> +#define ICC_IGRPEN0_EL1_SHIFT (0)
> +#define ICC_IGRPEN0_EL1_MASK (1 << ICC_IGRPEN0_EL1_SHIFT)
> +#define ICC_IGRPEN1_EL1_SHIFT (0)
> +#define ICC_IGRPEN1_EL1_MASK (1 << ICC_IGRPEN1_EL1_SHIFT)
> #define ICC_SRE_EL1_SRE (1U << 0)
>
> /*
> @@ -383,7 +401,19 @@
> #define ICH_HCR_UIE (1 << 1)
>
> #define ICH_VMCR_CTLR_SHIFT 0
> -#define ICH_VMCR_CTLR_MASK (0x21f << ICH_VMCR_CTLR_SHIFT)
> +#define ICH_VMCR_CTLR_MASK (0x210 << ICH_VMCR_CTLR_SHIFT)
Why are you dropping the four control bits? You're now only covering
VEOIM and VCBPR. Worse, you don't even use that modified macro in this
patch.
> +#define ICH_VMCR_CBPR_SHIFT 4
> +#define ICH_VMCR_CBPR_MASK (1 << ICH_VMCR_CBPR_SHIFT)
> +#define ICH_VMCR_EOIM_SHIFT 9
> +#define ICH_VMCR_EOIM_MASK (1 << ICH_VMCR_EOIM_SHIFT)
> +#define ICH_VMCR_ENG0_SHIFT 0
> +#define ICH_VMCR_ENG0_MASK (1 << ICH_VMCR_ENG0_SHIFT)
> +#define ICH_VMCR_ENG1_SHIFT 1
> +#define ICH_VMCR_ENG1_MASK (1 << ICH_VMCR_ENG1_SHIFT)
> +#define ICH_VMCR_ENG0_SHIFT 0
> +#define ICH_VMCR_ENG0 (1 << ICH_VMCR_ENG0_SHIFT)
> +#define ICH_VMCR_ENG1_SHIFT 1
> +#define ICH_VMCR_ENG1 (1 << ICH_VMCR_ENG1_SHIFT)
> #define ICH_VMCR_BPR1_SHIFT 18
> #define ICH_VMCR_BPR1_MASK (7 << ICH_VMCR_BPR1_SHIFT)
> #define ICH_VMCR_BPR0_SHIFT 21
And here you're covering for all the bits. So what is now the purpose
of ICH_VMCR_CTLR_MASK now?
In general, I'd like this kind of change to be split from the rest of
the patch so that it can be reviewed independently by the irqchip
maintainers (tglx, Jason and myself).
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 3225388..e580b6d 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -509,6 +509,14 @@ static int vgic_attr_regs_access_v3(struct kvm_device *dev,
> if (!is_write)
> *reg = tmp32;
> break;
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 regid;
> +
> + regid = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
> + ret = vgic_v3_cpu_sysregs_uaccess(vcpu, is_write,
> + regid, reg);
> + break;
> + }
> default:
> ret = -EINVAL;
> break;
> @@ -542,6 +550,15 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
> reg = tmp32;
> return vgic_attr_regs_access_v3(dev, attr, ®, true);
> }
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 reg;
> +
> + if (get_user(reg, uaddr))
> + return -EFAULT;
> +
> + return vgic_attr_regs_access_v3(dev, attr, ®, true);
> + }
> }
> return -ENXIO;
> }
> @@ -569,6 +586,15 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
> ret = put_user(tmp32, uaddr);
> return ret;
> }
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 reg;
> +
> + ret = vgic_attr_regs_access_v3(dev, attr, ®, false);
> + if (ret)
> + return ret;
> + return put_user(reg, uaddr);
> + }
> }
>
> return -ENXIO;
> @@ -587,6 +613,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
> break;
> case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS:
> return vgic_v3_has_attr_regs(dev, attr);
> case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
> return 0;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 2cb04b7..ad353b5 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -212,22 +212,6 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
> }
> }
>
> -static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> -{
> - if (kvm_vgic_global_state.type == VGIC_V2)
> - vgic_v2_set_vmcr(vcpu, vmcr);
> - else
> - vgic_v3_set_vmcr(vcpu, vmcr);
> -}
> -
> -static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> -{
> - if (kvm_vgic_global_state.type == VGIC_V2)
> - vgic_v2_get_vmcr(vcpu, vmcr);
> - else
> - vgic_v3_get_vmcr(vcpu, vmcr);
> -}
> -
> #define GICC_ARCH_VERSION_V2 0x2
>
> /* These are for userland accesses only, there is no guest-facing emulation. */
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index ffbe1ae..04e0f2c 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -23,6 +23,7 @@
>
> #include "vgic.h"
> #include "vgic-mmio.h"
> +#include "sys_regs.h"
>
> /* extract @num bytes at @offset bytes offset in data */
> unsigned long extract_bytes(unsigned long data, unsigned int offset,
> @@ -581,6 +582,23 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
> nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
> break;
> }
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 reg, id;
> + unsigned long mpidr;
> + struct kvm_vcpu *vcpu;
> +
> + mpidr = (attr->attr & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) >>
> + KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT;
> +
> + vcpu = kvm_mpidr_to_vcpu(dev->kvm, mpidr);
> + if (!vcpu)
> + return -EINVAL;
> + if (vcpu->vcpu_id >= atomic_read(&dev->kvm->online_vcpus))
> + return -EINVAL;
> +
> + id = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
> + return vgic_v3_has_cpu_sysregs_attr(vcpu, 0, id, ®);
> + }
> default:
> return -ENXIO;
> }
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 9294555..81d851c 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -470,6 +470,22 @@ int vgic_validate_mmio_region_addr(struct kvm_device *dev,
> return -ENXIO;
> }
>
> +void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> + if (kvm_vgic_global_state.type == VGIC_V2)
> + vgic_v2_set_vmcr(vcpu, vmcr);
> + else
> + vgic_v3_set_vmcr(vcpu, vmcr);
> +}
> +
> +void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> + if (kvm_vgic_global_state.type == VGIC_V2)
> + vgic_v2_get_vmcr(vcpu, vmcr);
> + else
> + vgic_v3_get_vmcr(vcpu, vmcr);
> +}
> +
> /*
> * kvm_mmio_read_buf() returns a value in a format where it can be converted
> * to a byte array and be directly observed as the guest wanted it to appear
> 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..437ed27
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
> @@ -0,0 +1,261 @@
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/arm_vgic.h>
> +#include <asm/kvm_emulate.h>
> +#include <asm/kvm_arm.h>
> +#include <asm/kvm_mmu.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +#include "sys_regs.h"
> +
> +static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> + u64 val;
> + u32 id_bits;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + val = p->regval;
> + vmcr.ctlr &= ~(ICH_VMCR_CBPR_MASK | ICH_VMCR_EOIM_MASK);
> + vmcr.ctlr |= ((val & ICC_CTLR_EL1_CBPR_MASK) >>
> + ICC_CTLR_EL1_CBPR_SHIFT) << ICH_VMCR_CBPR_SHIFT;
> + vmcr.ctlr |= ((val & ICC_CTLR_EL1_EOImode_MASK) >>
> + ICC_CTLR_EL1_EOImode_SHIFT) << ICH_VMCR_EOIM_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
What if userspace writes something that is incompatible with the
current configuration? Wrong number of ID bits, or number of priorities?
> + } else {
> + val = 0;
> + /* ICC_CTLR_EL1.A3V and ICC_CTRL_EL1.SEIS are not set */
> + val |= VGIC_PRI_BITS << ICC_CTLR_EL1_PRI_BITS_SHIFT;
Shouldn't that come from the actual HW?
> +
> + if (vgic_has_its(vcpu->kvm))
> + id_bits = INTERRUPT_ID_BITS_ITS;
> + else
> + id_bits = INTERRUPT_ID_BITS_SPIS;
> +
> + if (id_bits >= 24)
> + val |= (1 << ICC_CTLR_EL1_ID_BITS_SHIFT);
> + else
> + val |= (0 << ICC_CTLR_EL1_ID_BITS_SHIFT);
> +
> + val |= ((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >>
> + ICH_VMCR_CBPR_SHIFT) << ICC_CTLR_EL1_CBPR_SHIFT;
> + val |= ((vmcr.ctlr & ICH_VMCR_EOIM_MASK) >>
> + ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
> +
> + p->regval = val;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_pmr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.pmr = (p->regval << ICC_PMR_EL1_SHIFT) & ICC_PMR_EL1_MASK;
I don't get this. You're trying to extract a field from a register, and
yet you're starting by shifting it *up* before masking it. This only
works because your shift is 0. In general, I believe this should read:
val = (regval & MASK) >> SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.pmr & ICC_PMR_EL1_MASK) >> ICC_PMR_EL1_SHIFT;
and this the other way around.
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_bpr0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.bpr = (p->regval << ICC_BPR0_EL1_SHIFT) &
> + ICC_BPR0_EL1_MASK;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.bpr & ICC_BPR0_EL1_MASK) >>
> + ICC_BPR0_EL1_SHIFT;
> + }
Same problems (and I'll stop commenting on this issue).
> +
> + return true;
> +}
> +
> +static bool access_gic_bpr1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.abpr = (p->regval << ICC_BPR1_EL1_SHIFT) &
> + ICC_BPR1_EL1_MASK;
nit: I'd prefer it if the binary points were called bpr0 and bpr1
instead of bpr and abpr.
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.abpr & ICC_BPR1_EL1_MASK) >>
> + ICC_BPR1_EL1_SHIFT;
> + }
Shouldn't this account for the ICC_CTLR_EL1.CBPR setting?
> +
> + return true;
> +}
> +
> +static bool access_gic_grpen0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.grpen0 = (p->regval << ICC_IGRPEN0_EL1_SHIFT) &
> + ICC_IGRPEN0_EL1_MASK;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.grpen0 & ICC_IGRPEN0_EL1_MASK) >>
> + ICC_IGRPEN0_EL1_SHIFT;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_grpen1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.grpen1 = (p->regval << ICC_IGRPEN1_EL1_SHIFT) &
> + ICC_IGRPEN1_EL1_MASK;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.grpen1 & ICC_IGRPEN1_EL1_MASK) >>
> + ICC_IGRPEN1_EL1_SHIFT;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_ap0r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
> + u8 idx = r->Op2 & 3;
> +
> + if (p->is_write)
> + vgicv3->vgic_ap0r[idx] = p->regval;
What if some of the priority levels are not implemented? Restoring such
an active priority will result in a VM that silently breaks.
> + else
> + p->regval = vgicv3->vgic_ap0r[idx];
> +
> + return true;
> +}
> +
> +static bool access_gic_ap1r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
> + u8 idx = r->Op2 & 3;
> +
> + if (p->is_write)
> + vgicv3->vgic_ap1r[idx] = p->regval;
Same here.
> + else
> + p->regval = vgicv3->vgic_ap1r[idx];
> +
> + return true;
> +}
> +
> +static bool access_gic_sre(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
> +
> + /* Read only. Write ignore */
> + if (!p->is_write)
> + p->regval = vgicv3->vgic_sre;
> +
> + return true;
> +}
> +
> +static const struct sys_reg_desc gic_v3_icc_reg_descs[] = {
> + /* ICC_PMR_EL1 */
> + { Op0(3), Op1(0), CRn(4), CRm(6), Op2(0), access_gic_pmr },
> + /* ICC_BPR0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(3), access_gic_bpr0 },
> + /* ICC_AP0R0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(4), access_gic_ap0r },
> + /* ICC_AP0R1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(5), access_gic_ap0r },
> + /* ICC_AP0R2_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(6), access_gic_ap0r },
> + /* ICC_AP0R3_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(7), access_gic_ap0r },
> + /* ICC_AP1R0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(0), access_gic_ap1r },
> + /* ICC_AP1R1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(1), access_gic_ap1r },
> + /* ICC_AP1R2_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(2), access_gic_ap1r },
> + /* ICC_AP1R3_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(3), access_gic_ap1r },
> + /* ICC_BPR1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(3), access_gic_bpr1 },
> + /* ICC_CTLR_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(4), access_gic_ctlr },
> + /* ICC_SRE_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(5), access_gic_sre },
> + /* ICC_IGRPEN0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(6), access_gic_grpen0 },
> + /* ICC_GRPEN1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(7), access_gic_grpen1 },
> +};
> +
> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg)
> +{
> + struct sys_reg_params params;
> + u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
> +
> + params.regval = *reg;
> + params.is_write = is_write;
> + params.is_aarch32 = false;
> + params.is_32bit = false;
> +
> + if (find_reg_by_id(sysreg, ¶ms, gic_v3_icc_reg_descs,
> + ARRAY_SIZE(gic_v3_icc_reg_descs)))
> + return 0;
> + else
You can loose the else.
> + return -ENXIO;
> +}
> +
> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg)
> +{
> + struct sys_reg_params params;
> + const struct sys_reg_desc *r;
> + u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
> +
> + if (is_write)
> + params.regval = *reg;
> + params.is_write = is_write;
> + params.is_aarch32 = false;
> + params.is_32bit = false;
> +
> + r = find_reg_by_id(sysreg, ¶ms, gic_v3_icc_reg_descs,
> + ARRAY_SIZE(gic_v3_icc_reg_descs));
> + if (!r)
> + return -ENXIO;
> +
> + if (!r->access(vcpu, ¶ms, r))
> + return -EINVAL;
> +
> + if (!is_write)
> + *reg = params.regval;
> +
> + return 0;
> +}
> +
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 9f0dae3..cf34095 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -179,6 +179,8 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
> vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
> vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
> + vmcr |= (vmcrp->grpen0 << ICH_VMCR_ENG0_SHIFT) & ICH_VMCR_ENG0_MASK;
> + vmcr |= (vmcrp->grpen1 << ICH_VMCR_ENG1_SHIFT) & ICH_VMCR_ENG1_MASK;
>
> vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
> }
> @@ -191,6 +193,8 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
> vmcrp->bpr = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
> vmcrp->pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
> + vmcrp->grpen0 = (vmcr & ICH_VMCR_ENG0_MASK) >> ICH_VMCR_ENG0_SHIFT;
> + vmcrp->grpen1 = (vmcr & ICH_VMCR_ENG1_MASK) >> ICH_VMCR_ENG1_SHIFT;
> }
>
> #define INITIAL_PENDBASER_VALUE \
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 94b3479..04a397c 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -30,11 +30,20 @@
>
> #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
>
> +#define KVM_DEV_ARM_VGIC_SYSREG_MASK (KVM_REG_ARM64_SYSREG_OP0_MASK | \
> + KVM_REG_ARM64_SYSREG_OP1_MASK | \
> + KVM_REG_ARM64_SYSREG_CRN_MASK | \
> + KVM_REG_ARM64_SYSREG_CRM_MASK | \
> + KVM_REG_ARM64_SYSREG_OP2_MASK)
> +
> struct vgic_vmcr {
> u32 ctlr;
> u32 abpr;
> u32 bpr;
> u32 pmr;
> + /* Below member variable are valid only for GICv3 */
> + u32 grpen0;
> + u32 grpen1;
> };
>
> struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
> @@ -94,6 +103,10 @@ int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> int offset, u32 *val);
> int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> int offset, u32 *val);
> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> + u64 id, u64 *val);
> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg);
> #else
> static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> {
> @@ -172,6 +185,8 @@ static inline int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
> #endif
>
> int kvm_register_vgic_device(unsigned long type);
> +void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> int vgic_lazy_init(struct kvm *kvm);
> int vgic_init(struct kvm *kvm);
>
Thanks,
M.
--
Jazz is not dead. It just smells funny.
^ permalink raw reply
* [PATCH] pwm: imx: Port "pwm: imx: support output polarity inversion" to Linux v4.7
From: Lukasz Majewski @ 2016-09-11 8:55 UTC (permalink / raw)
To: linux-arm-kernel
This patch ports "pwm: imx: support output polarity inversion" patch set
written by Lothar Wassmann (v6 from 10.2014).
It is used to control backlight of panels via inverted PWM signal.
The "inversion" of PWM output is not an issue at such devices, since
separate GPIO pin is responsible for enabling and disabling the panel's
backlight.
This patch should be put on top of:
https://patchwork.kernel.org/patch/5065841/
https://patchwork.kernel.org/patch/5065821/
https://patchwork.kernel.org/patch/5065811/
Signed-off-by: Lukasz Majewski <l.majewski@majess.pl>
---
drivers/pwm/pwm-imx.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 471a99e..c37d223 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -181,7 +181,7 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
if (enable)
cr |= MX3_PWMCR_EN;
- if (pwm->polarity == PWM_POLARITY_INVERSED)
+ if (pwm->args.polarity == PWM_POLARITY_INVERSED)
cr |= MX3_PWMCR_POUTC;
writel(cr, imx->mmio_base + MX3_PWMCR);
@@ -201,11 +201,6 @@ static void imx_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
else
val &= ~MX3_PWMCR_EN;
- if (chip->pwms[0].polarity == PWM_POLARITY_INVERSED)
- val |= MX3_PWMCR_POUTC;
- else
- val &= ~MX3_PWMCR_POUTC;
-
writel(val, imx->mmio_base + MX3_PWMCR);
}
@@ -253,6 +248,19 @@ static int imx_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
enum pwm_polarity polarity)
{
struct imx_chip *imx = to_imx_chip(chip);
+ u32 val;
+
+ if (polarity == pwm->args.polarity)
+ return 0;
+
+ val = readl(imx->mmio_base + MX3_PWMCR);
+
+ if (polarity == PWM_POLARITY_INVERSED)
+ val |= MX3_PWMCR_POUTC;
+ else
+ val &= ~MX3_PWMCR_POUTC;
+
+ writel(val, imx->mmio_base + MX3_PWMCR);
dev_dbg(imx->chip.dev, "%s: polarity set to %s\n", __func__,
polarity == PWM_POLARITY_INVERSED ? "inverted" : "normal");
--
2.1.4
^ permalink raw reply related
* [PATCH] pwm: imx: Port "pwm: imx: support output polarity inversion" to Linux v4.7
From: Lukasz Majewski @ 2016-09-11 9:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473584109-10710-1-git-send-email-l.majewski@majess.pl>
Dear Lothar, Stefan,
> This patch ports "pwm: imx: support output polarity inversion" patch
> set written by Lothar Wassmann (v6 from 10.2014).
>
I've read the e-mail from Stefan regarding missing support for pwm-imx
polarity inversion feature.
I also would like to see it in ML. Hence, my patch. Lothar, please feel
free to squash it to your patches when you (I hope :-) ) will prepare
v7 of this feature.
I hope that this would help.
Best regards,
?ukasz Majewski
> It is used to control backlight of panels via inverted PWM signal.
>
> The "inversion" of PWM output is not an issue at such devices, since
> separate GPIO pin is responsible for enabling and disabling the
> panel's backlight.
>
> This patch should be put on top of:
>
> https://patchwork.kernel.org/patch/5065841/
> https://patchwork.kernel.org/patch/5065821/
> https://patchwork.kernel.org/patch/5065811/
>
>
> Signed-off-by: Lukasz Majewski <l.majewski@majess.pl>
> ---
> drivers/pwm/pwm-imx.c | 20 ++++++++++++++------
> 1 file changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
> index 471a99e..c37d223 100644
> --- a/drivers/pwm/pwm-imx.c
> +++ b/drivers/pwm/pwm-imx.c
> @@ -181,7 +181,7 @@ static int imx_pwm_config_v2(struct pwm_chip
> *chip, if (enable)
> cr |= MX3_PWMCR_EN;
>
> - if (pwm->polarity == PWM_POLARITY_INVERSED)
> + if (pwm->args.polarity == PWM_POLARITY_INVERSED)
> cr |= MX3_PWMCR_POUTC;
>
> writel(cr, imx->mmio_base + MX3_PWMCR);
> @@ -201,11 +201,6 @@ static void imx_pwm_set_enable_v2(struct
> pwm_chip *chip, bool enable) else
> val &= ~MX3_PWMCR_EN;
>
> - if (chip->pwms[0].polarity == PWM_POLARITY_INVERSED)
> - val |= MX3_PWMCR_POUTC;
> - else
> - val &= ~MX3_PWMCR_POUTC;
> -
> writel(val, imx->mmio_base + MX3_PWMCR);
> }
>
> @@ -253,6 +248,19 @@ static int imx_pwm_set_polarity(struct pwm_chip
> *chip, struct pwm_device *pwm, enum pwm_polarity polarity)
> {
> struct imx_chip *imx = to_imx_chip(chip);
> + u32 val;
> +
> + if (polarity == pwm->args.polarity)
> + return 0;
> +
> + val = readl(imx->mmio_base + MX3_PWMCR);
> +
> + if (polarity == PWM_POLARITY_INVERSED)
> + val |= MX3_PWMCR_POUTC;
> + else
> + val &= ~MX3_PWMCR_POUTC;
> +
> + writel(val, imx->mmio_base + MX3_PWMCR);
>
> dev_dbg(imx->chip.dev, "%s: polarity set to %s\n", __func__,
> polarity == PWM_POLARITY_INVERSED ? "inverted" :
> "normal");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160911/01d39f48/attachment-0001.sig>
^ permalink raw reply
* [PATCH 0/6] constify gpio_chip structures
From: Julia Lawall @ 2016-09-11 12:14 UTC (permalink / raw)
To: linux-arm-kernel
Constify gpio_chip structures
---
drivers/gpio/gpio-arizona.c | 2 +-
drivers/gpio/gpio-bcm-kona.c | 2 +-
drivers/gpio/gpio-da9052.c | 2 +-
drivers/gpio/gpio-da9055.c | 2 +-
drivers/gpio/gpio-it87.c | 2 +-
drivers/gpio/gpio-lp873x.c | 2 +-
drivers/gpio/gpio-lpc18xx.c | 2 +-
drivers/gpio/gpio-pisosr.c | 2 +-
drivers/gpio/gpio-sch.c | 2 +-
drivers/gpio/gpio-stmpe.c | 2 +-
drivers/gpio/gpio-tc3589x.c | 2 +-
drivers/gpio/gpio-tpic2810.c | 2 +-
drivers/gpio/gpio-tps65086.c | 2 +-
drivers/gpio/gpio-tps65218.c | 2 +-
drivers/gpio/gpio-tps65912.c | 2 +-
drivers/gpio/gpio-ts4900.c | 2 +-
drivers/gpio/gpio-twl4030.c | 2 +-
drivers/gpio/gpio-wm831x.c | 2 +-
drivers/gpio/gpio-wm8350.c | 2 +-
drivers/gpio/gpio-wm8994.c | 2 +-
drivers/mfd/sm501.c | 2 +-
drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 +-
drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +-
sound/soc/codecs/rt5677.c | 2 +-
sound/soc/codecs/wm5100.c | 2 +-
sound/soc/codecs/wm8903.c | 2 +-
sound/soc/codecs/wm8962.c | 2 +-
sound/soc/codecs/wm8996.c | 2 +-
sound/soc/soc-ac97.c | 2 +-
29 files changed, 29 insertions(+), 29 deletions(-)
^ permalink raw reply
* [PATCH 1/6] gpio: constify gpio_chip structures
From: Julia Lawall @ 2016-09-11 12:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473596082-32690-1-git-send-email-Julia.Lawall@lip6.fr>
These structures are only used to copy into other structures, so declare
them as const.
The semantic patch that makes this change is as follows:
(http://coccinelle.lip6.fr/)
// <smpl>
@r disable optional_qualifier@
identifier i;
position p;
@@
static struct gpio_chip i at p = { ... };
@ok@
identifier r.i;
expression e;
position p;
@@
e = i at p;
@bad@
position p != {r.p,ok.p};
identifier r.i;
struct gpio_chip e;
@@
e at i@p
@depends on !bad disable optional_qualifier@
identifier r.i;
@@
static
+const
struct gpio_chip i = { ... };
// </smpl>
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/gpio/gpio-arizona.c | 2 +-
drivers/gpio/gpio-bcm-kona.c | 2 +-
drivers/gpio/gpio-da9052.c | 2 +-
drivers/gpio/gpio-da9055.c | 2 +-
drivers/gpio/gpio-it87.c | 2 +-
drivers/gpio/gpio-lp873x.c | 2 +-
drivers/gpio/gpio-lpc18xx.c | 2 +-
drivers/gpio/gpio-pisosr.c | 2 +-
drivers/gpio/gpio-sch.c | 2 +-
drivers/gpio/gpio-stmpe.c | 2 +-
drivers/gpio/gpio-tc3589x.c | 2 +-
drivers/gpio/gpio-tpic2810.c | 2 +-
drivers/gpio/gpio-tps65086.c | 2 +-
drivers/gpio/gpio-tps65218.c | 2 +-
drivers/gpio/gpio-tps65912.c | 2 +-
drivers/gpio/gpio-ts4900.c | 2 +-
drivers/gpio/gpio-twl4030.c | 2 +-
drivers/gpio/gpio-wm831x.c | 2 +-
drivers/gpio/gpio-wm8350.c | 2 +-
drivers/gpio/gpio-wm8994.c | 2 +-
20 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 9913704..4824628 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -79,7 +79,7 @@ static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
ARIZONA_GPN_LVL, value);
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "arizona",
.owner = THIS_MODULE,
.direction_input = arizona_gpio_direction_in,
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
index 21f97bc..533707f 100644
--- a/drivers/gpio/gpio-wm831x.c
+++ b/drivers/gpio/gpio-wm831x.c
@@ -247,7 +247,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
#define wm831x_gpio_dbg_show NULL
#endif
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "wm831x",
.owner = THIS_MODULE,
.direction_input = wm831x_gpio_direction_in,
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
index e976570..e46752e 100644
--- a/drivers/gpio/gpio-wm8350.c
+++ b/drivers/gpio/gpio-wm8350.c
@@ -93,7 +93,7 @@ static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "wm8350",
.owner = THIS_MODULE,
.direction_input = wm8350_gpio_direction_in,
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
index 2457aac..68410fd 100644
--- a/drivers/gpio/gpio-wm8994.c
+++ b/drivers/gpio/gpio-wm8994.c
@@ -249,7 +249,7 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
#define wm8994_gpio_dbg_show NULL
#endif
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "wm8994",
.owner = THIS_MODULE,
.request = wm8994_gpio_request,
diff --git a/drivers/gpio/gpio-it87.c b/drivers/gpio/gpio-it87.c
index 63a962d..45d29e4 100644
--- a/drivers/gpio/gpio-it87.c
+++ b/drivers/gpio/gpio-it87.c
@@ -273,7 +273,7 @@ exit:
return rc;
}
-static struct gpio_chip it87_template_chip = {
+static const struct gpio_chip it87_template_chip = {
.label = KBUILD_MODNAME,
.owner = THIS_MODULE,
.request = it87_gpio_request,
diff --git a/drivers/gpio/gpio-lp873x.c b/drivers/gpio/gpio-lp873x.c
index f10d49d..134f6b3 100644
--- a/drivers/gpio/gpio-lp873x.c
+++ b/drivers/gpio/gpio-lp873x.c
@@ -124,7 +124,7 @@ static int lp873x_gpio_set_single_ended(struct gpio_chip *gc,
}
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "lp873x-gpio",
.owner = THIS_MODULE,
.request = lp873x_gpio_request,
diff --git a/drivers/gpio/gpio-pisosr.c b/drivers/gpio/gpio-pisosr.c
index cb14b8d..f5545049 100644
--- a/drivers/gpio/gpio-pisosr.c
+++ b/drivers/gpio/gpio-pisosr.c
@@ -90,7 +90,7 @@ static int pisosr_gpio_get(struct gpio_chip *chip, unsigned offset)
return (gpio->buffer[offset / 8] >> (offset % 8)) & 0x1;
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "pisosr-gpio",
.owner = THIS_MODULE,
.get_direction = pisosr_gpio_get_direction,
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index eb43ae4..5450044 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -138,7 +138,7 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
return 0;
}
-static struct gpio_chip sch_gpio_chip = {
+static const struct gpio_chip sch_gpio_chip = {
.label = "sch_gpio",
.owner = THIS_MODULE,
.direction_input = sch_gpio_direction_in,
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 5c0d818..b51c5be 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -121,7 +121,7 @@ static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO);
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "stmpe",
.owner = THIS_MODULE,
.get_direction = stmpe_gpio_get_direction,
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 8b36593..5baa457 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -124,7 +124,7 @@ static int tc3589x_gpio_single_ended(struct gpio_chip *chip,
return -ENOTSUPP;
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "tc3589x",
.owner = THIS_MODULE,
.direction_input = tc3589x_gpio_direction_input,
diff --git a/drivers/gpio/gpio-tpic2810.c b/drivers/gpio/gpio-tpic2810.c
index cace79c..c8b34d7 100644
--- a/drivers/gpio/gpio-tpic2810.c
+++ b/drivers/gpio/gpio-tpic2810.c
@@ -87,7 +87,7 @@ static void tpic2810_set_multiple(struct gpio_chip *chip, unsigned long *mask,
tpic2810_set_mask_bits(chip, *mask, *bits);
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "tpic2810",
.owner = THIS_MODULE,
.get_direction = tpic2810_get_direction,
diff --git a/drivers/gpio/gpio-tps65086.c b/drivers/gpio/gpio-tps65086.c
index 8e25f01..b23c4d2 100644
--- a/drivers/gpio/gpio-tps65086.c
+++ b/drivers/gpio/gpio-tps65086.c
@@ -72,7 +72,7 @@ static void tps65086_gpio_set(struct gpio_chip *chip, unsigned offset,
BIT(4 + offset), value ? BIT(4 + offset) : 0);
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "tps65086-gpio",
.owner = THIS_MODULE,
.get_direction = tps65086_gpio_get_direction,
diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c
index 1c09a19..03e0dfb 100644
--- a/drivers/gpio/gpio-tps65218.c
+++ b/drivers/gpio/gpio-tps65218.c
@@ -172,7 +172,7 @@ static int tps65218_gpio_set_single_ended(struct gpio_chip *gc,
return -ENOTSUPP;
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "gpio-tps65218",
.owner = THIS_MODULE,
.request = tps65218_gpio_request,
diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
index acfd30a..abc0798 100644
--- a/drivers/gpio/gpio-tps65912.c
+++ b/drivers/gpio/gpio-tps65912.c
@@ -90,7 +90,7 @@ static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset,
GPIO_SET_MASK, value ? GPIO_SET_MASK : 0);
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "tps65912-gpio",
.owner = THIS_MODULE,
.get_direction = tps65912_gpio_get_direction,
diff --git a/drivers/gpio/gpio-ts4900.c b/drivers/gpio/gpio-ts4900.c
index 9dd9aca..5bd2172 100644
--- a/drivers/gpio/gpio-ts4900.c
+++ b/drivers/gpio/gpio-ts4900.c
@@ -101,7 +101,7 @@ static const struct regmap_config ts4900_regmap_config = {
.val_bits = 8,
};
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "ts4900-gpio",
.owner = THIS_MODULE,
.get_direction = ts4900_gpio_get_direction,
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index 4b807b0..dfcfbba 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -381,7 +381,7 @@ static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
: -EINVAL;
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "twl4030",
.owner = THIS_MODULE,
.request = twl_request,
diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c
index 98832c9..f12e02e 100644
--- a/drivers/gpio/gpio-lpc18xx.c
+++ b/drivers/gpio/gpio-lpc18xx.c
@@ -78,7 +78,7 @@ static int lpc18xx_gpio_direction_output(struct gpio_chip *chip,
return lpc18xx_gpio_direction(chip, offset, true);
}
-static struct gpio_chip lpc18xx_chip = {
+static const struct gpio_chip lpc18xx_chip = {
.label = "lpc18xx/43xx-gpio",
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
index e29553b..dd8977c 100644
--- a/drivers/gpio/gpio-da9052.c
+++ b/drivers/gpio/gpio-da9052.c
@@ -184,7 +184,7 @@ static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
return irq;
}
-static struct gpio_chip reference_gp = {
+static const struct gpio_chip reference_gp = {
.label = "da9052-gpio",
.owner = THIS_MODULE,
.get = da9052_gpio_get,
diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c
index 2c2c18d..82053b5 100644
--- a/drivers/gpio/gpio-da9055.c
+++ b/drivers/gpio/gpio-da9055.c
@@ -121,7 +121,7 @@ static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
DA9055_IRQ_GPI0 + offset);
}
-static struct gpio_chip reference_gp = {
+static const struct gpio_chip reference_gp = {
.label = "da9055-gpio",
.owner = THIS_MODULE,
.get = da9055_gpio_get,
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
index 953e4b8..3d1cf01 100644
--- a/drivers/gpio/gpio-bcm-kona.c
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -308,7 +308,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
return 0;
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "bcm-kona-gpio",
.owner = THIS_MODULE,
.request = bcm_kona_gpio_request,
^ permalink raw reply related
* [PATCH 3/6] pinctrl: mediatek: constify gpio_chip structures
From: Julia Lawall @ 2016-09-11 12:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473596082-32690-1-git-send-email-Julia.Lawall@lip6.fr>
These structures are only used to copy into other structures, so declare
them as const.
The semantic patch that makes this change is as follows:
(http://coccinelle.lip6.fr/)
// <smpl>
@r disable optional_qualifier@
identifier i;
position p;
@@
static struct gpio_chip i at p = { ... };
@ok@
identifier r.i;
expression e;
position p;
@@
e = i at p;
@bad@
position p != {r.p,ok.p};
identifier r.i;
struct gpio_chip e;
@@
e at i@p
@depends on !bad disable optional_qualifier@
identifier r.i;
@@
static
+const
struct gpio_chip i = { ... };
// </smpl>
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index ba2b03d..f9aef2a 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1054,7 +1054,7 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
return 0;
}
-static struct gpio_chip mtk_gpio_chip = {
+static const struct gpio_chip mtk_gpio_chip = {
.owner = THIS_MODULE,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
^ permalink raw reply related
* [PATCH 4/6] pinctrl: stm32: constify gpio_chip structures
From: Julia Lawall @ 2016-09-11 12:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473596082-32690-1-git-send-email-Julia.Lawall@lip6.fr>
These structures are only used to copy into other structures, so declare
them as const.
The semantic patch that makes this change is as follows:
(http://coccinelle.lip6.fr/)
// <smpl>
@r disable optional_qualifier@
identifier i;
position p;
@@
static struct gpio_chip i at p = { ... };
@ok@
identifier r.i;
expression e;
position p;
@@
e = i at p;
@bad@
position p != {r.p,ok.p};
identifier r.i;
struct gpio_chip e;
@@
e at i@p
@depends on !bad disable optional_qualifier@
identifier r.i;
@@
static
+const
struct gpio_chip i = { ... };
// </smpl>
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 4ae596b..6d92351 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -174,7 +174,7 @@ static int stm32_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
-static struct gpio_chip stm32_gpio_template = {
+static const struct gpio_chip stm32_gpio_template = {
.request = stm32_gpio_request,
.free = stm32_gpio_free,
.get = stm32_gpio_get,
^ permalink raw reply related
* [PATCH v2 0/7] arm64: Privileged Access Never using TTBR0_EL1 switching
From: Catalin Marinas @ 2016-09-11 12:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu9P4_90LEoyu1apeKZH20imLPD_EiB=zNAvyin-67ivKQ@mail.gmail.com>
On Sat, Sep 10, 2016 at 11:56:14AM +0100, Ard Biesheuvel wrote:
> On 10 September 2016 at 10:51, Catalin Marinas <catalin.marinas@arm.com> wrote:
> > On Fri, Sep 02, 2016 at 04:02:06PM +0100, Catalin Marinas wrote:
> >> This is the second version of the arm64 PAN emulation by disabling
> >> TTBR0_EL1 accesses. The major change from v1 is the use of a thread_info
> >> member to store the real TTBR0_EL1 value. The advantage is slightly
> >> simpler assembler macros for uaccess_enable with the downside that
> >> switch_mm() must always update the saved ttbr0 even if there is no mm
> >> switch.
> >
> > FYI, I got the Juno board rebooting in a loop with defconfig +
> > ARM64_TTBR0_PAN enabled. It takes about 20-40 reboots to get the panic
> > below on the EFI run-time services. I'll look into it on Monday (and
> > cc'ing Ard who I forgot to add originally). Including the full log
> > below:
>
> Could you please try to reproduce it again, but this time with
> 'efi=debug' on the kernel command line? Thanks
Just for the record, following our private email exchanges: when
executing an EFI runtime service, an interrupt comes in and Linux
disables TTBR0 accesses. When returning from interrupt, the kernel
restores TTBR0_EL1 with the value in current thread_info which is
different from the efi_mm one.
Two potential solutions:
1. Temporarily update the current thread_info ttbr0 during EFI runtime
services (preemption is disabled). Suggested by Ard
2. Go back to per-CPU saving of TTBR0_EL1 as in v1
I'll implement 1 on Monday and give it a try.
--
Catalin
^ permalink raw reply
* [PATCH v2 0/2] add support for the SDIO pins on GXBB
From: Martin Blumenstingl @ 2016-09-11 12:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160828164725.19429-1-martin.blumenstingl@googlemail.com>
This series adds the pins for the SDIO controller (sd_emmc_a) found on
Meson GXBB SoCs.
Changes since v1:
- add the missing SDIO interrupt pin:
The initial pinctrl patch was already applied to linux-pinctrl's
for-next branch, so patch 1 applies on top of the already existing
patch (both can be squashed if needed).
The dts patch was not applied anywhere yet, so patch 2 contains a
fixed version of the patch (provided by Neil Armstrong - thanks!).
Martin Blumenstingl (1):
pinctrl: meson-gxbb: add the missing SDIO interrupt pin
Neil Armstrong (1):
ARM64: dts: meson-gxbb: add the SDIO pins
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 19 +++++++++++++++++++
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 4 +++-
2 files changed, 22 insertions(+), 1 deletion(-)
--
2.9.3
^ permalink raw reply
* [PATCH v2 1/2] pinctrl: meson-gxbb: add the missing SDIO interrupt pin
From: Martin Blumenstingl @ 2016-09-11 12:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160911123903.20027-1-martin.blumenstingl@googlemail.com>
This adds the SDIO interrupt pin which can be used by sd_emmc_a.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Suggested-by: Neil Armstrong <narmstrong@baylibre.com>
Fixes: 29885a656511 ("pinctrl: meson-gxbb: add the pins for the
SDIO/sd_emmc_a controller")
---
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index fb479b8..4a27ae0 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -169,6 +169,7 @@ static const unsigned int sdio_d2_pins[] = { PIN(GPIOX_2, EE_OFF) };
static const unsigned int sdio_d3_pins[] = { PIN(GPIOX_3, EE_OFF) };
static const unsigned int sdio_cmd_pins[] = { PIN(GPIOX_4, EE_OFF) };
static const unsigned int sdio_clk_pins[] = { PIN(GPIOX_5, EE_OFF) };
+static const unsigned int sdio_irq_pins[] = { PIN(GPIOX_7, EE_OFF) };
static const unsigned int uart_tx_a_pins[] = { PIN(GPIOX_12, EE_OFF) };
static const unsigned int uart_rx_a_pins[] = { PIN(GPIOX_13, EE_OFF) };
@@ -383,6 +384,7 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
GROUP(sdio_d3, 8, 2),
GROUP(sdio_cmd, 8, 1),
GROUP(sdio_clk, 8, 0),
+ GROUP(sdio_irq, 8, 11),
GROUP(uart_tx_a, 4, 13),
GROUP(uart_rx_a, 4, 12),
GROUP(uart_cts_a, 4, 11),
@@ -522,7 +524,7 @@ static const char * const sdcard_groups[] = {
static const char * const sdio_groups[] = {
"sdio_d0", "sdio_d1", "sdio_d2", "sdio_d3",
- "sdio_cmd", "sdio_clk",
+ "sdio_cmd", "sdio_clk", "sdio_irq",
};
static const char * const uart_a_groups[] = {
--
2.9.3
^ permalink raw reply related
* [PATCH v2 2/2] ARM64: dts: meson-gxbb: add the SDIO pins
From: Martin Blumenstingl @ 2016-09-11 12:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160911123903.20027-1-martin.blumenstingl@googlemail.com>
From: Neil Armstrong <narmstrong@baylibre.com>
This is used to configure the pins of the sd_emmc_a controller to
which an SDIO module is connected (when available).
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Tested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index c84cacf..fe2a1fc 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -394,6 +394,25 @@
};
};
+ sdio_pins: sdio {
+ mux {
+ groups = "sdio_d0",
+ "sdio_d1",
+ "sdio_d2",
+ "sdio_d3",
+ "sdio_cmd",
+ "sdio_clk";
+ function = "sdio";
+ };
+ };
+
+ sdio_irq_pins: sdio_irq {
+ mux {
+ groups = "sdio_irq";
+ function = "sdio";
+ };
+ };
+
uart_a_pins: uart_a {
mux {
groups = "uart_tx_a",
--
2.9.3
^ permalink raw reply related
* [PATCH 1/6] gpio: constify gpio_chip structures
From: Joachim Eastwood @ 2016-09-11 13:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473596082-32690-2-git-send-email-Julia.Lawall@lip6.fr>
Hi Julia,
On 11 September 2016 at 14:14, Julia Lawall <Julia.Lawall@lip6.fr> wrote:
> These structures are only used to copy into other structures, so declare
> them as const.
>
> The semantic patch that makes this change is as follows:
> (http://coccinelle.lip6.fr/)
>
> // <smpl>
> @r disable optional_qualifier@
> identifier i;
> position p;
> @@
> static struct gpio_chip i at p = { ... };
>
> @ok@
> identifier r.i;
> expression e;
> position p;
> @@
> e = i at p;
>
> @bad@
> position p != {r.p,ok.p};
> identifier r.i;
> struct gpio_chip e;
> @@
> e at i@p
>
> @depends on !bad disable optional_qualifier@
> identifier r.i;
> @@
> static
> +const
> struct gpio_chip i = { ... };
> // </smpl>
>
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
>
> ---
> drivers/gpio/gpio-arizona.c | 2 +-
> drivers/gpio/gpio-bcm-kona.c | 2 +-
> drivers/gpio/gpio-da9052.c | 2 +-
> drivers/gpio/gpio-da9055.c | 2 +-
> drivers/gpio/gpio-it87.c | 2 +-
> drivers/gpio/gpio-lp873x.c | 2 +-
> drivers/gpio/gpio-lpc18xx.c | 2 +-
> drivers/gpio/gpio-pisosr.c | 2 +-
> drivers/gpio/gpio-sch.c | 2 +-
> drivers/gpio/gpio-stmpe.c | 2 +-
> drivers/gpio/gpio-tc3589x.c | 2 +-
> drivers/gpio/gpio-tpic2810.c | 2 +-
> drivers/gpio/gpio-tps65086.c | 2 +-
> drivers/gpio/gpio-tps65218.c | 2 +-
> drivers/gpio/gpio-tps65912.c | 2 +-
> drivers/gpio/gpio-ts4900.c | 2 +-
> drivers/gpio/gpio-twl4030.c | 2 +-
> drivers/gpio/gpio-wm831x.c | 2 +-
> drivers/gpio/gpio-wm8350.c | 2 +-
> drivers/gpio/gpio-wm8994.c | 2 +-
> 20 files changed, 20 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c
> index 98832c9..f12e02e 100644
> --- a/drivers/gpio/gpio-lpc18xx.c
> +++ b/drivers/gpio/gpio-lpc18xx.c
> @@ -78,7 +78,7 @@ static int lpc18xx_gpio_direction_output(struct gpio_chip *chip,
> return lpc18xx_gpio_direction(chip, offset, true);
> }
>
> -static struct gpio_chip lpc18xx_chip = {
> +static const struct gpio_chip lpc18xx_chip = {
> .label = "lpc18xx/43xx-gpio",
> .request = gpiochip_generic_request,
> .free = gpiochip_generic_free,
For lpc18xx:
Acked-by: Joachim Eastwood <manabian@gmail.com>
regards,
Joachim Eastwood
^ permalink raw reply
* [PATCH v2 0/6] usb/phy: Add Amlogic Meson8b and GXBB USB support
From: Martin Blumenstingl @ 2016-09-11 13:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160904213152.25837-1-martin.blumenstingl@googlemail.com>
This series adds initial support for the DWC2 USB controllers and Meson
specific USB PHYs found in Meson8b and GXBB SoCs, which means:
- new DWC2 bindings and platform specific core configuration
- a PHY driver supporting the USB2 PHY on Meson8b and GXBB SoCs
The first DWC2 controller is usually configured in OTG mode, whereas
the second DWC2 controller is usually configured in host(-only) mode.
Unfortunately no (public) datasheet is available and the reference PHY
driver does not contain comments or speaking register name definitions.
The nice people from BayLibre have already requested the datasheets
(currently we can for example only guess that there is a mux clock
inside the PHY, but we don't know it's parents).
With this series both DWC2 controllers are configure in host mode,
because the reference driver polls some of the PHY registers in OTG
mode and then re-configures the dwc2 driver instance accordingly (if
anyone is interested, this is the relevant piece of code: [0]). This
seems good enough for the beginning though.
Changes since v1:
- the patch "clk: gxbb: expose USB clocks" was not sent again as it was
already applied by Kevin Hilman (thanks!)
- dropped (unnecessary) USB PHY bus from .dts
- remove underscores from PHY node names in .dts
- rename the dwc2 nodes in the .dts to usb (as per convention)
- remove unused struct reset_control from phy_meson_usb2_priv
- removed refcounting "reset" workaround and only specify the reset for
the first PHY in the .dts (Jerome has reported that his boards don't
need the explicit reset, while my board needs it). In addition (to
make this work) the driver now treats the reset as optional
- use the RESET_USB_OTG definition (from
<dt-bindings/reset/amlogic,meson-gxbb-reset.h>) instead of a magic
number in the .dts
[0] https://github.com/150balbes/Amlogic_s905-kernel/blob/master/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c#L642
Jerome Brunet (2):
usb: dwc2: add support for Meson8b and GXBB SoCs
ARM64: meson-gxbb-p20x: Enable USB Nodes
Martin Blumenstingl (4):
Documentation: dt-bindings: Add documentation for the Meson USB2 PHYs
phy: meson: add USB2 PHY support for Meson8b and GXBB
ARM64: meson-gxbb: add USB Nodes
ARM64: meson-gxbb-vega-s95: Enable USB Nodes
.../devicetree/bindings/phy/meson-usb2-phy.txt | 27 ++
Documentation/devicetree/bindings/usb/dwc2.txt | 2 +
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 29 +++
.../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 30 +++
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 43 ++++
drivers/phy/Kconfig | 11 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-meson-usb2.c | 280 +++++++++++++++++++++
drivers/usb/dwc2/platform.c | 34 +++
9 files changed, 457 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
create mode 100644 drivers/phy/phy-meson-usb2.c
--
2.9.3
^ permalink raw reply
* [PATCH v2 1/6] usb: dwc2: add support for Meson8b and GXBB SoCs
From: Martin Blumenstingl @ 2016-09-11 13:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160911134111.31141-1-martin.blumenstingl@googlemail.com>
From: Jerome Brunet <jbrunet@baylibre.com>
Add compatible strings for amlogic Meson8b and GXBB SoCs with the
corresponding configuration parameters.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
Documentation/devicetree/bindings/usb/dwc2.txt | 2 ++
drivers/usb/dwc2/platform.c | 34 ++++++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt
index 20a68bf..2c30a54 100644
--- a/Documentation/devicetree/bindings/usb/dwc2.txt
+++ b/Documentation/devicetree/bindings/usb/dwc2.txt
@@ -10,6 +10,8 @@ Required properties:
- "rockchip,rk3288-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3288 Soc;
- "lantiq,arx100-usb": The DWC2 USB controller instance in Lantiq ARX SoCs;
- "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs;
+ - "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs;
+ - "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs;
- snps,dwc2: A generic DWC2 USB controller with default parameters.
- reg : Should contain 1 register range (address and length)
- interrupts : Should contain 1 interrupt
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index fc6f525..8f7b34c 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -181,6 +181,38 @@ static const struct dwc2_core_params params_ltq = {
.hibernation = -1,
};
+static const struct dwc2_core_params params_amlogic = {
+ .otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE,
+ .otg_ver = -1,
+ .dma_enable = 1,
+ .dma_desc_enable = 0,
+ .dma_desc_fs_enable = 0,
+ .speed = DWC2_SPEED_PARAM_HIGH,
+ .enable_dynamic_fifo = 1,
+ .en_multiple_tx_fifo = -1,
+ .host_rx_fifo_size = 512,
+ .host_nperio_tx_fifo_size = 500,
+ .host_perio_tx_fifo_size = 500,
+ .max_transfer_size = -1,
+ .max_packet_count = -1,
+ .host_channels = 16,
+ .phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
+ .phy_utmi_width = -1,
+ .phy_ulpi_ddr = -1,
+ .phy_ulpi_ext_vbus = -1,
+ .i2c_enable = -1,
+ .ulpi_fs_ls = -1,
+ .host_support_fs_ls_low_power = -1,
+ .host_ls_low_power_phy_clk = -1,
+ .ts_dline = -1,
+ .reload_ctl = 1,
+ .ahbcfg = GAHBCFG_HBSTLEN_INCR8 <<
+ GAHBCFG_HBSTLEN_SHIFT,
+ .uframe_sched = 0,
+ .external_id_pin_ctl = -1,
+ .hibernation = -1,
+};
+
/*
* Check the dr_mode against the module configuration and hardware
* capabilities.
@@ -464,6 +496,8 @@ static const struct of_device_id dwc2_of_match_table[] = {
{ .compatible = "lantiq,xrx200-usb", .data = ¶ms_ltq },
{ .compatible = "snps,dwc2", .data = NULL },
{ .compatible = "samsung,s3c6400-hsotg", .data = NULL},
+ { .compatible = "amlogic,meson8b-usb", .data = ¶ms_amlogic },
+ { .compatible = "amlogic,meson-gxbb-usb", .data = ¶ms_amlogic },
{},
};
MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
--
2.9.3
^ permalink raw reply related
* [PATCH v2 2/6] Documentation: dt-bindings: Add documentation for the Meson USB2 PHYs
From: Martin Blumenstingl @ 2016-09-11 13:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160911134111.31141-1-martin.blumenstingl@googlemail.com>
Add the documentation for the bindings for the Meson8b and GXBB USB2
PHYs.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
.../devicetree/bindings/phy/meson-usb2-phy.txt | 27 ++++++++++++++++++++++
1 file changed, 27 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
diff --git a/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt b/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
new file mode 100644
index 0000000..9da5ea2
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
@@ -0,0 +1,27 @@
+* Amlogic USB2 PHY
+
+Required properties:
+- compatible: Depending on the platform this should be one of:
+ "amlogic,meson8b-usb2-phy"
+ "amlogic,meson-gxbb-usb2-phy"
+- reg: The base address and length of the registers
+- #phys-cells: should be 0 (see phy-bindings.txt in this directory)
+- clocks: phandle and clock identifier for the phy clocks
+- clock-names: "usb_general" and "usb"
+
+Optional properties:
+- resets: reference to the reset controller
+- phy-supply: see phy-bindings.txt in this directory
+
+
+Example:
+
+usb0_phy: usb_phy at 0 {
+ compatible = "amlogic,meson-gxbb-usb2-phy";
+ #phy-cells = <0>;
+ reg = <0x0 0x0 0x0 0x20>;
+ resets = <&reset RESET_USB_OTG>;
+ clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
+ clock-names = "usb_general", "usb";
+ phy-supply = <&usb_vbus>;
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 3/6] phy: meson: add USB2 PHY support for Meson8b and GXBB
From: Martin Blumenstingl @ 2016-09-11 13:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160911134111.31141-1-martin.blumenstingl@googlemail.com>
This is a new driver for the USB PHY found in Meson8b and GXBB SoCs.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Tested-by: Kevin Hilman <khilman@baylibre.com>
---
drivers/phy/Kconfig | 11 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-meson-usb2.c | 280 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 292 insertions(+)
create mode 100644 drivers/phy/phy-meson-usb2.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 19bff3a..6ad87ec 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -453,4 +453,15 @@ config PHY_NS2_PCIE
help
Enable this to support the Broadcom Northstar2 PCIe PHY.
If unsure, say N.
+
+config PHY_MESON_USB2
+ tristate "Meson USB2 PHY driver"
+ default ARCH_MESON
+ depends on OF && (ARCH_MESON || COMPILE_TEST)
+ select GENERIC_PHY
+ help
+ Enable this to support the Meson USB2 PHYs found in Meson8b
+ and GXBB SoCs.
+ If unsure, say N.
+
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 90ae198..dd507ac 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -56,3 +56,4 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
+obj-$(CONFIG_PHY_MESON_USB2) += phy-meson-usb2.o
diff --git a/drivers/phy/phy-meson-usb2.c b/drivers/phy/phy-meson-usb2.c
new file mode 100644
index 0000000..eece521
--- /dev/null
+++ b/drivers/phy/phy-meson-usb2.c
@@ -0,0 +1,280 @@
+/*
+ * Meson USB2 PHY driver
+ *
+ * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/reset.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/usb/of.h>
+
+#define REG_CONFIG 0x00
+ #define REG_CONFIG_CLK_EN BIT(0)
+ #define REG_CONFIG_CLK_SEL_MASK GENMASK(3, 1)
+ #define REG_CONFIG_CLK_DIV_MASK GENMASK(10, 4)
+ #define REG_CONFIG_CLK_32k_ALTSEL BIT(15)
+ #define REG_CONFIG_TEST_TRIG BIT(31)
+
+#define REG_CTRL 0x04
+ #define REG_CTRL_SOFT_PRST BIT(0)
+ #define REG_CTRL_SOFT_HRESET BIT(1)
+ #define REG_CTRL_SS_SCALEDOWN_MODE_MASK GENMASK(3, 2)
+ #define REG_CTRL_CLK_DET_RST BIT(4)
+ #define REG_CTRL_INTR_SEL BIT(5)
+ #define REG_CTRL_CLK_DETECTED BIT(8)
+ #define REG_CTRL_SOF_SENT_RCVD_TGL BIT(9)
+ #define REG_CTRL_SOF_TOGGLE_OUT BIT(10)
+ #define REG_CTRL_POWER_ON_RESET BIT(15)
+ #define REG_CTRL_SLEEPM BIT(16)
+ #define REG_CTRL_TX_BITSTUFF_ENN_H BIT(17)
+ #define REG_CTRL_TX_BITSTUFF_ENN BIT(18)
+ #define REG_CTRL_COMMON_ON BIT(19)
+ #define REG_CTRL_REF_CLK_SEL_MASK GENMASK(21, 20)
+ #define REG_CTRL_REF_CLK_SEL_SHIFT 20
+ #define REG_CTRL_FSEL_MASK GENMASK(24, 22)
+ #define REG_CTRL_FSEL_SHIFT 22
+ #define REG_CTRL_PORT_RESET BIT(25)
+ #define REG_CTRL_THREAD_ID_MASK GENMASK(31, 26)
+
+#define REG_ENDP_INTR 0x08
+
+/* bits [31:26], [24:21] and [15:3] seem to be read-only */
+#define REG_ADP_BC 0x0c
+ #define REG_ADP_BC_VBUS_VLD_EXT_SEL BIT(0)
+ #define REG_ADP_BC_VBUS_VLD_EXT BIT(1)
+ #define REG_ADP_BC_OTG_DISABLE BIT(2)
+ #define REG_ADP_BC_ID_PULLUP BIT(3)
+ #define REG_ADP_BC_DRV_VBUS BIT(4)
+ #define REG_ADP_BC_ADP_PRB_EN BIT(5)
+ #define REG_ADP_BC_ADP_DISCHARGE BIT(6)
+ #define REG_ADP_BC_ADP_CHARGE BIT(7)
+ #define REG_ADP_BC_SESS_END BIT(8)
+ #define REG_ADP_BC_DEVICE_SESS_VLD BIT(9)
+ #define REG_ADP_BC_B_VALID BIT(10)
+ #define REG_ADP_BC_A_VALID BIT(11)
+ #define REG_ADP_BC_ID_DIG BIT(12)
+ #define REG_ADP_BC_VBUS_VALID BIT(13)
+ #define REG_ADP_BC_ADP_PROBE BIT(14)
+ #define REG_ADP_BC_ADP_SENSE BIT(15)
+ #define REG_ADP_BC_ACA_ENABLE BIT(16)
+ #define REG_ADP_BC_DCD_ENABLE BIT(17)
+ #define REG_ADP_BC_VDAT_DET_EN_B BIT(18)
+ #define REG_ADP_BC_VDAT_SRC_EN_B BIT(19)
+ #define REG_ADP_BC_CHARGE_SEL BIT(20)
+ #define REG_ADP_BC_CHARGE_DETECT BIT(21)
+ #define REG_ADP_BC_ACA_PIN_RANGE_C BIT(22)
+ #define REG_ADP_BC_ACA_PIN_RANGE_B BIT(23)
+ #define REG_ADP_BC_ACA_PIN_RANGE_A BIT(24)
+ #define REG_ADP_BC_ACA_PIN_GND BIT(25)
+ #define REG_ADP_BC_ACA_PIN_FLOAT BIT(26)
+
+#define REG_DBG_UART 0x14
+
+#define REG_TEST 0x18
+ #define REG_TEST_DATA_IN_MASK GENMASK(3, 0)
+ #define REG_TEST_EN_MASK GENMASK(7, 4)
+ #define REG_TEST_ADDR_MASK GENMASK(11, 8)
+ #define REG_TEST_DATA_OUT_SEL BIT(12)
+ #define REG_TEST_CLK BIT(13)
+ #define REG_TEST_VA_TEST_EN_B_MASK GENMASK(15, 14)
+ #define REG_TEST_DATA_OUT_MASK GENMASK(19, 16)
+ #define REG_TEST_DISABLE_ID_PULLUP BIT(20)
+
+#define REG_TUNE 0x1c
+ #define REG_TUNE_TX_RES_TUNE_MASK GENMASK(1, 0)
+ #define REG_TUNE_TX_HSXV_TUNE_MASK GENMASK(3, 2)
+ #define REG_TUNE_TX_VREF_TUNE_MASK GENMASK(7, 4)
+ #define REG_TUNE_TX_RISE_TUNE_MASK GENMASK(9, 8)
+ #define REG_TUNE_TX_PREEMP_PULSE_TUNE BIT(10)
+ #define REG_TUNE_TX_PREEMP_AMP_TUNE_MASK GENMASK(12, 11)
+ #define REG_TUNE_TX_FSLS_TUNE_MASK GENMASK(16, 13)
+ #define REG_TUNE_SQRX_TUNE_MASK GENMASK(19, 17)
+ #define REG_TUNE_OTG_TUNE GENMASK(22, 20)
+ #define REG_TUNE_COMP_DIS_TUNE GENMASK(25, 23)
+ #define REG_TUNE_HOST_DM_PULLDOWN BIT(26)
+ #define REG_TUNE_HOST_DP_PULLDOWN BIT(27)
+
+#define RESET_COMPLETE_TIME 500
+#define ACA_ENABLE_COMPLETE_TIME 50
+
+struct phy_meson_usb2_priv {
+ void __iomem *regs;
+ enum usb_dr_mode dr_mode;
+ struct clk *clk_usb_general;
+ struct clk *clk_usb;
+};
+
+static u32 phy_meson_usb2_read(struct phy_meson_usb2_priv *phy_priv, u32 reg)
+{
+ return readl(phy_priv->regs + reg);
+}
+
+static void phy_meson_usb2_mask_bits(struct phy_meson_usb2_priv *phy_priv,
+ u32 reg, u32 mask, u32 value)
+{
+ u32 data;
+
+ data = phy_meson_usb2_read(phy_priv, reg);
+ data &= ~mask;
+ data |= (value & mask);
+
+ writel(data, phy_priv->regs + reg);
+}
+
+static int phy_meson_usb2_power_on(struct phy *phy)
+{
+ struct phy_meson_usb2_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ ret = clk_prepare_enable(priv->clk_usb_general);
+ if (ret) {
+ dev_err(&phy->dev, "Failed to enable USB general clock\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(priv->clk_usb);
+ if (ret) {
+ dev_err(&phy->dev, "Failed to enable USB DDR clock\n");
+ return ret;
+ }
+
+ phy_meson_usb2_mask_bits(priv, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL,
+ REG_CONFIG_CLK_32k_ALTSEL);
+
+ phy_meson_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK,
+ 0x2 << REG_CTRL_REF_CLK_SEL_SHIFT);
+
+ phy_meson_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_FSEL_MASK,
+ 0x5 << REG_CTRL_FSEL_SHIFT);
+
+ /* reset the PHY */
+ phy_meson_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET,
+ REG_CTRL_POWER_ON_RESET);
+ udelay(RESET_COMPLETE_TIME);
+ phy_meson_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0);
+ udelay(RESET_COMPLETE_TIME);
+
+ phy_meson_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT,
+ REG_CTRL_SOF_TOGGLE_OUT);
+
+ if (priv->dr_mode == USB_DR_MODE_HOST) {
+ phy_meson_usb2_mask_bits(priv, REG_ADP_BC,
+ REG_ADP_BC_ACA_ENABLE,
+ REG_ADP_BC_ACA_ENABLE);
+
+ udelay(ACA_ENABLE_COMPLETE_TIME);
+
+ if (phy_meson_usb2_read(priv, REG_ADP_BC) &
+ REG_ADP_BC_ACA_PIN_FLOAT) {
+ dev_warn(&phy->dev, "USB ID detect failed!\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int phy_meson_usb2_power_off(struct phy *phy)
+{
+ struct phy_meson_usb2_priv *priv = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(priv->clk_usb);
+ clk_disable_unprepare(priv->clk_usb_general);
+
+ return 0;
+}
+
+static const struct phy_ops phy_meson_usb2_ops = {
+ .power_on = phy_meson_usb2_power_on,
+ .power_off = phy_meson_usb2_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int phy_meson_usb2_probe(struct platform_device *pdev)
+{
+ struct phy_meson_usb2_priv *priv;
+ struct resource *res;
+ struct phy *phy;
+ struct phy_provider *phy_provider;
+ int ret;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->regs))
+ return PTR_ERR(priv->regs);
+
+ priv->clk_usb_general = devm_clk_get(&pdev->dev, "usb_general");
+ if (IS_ERR(priv->clk_usb_general))
+ return PTR_ERR(priv->clk_usb_general);
+
+ priv->clk_usb = devm_clk_get(&pdev->dev, "usb");
+ if (IS_ERR(priv->clk_usb))
+ return PTR_ERR(priv->clk_usb);
+
+ priv->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1);
+ if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
+ dev_err(&pdev->dev,
+ "missing dual role configuration of the controller\n");
+ return -EINVAL;
+ }
+
+ phy = devm_phy_create(&pdev->dev, NULL, &phy_meson_usb2_ops);
+ if (IS_ERR(phy)) {
+ dev_err(&pdev->dev, "failed to create PHY\n");
+ return PTR_ERR(phy);
+ }
+
+ /*
+ * No actual error check here because the hardware only has one reset
+ * line for both PHYs. Using a shared reset is not possible because we
+ * must call reset_control_reset to trigger the reset (which is not
+ * allowed for shared resets in the reset framework).
+ */
+ ret = device_reset_optional(&pdev->dev);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ phy_set_drvdata(phy, priv);
+
+ phy_provider =
+ devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id phy_meson_usb2_of_match[] = {
+ { .compatible = "amlogic,meson8b-usb2-phy", },
+ { .compatible = "amlogic,meson-gxbb-usb2-phy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, phy_meson_usb2_of_match);
+
+static struct platform_driver phy_meson_usb2_driver = {
+ .probe = phy_meson_usb2_probe,
+ .driver = {
+ .name = "phy-meson-usb2",
+ .of_match_table = phy_meson_usb2_of_match,
+ },
+};
+module_platform_driver(phy_meson_usb2_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
+MODULE_DESCRIPTION("Meson USB2 PHY driver");
+MODULE_LICENSE("GPL");
--
2.9.3
^ permalink raw reply related
* [PATCH v2 4/6] ARM64: meson-gxbb: add USB Nodes
From: Martin Blumenstingl @ 2016-09-11 13:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160911134111.31141-1-martin.blumenstingl@googlemail.com>
Add the nodes for the dwc2 USB controller and the related USB PHYs.
Currently we force usb0 to host mode because OTG is currently not
working in our PHY driver.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 43 +++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 2e8a3d9..30a8661 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -151,6 +151,25 @@
#size-cells = <2>;
ranges;
+ usb0_phy: phy at c0000000 {
+ compatible = "amlogic,meson-gxbb-usb2-phy";
+ #phy-cells = <0>;
+ reg = <0x0 0xc0000000 0x0 0x20>;
+ resets = <&reset RESET_USB_OTG>;
+ clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
+ clock-names = "usb_general", "usb";
+ status = "disabled";
+ };
+
+ usb1_phy: phy at c0000020 {
+ compatible = "amlogic,meson-gxbb-usb2-phy";
+ #phy-cells = <0>;
+ reg = <0x0 0xc0000020 0x0 0x20>;
+ clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1>;
+ clock-names = "usb_general", "usb";
+ status = "disabled";
+ };
+
cbus: cbus at c1100000 {
compatible = "simple-bus";
reg = <0x0 0xc1100000 0x0 0x100000>;
@@ -496,6 +515,30 @@
};
};
+ usb0: usb at c9000000 {
+ compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
+ reg = <0x0 0xc9000000 0x0 0x40000>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc CLKID_USB0_DDR_BRIDGE>;
+ clock-names = "otg";
+ phys = <&usb0_phy>;
+ phy-names = "usb2-phy";
+ dr_mode = "host";
+ status = "disabled";
+ };
+
+ usb1: usb at c9100000 {
+ compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
+ reg = <0x0 0xc9100000 0x0 0x40000>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
+ clock-names = "otg";
+ phys = <&usb1_phy>;
+ phy-names = "usb2-phy";
+ dr_mode = "host";
+ status = "disabled";
+ };
+
ethmac: ethernet at c9410000 {
compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
reg = <0x0 0xc9410000 0x0 0x10000
--
2.9.3
^ permalink raw reply related
* [PATCH v2 5/6] ARM64: meson-gxbb-p20x: Enable USB Nodes
From: Martin Blumenstingl @ 2016-09-11 13:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160911134111.31141-1-martin.blumenstingl@googlemail.com>
From: Jerome Brunet <jbrunet@baylibre.com>
Enable both gxbb USB controller and add a 5V regulator for the OTG port
VBUS
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 29 ++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index ce105fe..4493bce 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -93,6 +93,18 @@
compatible = "mmc-pwrseq-emmc";
reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
};
+
+ usb_vbus: regulator-usb0-vbus {
+ compatible = "regulator-fixed";
+
+ regulator-name = "USB0_VBUS";
+
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ gpio = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
};
/* This UART is brought out to the DB9 connector */
@@ -149,3 +161,20 @@
vmmc-supply = <&vcc_3v3>;
vmmcq-sumpply = <&vddio_boot>;
};
+
+&usb0_phy {
+ status = "okay";
+ phy-supply = <&usb_vbus>;
+};
+
+&usb1_phy {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 6/6] ARM64: meson-gxbb-vega-s95: Enable USB Nodes
From: Martin Blumenstingl @ 2016-09-11 13:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160911134111.31141-1-martin.blumenstingl@googlemail.com>
Enable both gxbb USB controller and add a 5V regulator for the OTG port
VBUS
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
.../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 30 ++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index 463185d..bad32e6 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -77,6 +77,19 @@
compatible = "mmc-pwrseq-emmc";
reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
};
+
+ usb_vbus: regulator-usb0-vbus {
+ compatible = "regulator-fixed";
+
+ regulator-name = "USB0_VBUS";
+
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ gpio = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
};
&uart_AO {
@@ -133,3 +146,20 @@
vmmc-supply = <&vcc_3v3>;
vmmcq-sumpply = <&vcc_1v8>;
};
+
+&usb0_phy {
+ status = "okay";
+ phy-supply = <&usb_vbus>;
+};
+
+&usb1_phy {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
--
2.9.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox