* [PATCH 1/2] ARM: dts: imx6ul-isiot: Add eMMC node
From: Jagan Teki @ 2017-01-15 21:50 UTC (permalink / raw)
To: Shawn Guo
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Matteo Lisi,
Michael Trimarchi, Jagan Teki
From: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
Add usdhc2 node, which is eMMC for Engicam Is.IoT MX6UL modules.
dmesg:
-----
mmc1: SDHCI controller on 2194000.usdhc [2194000.usdhc] using ADMA
mmc1: new DDR MMC card at address 0001
mmcblk1: mmc1:0001 M62704 3.53 GiB
Cc: Matteo Lisi <matteo.lisi-4s7YQHO/iPVBDgjK7y7TUQ@public.gmane.org>
Cc: Michael Trimarchi <michael-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
Cc: Signed-off-by: Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
---
arch/arm/boot/dts/imx6ul-isiot.dts | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/arch/arm/boot/dts/imx6ul-isiot.dts b/arch/arm/boot/dts/imx6ul-isiot.dts
index 077bc26..acb97bd 100644
--- a/arch/arm/boot/dts/imx6ul-isiot.dts
+++ b/arch/arm/boot/dts/imx6ul-isiot.dts
@@ -76,6 +76,15 @@
status = "okay";
};
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ cd-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>;
+ bus-width = <8>;
+ no-1-8-v;
+ status = "okay";
+};
+
&iomuxc {
pinctrl_uart1: uart1grp {
fsl,pins = <
@@ -116,4 +125,20 @@
MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
>;
};
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x17070
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x10070
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17070
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17070
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17070
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17070
+ MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17070
+ MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17070
+ MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17070
+ MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17070
+ MX6UL_PAD_NAND_ALE__USDHC2_RESET_B 0x17070
+ >;
+ };
};
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 2/2] ARM: dts: imx6qdl: Fix "ERROR: code indent should use tabs where possible"
From: Jagan Teki @ 2017-01-15 21:50 UTC (permalink / raw)
To: Shawn Guo
Cc: linux-arm-kernel, devicetree, linux-kernel, Matteo Lisi,
Michael Trimarchi, Jagan Teki
In-Reply-To: <1484517012-13321-1-git-send-email-jagan@openedev.com>
From: Jagan Teki <jagan@amarulasolutions.com>
Fixed code indent tabs in respetcive imx6qdl dtsi files and
also add space on imx6qdl-icore-rqs.dtsi on usdhc bus-width nodes.
Cc: Shawn Guo <shawnguo@kernel.org>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
arch/arm/boot/dts/imx6qdl-gw52xx.dtsi | 2 +-
arch/arm/boot/dts/imx6qdl-gw53xx.dtsi | 2 +-
arch/arm/boot/dts/imx6qdl-gw552x.dtsi | 2 +-
arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
index b6078b1..91991d6 100644
--- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -235,7 +235,7 @@
/* VDD_1P8 (1+R1/R2 = 2.505): GPS/VideoIn/ENET-PHY */
reg_1p8v: sw2 {
- regulator-name = "vdd1p8";
+ regulator-name = "vdd1p8";
regulator-min-microvolt = <1033310>;
regulator-max-microvolt = <2004000>;
lltc,fb-voltage-divider = <301000 200000>;
diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
index 19cf036..a208e7e 100644
--- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
@@ -227,7 +227,7 @@
/* VDD_1P8 (1+R1/R2 = 2.505): GPS/VideoIn/ENET-PHY */
reg_1p8v: sw2 {
- regulator-name = "vdd1p8";
+ regulator-name = "vdd1p8";
regulator-min-microvolt = <1033310>;
regulator-max-microvolt = <2004000>;
lltc,fb-voltage-divider = <301000 200000>;
diff --git a/arch/arm/boot/dts/imx6qdl-gw552x.dtsi b/arch/arm/boot/dts/imx6qdl-gw552x.dtsi
index 90200fa..67613dd 100644
--- a/arch/arm/boot/dts/imx6qdl-gw552x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw552x.dtsi
@@ -162,7 +162,7 @@
/* VDD_1P8 (1+R1/R2 = 2.505): ENET-PHY */
reg_1p8v: sw2 {
- regulator-name = "vdd1p8";
+ regulator-name = "vdd1p8";
regulator-min-microvolt = <1033310>;
regulator-max-microvolt = <2004000>;
lltc,fb-voltage-divider = <301000 200000>;
diff --git a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
index d5c3aa8..6e29d8b 100644
--- a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
@@ -223,7 +223,7 @@
pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
vmcc-supply = <®_sd3_vmmc>;
cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
- bus-witdh=<4>;
+ bus-witdh = <4>;
no-1-8-v;
status = "okay";
};
@@ -234,7 +234,7 @@
pinctrl-1 = <&pinctrl_usdhc4_100mhz>;
pinctrl-2 = <&pinctrl_usdhc4_200mhz>;
vmcc-supply = <®_sd4_vmmc>;
- bus-witdh=<8>;
+ bus-witdh = <8>;
no-1-8-v;
non-removable;
status = "okay";
--
1.9.1
^ permalink raw reply related
* [PATCH 0/2] add support for uart_AO_B
From: Martin Blumenstingl @ 2017-01-15 22:20 UTC (permalink / raw)
To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
khilman-rdvid1DuHRBWk0Htik3J/w
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
carlo-KA+7E9HrN00dnm+yROfE0A, will.deacon-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Martin Blumenstingl
This adds the uart_AO_B serial port and the related pinctrl nodes to
meson-gx.
Due to a bug in the current GXBB and GXL/GXM pinctrl code uart_AO_B
could not be used when uart_AO(_A) was enabled at the same time. The
reason for this is that uart_AO_A and uart_AO_B were both trying to
request the same pin as their RX pin (GPIOAO_1). uart_AO_B also
requests a second pin for it's RX (GPIOAO_5), which does not make any
sense.
Thus uart_AO_B is changed to only use GPIOAO_5 for RX and GPIOAO_4
for TX, which is also what the Amlogic reference kernel does.
Adding uart_AO_B is preparation work for adding support for the
Khadas VIM and VIM Pro boards, as these are both exposing uart_AO_B
on the pin-header.
Martin Blumenstingl (2):
pinctrl: meson: fix uart_ao_b for GXBB and GXL/GXM
ARM64: dts: meson-gx: add the missing uart_AO_B
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 8 ++++++++
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +++++++
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 7 +++++++
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 7 +++----
drivers/pinctrl/meson/pinctrl-meson-gxl.c | 7 +++----
5 files changed, 28 insertions(+), 8 deletions(-)
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 1/2] pinctrl: meson: fix uart_ao_b for GXBB and GXL/GXM
From: Martin Blumenstingl @ 2017-01-15 22:20 UTC (permalink / raw)
To: linux-amlogic, linux-gpio, linus.walleij, khilman
Cc: devicetree, linux-arm-kernel, carlo, will.deacon, catalin.marinas,
mark.rutland, robh+dt, Martin Blumenstingl
In-Reply-To: <20170115222029.8271-1-martin.blumenstingl@googlemail.com>
The GXBB and GXL/GXM pinctrl drivers had a configuration which conflicts
with uart_ao_a. According to the GXBB ("S905") datasheet the AO UART
functions are:
- GPIOAO_0: Func1 = UART_TX_AO_A (bit 12), Func2 = UART_TX_AO_B (bit 26)
- GPIOAO_1: Func1 = UART_RX_AO_A (bit 11), Func2 = UART_RX_AO_B (bit 25)
- GPIOAO_4: Func2 = UART_TX_AO_B (bit 24)
- GPIOAO_5: Func2 = UART_RX_AO_B (bit 25)
The existing definition for uart_AO_A already uses GPIOAO_0 and GPIOAO_1.
The old definition of uart_AO_B however was broken, as it used GPIOAO_0
for TX (which would be fine) and two pins (GPIOAO_1 and GPIOAO_5) for RX
(which does not make any sense).
This fixes the uart_AO_B configuration by moving it to GPIOAO_4 and
GPIOAO_5 (it would be possible to use GPIOAO_0 and GPIOAO_1 in theory,
but all existing hardware uses uart_AO_A there).
The fix for GXBB and GXL/GXM is identical since it seems that these
specific pins are identical on both SoC variants.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 7 +++----
drivers/pinctrl/meson/pinctrl-meson-gxl.c | 7 +++----
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index c3928aa3fefa..e0bca4df2a2f 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -253,9 +253,8 @@ static const unsigned int uart_tx_ao_a_pins[] = { PIN(GPIOAO_0, 0) };
static const unsigned int uart_rx_ao_a_pins[] = { PIN(GPIOAO_1, 0) };
static const unsigned int uart_cts_ao_a_pins[] = { PIN(GPIOAO_2, 0) };
static const unsigned int uart_rts_ao_a_pins[] = { PIN(GPIOAO_3, 0) };
-static const unsigned int uart_tx_ao_b_pins[] = { PIN(GPIOAO_0, 0) };
-static const unsigned int uart_rx_ao_b_pins[] = { PIN(GPIOAO_1, 0),
- PIN(GPIOAO_5, 0) };
+static const unsigned int uart_tx_ao_b_pins[] = { PIN(GPIOAO_4, 0) };
+static const unsigned int uart_rx_ao_b_pins[] = { PIN(GPIOAO_5, 0) };
static const unsigned int uart_cts_ao_b_pins[] = { PIN(GPIOAO_2, 0) };
static const unsigned int uart_rts_ao_b_pins[] = { PIN(GPIOAO_3, 0) };
@@ -498,7 +497,7 @@ static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
GPIO_GROUP(GPIOAO_13, 0),
/* bank AO */
- GROUP(uart_tx_ao_b, 0, 26),
+ GROUP(uart_tx_ao_b, 0, 24),
GROUP(uart_rx_ao_b, 0, 25),
GROUP(uart_tx_ao_a, 0, 12),
GROUP(uart_rx_ao_a, 0, 11),
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
index 25694f7094c7..b69743b07a1d 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
@@ -214,9 +214,8 @@ static const unsigned int uart_tx_ao_a_pins[] = { PIN(GPIOAO_0, 0) };
static const unsigned int uart_rx_ao_a_pins[] = { PIN(GPIOAO_1, 0) };
static const unsigned int uart_cts_ao_a_pins[] = { PIN(GPIOAO_2, 0) };
static const unsigned int uart_rts_ao_a_pins[] = { PIN(GPIOAO_3, 0) };
-static const unsigned int uart_tx_ao_b_pins[] = { PIN(GPIOAO_0, 0) };
-static const unsigned int uart_rx_ao_b_pins[] = { PIN(GPIOAO_1, 0),
- PIN(GPIOAO_5, 0) };
+static const unsigned int uart_tx_ao_b_pins[] = { PIN(GPIOAO_4, 0) };
+static const unsigned int uart_rx_ao_b_pins[] = { PIN(GPIOAO_5, 0) };
static const unsigned int uart_cts_ao_b_pins[] = { PIN(GPIOAO_2, 0) };
static const unsigned int uart_rts_ao_b_pins[] = { PIN(GPIOAO_3, 0) };
@@ -409,7 +408,7 @@ static struct meson_pmx_group meson_gxl_aobus_groups[] = {
GPIO_GROUP(GPIOAO_9, 0),
/* bank AO */
- GROUP(uart_tx_ao_b, 0, 26),
+ GROUP(uart_tx_ao_b, 0, 24),
GROUP(uart_rx_ao_b, 0, 25),
GROUP(uart_tx_ao_a, 0, 12),
GROUP(uart_rx_ao_a, 0, 11),
--
2.11.0
^ permalink raw reply related
* [PATCH 2/2] ARM64: dts: meson-gx: add the missing uart_AO_B
From: Martin Blumenstingl @ 2017-01-15 22:20 UTC (permalink / raw)
To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
khilman-rdvid1DuHRBWk0Htik3J/w
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
carlo-KA+7E9HrN00dnm+yROfE0A, will.deacon-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Martin Blumenstingl
In-Reply-To: <20170115222029.8271-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
This adds the missing node for the uart_AO_B port to the meson-gx.dtsi
(as this is supported by GXBB, GXL and GXM) along with the required
pinctrl pins. This is required as some boards are using it (the boards
from the Khadas VIM series for example have it exposed on the pin
headers).
Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 8 ++++++++
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +++++++
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 7 +++++++
3 files changed, 22 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index cddad8c795ec..5ece505dca71 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -324,6 +324,14 @@
status = "disabled";
};
+ uart_AO_B: serial@4e0 {
+ compatible = "amlogic,meson-uart";
+ reg = <0x0 0x004e0 0x0 0x14>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&xtal>;
+ status = "disabled";
+ };
+
ir: ir@580 {
compatible = "amlogic,meson-gxbb-ir";
reg = <0x0 0x00580 0x0 0x40>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 5d686334f692..474435e21759 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -138,6 +138,13 @@
};
};
+ uart_ao_b_pins: uart_ao_b {
+ mux {
+ groups = "uart_tx_ao_b", "uart_rx_ao_b";
+ function = "uart_ao_b";
+ };
+ };
+
remote_input_ao_pins: remote_input_ao {
mux {
groups = "remote_input_ao";
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index bb2842f8a08f..53ed7a5f50ab 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -82,6 +82,13 @@
};
};
+ uart_ao_b_pins: uart_ao_b {
+ mux {
+ groups = "uart_tx_ao_b", "uart_rx_ao_b";
+ function = "uart_ao_b";
+ };
+ };
+
remote_input_ao_pins: remote_input_ao {
mux {
groups = "remote_input_ao";
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 0/4] Bluetooth support for GXBB/GXL/GXM based devices
From: Martin Blumenstingl @ 2017-01-15 22:32 UTC (permalink / raw)
To: linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
jslaby-IBi9RG/b67k, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Martin Blumenstingl
This adds the missing kernel bits for Bluetooth support on the
Tronsmart Vega S95 (GXBB based) boards as well as for the GXL
P230/P231 and GXM Q200/Q201 reference boards.
The Bluetooth functionality on these boards is provided by the
SDIO wifi/Bluetooth combo-chip (Broadcom bcm43xx based). The
Bluetooth module on that combo-chip has to be taken out of reset,
which is taken care of the GPIO in the sdio_pwrseq.
Once the module is taken out of reset it can be set up from userspace
using the "hciattach" tool from bluez, which talks to the Bluetooth
module which is connected to one of the serial ports (in our case
uart_A). To get the Bluetooth module initialized within the timeout
defined by "hciattach" (and to achieve usable speeds for Bluetooth
transfers) the communication uses a speed of 2000000 baud, which was
not supported by meson_uart before.
NOTE: The .dts-changes from this series depends on my previous series
"add support for uart_AO_B" - see [0]
[0] http://lists.infradead.org/pipermail/linux-amlogic/2017-January/001982.html
Martin Blumenstingl (4):
tty: serial: meson: allow baud-rates higher than 115200
ARM64: dts: meson-gx: add the serial CTS and RTS pin groups
ARM64: dts: meson-gx-p23x-q20x: enable the Bluetooth module
ARM64: dts: meson-gxbb-vega-s95: enable the Bluetooth module
.../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi | 12 ++++++-
.../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 9 +++++
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 40 ++++++++++++++++++++++
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 40 ++++++++++++++++++++++
drivers/tty/serial/meson_uart.c | 2 +-
5 files changed, 101 insertions(+), 2 deletions(-)
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 1/4] tty: serial: meson: allow baud-rates higher than 115200
From: Martin Blumenstingl @ 2017-01-15 22:32 UTC (permalink / raw)
To: linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
jslaby-IBi9RG/b67k, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Martin Blumenstingl
In-Reply-To: <20170115223255.10350-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
The vendor driver allows setting baud-rates higher than 115200 baud.
There is a check in the vendor driver which prevents using more than
115200 baud during startup, however it does not have such a check in
.set_termios.
Higher baud-rates are often used by the bluetooth modules embedded into
the SDIO wifi chips (Amlogic devices use brcmfmac based wifi chips quite
often, 2000000 baud seems to be a common value for the UART baud-rate in
Amlogic's "libbt").
I have tested this on a Meson GXL device with uart_A (to which the
bluetooth module is connected, where initialization times out with
115200 baud) and uart_AO (which I manually set to 2000000 baud and then
connected with my USB UART adapter to that).
Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
drivers/tty/serial/meson_uart.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 6aea0f4a9165..60f16795d16b 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -364,7 +364,7 @@ static void meson_uart_set_termios(struct uart_port *port,
writel(val, port->membase + AML_UART_CONTROL);
- baud = uart_get_baud_rate(port, termios, old, 9600, 115200);
+ baud = uart_get_baud_rate(port, termios, old, 9600, 4000000);
meson_uart_change_speed(port, baud);
port->read_status_mask = AML_UART_TX_FIFO_WERR;
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 2/4] ARM64: dts: meson-gx: add the serial CTS and RTS pin groups
From: Martin Blumenstingl @ 2017-01-15 22:32 UTC (permalink / raw)
To: linux-serial, linux-amlogic, jslaby, gregkh, khilman, carlo
Cc: mark.rutland, devicetree, Martin Blumenstingl, catalin.marinas,
will.deacon, robh+dt, linux-arm-kernel
In-Reply-To: <20170115223255.10350-1-martin.blumenstingl@googlemail.com>
This adds pinctrl group nodes for the CTS and RTS pins of each serial
controller. This makes it possible to enable the CTS and RTS pins which
are controlled by the serial controller hardware (through the meson_uart
driver).
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 40 +++++++++++++++++++++++++++++
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 40 +++++++++++++++++++++++++++++
2 files changed, 80 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 474435e21759..f001c4d007bc 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -138,6 +138,14 @@
};
};
+ uart_ao_a_cts_rts_pins: uart_ao_a_cts_rts {
+ mux {
+ groups = "uart_cts_ao_a",
+ "uart_rts_ao_a";
+ function = "uart_ao";
+ };
+ };
+
uart_ao_b_pins: uart_ao_b {
mux {
groups = "uart_tx_ao_b", "uart_rx_ao_b";
@@ -145,6 +153,14 @@
};
};
+ uart_ao_b_cts_rts_pins: uart_ao_b_cts_rts {
+ mux {
+ groups = "uart_cts_ao_b",
+ "uart_rts_ao_b";
+ function = "uart_ao_b";
+ };
+ };
+
remote_input_ao_pins: remote_input_ao {
mux {
groups = "remote_input_ao";
@@ -290,6 +306,14 @@
};
};
+ uart_a_cts_rts_pins: uart_a_cts_rts {
+ mux {
+ groups = "uart_cts_a",
+ "uart_rts_a";
+ function = "uart_a";
+ };
+ };
+
uart_b_pins: uart_b {
mux {
groups = "uart_tx_b",
@@ -298,6 +322,14 @@
};
};
+ uart_b_cts_rts_pins: uart_b_cts_rts {
+ mux {
+ groups = "uart_cts_b",
+ "uart_rts_b";
+ function = "uart_b";
+ };
+ };
+
uart_c_pins: uart_c {
mux {
groups = "uart_tx_c",
@@ -306,6 +338,14 @@
};
};
+ uart_c_cts_rts_pins: uart_c_cts_rts {
+ mux {
+ groups = "uart_cts_c",
+ "uart_rts_c";
+ function = "uart_c";
+ };
+ };
+
i2c_a_pins: i2c_a {
mux {
groups = "i2c_sck_a",
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index 53ed7a5f50ab..7d7fd87f094b 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -82,6 +82,14 @@
};
};
+ uart_ao_a_cts_rts_pins: uart_ao_a_cts_rts {
+ mux {
+ groups = "uart_cts_ao_a",
+ "uart_rts_ao_a";
+ function = "uart_ao";
+ };
+ };
+
uart_ao_b_pins: uart_ao_b {
mux {
groups = "uart_tx_ao_b", "uart_rx_ao_b";
@@ -89,6 +97,14 @@
};
};
+ uart_ao_b_cts_rts_pins: uart_ao_b_cts_rts {
+ mux {
+ groups = "uart_cts_ao_b",
+ "uart_rts_ao_b";
+ function = "uart_ao_b";
+ };
+ };
+
remote_input_ao_pins: remote_input_ao {
mux {
groups = "remote_input_ao";
@@ -164,6 +180,14 @@
};
};
+ uart_a_cts_rts_pins: uart_a_cts_rts {
+ mux {
+ groups = "uart_cts_a",
+ "uart_rts_a";
+ function = "uart_a";
+ };
+ };
+
uart_b_pins: uart_b {
mux {
groups = "uart_tx_b",
@@ -172,6 +196,14 @@
};
};
+ uart_b_cts_rts_pins: uart_b_cts_rts {
+ mux {
+ groups = "uart_cts_b",
+ "uart_rts_b";
+ function = "uart_b";
+ };
+ };
+
uart_c_pins: uart_c {
mux {
groups = "uart_tx_c",
@@ -180,6 +212,14 @@
};
};
+ uart_c_cts_rts_pins: uart_c_cts_rts {
+ mux {
+ groups = "uart_cts_c",
+ "uart_rts_c";
+ function = "uart_c";
+ };
+ };
+
i2c_a_pins: i2c_a {
mux {
groups = "i2c_sck_a",
--
2.11.0
^ permalink raw reply related
* [PATCH 3/4] ARM64: dts: meson-gx-p23x-q20x: enable the Bluetooth module
From: Martin Blumenstingl @ 2017-01-15 22:32 UTC (permalink / raw)
To: linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
jslaby-IBi9RG/b67k, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Martin Blumenstingl
In-Reply-To: <20170115223255.10350-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
This takes the Bluetooth module out of reset (the reset line is
connected to GPIOX_17) and enables uart_A which is used to configure the
module.
This is identical for all boards which inherit meson-gx-p23x-q20x:
- GXL S905D P230
- GXL S905D P231
- GXM S912 Q200
- GXM S912 Q201
To get the HCI interface up one has to install bluez-utils and run:
hciattach -s115200 /dev/ttyAML1 bcm43xx 2000000 flow -
Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
index 7a078bef04cd..7db779048091 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
@@ -48,6 +48,7 @@
/ {
aliases {
serial0 = &uart_AO;
+ serial1 = &uart_A;
};
chosen {
@@ -94,12 +95,21 @@
sdio_pwrseq: sdio-pwrseq {
compatible = "mmc-pwrseq-simple";
- reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>,
+ <&gpio GPIOX_17 GPIO_ACTIVE_LOW>;
clocks = <&wifi32k>;
clock-names = "ext_clock";
};
};
+/* This is connected to the Bluetooth module of the wifi/BT combo chip: */
+&uart_A {
+ status = "okay";
+ pinctrl-0 = <&uart_a_pins &uart_a_cts_rts_pins>;
+ pinctrl-names = "default";
+ uart-has-rtscts;
+};
+
/* This UART is brought out to the DB9 connector */
&uart_AO {
status = "okay";
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 4/4] ARM64: dts: meson-gxbb-vega-s95: enable the Bluetooth module
From: Martin Blumenstingl @ 2017-01-15 22:32 UTC (permalink / raw)
To: linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
jslaby-IBi9RG/b67k, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Martin Blumenstingl
In-Reply-To: <20170115223255.10350-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
This takes the Bluetooth module out of reset (the reset line is
connected to GPIOX_20) and enables uart_A which is used to configure the
module. This is common for all Vega S95 boards.
The device can then be initialized by running the hciattach tool:
hciattach -s115200 /dev/ttyAML1 bcm43xx 2000000 flow -
Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 9 +++++++++
1 file changed, 9 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 ab497126c9a3..9e0a13b1ac93 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -47,6 +47,7 @@
aliases {
serial0 = &uart_AO;
+ serial1 = &uart_A;
};
chosen {
@@ -100,6 +101,14 @@
};
};
+/* This is connected to the Bluetooth module of the wifi/BT combo chip: */
+&uart_A {
+ status = "okay";
+ pinctrl-0 = <&uart_a_pins &uart_a_cts_rts_pins>;
+ pinctrl-names = "default";
+ uart-has-rtscts;
+};
+
&uart_AO {
status = "okay";
pinctrl-0 = <&uart_ao_a_pins>;
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 0/4] Amlogic Meson SAR ADC support
From: Martin Blumenstingl @ 2017-01-15 22:42 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A, knaack.h-Mmb7MZpHnFY,
lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
khilman-rdvid1DuHRBWk0Htik3J/w, linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
Cc: carlo-KA+7E9HrN00dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, mturquette-rdvid1DuHRBWk0Htik3J/w,
sboyd-sgV2jX0FEOL9JmXXK+q4OQ, narmstrong-rdvid1DuHRBWk0Htik3J/w,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Martin Blumenstingl
In-Reply-To: <20170111174334.24343-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
This series add support for the SAR ADC on Amlogic Meson GXBB, GXL and
GXM SoCs.
The hardware on GXBB provides 10-bit ADC results, while GXL and GXM are
providing 12-bit results. Support for older SoCs (Meson8b and Meson8)
can be added with little effort, most of which is testing I guess (I
don't have any pre-GXBB hardware so I can't say).
A new set of clocks had to be added to the GXBB clock controller (used
by the GXBB/GXL/GXM SoCs) which are required to get the ADC working.
The ADC itself can sample multiple channels at the same time and allows
capturing multiple samples (which can be used for filtering/averaging).
The ADC results are stored inside a FIFO register. More details on what
the driver supports (or doesn't) can be found in the description of
patch #3.
The code is based on the public S805 (Meson8b) and S905 (GXBB)
datasheets, as well as by reading (various versions of) the vendor
driver and by inspecting the registers on the vendor kernels of my
testing-hardware.
Typical use-cases for the ADC on the Meson GX SoCs are:
- adc-keys ("ADC attached resistor ladder buttons")
- SoC temperature measurement (not supported by this driver yet as
the system firmware does this already and provides the values via the
SCPI protocol)
- "version-strapping" (different resistor values are used to indicate
the board-revision)
- and of course typical ADC measurements
Thanks to Heiner Kallweit, Jonathan Cameron and Lars-Peter Clausen for
reviewing this series and providing valuable input!
Changes since v1 (all changes are for patch #3, except where noted):
- fix IRQ number in meson-gx.dtsi (thanks to Heiner Kallweit for
providing the correct value), affects patch #4
- move the most used members of meson_saradc_priv to the beginning
- remove unused struct member "completion" from meson_saradc_priv
- use devm_kasprintf() instead of snprintf() + devm_kstrdup()
- initialize indio_dev->dev.parent earlier in meson_saradc_probe()
- moved meson_saradc_clear_fifo() logic to a separate function
- add comment why a do ... while loop is required in
meson_saradc_wait_busy_clear()
- remove SAR_ADC_NUM_CHANNELS and SAR_ADC_VALUE_MASK macros (each of them
was only used once and it's an unneeded level of abstraction)
- fixed multiline comment syntax violations
- dropped unneeded log messages during initialization
- set iio_dev name to "meson-gxbb-saradc" or "meson-gxl-saradc"
- use "indio_dev->dev.parent" in all kernel log calls (dev_warn/err/etc)
to make it show the OF node name (instead of the iio device name)
- introduce struct meson_saradc_data to hold platform-specific
information (such as resolution in bits and the iio_dev name)
Martin Blumenstingl (4):
Documentation: dt-bindings: add the Amlogic Meson SAR ADC
documentation
clk: gxbb: add the SAR ADC clocks and expose them
iio: adc: add a driver for the SAR ADC found in Amlogic Meson SoCs
ARM64: dts: meson: meson-gx: add the SAR ADC
.../bindings/iio/adc/amlogic,meson-saradc.txt | 31 +
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 8 +
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 10 +
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 10 +
drivers/clk/meson/gxbb.c | 48 ++
drivers/clk/meson/gxbb.h | 9 +-
drivers/iio/adc/Kconfig | 12 +
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/meson_saradc.c | 893 +++++++++++++++++++++
include/dt-bindings/clock/gxbb-clkc.h | 4 +
10 files changed, 1023 insertions(+), 3 deletions(-)
create mode 100644 Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
create mode 100644 drivers/iio/adc/meson_saradc.c
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 1/4] Documentation: dt-bindings: add the Amlogic Meson SAR ADC documentation
From: Martin Blumenstingl @ 2017-01-15 22:42 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A, knaack.h-Mmb7MZpHnFY,
lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
khilman-rdvid1DuHRBWk0Htik3J/w, linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
Cc: carlo-KA+7E9HrN00dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, mturquette-rdvid1DuHRBWk0Htik3J/w,
sboyd-sgV2jX0FEOL9JmXXK+q4OQ, narmstrong-rdvid1DuHRBWk0Htik3J/w,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Martin Blumenstingl
In-Reply-To: <20170115224221.15510-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
This adds the devicetree binding documentation for the SAR ADC found in
Amlogic Meson SoCs.
Currently only the GXBB, GXL and GXM SoCs are supported.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
.../bindings/iio/adc/amlogic,meson-saradc.txt | 31 ++++++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
new file mode 100644
index 000000000000..9a0bec7afc63
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
@@ -0,0 +1,31 @@
+* Amlogic Meson SAR (Successive Approximation Register) A/D converter
+
+Required properties:
+- compatible: depending on the SoC this should be one of:
+ - "amlogic,meson-gxbb-saradc" for GXBB
+ - "amlogic,meson-gxl-saradc" for GXL and GXM
+ along with the generic "amlogic,meson-saradc"
+- reg: the physical base address and length of the registers
+- clocks: phandle and clock identifier (see clock-names)
+- clock-names: mandatory clocks:
+ - "clkin" for the reference clock (typically XTAL)
+ - "core" for the SAR ADC core clock
+ optional clocks:
+ - "sana" for the analog clock
+ - "adc_clk" for the ADC (sampling) clock
+ - "adc_sel" for the ADC (sampling) clock mux
+- vref-supply: the regulator supply for the ADC reference voltage
+- #io-channel-cells: must be 1, see ../iio-bindings.txt
+
+Example:
+ saradc: adc@8680 {
+ compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
+ #io-channel-cells = <1>;
+ reg = <0x0 0x8680 0x0 0x34>;
+ clocks = <&xtal>,
+ <&clkc CLKID_SAR_ADC>,
+ <&clkc CLKID_SANA>,
+ <&clkc CLKID_SAR_ADC_CLK>,
+ <&clkc CLKID_SAR_ADC_SEL>;
+ clock-names = "clkin", "core", "sana", "adc_clk", "adc_sel";
+ };
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 2/4] clk: gxbb: add the SAR ADC clocks and expose them
From: Martin Blumenstingl @ 2017-01-15 22:42 UTC (permalink / raw)
To: jic23, knaack.h, lars, pmeerw, robh+dt, mark.rutland, khilman,
linux-iio, devicetree, linux-amlogic, linux-clk
Cc: carlo, catalin.marinas, will.deacon, mturquette, sboyd,
narmstrong, linux-arm-kernel, Martin Blumenstingl
In-Reply-To: <20170115224221.15510-1-martin.blumenstingl@googlemail.com>
The HHI_SAR_CLK_CNTL contains three SAR ADC specific clocks:
- a mux clock to choose between different ADC reference clocks (this is
2-bit wide, but the datasheet only lists the parents for the first
bit)
- a divider for the input/reference clock
- a gate which enables the ADC clock
Additionally this exposes the ADC core clock (CLKID_SAR_ADC) and
CLKID_SANA (which seems to enable the analog inputs, but unfortunately
there is no documentation for this - we just mimic what the vendor
driver does).
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/clk/meson/gxbb.c | 48 +++++++++++++++++++++++++++++++++++
drivers/clk/meson/gxbb.h | 9 ++++---
include/dt-bindings/clock/gxbb-clkc.h | 4 +++
3 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 9d9af446bafc..1c1ec137a3cc 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -564,6 +564,46 @@ static struct clk_gate gxbb_clk81 = {
},
};
+static struct clk_mux gxbb_sar_adc_clk_sel = {
+ .reg = (void *)HHI_SAR_CLK_CNTL,
+ .mask = 0x3,
+ .shift = 9,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "sar_adc_clk_sel",
+ .ops = &clk_mux_ops,
+ /* NOTE: The datasheet doesn't list the parents for bit 10 */
+ .parent_names = (const char *[]){ "xtal", "clk81", },
+ .num_parents = 2,
+ },
+};
+
+static struct clk_divider gxbb_sar_adc_clk_div = {
+ .reg = (void *)HHI_SAR_CLK_CNTL,
+ .shift = 0,
+ .width = 8,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "sar_adc_clk_div",
+ .ops = &clk_divider_ops,
+ .parent_names = (const char *[]){ "sar_adc_clk_sel" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_gate gxbb_sar_adc_clk = {
+ .reg = (void *)HHI_SAR_CLK_CNTL,
+ .bit_idx = 8,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "sar_adc_clk",
+ .ops = &clk_gate_ops,
+ .parent_names = (const char *[]){ "sar_adc_clk_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
/* Everything Else (EE) domain gates */
static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
@@ -754,6 +794,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
[CLKID_SD_EMMC_A] = &gxbb_emmc_a.hw,
[CLKID_SD_EMMC_B] = &gxbb_emmc_b.hw,
[CLKID_SD_EMMC_C] = &gxbb_emmc_c.hw,
+ [CLKID_SAR_ADC_CLK] = &gxbb_sar_adc_clk.hw,
+ [CLKID_SAR_ADC_SEL] = &gxbb_sar_adc_clk_sel.hw,
+ [CLKID_SAR_ADC_DIV] = &gxbb_sar_adc_clk_div.hw,
},
.num = NR_CLKS,
};
@@ -856,6 +899,7 @@ static struct clk_gate *gxbb_clk_gates[] = {
&gxbb_emmc_a,
&gxbb_emmc_b,
&gxbb_emmc_c,
+ &gxbb_sar_adc_clk,
};
static int gxbb_clkc_probe(struct platform_device *pdev)
@@ -888,6 +932,10 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg;
gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg;
+ /* Populate the base address for the SAR ADC clks */
+ gxbb_sar_adc_clk_sel.reg = clk_base + (u64)gxbb_sar_adc_clk_sel.reg;
+ gxbb_sar_adc_clk_div.reg = clk_base + (u64)gxbb_sar_adc_clk_div.reg;
+
/* Populate base address for gates */
for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++)
gxbb_clk_gates[i]->reg = clk_base +
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index 0252939ba58f..d90052d74abd 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -191,7 +191,7 @@
#define CLKID_PERIPHS 20
#define CLKID_SPICC 21
/* CLKID_I2C */
-#define CLKID_SAR_ADC 23
+/* #define CLKID_SAR_ADC */
#define CLKID_SMART_CARD 24
#define CLKID_RNG0 25
#define CLKID_UART0 26
@@ -237,7 +237,7 @@
#define CLKID_MMC_PCLK 66
#define CLKID_DVIN 67
#define CLKID_UART2 68
-#define CLKID_SANA 69
+/* #define CLKID_SANA */
#define CLKID_VPU_INTR 70
#define CLKID_SEC_AHB_AHB3_BRIDGE 71
#define CLKID_CLK81_A53 72
@@ -265,8 +265,11 @@
/* CLKID_SD_EMMC_A */
/* CLKID_SD_EMMC_B */
/* CLKID_SD_EMMC_C */
+/* CLKID_SAR_ADC_CLK */
+/* CLKID_SAR_ADC_SEL */
+#define CLKID_SAR_ADC_DIV 99
-#define NR_CLKS 97
+#define NR_CLKS 100
/* include the CLKIDs that have been made part of the stable DT binding */
#include <dt-bindings/clock/gxbb-clkc.h>
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
index baade6f429d0..c2e93676010d 100644
--- a/include/dt-bindings/clock/gxbb-clkc.h
+++ b/include/dt-bindings/clock/gxbb-clkc.h
@@ -14,15 +14,19 @@
#define CLKID_MPLL2 15
#define CLKID_SPI 34
#define CLKID_I2C 22
+#define CLKID_SAR_ADC 23
#define CLKID_ETH 36
#define CLKID_USB0 50
#define CLKID_USB1 51
#define CLKID_USB 55
#define CLKID_USB1_DDR_BRIDGE 64
#define CLKID_USB0_DDR_BRIDGE 65
+#define CLKID_SANA 69
#define CLKID_AO_I2C 93
#define CLKID_SD_EMMC_A 94
#define CLKID_SD_EMMC_B 95
#define CLKID_SD_EMMC_C 96
+#define CLKID_SAR_ADC_CLK 97
+#define CLKID_SAR_ADC_SEL 98
#endif /* __GXBB_CLKC_H */
--
2.11.0
^ permalink raw reply related
* [PATCH v2 3/4] iio: adc: add a driver for the SAR ADC found in Amlogic Meson SoCs
From: Martin Blumenstingl @ 2017-01-15 22:42 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A, knaack.h-Mmb7MZpHnFY,
lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
khilman-rdvid1DuHRBWk0Htik3J/w, linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
Cc: carlo-KA+7E9HrN00dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, mturquette-rdvid1DuHRBWk0Htik3J/w,
sboyd-sgV2jX0FEOL9JmXXK+q4OQ, narmstrong-rdvid1DuHRBWk0Htik3J/w,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Martin Blumenstingl
In-Reply-To: <20170115224221.15510-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
This adds support for the SAR (Successive Approximation Register) ADC
on the Amlogic Meson SoCs.
The code is based on the public S805 (Meson8b) and S905 (GXBB)
datasheets (see [0] and [1]), as well as by reading (various versions
of) the vendor driver and by inspecting the registers on the vendor
kernels of my testing-hardware.
Currently the GXBB, GXL and GXM SoCs are supported. GXBB hardware has
10-bit ADC resolution, while GXL and GXM have 12-bit ADC resolution.
The code was written to support older SoCs (Meson8 and Meson8b) as well,
but due to lack of actual testing-hardware no of_device_id was added for
these.
Two "features" from the vendor driver are currently missing:
- the vendor driver uses channel #7 for calibration (this improves the
accuracy of the results - in my tests the results were less than 3%
off without calibration compared to the vendor driver). Adding support
for this should be easy, but is not required for most applications.
- channel #6 is connected to the SoCs internal temperature sensor.
Adding support for this is probably not so easy since (based on the
u-boot sources) most SoC versions are using different registers and
algorithms for the conversion from "ADC value" to temperature.
Supported by the hardware but currently not supported by the driver:
- reading multiple channels at the same time (the hardware has a FIFO
buffer which stores multiple results)
- continuous sampling (this would require a way to enable this
individually because otherwise the ADC would be drawing power
constantly)
- interrupt support (similar to the vendor driver this new driver is
polling the results. It is unclear if the IRQ-mode is supported on
older (Meson6 or Meson8) hardware as well or if there are any errata)
[0]
http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
[1] http://dn.odroid.com/S905/DataSheet/S905_Public_Datasheet_V1.1.4.pdf
Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
drivers/iio/adc/Kconfig | 12 +
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/meson_saradc.c | 893 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 906 insertions(+)
create mode 100644 drivers/iio/adc/meson_saradc.c
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 9c8b558ba19e..86059b9b91bf 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -371,6 +371,18 @@ config MEN_Z188_ADC
This driver can also be built as a module. If so, the module will be
called men_z188_adc.
+config MESON_SARADC
+ tristate "Amlogic Meson SAR ADC driver"
+ default ARCH_MESON
+ depends on OF && COMMON_CLK && (ARCH_MESON || COMPILE_TEST)
+ select REGMAP_MMIO
+ help
+ Say yes here to build support for the SAR ADC found in Amlogic Meson
+ SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called meson_saradc.
+
config MXS_LRADC
tristate "Freescale i.MX23/i.MX28 LRADC"
depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index d36c4be8d1fc..de05b9e75f8f 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
+obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o
obj-$(CONFIG_NAU7802) += nau7802.o
obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
new file mode 100644
index 000000000000..4c189e5fd7cc
--- /dev/null
+++ b/drivers/iio/adc/meson_saradc.c
@@ -0,0 +1,893 @@
+/*
+ * Amlogic Meson Successive Approximation Register (SAR) A/D Converter
+ *
+ * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
+ *
+ * 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/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define SAR_ADC_REG0 0x00
+ #define SAR_ADC_REG0_PANEL_DETECT BIT(31)
+ #define SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28)
+ #define SAR_ADC_REG0_DELTA_BUSY BIT(30)
+ #define SAR_ADC_REG0_AVG_BUSY BIT(29)
+ #define SAR_ADC_REG0_SAMPLE_BUSY BIT(28)
+ #define SAR_ADC_REG0_FIFO_FULL BIT(27)
+ #define SAR_ADC_REG0_FIFO_EMPTY BIT(26)
+ #define SAR_ADC_REG0_FIFO_COUNT_MASK GENMASK(25, 21)
+ #define SAR_ADC_REG0_ADC_BIAS_CTRL_MASK GENMASK(20, 19)
+ #define SAR_ADC_REG0_CURR_CHAN_ID_MASK GENMASK(18, 16)
+ #define SAR_ADC_REG0_ADC_TEMP_SEN_SEL BIT(15)
+ #define SAR_ADC_REG0_SAMPLING_STOP BIT(14)
+ #define SAR_ADC_REG0_CHAN_DELTA_EN_MASK GENMASK(13, 12)
+ #define SAR_ADC_REG0_DETECT_IRQ_POL BIT(10)
+ #define SAR_ADC_REG0_DETECT_IRQ_EN BIT(9)
+ #define SAR_ADC_REG0_FIFO_CNT_IRQ_MASK GENMASK(8, 4)
+ #define SAR_ADC_REG0_FIFO_IRQ_EN BIT(3)
+ #define SAR_ADC_REG0_SAMPLING_START BIT(2)
+ #define SAR_ADC_REG0_CONTINUOUS_EN BIT(1)
+ #define SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE BIT(0)
+
+#define SAR_ADC_CHAN_LIST 0x04
+ #define SAR_ADC_CHAN_LIST_MAX_INDEX_MASK GENMASK(26, 24)
+ #define SAR_ADC_CHAN_CHAN_ENTRY_MASK(_chan) \
+ (GENMASK(2, 0) << (_chan * 3))
+
+#define SAR_ADC_AVG_CNTL 0x08
+ #define SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan) \
+ (16 + (_chan * 2))
+ #define SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan) \
+ (GENMASK(17, 16) << (_chan * 2))
+ #define SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan) \
+ (0 + (_chan * 2))
+ #define SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan) \
+ (GENMASK(1, 0) << (_chan * 2))
+
+#define SAR_ADC_REG3 0x0c
+ #define SAR_ADC_REG3_CNTL_USE_SC_DLY BIT(31)
+ #define SAR_ADC_REG3_CLK_EN BIT(30)
+ #define SAR_ADC_REG3_BL30_INITIALIZED BIT(28)
+ #define SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN BIT(27)
+ #define SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE BIT(26)
+ #define SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK GENMASK(25, 23)
+ #define SAR_ADC_REG3_DETECT_EN BIT(22)
+ #define SAR_ADC_REG3_ADC_EN BIT(21)
+ #define SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18)
+ #define SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16)
+ #define SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10
+ #define SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5
+ #define SAR_ADC_REG3_ADC_CLK_DIV_MASK GENMASK(15, 10)
+ #define SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8)
+ #define SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0)
+
+#define SAR_ADC_DELAY 0x10
+ #define SAR_ADC_DELAY_INPUT_DLY_SEL_MASK GENMASK(25, 24)
+ #define SAR_ADC_DELAY_BL30_BUSY BIT(15)
+ #define SAR_ADC_DELAY_KERNEL_BUSY BIT(14)
+ #define SAR_ADC_DELAY_INPUT_DLY_CNT_MASK GENMASK(23, 16)
+ #define SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK GENMASK(9, 8)
+ #define SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK GENMASK(7, 0)
+
+#define SAR_ADC_LAST_RD 0x14
+ #define SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK GENMASK(23, 16)
+ #define SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK GENMASK(9, 0)
+
+#define SAR_ADC_FIFO_RD 0x18
+ #define SAR_ADC_FIFO_RD_CHAN_ID_MASK GENMASK(14, 12)
+ #define SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0)
+
+#define SAR_ADC_AUX_SW 0x1c
+ #define SAR_ADC_AUX_SW_MUX_SEL_CHAN_MASK(_chan) \
+ (GENMASK(10, 8) << ((_chan - 2) * 2))
+ #define SAR_ADC_AUX_SW_VREF_P_MUX BIT(6)
+ #define SAR_ADC_AUX_SW_VREF_N_MUX BIT(5)
+ #define SAR_ADC_AUX_SW_MODE_SEL BIT(4)
+ #define SAR_ADC_AUX_SW_YP_DRIVE_SW BIT(3)
+ #define SAR_ADC_AUX_SW_XP_DRIVE_SW BIT(2)
+ #define SAR_ADC_AUX_SW_YM_DRIVE_SW BIT(1)
+ #define SAR_ADC_AUX_SW_XM_DRIVE_SW BIT(0)
+
+#define SAR_ADC_CHAN_10_SW 0x20
+ #define SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK GENMASK(25, 23)
+ #define SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX BIT(22)
+ #define SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX BIT(21)
+ #define SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL BIT(20)
+ #define SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW BIT(19)
+ #define SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW BIT(18)
+ #define SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW BIT(17)
+ #define SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW BIT(16)
+ #define SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK GENMASK(9, 7)
+ #define SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX BIT(6)
+ #define SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX BIT(5)
+ #define SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL BIT(4)
+ #define SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW BIT(3)
+ #define SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW BIT(2)
+ #define SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW BIT(1)
+ #define SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW BIT(0)
+
+#define SAR_ADC_DETECT_IDLE_SW 0x24
+ #define SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN BIT(26)
+ #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_MUX_MASK GENMASK(25, 23)
+ #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_VREF_P_MUX BIT(22)
+ #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_VREF_N_MUX BIT(21)
+ #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL BIT(20)
+ #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_YP_DRIVE_SW BIT(19)
+ #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_XP_DRIVE_SW BIT(18)
+ #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_YM_DRIVE_SW BIT(17)
+ #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_XM_DRIVE_SW BIT(16)
+ #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_MUX_SEL_MASK GENMASK(9, 7)
+ #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_VREF_P_MUX BIT(6)
+ #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_VREF_N_MUX BIT(5)
+ #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL BIT(4)
+ #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_YP_DRIVE_SW BIT(3)
+ #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_XP_DRIVE_SW BIT(2)
+ #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_YM_DRIVE_SW BIT(1)
+ #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_XM_DRIVE_SW BIT(0)
+
+#define SAR_ADC_DELTA_10 0x28
+ #define SAR_ADC_DELTA_10_TEMP_SEL BIT(27)
+ #define SAR_ADC_DELTA_10_TS_REVE1 BIT(26)
+ #define SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_SHIFT 16
+ #define SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16)
+ #define SAR_ADC_DELTA_10_TS_REVE0 BIT(15)
+ #define SAR_ADC_DELTA_10_TS_C_SHIFT 11
+ #define SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11)
+ #define SAR_ADC_DELTA_10_TS_VBG_EN BIT(10)
+ #define SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_SHIFT 0
+ #define SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0)
+
+/*
+ * NOTE: registers from here are undocumented (the vendor Linux kernel driver
+ * and u-boot source served as reference). These only seem to be relevant on
+ * GXBB and newer.
+ */
+#define SAR_ADC_REG11 0x2c
+ #define SAR_ADC_REG11_BANDGAP_EN BIT(13)
+
+#define SAR_ADC_REG13 0x34
+ #define SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8)
+
+#define SAR_ADC_MAX_FIFO_SIZE 32
+
+#define MESON_SAR_ADC_CHAN(_chan, _type) { \
+ .type = _type, \
+ .indexed = true, \
+ .channel = _chan, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .datasheet_name = "SAR_ADC_CH"#_chan, \
+}
+
+/*
+ * TODO: the hardware supports IIO_TEMP for channel 6 as well which is
+ * currently not supported by this driver.
+ */
+static const struct iio_chan_spec meson_saradc_iio_channels[] = {
+ MESON_SAR_ADC_CHAN(0, IIO_VOLTAGE),
+ MESON_SAR_ADC_CHAN(1, IIO_VOLTAGE),
+ MESON_SAR_ADC_CHAN(2, IIO_VOLTAGE),
+ MESON_SAR_ADC_CHAN(3, IIO_VOLTAGE),
+ MESON_SAR_ADC_CHAN(4, IIO_VOLTAGE),
+ MESON_SAR_ADC_CHAN(5, IIO_VOLTAGE),
+ MESON_SAR_ADC_CHAN(6, IIO_VOLTAGE),
+ MESON_SAR_ADC_CHAN(7, IIO_VOLTAGE),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+enum meson_saradc_avg_mode {
+ NO_AVERAGING = 0x0,
+ MEAN_AVERAGING = 0x1,
+ MEDIAN_AVERAGING = 0x2,
+};
+
+enum meson_saradc_num_samples {
+ ONE_SAMPLE = 0x0,
+ TWO_SAMPLES = 0x1,
+ FOUR_SAMPLES = 0x2,
+ EIGHT_SAMPLES = 0x3,
+};
+
+enum meson_saradc_chan7_mux_sel {
+ CHAN7_MUX_VSS = 0x0,
+ CHAN7_MUX_VDD_DIV4 = 0x1,
+ CHAN7_MUX_VDD_DIV2 = 0x2,
+ CHAN7_MUX_VDD_MUL3_DIV4 = 0x3,
+ CHAN7_MUX_VDD = 0x4,
+ CHAN7_MUX_CH7_INPUT = 0x7,
+};
+
+struct meson_saradc_data {
+ unsigned int resolution;
+ const char *name;
+};
+
+struct meson_saradc_priv {
+ struct regmap *regmap;
+ struct regulator *vref;
+ const struct meson_saradc_data *data;
+ struct clk *clkin;
+ struct clk *core_clk;
+ struct clk *sana_clk;
+ struct clk *adc_sel_clk;
+ struct clk *adc_clk;
+ struct clk_gate clk_gate;
+ struct clk *adc_div_clk;
+ struct clk_divider clk_div;
+};
+
+static const struct regmap_config meson_saradc_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = SAR_ADC_REG13,
+};
+
+static unsigned int meson_saradc_get_fifo_count(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ u32 regval;
+
+ regmap_read(priv->regmap, SAR_ADC_REG0, ®val);
+
+ return FIELD_GET(SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
+}
+
+static int meson_saradc_wait_busy_clear(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ int regval, timeout = 10000;
+
+ /*
+ * NOTE: we need a small delay before reading the status, otherwise
+ * the sample engine may not have started internally (which would
+ * seem to us that sampling is already finished).
+ */
+ do {
+ udelay(1);
+ regmap_read(priv->regmap, SAR_ADC_REG0, ®val);
+ } while (FIELD_GET(SAR_ADC_REG0_BUSY_MASK, regval) && timeout--);
+
+ if (timeout < 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int meson_saradc_read_raw_sample(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
+
+ ret = meson_saradc_wait_busy_clear(indio_dev);
+ if (ret)
+ return ret;
+
+ while (meson_saradc_get_fifo_count(indio_dev) > 0 &&
+ count < SAR_ADC_MAX_FIFO_SIZE) {
+ regmap_read(priv->regmap, SAR_ADC_FIFO_RD, ®val);
+
+ fifo_chan = FIELD_GET(SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
+ if (fifo_chan == chan->channel) {
+ fifo_val = FIELD_GET(SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK,
+ regval);
+ fifo_val &= (BIT(priv->data->resolution) - 1);
+
+ sum += fifo_val;
+ count++;
+ }
+ }
+
+ if (!count)
+ return -ENOENT;
+
+ *val = sum / count;
+
+ return 0;
+}
+
+static void meson_saradc_set_averaging(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum meson_saradc_avg_mode mode,
+ enum meson_saradc_num_samples samples)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ u32 val;
+
+ val = samples << SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(chan->channel);
+ regmap_update_bits(priv->regmap, SAR_ADC_AVG_CNTL,
+ SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(chan->channel),
+ val);
+
+ val = mode << SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(chan->channel);
+ regmap_update_bits(priv->regmap, SAR_ADC_AVG_CNTL,
+ SAR_ADC_AVG_CNTL_AVG_MODE_MASK(chan->channel), val);
+}
+
+static void meson_saradc_enable_channel(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ u32 regval;
+
+ /* the SAR ADC engine allows sampling multiple channels at the same
+ * time. to keep it simple we're only working with one *internal*
+ * channel, which starts counting at index 0 (which means: count = 1).
+ */
+ regval = FIELD_PREP(SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0);
+ regmap_update_bits(priv->regmap, SAR_ADC_CHAN_LIST,
+ SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval);
+
+ /* map channel index 0 to the channel which we want to read */
+ regval = FIELD_PREP(SAR_ADC_CHAN_CHAN_ENTRY_MASK(0), chan->channel);
+ regmap_update_bits(priv->regmap, SAR_ADC_CHAN_LIST,
+ SAR_ADC_CHAN_CHAN_ENTRY_MASK(0), regval);
+
+ regval = FIELD_PREP(SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_MUX_MASK,
+ chan->channel);
+ regmap_update_bits(priv->regmap, SAR_ADC_DETECT_IDLE_SW,
+ SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_MUX_MASK,
+ regval);
+
+ regval = FIELD_PREP(SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_MUX_SEL_MASK,
+ chan->channel);
+ regmap_update_bits(priv->regmap, SAR_ADC_DETECT_IDLE_SW,
+ SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_MUX_SEL_MASK,
+ regval);
+
+ if (chan->channel == 6)
+ regmap_update_bits(priv->regmap, SAR_ADC_DELTA_10,
+ SAR_ADC_DELTA_10_TEMP_SEL, 0);
+}
+
+static void meson_saradc_set_channel7_mux(struct iio_dev *indio_dev,
+ enum meson_saradc_chan7_mux_sel sel)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ u32 regval;
+
+ regval = FIELD_PREP(SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel);
+ regmap_update_bits(priv->regmap, SAR_ADC_REG3,
+ SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval);
+
+ usleep_range(10, 20);
+}
+
+static void meson_saradc_start_sample_engine(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+
+ regmap_update_bits(priv->regmap, SAR_ADC_REG0,
+ SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
+ SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
+
+ regmap_update_bits(priv->regmap, SAR_ADC_REG0,
+ SAR_ADC_REG0_SAMPLING_START,
+ SAR_ADC_REG0_SAMPLING_START);
+}
+
+static void meson_saradc_stop_sample_engine(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+
+ regmap_update_bits(priv->regmap, SAR_ADC_REG0,
+ SAR_ADC_REG0_SAMPLING_STOP,
+ SAR_ADC_REG0_SAMPLING_STOP);
+
+ /* wait until all modules are stopped */
+ meson_saradc_wait_busy_clear(indio_dev);
+
+ regmap_update_bits(priv->regmap, SAR_ADC_REG0,
+ SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0);
+}
+
+static void meson_saradc_lock(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ int val;
+
+ mutex_lock(&indio_dev->mlock);
+
+ /* prevent BL30 from using the SAR ADC while we are using it */
+ regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
+ SAR_ADC_DELAY_KERNEL_BUSY,
+ SAR_ADC_DELAY_KERNEL_BUSY);
+
+ /* wait until BL30 releases it's lock (so we can use the SAR ADC) */
+ do {
+ udelay(1);
+ regmap_read(priv->regmap, SAR_ADC_DELAY, &val);
+ } while (val & SAR_ADC_DELAY_BL30_BUSY);
+}
+
+static void meson_saradc_unlock(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+
+ /* allow BL30 to use the SAR ADC again */
+ regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
+ SAR_ADC_DELAY_KERNEL_BUSY, 0);
+
+ mutex_unlock(&indio_dev->mlock);
+}
+
+static void meson_saradc_clear_fifo(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ int count;
+
+ for (count = 0; count < SAR_ADC_MAX_FIFO_SIZE; count++) {
+ if (!meson_saradc_get_fifo_count(indio_dev))
+ break;
+
+ regmap_read(priv->regmap, SAR_ADC_FIFO_RD, 0);
+ }
+}
+
+static int meson_saradc_get_sample(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum meson_saradc_avg_mode avg_mode,
+ enum meson_saradc_num_samples avg_samples,
+ int *val)
+{
+ int ret;
+
+ meson_saradc_lock(indio_dev);
+
+ /* clear the FIFO to make sure we're not reading old values */
+ meson_saradc_clear_fifo(indio_dev);
+
+ meson_saradc_set_averaging(indio_dev, chan, avg_mode, avg_samples);
+
+ meson_saradc_enable_channel(indio_dev, chan);
+
+ meson_saradc_start_sample_engine(indio_dev);
+ ret = meson_saradc_read_raw_sample(indio_dev, chan, val);
+ meson_saradc_stop_sample_engine(indio_dev);
+
+ meson_saradc_unlock(indio_dev);
+
+ if (ret) {
+ dev_warn(indio_dev->dev.parent,
+ "failed to read sample for channel %d: %d\n",
+ chan->channel, ret);
+ return ret;
+ }
+
+ return IIO_VAL_INT;
+}
+
+static int meson_saradc_iio_info_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long mask)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ return meson_saradc_get_sample(indio_dev, chan, NO_AVERAGING,
+ ONE_SAMPLE, val);
+ break;
+
+ case IIO_CHAN_INFO_AVERAGE_RAW:
+ return meson_saradc_get_sample(indio_dev, chan, MEAN_AVERAGING,
+ EIGHT_SAMPLES, val);
+ break;
+
+ case IIO_CHAN_INFO_SCALE:
+ ret = regulator_get_voltage(priv->vref);
+ if (ret < 0) {
+ dev_err(indio_dev->dev.parent,
+ "failed to get vref voltage: %d\n", ret);
+ return ret;
+ }
+
+ *val = ret / 1000;
+ *val2 = priv->data->resolution;
+ return IIO_VAL_FRACTIONAL_LOG2;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int meson_saradc_clk_init(struct iio_dev *indio_dev, void __iomem *base)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ struct clk_init_data init;
+ const char *clk_parents[1];
+
+ init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_div",
+ of_node_full_name(indio_dev->dev.of_node));
+ init.flags = 0;
+ init.ops = &clk_divider_ops;
+ clk_parents[0] = __clk_get_name(priv->clkin);
+ init.parent_names = clk_parents;
+ init.num_parents = 1;
+
+ priv->clk_div.reg = base + SAR_ADC_REG3;
+ priv->clk_div.shift = SAR_ADC_REG3_ADC_CLK_DIV_SHIFT;
+ priv->clk_div.width = SAR_ADC_REG3_ADC_CLK_DIV_WIDTH;
+ priv->clk_div.hw.init = &init;
+ priv->clk_div.flags = 0;
+
+ priv->adc_div_clk = devm_clk_register(&indio_dev->dev,
+ &priv->clk_div.hw);
+ if (WARN_ON(IS_ERR(priv->adc_div_clk)))
+ return PTR_ERR(priv->adc_div_clk);
+
+ init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_en",
+ of_node_full_name(indio_dev->dev.of_node));
+ init.flags = CLK_SET_RATE_PARENT;
+ init.ops = &clk_gate_ops;
+ clk_parents[0] = __clk_get_name(priv->adc_div_clk);
+ init.parent_names = clk_parents;
+ init.num_parents = 1;
+
+ priv->clk_gate.reg = base + SAR_ADC_REG3;
+ priv->clk_gate.bit_idx = fls(SAR_ADC_REG3_CLK_EN);
+ priv->clk_gate.hw.init = &init;
+
+ priv->adc_clk = devm_clk_register(&indio_dev->dev, &priv->clk_gate.hw);
+ if (WARN_ON(IS_ERR(priv->adc_clk)))
+ return PTR_ERR(priv->adc_clk);
+
+ return 0;
+}
+
+static int meson_saradc_init(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ int regval, ret;
+
+ /*
+ * make sure we start at CH7 input since the other muxes are only used
+ * for internal calibration.
+ */
+ meson_saradc_set_channel7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
+
+ /*
+ * leave sampling delay and the input clocks as configured by BL30 to
+ * make sure BL30 gets the values it expects when reading the
+ * temperature sensor.
+ */
+ regmap_read(priv->regmap, SAR_ADC_REG3, ®val);
+ if (regval & SAR_ADC_REG3_BL30_INITIALIZED)
+ return 0;
+
+ meson_saradc_stop_sample_engine(indio_dev);
+
+ /* update the channel 6 MUX to select the temperature sensor */
+ regmap_update_bits(priv->regmap, SAR_ADC_REG0,
+ SAR_ADC_REG0_ADC_TEMP_SEN_SEL,
+ SAR_ADC_REG0_ADC_TEMP_SEN_SEL);
+
+ /* disable all channels by default */
+ regmap_write(priv->regmap, SAR_ADC_CHAN_LIST, 0x0);
+
+ regmap_update_bits(priv->regmap, SAR_ADC_REG3,
+ SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0);
+ regmap_update_bits(priv->regmap, SAR_ADC_REG3,
+ SAR_ADC_REG3_CNTL_USE_SC_DLY,
+ SAR_ADC_REG3_CNTL_USE_SC_DLY);
+
+ /* delay between two samples = (10+1) * 1uS */
+ regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
+ SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
+ FIELD_PREP(SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK, 10));
+ regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
+ SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK,
+ FIELD_PREP(SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 0));
+
+ /* delay between two samples = (10+1) * 1uS */
+ regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
+ SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
+ FIELD_PREP(SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 10));
+ regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
+ SAR_ADC_DELAY_INPUT_DLY_SEL_MASK,
+ FIELD_PREP(SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 1));
+
+ ret = clk_set_parent(priv->adc_sel_clk, priv->clkin);
+ if (ret) {
+ dev_err(indio_dev->dev.parent,
+ "failed to set adc parent to clkin\n");
+ return ret;
+ }
+
+ ret = clk_set_rate(priv->adc_clk, 1200000);
+ if (ret) {
+ dev_err(indio_dev->dev.parent,
+ "failed to set adc clock rate\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int meson_saradc_hw_enable(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+ int ret;
+
+ meson_saradc_lock(indio_dev);
+
+ ret = regulator_enable(priv->vref);
+ if (ret < 0) {
+ dev_err(indio_dev->dev.parent,
+ "failed to enable vref regulator\n");
+ goto err_vref;
+ }
+
+ ret = clk_prepare_enable(priv->core_clk);
+ if (ret) {
+ dev_err(indio_dev->dev.parent, "failed to enable core clk\n");
+ goto err_core_clk;
+ }
+
+ ret = clk_prepare_enable(priv->sana_clk);
+ if (ret) {
+ dev_err(indio_dev->dev.parent, "failed to enable sana clk\n");
+ goto err_sana_clk;
+ }
+
+ regmap_update_bits(priv->regmap, SAR_ADC_REG11,
+ SAR_ADC_REG11_BANDGAP_EN, SAR_ADC_REG11_BANDGAP_EN);
+ regmap_update_bits(priv->regmap, SAR_ADC_REG3, SAR_ADC_REG3_ADC_EN,
+ SAR_ADC_REG3_ADC_EN);
+
+ udelay(5);
+
+ ret = clk_prepare_enable(priv->adc_clk);
+ if (ret) {
+ dev_err(indio_dev->dev.parent, "failed to enable adc clk\n");
+ goto err_adc_clk;
+ }
+
+ meson_saradc_unlock(indio_dev);
+
+ return 0;
+
+err_adc_clk:
+ regmap_update_bits(priv->regmap, SAR_ADC_REG3, SAR_ADC_REG3_ADC_EN, 0);
+ regmap_update_bits(priv->regmap, SAR_ADC_REG11,
+ SAR_ADC_REG11_BANDGAP_EN, 0);
+ clk_disable_unprepare(priv->sana_clk);
+err_sana_clk:
+ clk_disable_unprepare(priv->core_clk);
+err_core_clk:
+ regulator_disable(priv->vref);
+err_vref:
+ meson_saradc_unlock(indio_dev);
+ return ret;
+}
+
+static void meson_saradc_hw_disable(struct iio_dev *indio_dev)
+{
+ struct meson_saradc_priv *priv = iio_priv(indio_dev);
+
+ meson_saradc_lock(indio_dev);
+
+ clk_disable_unprepare(priv->adc_clk);
+
+ regmap_update_bits(priv->regmap, SAR_ADC_REG3, SAR_ADC_REG3_ADC_EN, 0);
+ regmap_update_bits(priv->regmap, SAR_ADC_REG11,
+ SAR_ADC_REG11_BANDGAP_EN, 0);
+
+ clk_disable_unprepare(priv->sana_clk);
+ clk_disable_unprepare(priv->core_clk);
+
+ regulator_disable(priv->vref);
+
+ meson_saradc_unlock(indio_dev);
+}
+
+static const struct iio_info meson_saradc_iio_info = {
+ .read_raw = meson_saradc_iio_info_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
+struct meson_saradc_data meson_saradc_gxbb_data = {
+ .resolution = 10,
+ .name = "meson-gxbb-saradc",
+};
+
+struct meson_saradc_data meson_saradc_gxl_data = {
+ .resolution = 12,
+ .name = "meson-gxl-saradc",
+};
+
+static const struct of_device_id meson_saradc_of_match[] = {
+ {
+ .compatible = "amlogic,meson-gxbb-saradc",
+ .data = &meson_saradc_gxbb_data,
+ }, {
+ .compatible = "amlogic,meson-gxl-saradc",
+ .data = &meson_saradc_gxl_data,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, meson_saradc_of_match);
+
+static int meson_saradc_probe(struct platform_device *pdev)
+{
+ struct meson_saradc_priv *priv;
+ struct iio_dev *indio_dev;
+ struct resource *res;
+ void __iomem *base;
+ const struct of_device_id *match;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
+ if (!indio_dev) {
+ dev_err(&pdev->dev, "failed allocating iio device\n");
+ return -ENOMEM;
+ }
+
+ priv = iio_priv(indio_dev);
+
+ match = of_match_device(meson_saradc_of_match, &pdev->dev);
+ priv->data = match->data;
+
+ indio_dev->name = priv->data->name;
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->dev.of_node = pdev->dev.of_node;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &meson_saradc_iio_info;
+
+ indio_dev->channels = meson_saradc_iio_channels;
+ indio_dev->num_channels = ARRAY_SIZE(meson_saradc_iio_channels);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &meson_saradc_regmap_config);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
+ priv->clkin = devm_clk_get(&pdev->dev, "clkin");
+ if (IS_ERR(priv->clkin)) {
+ dev_err(&pdev->dev, "failed to get clkin\n");
+ return PTR_ERR(priv->clkin);
+ }
+
+ priv->core_clk = devm_clk_get(&pdev->dev, "core");
+ if (IS_ERR(priv->core_clk)) {
+ dev_err(&pdev->dev, "failed to get core clk\n");
+ return PTR_ERR(priv->core_clk);
+ }
+
+ priv->sana_clk = devm_clk_get(&pdev->dev, "sana");
+ if (IS_ERR(priv->sana_clk)) {
+ if (PTR_ERR(priv->sana_clk) == -ENOENT) {
+ priv->sana_clk = NULL;
+ } else {
+ dev_err(&pdev->dev, "failed to get sana clk\n");
+ return PTR_ERR(priv->sana_clk);
+ }
+ }
+
+ priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk");
+ if (IS_ERR(priv->adc_clk)) {
+ if (PTR_ERR(priv->adc_clk) == -ENOENT) {
+ priv->adc_clk = NULL;
+ } else {
+ dev_err(&pdev->dev, "failed to get adc clk\n");
+ return PTR_ERR(priv->adc_clk);
+ }
+ }
+
+ priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel");
+ if (IS_ERR(priv->adc_sel_clk)) {
+ if (PTR_ERR(priv->adc_sel_clk) == -ENOENT) {
+ priv->adc_sel_clk = NULL;
+ } else {
+ dev_err(&pdev->dev, "failed to get adc_sel clk\n");
+ return PTR_ERR(priv->adc_sel_clk);
+ }
+ }
+
+ /* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */
+ if (!priv->adc_clk) {
+ ret = meson_saradc_clk_init(indio_dev, base);
+ if (ret)
+ return ret;
+ }
+
+ priv->vref = devm_regulator_get(&pdev->dev, "vref");
+ if (IS_ERR(priv->vref)) {
+ dev_err(&pdev->dev, "failed to get vref regulator\n");
+ return PTR_ERR(priv->vref);
+ }
+
+ ret = meson_saradc_init(indio_dev);
+ if (ret)
+ goto err;
+
+ ret = meson_saradc_hw_enable(indio_dev);
+ if (ret)
+ goto err;
+
+ platform_set_drvdata(pdev, indio_dev);
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto err_hw;
+
+ return 0;
+
+err_hw:
+ meson_saradc_hw_disable(indio_dev);
+err:
+ return ret;
+}
+
+static int meson_saradc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+ meson_saradc_hw_disable(indio_dev);
+ iio_device_unregister(indio_dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int meson_saradc_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
+ meson_saradc_hw_disable(indio_dev);
+
+ return 0;
+}
+
+static int meson_saradc_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
+ return meson_saradc_hw_enable(indio_dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(meson_saradc_pm_ops,
+ meson_saradc_suspend, meson_saradc_resume);
+
+static struct platform_driver meson_saradc_driver = {
+ .probe = meson_saradc_probe,
+ .remove = meson_saradc_remove,
+ .driver = {
+ .name = "meson-saradc",
+ .of_match_table = meson_saradc_of_match,
+ .pm = &meson_saradc_pm_ops,
+ },
+};
+
+module_platform_driver(meson_saradc_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>");
+MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver");
+MODULE_LICENSE("GPL v2");
--
2.11.0
^ permalink raw reply related
* [PATCH v2 4/4] ARM64: dts: meson: meson-gx: add the SAR ADC
From: Martin Blumenstingl @ 2017-01-15 22:42 UTC (permalink / raw)
To: jic23, knaack.h, lars, pmeerw, robh+dt, mark.rutland, khilman,
linux-iio, devicetree, linux-amlogic, linux-clk
Cc: carlo, catalin.marinas, will.deacon, mturquette, sboyd,
narmstrong, linux-arm-kernel, Martin Blumenstingl
In-Reply-To: <20170115224221.15510-1-martin.blumenstingl@googlemail.com>
Add the SAR ADC to meson-gxbb.dtsi and meson-gxl.dtsi. GXBB provides a
10-bit ADC while GXL (and GXM, which uses the same ADC as GXL) provides
a 12-bit ADC.
Some boards use resistor ladder buttons connected through one of the ADC
channels. On newer devices (GXL and GXM) some boards use pull-ups/downs
to change the resistance (and thus the ADC value) on of the ADC channels
to indicate the board revision.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 8 ++++++++
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 10 ++++++++++
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 10 ++++++++++
3 files changed, 28 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index cddad8c795ec..041e4f0ed7d7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -237,6 +237,14 @@
status = "disabled";
};
+ saradc: adc@8680 {
+ compatible = "amlogic,meson-saradc";
+ #io-channel-cells = <1>;
+ status = "disabled";
+ reg = <0x0 0x8680 0x0 0x34>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>;
+ };
+
pwm_ef: pwm@86c0 {
compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
reg = <0x0 0x086c0 0x0 0x10>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 5d686334f692..114d7e1c9fc0 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -429,6 +429,16 @@
clocks = <&clkc CLKID_I2C>;
};
+&saradc {
+ compatible = "amlogic,meson-gxbb-saradc", "amlogic,meson-saradc";
+ clocks = <&xtal>,
+ <&clkc CLKID_SAR_ADC>,
+ <&clkc CLKID_SANA>,
+ <&clkc CLKID_SAR_ADC_CLK>,
+ <&clkc CLKID_SAR_ADC_SEL>;
+ clock-names = "clkin", "core", "sana", "adc_clk", "adc_sel";
+};
+
&sd_emmc_a {
clocks = <&clkc CLKID_SD_EMMC_A>,
<&xtal>,
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index bb2842f8a08f..6b63296b6c60 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -273,6 +273,16 @@
clocks = <&clkc CLKID_I2C>;
};
+&saradc {
+ compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
+ clocks = <&xtal>,
+ <&clkc CLKID_SAR_ADC>,
+ <&clkc CLKID_SANA>,
+ <&clkc CLKID_SAR_ADC_CLK>,
+ <&clkc CLKID_SAR_ADC_SEL>;
+ clock-names = "clkin", "core", "sana", "adc_clk", "adc_sel";
+};
+
&sd_emmc_a {
clocks = <&clkc CLKID_SD_EMMC_A>,
<&xtal>,
--
2.11.0
^ permalink raw reply related
* Re: [PATCH 1/4] tty: serial: meson: allow baud-rates higher than 115200
From: Andreas Färber @ 2017-01-15 22:48 UTC (permalink / raw)
To: Martin Blumenstingl, linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
jslaby-IBi9RG/b67k, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
Cc: mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170115223255.10350-2-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
Am 15.01.2017 um 23:32 schrieb Martin Blumenstingl:
> The vendor driver allows setting baud-rates higher than 115200 baud.
> There is a check in the vendor driver which prevents using more than
> 115200 baud during startup, however it does not have such a check in
> .set_termios.
> Higher baud-rates are often used by the bluetooth modules embedded into
> the SDIO wifi chips (Amlogic devices use brcmfmac based wifi chips quite
> often, 2000000 baud seems to be a common value for the UART baud-rate in
> Amlogic's "libbt").
>
> I have tested this on a Meson GXL device with uart_A (to which the
> bluetooth module is connected, where initialization times out with
> 115200 baud) and uart_AO (which I manually set to 2000000 baud and then
> connected with my USB UART adapter to that).
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
Tested-by: Andreas Färber <afaerber-l3A5Bk7waGM@public.gmane.org>
Thanks,
Andreas
--
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 2/4] ARM64: dts: meson-gx: add the serial CTS and RTS pin groups
From: Andreas Färber @ 2017-01-15 22:50 UTC (permalink / raw)
To: Martin Blumenstingl, linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
jslaby-IBi9RG/b67k, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
Cc: mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170115223255.10350-3-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
Am 15.01.2017 um 23:32 schrieb Martin Blumenstingl:
> This adds pinctrl group nodes for the CTS and RTS pins of each serial
> controller. This makes it possible to enable the CTS and RTS pins which
> are controlled by the serial controller hardware (through the meson_uart
> driver).
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
Tested-by: Andreas Färber <afaerber-l3A5Bk7waGM@public.gmane.org>
Thanks,
Andreas
--
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 4/4] ARM64: dts: meson-gxbb-vega-s95: enable the Bluetooth module
From: Andreas Färber @ 2017-01-15 22:55 UTC (permalink / raw)
To: Martin Blumenstingl, linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
jslaby-IBi9RG/b67k, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
Cc: mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170115223255.10350-5-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
Am 15.01.2017 um 23:32 schrieb Martin Blumenstingl:
> This takes the Bluetooth module out of reset (the reset line is
> connected to GPIOX_20) and enables uart_A which is used to configure the
> module. This is common for all Vega S95 boards.
> The device can then be initialized by running the hciattach tool:
> hciattach -s115200 /dev/ttyAML1 bcm43xx 2000000 flow -
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> ---
> arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 9 +++++++++
> 1 file changed, 9 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 ab497126c9a3..9e0a13b1ac93 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
> @@ -47,6 +47,7 @@
>
> aliases {
> serial0 = &uart_AO;
> + serial1 = &uart_A;
> };
>
> chosen {
> @@ -100,6 +101,14 @@
> };
> };
>
> +/* This is connected to the Bluetooth module of the wifi/BT combo chip: */
Personally I would just say "Connected to the .... chip" or even just
"Bluetooth .... chip", without trailing colon, for consistency.
> +&uart_A {
> + status = "okay";
> + pinctrl-0 = <&uart_a_pins &uart_a_cts_rts_pins>;
> + pinctrl-names = "default";
> + uart-has-rtscts;
> +};
> +
> &uart_AO {
> status = "okay";
> pinctrl-0 = <&uart_ao_a_pins>;
Tested-by: Andreas Färber <afaerber-l3A5Bk7waGM@public.gmane.org>
Thanks,
Andreas
--
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 4/5] Input: mpr121 - handle multiple bits change of status register
From: Dmitry Torokhov @ 2017-01-15 23:05 UTC (permalink / raw)
To: Akinobu Mita
Cc: linux-input-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1484486144-27947-5-git-send-email-akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Sun, Jan 15, 2017 at 10:15:43PM +0900, Akinobu Mita wrote:
> This driver reports input events on their interrupts which are triggered
> by the sensor's status register changes. But only single bit change is
> reported in the interrupt handler. So if there are multiple bits are
> changed at almost the same time, other press or release events are ignored.
>
> This fixes it by detecting all changed bits in the status register.
>
> Cc: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Akinobu Mita <akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> * Use for_each_set_bit() to search changed bit
>
> drivers/input/keyboard/mpr121_touchkey.c | 23 ++++++++++++++---------
> 1 file changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
> index 2558c60..a0210ae 100644
> --- a/drivers/input/keyboard/mpr121_touchkey.c
> +++ b/drivers/input/keyboard/mpr121_touchkey.c
> @@ -86,7 +86,8 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
> struct mpr121_touchkey *mpr121 = dev_id;
> struct i2c_client *client = mpr121->client;
> struct input_dev *input = mpr121->input_dev;
> - unsigned int key_num, key_val, pressed;
> + unsigned long bit_changed;
> + unsigned int key_num;
> int reg;
>
> reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR);
> @@ -104,18 +105,22 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
>
> reg &= TOUCH_STATUS_MASK;
> /* use old press bit to figure out which bit changed */
> - key_num = ffs(reg ^ mpr121->statusbits) - 1;
> - pressed = reg & (1 << key_num);
> + bit_changed = reg ^ mpr121->statusbits;
> mpr121->statusbits = reg;
> + for_each_set_bit(key_num, &bit_changed, mpr121->keycount) {
> + unsigned int key_val, pressed;
>
> - key_val = mpr121->keycodes[key_num];
> + pressed = reg & (1 << key_num);
Changed to
pressed = reg & BIT(key_num);
and applied, thank you.
> + key_val = mpr121->keycodes[key_num];
>
> - input_event(input, EV_MSC, MSC_SCAN, key_num);
> - input_report_key(input, key_val, pressed);
> - input_sync(input);
> + input_event(input, EV_MSC, MSC_SCAN, key_num);
> + input_report_key(input, key_val, pressed);
> +
> + dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val,
> + pressed ? "pressed" : "released");
>
> - dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val,
> - pressed ? "pressed" : "released");
> + }
> + input_sync(input);
>
> out:
> return IRQ_HANDLED;
> --
> 2.7.4
>
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 5/5] Input: mpr121 - switch to device tree probe
From: Dmitry Torokhov @ 2017-01-15 23:06 UTC (permalink / raw)
To: Akinobu Mita
Cc: linux-input-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring
In-Reply-To: <1484486144-27947-6-git-send-email-akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Sun, Jan 15, 2017 at 10:15:44PM +0900, Akinobu Mita wrote:
> This driver currently only supports legacy platform data probe. This
> change adds device tree support and gets rid of platform data probe code
> since no one is actually using mpr121 platform data in the mainline.
>
> The device tree property parsing code is based on the work of
> atmel_captouch driver.
>
> Cc: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Signed-off-by: Akinobu Mita <akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> * Newly added patch from v2
>
> .../devicetree/bindings/input/mpr121-touchkey.txt | 30 ++++++
> drivers/input/keyboard/mpr121_touchkey.c | 110 +++++++++++++++------
> include/linux/i2c/mpr121_touchkey.h | 20 ----
> 3 files changed, 110 insertions(+), 50 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/input/mpr121-touchkey.txt
> delete mode 100644 include/linux/i2c/mpr121_touchkey.h
>
> diff --git a/Documentation/devicetree/bindings/input/mpr121-touchkey.txt b/Documentation/devicetree/bindings/input/mpr121-touchkey.txt
> new file mode 100644
> index 0000000..b7c61ee
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/mpr121-touchkey.txt
> @@ -0,0 +1,30 @@
> +* Freescale MPR121 Controllor
> +
> +Required Properties:
> +- compatible: Should be "fsl,mpr121-touchkey"
> +- reg: The I2C slave address of the device.
> +- interrupts: The interrupt number to the cpu.
> +- vdd-supply: Phandle to the Vdd power supply.
> +- linux,keycodes: Specifies an array of numeric keycode values to
> + be used for reporting button presses. The array can
> + contain up to 12 entries.
> +
> +Optional Properties:
> +- wakeup-source: Use any event on keypad as wakeup event.
> +- autorepeat: Enable autorepeat feature.
> +
> +Example:
> +
> +#include "dt-bindings/input/input.h"
> +
> + touchkey: mpr121@5a {
> + compatible = "fsl,mpr121-touchkey";
> + reg = <0x5a>;
> + interrupt-parent = <&gpio1>;
> + interrupts = <28 2>;
> + autorepeat;
> + vdd-supply = <&ldo4_reg>;
> + linux,keycodes = <KEY_0>, <KEY_1>, <KEY_2>, <KEY_3>,
> + <KEY_4> <KEY_5>, <KEY_6>, <KEY_7>,
> + <KEY_8>, <KEY_9>, <KEY_A>, <KEY_B>;
> + };
> diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
> index a0210ae..ebb401f 100644
> --- a/drivers/input/keyboard/mpr121_touchkey.c
> +++ b/drivers/input/keyboard/mpr121_touchkey.c
> @@ -19,7 +19,7 @@
> #include <linux/delay.h>
> #include <linux/bitops.h>
> #include <linux/interrupt.h>
> -#include <linux/i2c/mpr121_touchkey.h>
> +#include <linux/regulator/consumer.h>
>
> /* Register definitions */
> #define ELE_TOUCH_STATUS_0_ADDR 0x0
> @@ -61,7 +61,7 @@ struct mpr121_touchkey {
> struct input_dev *input_dev;
> unsigned int statusbits;
> unsigned int keycount;
> - u16 keycodes[MPR121_MAX_KEY_COUNT];
> + u32 keycodes[MPR121_MAX_KEY_COUNT];
> };
>
> struct mpr121_init_register {
> @@ -81,6 +81,42 @@ static const struct mpr121_init_register init_reg_table[] = {
> { AUTO_CONFIG_CTRL_ADDR, 0x0b },
> };
>
> +static void mpr121_vdd_supply_disable(void *data)
> +{
> + struct regulator *vdd_supply = data;
> +
> + regulator_disable(vdd_supply);
> +}
> +
> +static struct regulator *mpr121_vdd_supply_init(struct device *dev)
> +{
> + struct regulator *vdd_supply;
> + int err;
> +
> + vdd_supply = devm_regulator_get(dev, "vdd");
> + if (IS_ERR(vdd_supply)) {
> + dev_err(dev, "failed to get vdd regulator: %ld\n",
> + PTR_ERR(vdd_supply));
> + return vdd_supply;
> + }
> +
> + err = regulator_enable(vdd_supply);
> + if (err) {
> + dev_err(dev, "failed to enable vdd regulator: %d\n", err);
> + return ERR_PTR(err);
> + }
> +
> + err = devm_add_action(dev, mpr121_vdd_supply_disable, vdd_supply);
> + if (err) {
> + regulator_disable(vdd_supply);
> + dev_err(dev, "failed to add disable regulator action: %d\n",
> + err);
> + return ERR_PTR(err);
> + }
> +
> + return vdd_supply;
> +}
> +
> static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
> {
> struct mpr121_touchkey *mpr121 = dev_id;
> @@ -126,9 +162,8 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> -static int mpr121_phys_init(const struct mpr121_platform_data *pdata,
> - struct mpr121_touchkey *mpr121,
> - struct i2c_client *client)
> +static int mpr121_phys_init(struct mpr121_touchkey *mpr121,
> + struct i2c_client *client, int vdd_uv)
> {
> const struct mpr121_init_register *reg;
> unsigned char usl, lsl, tl, eleconf;
> @@ -158,9 +193,9 @@ static int mpr121_phys_init(const struct mpr121_platform_data *pdata,
> /*
> * Capacitance on sensing input varies and needs to be compensated.
> * The internal MPR121-auto-configuration can do this if it's
> - * registers are set properly (based on pdata->vdd_uv).
> + * registers are set properly (based on vdd_uv).
> */
> - vdd = pdata->vdd_uv / 1000;
> + vdd = vdd_uv / 1000;
> usl = ((vdd - 700) * 256) / vdd;
> lsl = (usl * 65) / 100;
> tl = (usl * 90) / 100;
> @@ -191,27 +226,19 @@ static int mpr121_phys_init(const struct mpr121_platform_data *pdata,
> static int mpr_touchkey_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> - const struct mpr121_platform_data *pdata =
> - dev_get_platdata(&client->dev);
> + struct device *dev = &client->dev;
> + struct regulator *vdd_supply;
> + int vdd_uv;
> struct mpr121_touchkey *mpr121;
> struct input_dev *input_dev;
> int error;
> int i;
>
> - if (!pdata) {
> - dev_err(&client->dev, "no platform data defined\n");
> - return -EINVAL;
> - }
> + vdd_supply = mpr121_vdd_supply_init(dev);
> + if (IS_ERR(vdd_supply))
> + return PTR_ERR(vdd_supply);
>
> - if (!pdata->keymap || !pdata->keymap_size) {
> - dev_err(&client->dev, "missing keymap data\n");
> - return -EINVAL;
> - }
> -
> - if (pdata->keymap_size > MPR121_MAX_KEY_COUNT) {
> - dev_err(&client->dev, "too many keys defined\n");
> - return -EINVAL;
> - }
> + vdd_uv = regulator_get_voltage(vdd_supply);
>
> if (!client->irq) {
> dev_err(&client->dev, "irq number should not be zero\n");
> @@ -229,24 +256,37 @@ static int mpr_touchkey_probe(struct i2c_client *client,
>
> mpr121->client = client;
> mpr121->input_dev = input_dev;
> - mpr121->keycount = pdata->keymap_size;
> + mpr121->keycount = device_property_read_u32_array(dev, "linux,keycodes",
> + NULL, 0);
> + if (mpr121->keycount > MPR121_MAX_KEY_COUNT) {
> + dev_err(dev, "too many keys defined\n");
> + return -EINVAL;
> + }
> +
> + error = device_property_read_u32_array(dev, "linux,keycodes",
> + mpr121->keycodes,
> + mpr121->keycount);
> + if (error) {
> + dev_err(dev,
> + "failed to read linux,keycode property: %d\n", error);
> + return error;
> + }
>
> input_dev->name = "Freescale MPR121 Touchkey";
> input_dev->id.bustype = BUS_I2C;
> input_dev->dev.parent = &client->dev;
> - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
> + if (device_property_present(dev, "autorepeat"))
> + __set_bit(EV_REP, input_dev->evbit);
Replaced with device_property_read_bool(), added a couple headers, and
applied, thank you.
> input_set_capability(input_dev, EV_MSC, MSC_SCAN);
>
> input_dev->keycode = mpr121->keycodes;
> input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
> input_dev->keycodemax = mpr121->keycount;
>
> - for (i = 0; i < pdata->keymap_size; i++) {
> - input_set_capability(input_dev, EV_KEY, pdata->keymap[i]);
> - mpr121->keycodes[i] = pdata->keymap[i];
> - }
> + for (i = 0; i < mpr121->keycount; i++)
> + input_set_capability(input_dev, EV_KEY, mpr121->keycodes[i]);
>
> - error = mpr121_phys_init(pdata, mpr121, client);
> + error = mpr121_phys_init(mpr121, client, vdd_uv);
> if (error) {
> dev_err(&client->dev, "Failed to init register\n");
> return error;
> @@ -266,7 +306,8 @@ static int mpr_touchkey_probe(struct i2c_client *client,
> return error;
>
> i2c_set_clientdata(client, mpr121);
> - device_init_wakeup(&client->dev, pdata->wakeup);
> + device_init_wakeup(dev,
> + device_property_read_bool(dev, "wakeup-source"));
>
> return 0;
> }
> @@ -305,10 +346,19 @@ static const struct i2c_device_id mpr121_id[] = {
> };
> MODULE_DEVICE_TABLE(i2c, mpr121_id);
>
> +#ifdef CONFIG_OF
> +static const struct of_device_id mpr121_touchkey_dt_match_table[] = {
> + { .compatible = "fsl,mpr121-touchkey" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, mpr121_touchkey_dt_match_table);
> +#endif
> +
> static struct i2c_driver mpr_touchkey_driver = {
> .driver = {
> .name = "mpr121",
> .pm = &mpr121_touchkey_pm_ops,
> + .of_match_table = of_match_ptr(mpr121_touchkey_dt_match_table),
> },
> .id_table = mpr121_id,
> .probe = mpr_touchkey_probe,
> diff --git a/include/linux/i2c/mpr121_touchkey.h b/include/linux/i2c/mpr121_touchkey.h
> deleted file mode 100644
> index f0bcc38..0000000
> --- a/include/linux/i2c/mpr121_touchkey.h
> +++ /dev/null
> @@ -1,20 +0,0 @@
> -/* Header file for Freescale MPR121 Capacitive Touch Sensor */
> -
> -#ifndef _MPR121_TOUCHKEY_H
> -#define _MPR121_TOUCHKEY_H
> -
> -/**
> - * struct mpr121_platform_data - platform data for mpr121 sensor
> - * @keymap: pointer to array of KEY_* values representing keymap
> - * @keymap_size: size of the keymap
> - * @wakeup: configure the button as a wake-up source
> - * @vdd_uv: VDD voltage in uV
> - */
> -struct mpr121_platform_data {
> - const unsigned short *keymap;
> - unsigned int keymap_size;
> - bool wakeup;
> - int vdd_uv;
> -};
> -
> -#endif /* _MPR121_TOUCHKEY_H */
> --
> 2.7.4
>
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 0/5] nput: mpr121 - switch to use device tree probe
From: Dmitry Torokhov @ 2017-01-15 23:07 UTC (permalink / raw)
To: Akinobu Mita; +Cc: linux-input, devicetree, Rob Herring
In-Reply-To: <1484486144-27947-1-git-send-email-akinobu.mita@gmail.com>
On Sun, Jan 15, 2017 at 10:15:39PM +0900, Akinobu Mita wrote:
> This driver currently only supports legacy platform data probe. This
> change adds device tree support and gets rid of platform data probe code
> since no one is actually using mpr121 platform data in the mainline.
>
> This series also contains miscellaneous cleanup and bug fixes that
> mostly I found while playing with this driver.
>
> * Changes since v1 (All changes are suggested by Dmitry Torokhov)
> - Add patch 'annotate PM methods as __maybe_unused'
> - Use for_each_set_bit() to search changed bit
> - Use linux,keycodes property instead of using matrix keymap API
> - Get rid of platform data
>
> Akinobu Mita (5):
> Input: mpr121 - annotate PM methods as __maybe_unused
> Input: mpr121 - remove unused field in struct mpr121_touchkey
> Input: mpr121 - set missing event capability
> Input: mpr121 - handle multiple bits change of status register
> Input: mpr121 - switch to device tree probe
Applied the lot (the last 2 with minor edits), thank you.
--
Dmitry
^ permalink raw reply
* Re: [PATCH 04/10] sata: hardreset: retry if phys link is down
From: Tejun Heo @ 2017-01-15 23:10 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Kevin Hilman, Sekhar Nori, Patrick Titiano, Michael Turquette,
Rob Herring, Mark Rutland, Russell King, David Lechner, linux-ide,
devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <1484311084-31547-5-git-send-email-bgolaszewski@baylibre.com>
Hello,
On Fri, Jan 13, 2017 at 01:37:58PM +0100, Bartosz Golaszewski wrote:
> The sata core driver already retries to resume the link because some
> controllers ignore writes to the SControl register.
>
> We have a use case with the da850 SATA controller where at PLL0
> frequency of 456MHz (needed to properly service the LCD controller)
> the chip becomes unstable and the hardreset operation is ignored the
> first time 50% of times.
>
> Retrying just the resume operation doesn't work - we need to issue
> the phy/wake reset again to make it work.
>
> If ata_phys_link_offline() returns true in sata_link_hardreset(),
> retry a couple times before really giving up.
I think it'd be better to implement the driver specific implementation
rather than changing the behavior for everybody.
Thanks.
--
tejun
^ permalink raw reply
* Re: [PATCH 06/10] sata: ahci_da850: implement a softreset quirk
From: Tejun Heo @ 2017-01-15 23:12 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Kevin Hilman, Sekhar Nori, Patrick Titiano, Michael Turquette,
Rob Herring, Mark Rutland, Russell King, David Lechner,
linux-ide-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1484311084-31547-7-git-send-email-bgolaszewski-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
On Fri, Jan 13, 2017 at 01:38:00PM +0100, Bartosz Golaszewski wrote:
> +static int ahci_da850_softreset(struct ata_link *link,
> + unsigned int *class, unsigned long deadline)
> +{
> + int pmp, ret;
> +
> + pmp = sata_srst_pmp(link);
> +
> + ret = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
> + if (pmp && ret == -EBUSY)
> + return ahci_do_softreset(link, class, 0,
> + deadline, ahci_check_ready);
> +
> + return ret;
> +}
Please add some comments explaining what's going on.
Thanks.
--
tejun
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 0/3] ti,ads7950 device tree bindings
From: David Lechner @ 2017-01-15 23:44 UTC (permalink / raw)
To: Jonathan Cameron, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-iio-u79uwXL29TY76Z2rM5mHXA
Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
Rob Herring, Mark Rutland, linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <c4c59921-d0dc-0858-8d66-c56fa38d3b50-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On 01/15/2017 07:58 AM, Jonathan Cameron wrote:
> On 11/01/17 17:52, David Lechner wrote:
>> This series adds device tree bindings for the TI ADS7950 family of A/DC chips.
>> The series includes the bindings documentation and some fixes to the iio driver
>> to make it work with the device tree bindings.
>>
>> FYI, the ads7950 driver has not made it into mainline yet, so no worries about
>> breaking anyone with these changes.
>>
> And here's the bit I failed to read!
>
> As an extra point, could you confirm what /sys/bus/iio/iio\:deviceX/name for this
> one reads? I have a feeling this is another case of what Lars has been pointing
> out in other drivers this morning. That name should be the device part number..
>
cat /sys/bus/iio/devices/iio\:device0/name
ads7957
This is the part number for the specific chip I am using. So, I am
guessing that it is correct unless it is supposed to be upper case or
something like that.
> Thanks,
>
> Jonathan
>> David Lechner (3):
>> DT/bindings: Add bindings for TI ADS7950 A/DC chips
>> iio: adc: ti-ads7950: Drop "ti-" prefix from module name
>> iio: adc: ti-ads7950: Change regulator matching string to "vref"
>>
>> .../devicetree/bindings/iio/adc/ti-ads7950.txt | 23 ++++++++++++++++
>> drivers/iio/adc/ti-ads7950.c | 32 +++++++++++-----------
>> 2 files changed, 39 insertions(+), 16 deletions(-)
>> create mode 100644 Documentation/devicetree/bindings/iio/adc/ti-ads7950.txt
>>
>
^ permalink raw reply
* Re: [PATCH v2 3/3] Input: pwm-beeper: add optional amplifier regulator
From: David Lechner @ 2017-01-16 0:12 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, devicetree, Rob Herring, Mark Rutland, linux-kernel
In-Reply-To: <20170114191943.GC31309@dtor-ws>
On 01/14/2017 01:19 PM, Dmitry Torokhov wrote:
> On Wed, Jan 11, 2017 at 02:02:01PM -0600, David Lechner wrote:
>> This adds an optional regulator to the pwm-beeper device. This regulator
>> acts as an amplifier. The amplifier is only enabled while beeping in order
>> to reduce power consumption.
>>
>> Tested on LEGO MINDSTORMS EV3, which has a speaker connected to PWM through
>> an amplifier.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---
>> drivers/input/misc/pwm-beeper.c | 29 ++++++++++++++++++++++++++++-
>> 1 file changed, 28 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
>> index 30ac227..708e88e 100644
>> --- a/drivers/input/misc/pwm-beeper.c
>> +++ b/drivers/input/misc/pwm-beeper.c
>> @@ -14,6 +14,7 @@
>> */
>>
>> #include <linux/input.h>
>> +#include <linux/regulator/consumer.h>
>> #include <linux/module.h>
>> #include <linux/kernel.h>
>> #include <linux/of.h>
>> @@ -25,8 +26,10 @@
>> struct pwm_beeper {
>> struct input_dev *input;
>> struct pwm_device *pwm;
>> + struct regulator *reg;
>> struct work_struct work;
>> unsigned long period;
>> + bool reg_enabled;
>> };
>>
>> #define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
>> @@ -38,8 +41,20 @@ static void __pwm_beeper_set(struct pwm_beeper *beeper)
>> if (period) {
>> pwm_config(beeper->pwm, period / 2, period);
>> pwm_enable(beeper->pwm);
>> - } else
>> + if (beeper->reg) {
>> + int error;
>> +
>> + error = regulator_enable(beeper->reg);
>> + if (!error)
>> + beeper->reg_enabled = true;
>> + }
>> + } else {
>> + if (beeper->reg_enabled) {
>> + regulator_disable(beeper->reg);
>> + beeper->reg_enabled = false;
>> + }
>> pwm_disable(beeper->pwm);
>> + }
>> }
>>
>> static void pwm_beeper_work(struct work_struct *work)
>> @@ -82,6 +97,10 @@ static void pwm_beeper_stop(struct pwm_beeper *beeper)
>> {
>> cancel_work_sync(&beeper->work);
>>
>> + if (beeper->reg_enabled) {
>> + regulator_disable(beeper->reg);
>> + beeper->reg_enabled = false;
>> + }
>> if (beeper->period)
>> pwm_disable(beeper->pwm);
>> }
>> @@ -111,6 +130,14 @@ static int pwm_beeper_probe(struct platform_device *pdev)
>> return error;
>> }
>>
>> + beeper->reg = devm_regulator_get_optional(&pdev->dev, "amp");
>
> If you do not use optional regulator then you will not have to check if
> you have it or not everywhere: regulator core will give you a dummy that
> you can toggle to your heart's content.
Some months ago, I learned that if you are not using device tree and you
do not call regulator_has_full_constraints(), then you do not get a
dummy regulator. And here, we are only checking if the regulator exists
in one place. We will still need the checks for beeper->reg_enabled to
keep calls to regulator_enable() and regulator_disable() balanced.
On the other hand, it is recommended that you always call
regulator_has_full_constraints(), so I don't mind changing it if that is
what you think we should do. But, I don't really see much of an
advantage to changing it compared to the current implementation.
>
>> + error = PTR_ERR_OR_ZERO(beeper->reg);
>> + if (error) {
>> + if (error != -EPROBE_DEFER)
>> + dev_err(dev, "Failed to get amp regulator\n");
>> + return error;
>> + }
>> +
>> /*
>> * FIXME: pwm_apply_args() should be removed when switching to
>> * the atomic PWM API.
>> --
>> 2.7.4
>>
>
> Thanks.
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox