diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0002-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0001-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch similarity index 74% rename from device/testing/linux-samsung-coreprimevelte-mainline/0002-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch rename to device/testing/linux-samsung-coreprimevelte-mainline/0001-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch index a6c6e2d8a..5c7ac5f18 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0002-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0001-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch @@ -1,4 +1,4 @@ -From d53f28d1c946a99a5968f429219530655e95ff88 Mon Sep 17 00:00:00 2001 +From b5eaf20ed25d51d8523ce83e678ff9fab740c8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= Date: Fri, 21 Jul 2023 22:37:45 +0200 Subject: [PATCH] gpio: pxa: disable pinctrl calls for MMP_GPIO @@ -10,17 +10,19 @@ Similarly to PXA3xx and MMP2, pinctrl-single isn't capable of setting pin direction on MMP either. Fixes: a770d946371e ("gpio: pxa: add pin control gpio direction and request") -Signed-off-by: Duje Mihanović Reviewed-by: Andy Shevchenko +Acked-by: Bartosz Golaszewski +Reviewed-by: Linus Walleij +Signed-off-by: Duje Mihanović --- drivers/gpio/gpio-pxa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c -index a1630ed4b741..d92650aecb06 100644 +index 7e9f7a32d3ee..cae9661862fe 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c -@@ -238,6 +238,7 @@ static bool pxa_gpio_has_pinctrl(void) +@@ -237,6 +237,7 @@ static bool pxa_gpio_has_pinctrl(void) switch (gpio_type) { case PXA3XX_GPIO: case MMP2_GPIO: @@ -29,5 +31,5 @@ index a1630ed4b741..d92650aecb06 100644 default: -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0001-tty-serial-8250-Define-earlycon-for-mrvl-mmp-uart.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0001-tty-serial-8250-Define-earlycon-for-mrvl-mmp-uart.patch deleted file mode 100644 index c7b75968f..000000000 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0001-tty-serial-8250-Define-earlycon-for-mrvl-mmp-uart.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 210337a85f95f0c7f3411bd0028c325818a23839 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= -Date: Fri, 21 Jul 2023 22:37:43 +0200 -Subject: [PATCH] tty: serial: 8250: Define earlycon for mrvl,mmp-uart -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -mrvl,pxa-uart already supports earlycon and both compatible strings use -the same driver, so there's no reason for mmp-uart to not have earlycon -as well. - -Signed-off-by: Duje Mihanović ---- - drivers/tty/serial/8250/8250_pxa.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c -index 28b341f602c6..a5b3ea27fc90 100644 ---- a/drivers/tty/serial/8250/8250_pxa.c -+++ b/drivers/tty/serial/8250/8250_pxa.c -@@ -183,6 +183,7 @@ static int __init early_serial_pxa_setup(struct earlycon_device *device, - return early_serial8250_setup(device, NULL); - } - OF_EARLYCON_DECLARE(early_pxa, "mrvl,pxa-uart", early_serial_pxa_setup); -+OF_EARLYCON_DECLARE(mmp, "mrvl,mmp-uart", early_serial_pxa_setup); - #endif - - MODULE_AUTHOR("Sergei Ianovich"); --- -2.41.0 - diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0003-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0002-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch similarity index 79% rename from device/testing/linux-samsung-coreprimevelte-mainline/0003-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch rename to device/testing/linux-samsung-coreprimevelte-mainline/0002-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch index c930c5582..3f3099c04 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0003-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0002-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch @@ -1,4 +1,4 @@ -From ef90e6f6bdd88eb6700a1605b5ebd4a8aaeb98c2 Mon Sep 17 00:00:00 2001 +From 6510dc5474cbfb92f7aedf981fa3831f43886906 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Jul 2023 12:48:38 +0300 Subject: [PATCH] clk: mmp: Switch to use struct u32_fract instead of custom @@ -15,15 +15,12 @@ Tested-by: Duje Mihanović Signed-off-by: Duje Mihanović --- drivers/clk/mmp/clk-frac.c | 57 ++++++++++++++++---------------- - drivers/clk/mmp/clk-mmp2.c | 6 ++-- drivers/clk/mmp/clk-of-mmp2.c | 26 +++++++-------- drivers/clk/mmp/clk-of-pxa168.c | 4 +-- drivers/clk/mmp/clk-of-pxa1928.c | 6 ++-- drivers/clk/mmp/clk-of-pxa910.c | 4 +-- - drivers/clk/mmp/clk-pxa168.c | 4 +-- - drivers/clk/mmp/clk-pxa910.c | 4 +-- drivers/clk/mmp/clk.h | 10 ++---- - 9 files changed, 58 insertions(+), 63 deletions(-) + 6 files changed, 51 insertions(+), 56 deletions(-) diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c index 1b90867b60c4..6556f6ada2e8 100644 @@ -167,28 +164,11 @@ index 1b90867b60c4..6556f6ada2e8 100644 { struct mmp_clk_factor *factor; struct clk_init_data init; -diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c -index aabacfa10158..ab7dde7e7a44 100644 ---- a/drivers/clk/mmp/clk-mmp2.c -+++ b/drivers/clk/mmp/clk-mmp2.c -@@ -59,9 +59,9 @@ static struct mmp_clk_factor_masks uart_factor_masks = { - .den_shift = 0, - }; - --static struct mmp_clk_factor_tbl uart_factor_tbl[] = { -- {.num = 8125, .den = 1536}, /*14.745MHZ */ -- {.num = 3521, .den = 689}, /*19.23MHZ */ -+static struct u32_fract uart_factor_tbl[] = { -+ { .numerator = 8125, .denominator = 1536 }, /* 14.745MHZ */ -+ { .numerator = 3521, .denominator = 689 }, /* 19.23MHZ */ - }; - - static const char *uart_parent[] = {"uart_pll", "vctcxo"}; diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c -index bcf60f43aa13..d771b3e5fb2d 100644 +index eaad36ee323d..a4f15cee630e 100644 --- a/drivers/clk/mmp/clk-of-mmp2.c +++ b/drivers/clk/mmp/clk-of-mmp2.c -@@ -141,9 +141,9 @@ static struct mmp_clk_factor_masks uart_factor_masks = { +@@ -143,9 +143,9 @@ static struct mmp_clk_factor_masks uart_factor_masks = { .den_shift = 0, }; @@ -201,7 +181,7 @@ index bcf60f43aa13..d771b3e5fb2d 100644 }; static struct mmp_clk_factor_masks i2s_factor_masks = { -@@ -155,16 +155,16 @@ static struct mmp_clk_factor_masks i2s_factor_masks = { +@@ -157,16 +157,16 @@ static struct mmp_clk_factor_masks i2s_factor_masks = { .enable_mask = 0xd0000000, }; @@ -229,10 +209,10 @@ index bcf60f43aa13..d771b3e5fb2d 100644 static DEFINE_SPINLOCK(acgr_lock); diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c -index 130d1a723879..17cb5c622c31 100644 +index fb0df64cf053..ab5f83e77305 100644 --- a/drivers/clk/mmp/clk-of-pxa168.c +++ b/drivers/clk/mmp/clk-of-pxa168.c -@@ -104,8 +104,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = { +@@ -106,8 +106,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = { .den_shift = 0, }; @@ -244,10 +224,10 @@ index 130d1a723879..17cb5c622c31 100644 static void pxa168_pll_init(struct pxa168_clk_unit *pxa_unit) diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c -index 2508a0d795f8..675d695c5f7d 100644 +index 9def4b5f10e9..ebb6e278eda3 100644 --- a/drivers/clk/mmp/clk-of-pxa1928.c +++ b/drivers/clk/mmp/clk-of-pxa1928.c -@@ -58,9 +58,9 @@ static struct mmp_clk_factor_masks uart_factor_masks = { +@@ -61,9 +61,9 @@ static struct mmp_clk_factor_masks uart_factor_masks = { .den_shift = 0, }; @@ -261,10 +241,10 @@ index 2508a0d795f8..675d695c5f7d 100644 static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit) diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c -index 4d15bac987eb..f5b0b7b278c0 100644 +index 7a38c424782e..fe65e7bdb411 100644 --- a/drivers/clk/mmp/clk-of-pxa910.c +++ b/drivers/clk/mmp/clk-of-pxa910.c -@@ -84,8 +84,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = { +@@ -86,8 +86,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = { .den_shift = 0, }; @@ -275,36 +255,6 @@ index 4d15bac987eb..f5b0b7b278c0 100644 }; static void pxa910_pll_init(struct pxa910_clk_unit *pxa_unit) -diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c -index 8a9b8fb3a465..2ea88945bffd 100644 ---- a/drivers/clk/mmp/clk-pxa168.c -+++ b/drivers/clk/mmp/clk-pxa168.c -@@ -52,8 +52,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = { - .den_shift = 0, - }; - --static struct mmp_clk_factor_tbl uart_factor_tbl[] = { -- {.num = 8125, .den = 1536}, /*14.745MHZ */ -+static struct u32_fract uart_factor_tbl[] = { -+ { .numerator = 8125, .denominator = 1536 }, /* 14.745MHZ */ - }; - - static const char *uart_parent[] = {"pll1_3_16", "uart_pll"}; -diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c -index 9fcd76316d7e..e29b0fd6f423 100644 ---- a/drivers/clk/mmp/clk-pxa910.c -+++ b/drivers/clk/mmp/clk-pxa910.c -@@ -50,8 +50,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = { - .den_shift = 0, - }; - --static struct mmp_clk_factor_tbl uart_factor_tbl[] = { -- {.num = 8125, .den = 1536}, /*14.745MHZ */ -+static struct u32_fract uart_factor_tbl[] = { -+ { .numerator = 8125, .denominator = 1536 }, /* 14.745MHZ */ - }; - - static const char *uart_parent[] = {"pll1_3_16", "uart_pll"}; diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h index 55ac05379781..c83cec169ddc 100644 --- a/drivers/clk/mmp/clk.h @@ -345,5 +295,5 @@ index 55ac05379781..c83cec169ddc 100644 /* Clock type "mix" */ -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0004-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0003-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch similarity index 84% rename from device/testing/linux-samsung-coreprimevelte-mainline/0004-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch rename to device/testing/linux-samsung-coreprimevelte-mainline/0003-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch index dd5ae4d31..8edf7377b 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0004-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0003-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch @@ -1,4 +1,4 @@ -From 303c2b86cd5ebd0764e3768335883f0cd2e9fe04 Mon Sep 17 00:00:00 2001 +From 9495e512486a63d11baa2db46154cff4962f9f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= Date: Fri, 21 Jul 2023 22:37:47 +0200 Subject: [PATCH] dt-bindings: clock: Add Marvell PXA1908 clock bindings @@ -9,20 +9,21 @@ Content-Transfer-Encoding: 8bit Add dt bindings and documentation for the Marvell PXA1908 clock controller. +Reviewed-by: Conor Dooley Signed-off-by: Duje Mihanović --- - .../bindings/clock/marvell,pxa1908.yaml | 47 ++++++++++ - include/dt-bindings/clock/marvell,pxa1908.h | 92 +++++++++++++++++++ - 2 files changed, 139 insertions(+) + .../bindings/clock/marvell,pxa1908.yaml | 48 ++++++++++ + include/dt-bindings/clock/marvell,pxa1908.h | 88 +++++++++++++++++++ + 2 files changed, 136 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml create mode 100644 include/dt-bindings/clock/marvell,pxa1908.h diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml b/Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml new file mode 100644 -index 000000000000..a5af7992b1b6 +index 000000000000..4e78933232b6 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml -@@ -0,0 +1,47 @@ +@@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- @@ -49,6 +50,7 @@ index 000000000000..a5af7992b1b6 + - marvell,pxa1908-apbcp + - marvell,pxa1908-mpmu + - marvell,pxa1908-apmu ++ + reg: + maxItems: 1 + @@ -72,11 +74,11 @@ index 000000000000..a5af7992b1b6 + }; diff --git a/include/dt-bindings/clock/marvell,pxa1908.h b/include/dt-bindings/clock/marvell,pxa1908.h new file mode 100644 -index 000000000000..a4b035928137 +index 000000000000..fb15b0d0cd4c --- /dev/null +++ b/include/dt-bindings/clock/marvell,pxa1908.h -@@ -0,0 +1,92 @@ -+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ +@@ -0,0 +1,88 @@ ++/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +#ifndef __DTS_MARVELL_PXA1908_CLOCK_H +#define __DTS_MARVELL_PXA1908_CLOCK_H + @@ -106,20 +108,19 @@ index 000000000000..a4b035928137 +#define PXA1908_CLK_PLL1_832_GATE 23 +#define PXA1908_CLK_PLL1_1248_GATE 24 +#define PXA1908_CLK_PLL1_D2_GATE 25 -+#define PXA1908_CLK_PLL1_499_EN 26 ++#define PXA1908_CLK_PLL1_499_EN 26 +#define PXA1908_CLK_PLL2VCO 27 +#define PXA1908_CLK_PLL2 28 +#define PXA1908_CLK_PLL2P 29 -+#define PXA1908_CLK_PLL2VCODIV3 30 ++#define PXA1908_CLK_PLL2VCODIV3 30 +#define PXA1908_CLK_PLL3VCO 31 +#define PXA1908_CLK_PLL3 32 +#define PXA1908_CLK_PLL3P 33 -+#define PXA1908_CLK_PLL3VCODIV3 34 ++#define PXA1908_CLK_PLL3VCODIV3 34 +#define PXA1908_CLK_PLL4VCO 35 +#define PXA1908_CLK_PLL4 36 +#define PXA1908_CLK_PLL4P 37 -+#define PXA1908_CLK_PLL4VCODIV3 38 -+#define PXA1908_MPMU_NR_CLKS 38 ++#define PXA1908_CLK_PLL4VCODIV3 38 + +/* apb (apbc) peripherals */ +#define PXA1908_CLK_UART0 1 @@ -132,42 +133,39 @@ index 000000000000..a4b035928137 +#define PXA1908_CLK_SSP0 8 +#define PXA1908_CLK_SSP1 9 +#define PXA1908_CLK_IPC_RST 10 -+#define PXA1908_CLK_RTC 11 ++#define PXA1908_CLK_RTC 11 +#define PXA1908_CLK_TWSI0 12 -+#define PXA1908_CLK_KPC 13 ++#define PXA1908_CLK_KPC 13 +#define PXA1908_CLK_SWJTAG 14 +#define PXA1908_CLK_SSP2 15 +#define PXA1908_CLK_TWSI1 16 +#define PXA1908_CLK_THERMAL 17 +#define PXA1908_CLK_TWSI3 18 -+#define PXA1908_APBC_NR_CLKS 50 + +/* apb (apbcp) peripherals */ +#define PXA1908_CLK_UART2 1 +#define PXA1908_CLK_TWSI2 2 +#define PXA1908_CLK_AICER 3 -+#define PXA1908_APBCP_NR_CLKS 50 + +/* axi (apmu) peripherals */ +#define PXA1908_CLK_CCIC1 1 -+#define PXA1908_CLK_ISP 2 ++#define PXA1908_CLK_ISP 2 +#define PXA1908_CLK_DSI1 3 +#define PXA1908_CLK_DISP1 4 +#define PXA1908_CLK_CCIC0 5 +#define PXA1908_CLK_SDH0 6 +#define PXA1908_CLK_SDH1 7 -+#define PXA1908_CLK_USB 8 ++#define PXA1908_CLK_USB 8 +#define PXA1908_CLK_NF 9 +#define PXA1908_CLK_CORE_DEBUG 10 -+#define PXA1908_CLK_VPU 11 ++#define PXA1908_CLK_VPU 11 +#define PXA1908_CLK_GC 12 +#define PXA1908_CLK_SDH2 13 +#define PXA1908_CLK_GC2D 14 +#define PXA1908_CLK_TRACE 15 +#define PXA1908_CLK_DVC_DFC_DEBUG 16 -+#define PXA1908_APMU_NR_CLKS 50 + +#endif -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0005-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0004-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch similarity index 94% rename from device/testing/linux-samsung-coreprimevelte-mainline/0005-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch rename to device/testing/linux-samsung-coreprimevelte-mainline/0004-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch index da51b2028..a0a8a2215 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0005-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0004-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch @@ -1,4 +1,4 @@ -From 3db77bd6640b6b160e90b9228af922a5f647f069 Mon Sep 17 00:00:00 2001 +From 1117ce7ed0c45226667e5df8a74865b610e22856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= Date: Fri, 21 Jul 2023 22:37:46 +0200 Subject: [PATCH] clk: mmp: Add Marvell PXA1908 clock driver @@ -13,26 +13,26 @@ and APMU. Signed-off-by: Duje Mihanović --- drivers/clk/mmp/Makefile | 2 +- - drivers/clk/mmp/clk-of-pxa1908.c | 323 +++++++++++++++++++++++++++++++ - 2 files changed, 324 insertions(+), 1 deletion(-) + drivers/clk/mmp/clk-of-pxa1908.c | 328 +++++++++++++++++++++++++++++++ + 2 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/mmp/clk-of-pxa1908.c diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile -index cbcc2f8430a2..feacddb28fc4 100644 +index 441bf83080a1..69f9c3afde83 100644 --- a/drivers/clk/mmp/Makefile +++ b/drivers/clk/mmp/Makefile -@@ -15,4 +15,4 @@ obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o - obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o - obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o +@@ -11,4 +11,4 @@ obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o + obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o pwr-island.o + obj-$(CONFIG_COMMON_CLK_MMP2_AUDIO) += clk-audio.o -obj-y += clk-of-pxa1928.o +obj-$(CONFIG_ARCH_MMP) += clk-of-pxa1928.o clk-of-pxa1908.o diff --git a/drivers/clk/mmp/clk-of-pxa1908.c b/drivers/clk/mmp/clk-of-pxa1908.c new file mode 100644 -index 000000000000..520440cb082c +index 000000000000..753dd031b147 --- /dev/null +++ b/drivers/clk/mmp/clk-of-pxa1908.c -@@ -0,0 +1,323 @@ +@@ -0,0 +1,328 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include @@ -87,6 +87,11 @@ index 000000000000..520440cb082c +#define APMU_TRACE 0x108 +#define APMU_DVC_DFC_DEBUG 0x140 + ++#define MPMU_NR_CLKS 39 ++#define APBC_NR_CLKS 19 ++#define APBCP_NR_CLKS 4 ++#define APMU_NR_CLKS 17 ++ +struct pxa1908_clk_unit { + struct mmp_clk_unit unit; + void __iomem *mpmu_base; @@ -288,7 +293,7 @@ index 000000000000..520440cb082c + return; + } + -+ mmp_clk_init(np, &pxa_unit->unit, PXA1908_APBC_NR_CLKS); ++ mmp_clk_init(np, &pxa_unit->unit, APBC_NR_CLKS); + + pxa1908_apb_periph_clk_init(pxa_unit); +} @@ -309,7 +314,7 @@ index 000000000000..520440cb082c + return; + } + -+ mmp_clk_init(np, &pxa_unit->unit, PXA1908_APBCP_NR_CLKS); ++ mmp_clk_init(np, &pxa_unit->unit, APBCP_NR_CLKS); + + pxa1908_apb_p_periph_clk_init(pxa_unit); +} @@ -330,7 +335,7 @@ index 000000000000..520440cb082c + return; + } + -+ mmp_clk_init(np, &pxa_unit->unit, PXA1908_MPMU_NR_CLKS); ++ mmp_clk_init(np, &pxa_unit->unit, MPMU_NR_CLKS); + + pxa1908_pll_init(pxa_unit); +} @@ -351,11 +356,11 @@ index 000000000000..520440cb082c + return; + } + -+ mmp_clk_init(np, &pxa_unit->unit, PXA1908_APMU_NR_CLKS); ++ mmp_clk_init(np, &pxa_unit->unit, APMU_NR_CLKS); + + pxa1908_axi_periph_clk_init(pxa_unit); +} +CLK_OF_DECLARE(pxa1908_apmu, "marvell,pxa1908-apmu", pxa1908_apmu_clk_init); -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0006-dt-bindings-marvell-Document-PXA1908-SoC.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0005-dt-bindings-marvell-Document-PXA1908-SoC.patch similarity index 88% rename from device/testing/linux-samsung-coreprimevelte-mainline/0006-dt-bindings-marvell-Document-PXA1908-SoC.patch rename to device/testing/linux-samsung-coreprimevelte-mainline/0005-dt-bindings-marvell-Document-PXA1908-SoC.patch index b1fd43fcf..67457dcc1 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0006-dt-bindings-marvell-Document-PXA1908-SoC.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0005-dt-bindings-marvell-Document-PXA1908-SoC.patch @@ -1,4 +1,4 @@ -From 4a92c2d243b9516d119fb631666ec44d212e4405 Mon Sep 17 00:00:00 2001 +From 7f084b50032c0fb5f2c6b1fdadffd1d05a27d298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= Date: Fri, 21 Jul 2023 22:37:51 +0200 Subject: [PATCH] dt-bindings: marvell: Document PXA1908 SoC @@ -8,6 +8,7 @@ Content-Transfer-Encoding: 8bit Add dt binding for the Marvell PXA1908 SoC. +Reviewed-by: Krzysztof Kozlowski Signed-off-by: Duje Mihanović --- Documentation/devicetree/bindings/arm/mrvl/mrvl.yaml | 5 +++++ @@ -30,5 +31,5 @@ index 4c43eaf3632e..f73bb8ec3a1a 100644 additionalProperties: true -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0007-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0006-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch similarity index 93% rename from device/testing/linux-samsung-coreprimevelte-mainline/0007-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch rename to device/testing/linux-samsung-coreprimevelte-mainline/0006-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch index 7e2a0c33d..4080bbb0e 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0007-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0006-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch @@ -1,4 +1,4 @@ -From 2752ad57729b4b4f769c6014b81fdc3f6c416ba6 Mon Sep 17 00:00:00 2001 +From e3fa451f2abf3ed646ebe0676c86d9c4d54af37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= Date: Fri, 21 Jul 2023 22:37:49 +0200 Subject: [PATCH] arm64: Kconfig.platforms: Add config for Marvell PXA1908 @@ -37,5 +37,5 @@ index 6069120199bb..b417cae42c84 100644 bool "Bitmain SoC Platforms" help -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0008-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0007-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch similarity index 96% rename from device/testing/linux-samsung-coreprimevelte-mainline/0008-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch rename to device/testing/linux-samsung-coreprimevelte-mainline/0007-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch index 498790493..fe53f6816 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0008-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0007-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch @@ -1,4 +1,4 @@ -From bcd581ae175ab72d3ffa81386e11837923fb4328 Mon Sep 17 00:00:00 2001 +From ba77704a60653c40ccdbe59511cbfb6dfa8f9465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= Date: Fri, 21 Jul 2023 22:37:50 +0200 Subject: [PATCH] arm64: dts: Add DTS for Marvell PXA1908 and @@ -13,9 +13,9 @@ Edition LTE, a smartphone based on said SoC. Signed-off-by: Duje Mihanović --- arch/arm64/boot/dts/marvell/Makefile | 3 + - .../pxa1908-samsung-coreprimevelte.dts | 332 ++++++++++++++++++ - arch/arm64/boot/dts/marvell/pxa1908.dtsi | 292 +++++++++++++++ - 3 files changed, 627 insertions(+) + .../pxa1908-samsung-coreprimevelte.dts | 333 ++++++++++++++++++ + arch/arm64/boot/dts/marvell/pxa1908.dtsi | 295 ++++++++++++++++ + 3 files changed, 631 insertions(+) create mode 100644 arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts create mode 100644 arch/arm64/boot/dts/marvell/pxa1908.dtsi @@ -32,10 +32,10 @@ index 79ac09b58a89..263be6ec7567 100644 +dtb-$(CONFIG_ARCH_MMP) += pxa1908-samsung-coreprimevelte.dtb diff --git a/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts new file mode 100644 -index 000000000000..59e5d6f15dd2 +index 000000000000..e3c863d517a8 --- /dev/null +++ b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts -@@ -0,0 +1,332 @@ +@@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include "pxa1908.dtsi" +#include @@ -362,6 +362,7 @@ index 000000000000..59e5d6f15dd2 +}; + +&sdh0 { ++ pinctrl-names = "default"; + pinctrl-0 = <&sdh0_pins_1 &sdh0_pins_2 &sdh0_pins_3>; + cd-gpios = <&gpio 11 0>; + cd-inverted; @@ -370,10 +371,10 @@ index 000000000000..59e5d6f15dd2 +}; diff --git a/arch/arm64/boot/dts/marvell/pxa1908.dtsi b/arch/arm64/boot/dts/marvell/pxa1908.dtsi new file mode 100644 -index 000000000000..59b3e609bb24 +index 000000000000..cc322b9a0e9e --- /dev/null +++ b/arch/arm64/boot/dts/marvell/pxa1908.dtsi -@@ -0,0 +1,292 @@ +@@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-2.0-only +/dts-v1/; + @@ -452,7 +453,10 @@ index 000000000000..59b3e609bb24 + gic: interrupt-controller@d1df9000 { + compatible = "arm,gic-400"; + reg = <0 0xd1df9000 0 0x1000>, -+ <0 0xd1dfa000 0 0x2000>; ++ <0 0xd1dfa000 0 0x2000>, ++ /* The subsequent registers are guesses. */ ++ <0 0xd1dfc000 0 0x2000>, ++ <0 0xd1dfe000 0 0x2000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; @@ -667,5 +671,5 @@ index 000000000000..59b3e609bb24 + }; +}; -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0009-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0008-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch similarity index 86% rename from device/testing/linux-samsung-coreprimevelte-mainline/0009-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch rename to device/testing/linux-samsung-coreprimevelte-mainline/0008-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch index f2ce6a32d..5e23c9bc6 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0009-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0008-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch @@ -1,4 +1,4 @@ -From a9420a20d18c43f90c256e0b95c7c72ee2b4248d Mon Sep 17 00:00:00 2001 +From 91114902a64ccc922cc22777576eb9e4ceaa6cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= Date: Fri, 21 Jul 2023 22:37:52 +0200 Subject: [PATCH] MAINTAINERS: add myself as Marvell PXA1908 maintainer @@ -14,10 +14,10 @@ Signed-off-by: Duje Mihanović 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS -index 53b7ca804465..79173056e5cc 100644 +index b19995690904..1b0ca13c42eb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -2299,6 +2299,15 @@ F: drivers/irqchip/irq-mvebu-* +@@ -2313,6 +2313,15 @@ F: drivers/irqchip/irq-mvebu-* F: drivers/pinctrl/mvebu/ F: drivers/rtc/rtc-armada38x.c @@ -34,5 +34,5 @@ index 53b7ca804465..79173056e5cc 100644 M: Eddie Huang M: Sean Wang -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0011-DONOTMERGE-Enable-AArch64-system-timer-properly.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0009-DONOTMERGE-Enable-AArch64-system-timer-properly.patch similarity index 68% rename from device/testing/linux-samsung-coreprimevelte-mainline/0011-DONOTMERGE-Enable-AArch64-system-timer-properly.patch rename to device/testing/linux-samsung-coreprimevelte-mainline/0009-DONOTMERGE-Enable-AArch64-system-timer-properly.patch index 5323d1240..7a44a82ea 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0011-DONOTMERGE-Enable-AArch64-system-timer-properly.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0009-DONOTMERGE-Enable-AArch64-system-timer-properly.patch @@ -1,4 +1,4 @@ -From 171f19c6d38ba40dc49971ac0036eb7de2b40d33 Mon Sep 17 00:00:00 2001 +From 8f096d8846f8ca59060d4f4427568a343e4b4a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= Date: Sun, 4 Sep 2022 17:20:43 +0200 Subject: [PATCH] DONOTMERGE: Enable AArch64 system timer properly @@ -7,23 +7,23 @@ With this, an initramfs can be reached. Long-term, this will be moved someplace such as U-Boot. --- - drivers/clk/mmp/clk-of-pxa1908.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) + drivers/clk/mmp/clk-of-pxa1908.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) diff --git a/drivers/clk/mmp/clk-of-pxa1908.c b/drivers/clk/mmp/clk-of-pxa1908.c -index 520440cb082c..b75facde3f3f 100644 +index 753dd031b147..4c9580f9efa1 100644 --- a/drivers/clk/mmp/clk-of-pxa1908.c +++ b/drivers/clk/mmp/clk-of-pxa1908.c -@@ -12,6 +12,7 @@ - - #define APMU_CLK_GATE_CTRL 0x40 - #define MPMU_UART_PLL 0x14 +@@ -31,6 +31,7 @@ + #define APBC_TWSI1 0x60 + #define APBC_THERMAL 0x6c + #define APBC_TWSI3 0x70 +#define APBC_COUNTER_CLK_SEL 0x64 - #define APBC_UART0 0x0 - #define APBC_UART1 0x4 -@@ -256,6 +257,21 @@ static void __init pxa1908_apbc_clk_init(struct device_node *np) - mmp_clk_init(np, &pxa_unit->unit, PXA1908_APBC_NR_CLKS); + #define APBCP_UART2 0x1c + #define APBCP_TWSI2 0x28 +@@ -261,6 +262,23 @@ static void __init pxa1908_apbc_clk_init(struct device_node *np) + mmp_clk_init(np, &pxa_unit->unit, APBC_NR_CLKS); pxa1908_apb_periph_clk_init(pxa_unit); + @@ -41,9 +41,11 @@ index 520440cb082c..b75facde3f3f 100644 + writel(BIT(0) | BIT(1), cnt_base); + iounmap(cnt_base); + } ++ ++ pr_notice("apbc ready\n"); } CLK_OF_DECLARE(pxa1908_apbc, "marvell,pxa1908-apbc", pxa1908_apbc_clk_init); -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0010-DONOTMERGE-Add-pxa-rev-id-to-board-dts.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0010-DONOTMERGE-Add-pxa-rev-id-to-board-dts.patch index cd2677a48..ec99c1e1b 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/0010-DONOTMERGE-Add-pxa-rev-id-to-board-dts.patch +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0010-DONOTMERGE-Add-pxa-rev-id-to-board-dts.patch @@ -1,4 +1,4 @@ -From dd4943d63aa266bf25d5b57b5a11d629336efa93 Mon Sep 17 00:00:00 2001 +From dc03f0fbb400bad5c4748eb969f4a85c68e3bc0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= Date: Wed, 26 Jul 2023 21:14:34 +0200 Subject: [PATCH] DONOTMERGE: Add pxa,rev-id to board dts @@ -10,7 +10,7 @@ S-Boot, so add this here. 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts -index 59e5d6f15dd2..4dc07fa8ae70 100644 +index e3c863d517a8..04fb0566ed2b 100644 --- a/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts +++ b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts @@ -4,6 +4,7 @@ @@ -22,5 +22,5 @@ index 59e5d6f15dd2..4dc07fa8ae70 100644 compatible = "samsung,coreprimevelte", "marvell,pxa1908"; -- -2.41.0 +2.42.0 diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0011-input-generalize-the-Imagis-touchscreen-driver.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0011-input-generalize-the-Imagis-touchscreen-driver.patch new file mode 100644 index 000000000..07a5192bd --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0011-input-generalize-the-Imagis-touchscreen-driver.patch @@ -0,0 +1,99 @@ +From 7dded3d2412f6f1d1668034b3b2acc8ffa663ac3 Mon Sep 17 00:00:00 2001 +From: Karel Balej +Date: Mon, 25 Sep 2023 22:30:27 +0200 +Subject: [PATCH] input: generalize the Imagis touchscreen driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This driver works with other Imagis ICs of the IST30**C series. Make +that apparent. + +Signed-off-by: Karel Balej +Co-developed-by: Duje Mihanović +Signed-off-by: Duje Mihanović +--- + drivers/input/touchscreen/imagis.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c +index 07111ca24455..d61fbbe61bc8 100644 +--- a/drivers/input/touchscreen/imagis.c ++++ b/drivers/input/touchscreen/imagis.c +@@ -18,7 +18,6 @@ + #define IST3038C_REG_TOUCH_STATUS (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS) + #define IST3038C_REG_TOUCH_COORD (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x8) + #define IST3038C_REG_INTR_MESSAGE (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x4) +-#define IST3038C_WHOAMI 0x38c + #define IST3038C_CHIP_ON_DELAY_MS 60 + #define IST3038C_I2C_RETRY_COUNT 3 + #define IST3038C_MAX_FINGER_NUM 10 +@@ -31,6 +30,8 @@ + #define IST3038C_FINGER_COUNT_SHIFT 12 + #define IST3038C_FINGER_STATUS_MASK GENMASK(9, 0) + ++#define IST3038C_WHOAMI 0x38c ++ + struct imagis_ts { + struct i2c_client *client; + struct input_dev *input_dev; +@@ -253,7 +254,7 @@ static int imagis_probe(struct i2c_client *i2c) + { + struct device *dev = &i2c->dev; + struct imagis_ts *ts; +- int chip_id, error; ++ int chip_id, dt_chip_id, error; + + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); + if (!ts) +@@ -261,6 +262,8 @@ static int imagis_probe(struct i2c_client *i2c) + + ts->client = i2c; + ++ dt_chip_id = (int)(uintptr_t) device_get_match_data(&i2c->dev); ++ + error = imagis_init_regulators(ts); + if (error) { + dev_err(dev, "regulator init error: %d\n", error); +@@ -287,8 +290,8 @@ static int imagis_probe(struct i2c_client *i2c) + return error; + } + +- if (chip_id != IST3038C_WHOAMI) { +- dev_err(dev, "unknown chip ID: 0x%x\n", chip_id); ++ if (chip_id != dt_chip_id) { ++ dev_err(dev, "unknown or misconfigured chip ID: 0x%x\n", chip_id); + return -EINVAL; + } + +@@ -345,12 +348,18 @@ static DEFINE_SIMPLE_DEV_PM_OPS(imagis_pm_ops, imagis_suspend, imagis_resume); + + #ifdef CONFIG_OF + static const struct of_device_id imagis_of_match[] = { +- { .compatible = "imagis,ist3038c", }, ++ { .compatible = "imagis,ist3038c", .data = (void *) IST3038C_WHOAMI, }, + { }, + }; + MODULE_DEVICE_TABLE(of, imagis_of_match); + #endif + ++static const struct i2c_device_id imagis_ts_i2c_id[] = { ++ { "ist3038c", IST3038C_WHOAMI, }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, imagis_ts_i2c_id); ++ + static struct i2c_driver imagis_ts_driver = { + .driver = { + .name = "imagis-touchscreen", +@@ -358,6 +367,7 @@ static struct i2c_driver imagis_ts_driver = { + .of_match_table = of_match_ptr(imagis_of_match), + }, + .probe = imagis_probe, ++ .id_table = imagis_ts_i2c_id, + }; + + module_i2c_driver(imagis_ts_driver); +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0012-Documentation-imagis-document-IST3032C-support.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0012-Documentation-imagis-document-IST3032C-support.patch new file mode 100644 index 000000000..bb69cc64d --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0012-Documentation-imagis-document-IST3032C-support.patch @@ -0,0 +1,31 @@ +From 0485f6ddd33a4ca4105e18628e74318f5893c7ec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= +Date: Thu, 28 Sep 2023 18:49:25 +0200 +Subject: [PATCH] Documentation: imagis: document IST3032C support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The imagis driver supports the IST3032C. Add this to the driver +documentation. + +Signed-off-by: Duje Mihanović +--- + .../devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml +index 0d6b033fd5fb..f364ffb05c8d 100644 +--- a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml ++++ b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml +@@ -18,6 +18,7 @@ properties: + + compatible: + enum: ++ - imagis,ist3032c + - imagis,ist3038c + + reg: +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0013-input-Imagis-add-support-for-IST3032C-touchscreen.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0013-input-Imagis-add-support-for-IST3032C-touchscreen.patch new file mode 100644 index 000000000..072a7b96f --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0013-input-Imagis-add-support-for-IST3032C-touchscreen.patch @@ -0,0 +1,49 @@ +From 7d16c4619210af0f8793f74452b412a9711c8e9e Mon Sep 17 00:00:00 2001 +From: Karel Balej +Date: Mon, 25 Sep 2023 22:36:21 +0200 +Subject: [PATCH] input: Imagis: add support for IST3032C touchscreen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add the Imagis IST3032C to the imagis driver. The only functional +difference is in the WHOAMI identifier. + +Signed-off-by: Karel Balej +Co-developed-by: Duje Mihanović +Signed-off-by: Duje Mihanović +--- + drivers/input/touchscreen/imagis.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c +index d61fbbe61bc8..5367b8d96e66 100644 +--- a/drivers/input/touchscreen/imagis.c ++++ b/drivers/input/touchscreen/imagis.c +@@ -30,6 +30,7 @@ + #define IST3038C_FINGER_COUNT_SHIFT 12 + #define IST3038C_FINGER_STATUS_MASK GENMASK(9, 0) + ++#define IST3032C_WHOAMI 0x32c + #define IST3038C_WHOAMI 0x38c + + struct imagis_ts { +@@ -348,6 +349,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(imagis_pm_ops, imagis_suspend, imagis_resume); + + #ifdef CONFIG_OF + static const struct of_device_id imagis_of_match[] = { ++ { .compatible = "imagis,ist3032c", .data = (void *) IST3032C_WHOAMI, }, + { .compatible = "imagis,ist3038c", .data = (void *) IST3038C_WHOAMI, }, + { }, + }; +@@ -355,6 +357,7 @@ MODULE_DEVICE_TABLE(of, imagis_of_match); + #endif + + static const struct i2c_device_id imagis_ts_i2c_id[] = { ++ { "ist3032c", IST3032C_WHOAMI, }, + { "ist3038c", IST3038C_WHOAMI, }, + { } + }; +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0014-arm64-dts-add-touchscreen-bindings-for-samsung-corep.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0014-arm64-dts-add-touchscreen-bindings-for-samsung-corep.patch new file mode 100644 index 000000000..a7983ec59 --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0014-arm64-dts-add-touchscreen-bindings-for-samsung-corep.patch @@ -0,0 +1,35 @@ +From bdb5e1cd9435a942465d4e195a70b3b475eda6aa Mon Sep 17 00:00:00 2001 +From: Karel Balej +Date: Mon, 25 Sep 2023 22:41:24 +0200 +Subject: [PATCH] arm64: dts: add touchscreen bindings for + samsung,coreprimevelte + +Signed-off-by: Karel Balej +--- + .../dts/marvell/pxa1908-samsung-coreprimevelte.dts | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts +index 04fb0566ed2b..bd69358fd069 100644 +--- a/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts ++++ b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts +@@ -309,6 +309,16 @@ &twsi2 { + + &twsi3 { + status = "okay"; ++ ++ touchscreen@50 { ++ compatible = "imagis,ist3032c"; ++ reg = <0x50>; ++ interrupt-parent = <&gpio>; ++ interrupts = <72 IRQ_TYPE_EDGE_FALLING>; ++ vdd-supply = <&ldo2>; ++ touchscreen-size-x = <480>; ++ touchscreen-size-y = <800>; ++ }; + }; + + &usb { +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0015-mfd-add-Marvell-88pm88x-description.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0015-mfd-add-Marvell-88pm88x-description.patch new file mode 100644 index 000000000..a1bcd82e2 --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0015-mfd-add-Marvell-88pm88x-description.patch @@ -0,0 +1,56 @@ +From 15786525bbad9763a1ddff188d75e5a4c534fa9e Mon Sep 17 00:00:00 2001 +From: Yi Zhang +Date: Fri, 12 Jun 2015 16:43:20 +0800 +Subject: [PATCH] mfd: add Marvell 88pm88x description + +88pm880 and 88pm886 are two combo PMIC chips, most of the function and the +register mapping are the same + +Signed-off-by: Yi Zhang +--- + .../devicetree/bindings/mfd/88pm88x.txt | 33 +++++++++++++++++++ + 1 file changed, 33 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mfd/88pm88x.txt + +diff --git a/Documentation/devicetree/bindings/mfd/88pm88x.txt b/Documentation/devicetree/bindings/mfd/88pm88x.txt +new file mode 100644 +index 000000000000..72e741cf3ebf +--- /dev/null ++++ b/Documentation/devicetree/bindings/mfd/88pm88x.txt +@@ -0,0 +1,33 @@ ++Marvell 88pm88x combo PMIC chip ++ ++This series of chip integrates regulator, rtc, onkey, switch charger, ++fuelgauge, gpadc and a range of I/O pins. ++ ++88pm886 and 88pm880 are two very similar chips, most of the registers mapping ++and functions are the same, the main difference is the latter has a separate ++i2c slave address to cover BUCK related setting ++ ++Required properties: ++- compatible: one of the strings for a specific chip: ++ "marvell,88pm886" ++ "marvell,88pm880" ++- reg: the i2c address ++- interrupt-controller: it works as an interrupt controller managing its irqs ++- interrupt-cells: this value is 1 ++ ++Optional properties: ++- marvell,88pm88x-irq-write-clear: the interrupt ack method ++ ++ ++Example: ++ ++ pmic: 88pm886@30 { ++ compatible = "marvell,88pm886"; ++ reg = <0x30>; ++ interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-parent = <&gic>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ marvell,88pm88x-irq-write-clear; ++ }; +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0016-mfd-88pm88x-initialize-88pm886-88pm880-base-support.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0016-mfd-88pm88x-initialize-88pm886-88pm880-base-support.patch new file mode 100644 index 000000000..75684deaf --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0016-mfd-88pm88x-initialize-88pm886-88pm880-base-support.patch @@ -0,0 +1,2063 @@ +From 40b741f0e4148ef59e83df3a14613d91a3a2a2d8 Mon Sep 17 00:00:00 2001 +From: Yi Zhang +Date: Fri, 12 Jun 2015 16:43:21 +0800 +Subject: [PATCH] mfd: 88pm88x: initialize 88pm886/88pm880 base support + +88pm886 and 88pm880 are combo PMIC chip, which integrates +regulator, onkey, rtc, gpadc, charger, fuelgauge function; + +this patch add the basic support for them, adding related resource, such as +interrupt, preparing for the client-device driver + +Signed-off-by: Yi Zhang +--- + drivers/mfd/88pm880-table.c | 173 ++++++++++ + drivers/mfd/88pm886-table.c | 173 ++++++++++ + drivers/mfd/88pm88x-core.c | 584 ++++++++++++++++++++++++++++++++ + drivers/mfd/88pm88x-i2c.c | 167 +++++++++ + drivers/mfd/88pm88x-irq.c | 171 ++++++++++ + drivers/mfd/88pm88x.h | 51 +++ + drivers/mfd/Kconfig | 12 + + drivers/mfd/Makefile | 3 + + include/linux/mfd/88pm880-reg.h | 98 ++++++ + include/linux/mfd/88pm880.h | 59 ++++ + include/linux/mfd/88pm886-reg.h | 59 ++++ + include/linux/mfd/88pm886.h | 55 +++ + include/linux/mfd/88pm88x-reg.h | 118 +++++++ + include/linux/mfd/88pm88x.h | 202 +++++++++++ + 14 files changed, 1925 insertions(+) + create mode 100644 drivers/mfd/88pm880-table.c + create mode 100644 drivers/mfd/88pm886-table.c + create mode 100644 drivers/mfd/88pm88x-core.c + create mode 100644 drivers/mfd/88pm88x-i2c.c + create mode 100644 drivers/mfd/88pm88x-irq.c + create mode 100644 drivers/mfd/88pm88x.h + create mode 100644 include/linux/mfd/88pm880-reg.h + create mode 100644 include/linux/mfd/88pm880.h + create mode 100644 include/linux/mfd/88pm886-reg.h + create mode 100644 include/linux/mfd/88pm886.h + create mode 100644 include/linux/mfd/88pm88x-reg.h + create mode 100644 include/linux/mfd/88pm88x.h + +diff --git a/drivers/mfd/88pm880-table.c b/drivers/mfd/88pm880-table.c +new file mode 100644 +index 000000000000..28ca86028905 +--- /dev/null ++++ b/drivers/mfd/88pm880-table.c +@@ -0,0 +1,173 @@ ++/* ++ * Marvell 88PM880 specific setting ++ * ++ * Copyright (C) 2015 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "88pm88x.h" ++ ++#define PM880_BUCK_NAME "88pm880-buck" ++#define PM880_LDO_NAME "88pm880-ldo" ++ ++const struct regmap_config pm880_base_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++const struct regmap_config pm880_power_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++const struct regmap_config pm880_gpadc_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++const struct regmap_config pm880_battery_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++const struct regmap_config pm880_test_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++static const struct resource buck_resources[] = { ++ { ++ .name = PM880_BUCK_NAME, ++ }, ++}; ++ ++static const struct resource ldo_resources[] = { ++ { ++ .name = PM880_LDO_NAME, ++ }, ++}; ++ ++const struct mfd_cell pm880_cell_devs[] = { ++ CELL_DEV(PM880_BUCK_NAME, buck_resources, "marvell,88pm880-buck1a", 0), ++ CELL_DEV(PM880_BUCK_NAME, buck_resources, "marvell,88pm880-buck2", 1), ++ CELL_DEV(PM880_BUCK_NAME, buck_resources, "marvell,88pm880-buck3", 2), ++ CELL_DEV(PM880_BUCK_NAME, buck_resources, "marvell,88pm880-buck4", 3), ++ CELL_DEV(PM880_BUCK_NAME, buck_resources, "marvell,88pm880-buck5", 4), ++ CELL_DEV(PM880_BUCK_NAME, buck_resources, "marvell,88pm880-buck6", 5), ++ CELL_DEV(PM880_BUCK_NAME, buck_resources, "marvell,88pm880-buck7", 6), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo1", 7), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo2", 8), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo3", 9), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo4", 10), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo5", 11), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo6", 12), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo7", 13), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo8", 14), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo9", 15), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo10", 16), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo11", 17), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo12", 18), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo13", 19), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo14", 20), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo15", 21), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo16", 22), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo17", 23), ++ CELL_DEV(PM880_LDO_NAME, ldo_resources, "marvell,88pm880-ldo18", 24), ++}; ++ ++struct pmic_cell_info pm880_cell_info = { ++ .cells = pm880_cell_devs, ++ .cell_nr = ARRAY_SIZE(pm880_cell_devs), ++}; ++ ++static const struct reg_default pm880_base_patch[] = { ++ {PM88X_WDOG, 0x1}, /* disable watchdog */ ++ {PM88X_AON_CTRL2, 0x2a}, /* output 32kHZ from XO */ ++ {PM88X_BK_OSC_CTRL1, 0x0f}, /* OSC_FREERUN = 1, to lock FLL */ ++ {PM88X_LOWPOWER2, 0x20}, /* XO_LJ = 1, enable low jitter for 32kHZ */ ++ /* enable LPM for internal reference group in sleep */ ++ {PM88X_LOWPOWER4, 0xc0}, ++ {PM88X_BK_OSC_CTRL3, 0xc0}, /* set the duty cycle of charger DC/DC to max */ ++}; ++ ++static const struct reg_default pm880_power_patch[] = { ++}; ++ ++static const struct reg_default pm880_gpadc_patch[] = { ++ {PM88X_GPADC_CONFIG6, 0x03}, /* enable non-stop mode */ ++}; ++ ++static const struct reg_default pm880_battery_patch[] = { ++ {PM88X_CHGBK_CONFIG6, 0xe1}, ++}; ++ ++static const struct reg_default pm880_test_patch[] = { ++}; ++ ++/* 88pm880 chip itself related */ ++int pm880_apply_patch(struct pm88x_chip *chip) ++{ ++ int ret, size; ++ ++ if (!chip || !chip->base_regmap || !chip->power_regmap || ++ !chip->gpadc_regmap || !chip->battery_regmap || ++ !chip->test_regmap) ++ return -EINVAL; ++ ++ size = ARRAY_SIZE(pm880_base_patch); ++ if (size == 0) ++ goto power; ++ ret = regmap_register_patch(chip->base_regmap, pm880_base_patch, size); ++ if (ret < 0) ++ return ret; ++ ++power: ++ size = ARRAY_SIZE(pm880_power_patch); ++ if (size == 0) ++ goto gpadc; ++ ret = regmap_register_patch(chip->power_regmap, pm880_power_patch, size); ++ if (ret < 0) ++ return ret; ++ ++gpadc: ++ size = ARRAY_SIZE(pm880_gpadc_patch); ++ if (size == 0) ++ goto battery; ++ ret = regmap_register_patch(chip->gpadc_regmap, pm880_gpadc_patch, size); ++ if (ret < 0) ++ return ret; ++battery: ++ size = ARRAY_SIZE(pm880_battery_patch); ++ if (size == 0) ++ goto test; ++ ret = regmap_register_patch(chip->battery_regmap, pm880_battery_patch, size); ++ if (ret < 0) ++ return ret; ++ ++test: ++ size = ARRAY_SIZE(pm880_test_patch); ++ if (size == 0) ++ goto out; ++ ret = regmap_register_patch(chip->test_regmap, pm880_test_patch, size); ++ if (ret < 0) ++ return ret; ++out: ++ return 0; ++} ++EXPORT_SYMBOL_GPL(pm880_apply_patch); +diff --git a/drivers/mfd/88pm886-table.c b/drivers/mfd/88pm886-table.c +new file mode 100644 +index 000000000000..897ee82a30c7 +--- /dev/null ++++ b/drivers/mfd/88pm886-table.c +@@ -0,0 +1,173 @@ ++/* ++ * Marvell 88PM886 specific setting ++ * ++ * Copyright (C) 2015 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "88pm88x.h" ++ ++#define PM886_BUCK_NAME "88pm886-buck" ++#define PM886_LDO_NAME "88pm886-ldo" ++ ++const struct regmap_config pm886_base_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++const struct regmap_config pm886_power_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++const struct regmap_config pm886_gpadc_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++const struct regmap_config pm886_battery_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++const struct regmap_config pm886_test_i2c_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xfe, ++}; ++ ++static const struct resource buck_resources[] = { ++ { ++ .name = PM886_BUCK_NAME, ++ }, ++}; ++ ++static const struct resource ldo_resources[] = { ++ { ++ .name = PM886_LDO_NAME, ++ }, ++}; ++ ++const struct mfd_cell pm886_cell_devs[] = { ++ CELL_DEV(PM886_BUCK_NAME, buck_resources, "marvell,88pm886-buck1", 0), ++ CELL_DEV(PM886_BUCK_NAME, buck_resources, "marvell,88pm886-buck2", 1), ++ CELL_DEV(PM886_BUCK_NAME, buck_resources, "marvell,88pm886-buck3", 2), ++ CELL_DEV(PM886_BUCK_NAME, buck_resources, "marvell,88pm886-buck4", 3), ++ CELL_DEV(PM886_BUCK_NAME, buck_resources, "marvell,88pm886-buck5", 4), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo1", 5), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo2", 6), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo3", 7), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo4", 8), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo5", 9), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo6", 10), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo7", 11), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo8", 12), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo9", 13), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo10", 14), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo11", 15), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo12", 16), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo13", 17), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo14", 18), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo15", 19), ++ CELL_DEV(PM886_LDO_NAME, ldo_resources, "marvell,88pm886-ldo16", 20), ++}; ++ ++struct pmic_cell_info pm886_cell_info = { ++ .cells = pm886_cell_devs, ++ .cell_nr = ARRAY_SIZE(pm886_cell_devs), ++}; ++ ++static const struct reg_default pm886_base_patch[] = { ++ {PM88X_WDOG, 0x1}, /* disable watchdog */ ++ {PM88X_GPIO_CTRL1, 0x40}, /* gpio1: dvc , gpio0: input */ ++ {PM88X_GPIO_CTRL2, 0x00}, /* , gpio2: input */ ++ {PM88X_GPIO_CTRL3, 0x44}, /* dvc2 , dvc1 */ ++ {PM88X_GPIO_CTRL4, 0x00}, /* gpio5v_1:input, gpio5v_2: input*/ ++ {PM88X_AON_CTRL2, 0x2a}, /* output 32kHZ from XO */ ++ {PM88X_BK_OSC_CTRL1, 0x0f}, /* OSC_FREERUN = 1, to lock FLL */ ++ {PM88X_LOWPOWER2, 0x20}, /* XO_LJ = 1, enable low jitter for 32kHZ */ ++ /* enable LPM for internal reference group in sleep */ ++ {PM88X_LOWPOWER4, 0xc0}, ++ {PM88X_BK_OSC_CTRL3, 0xc0}, /* set the duty cycle of charger DC/DC to max */ ++}; ++ ++static const struct reg_default pm886_power_patch[] = { ++}; ++ ++static const struct reg_default pm886_gpadc_patch[] = { ++ {PM88X_GPADC_CONFIG6, 0x03}, /* enable non-stop mode */ ++}; ++ ++static const struct reg_default pm886_battery_patch[] = { ++ {PM88X_CHGBK_CONFIG6, 0xe1}, ++}; ++ ++static const struct reg_default pm886_test_patch[] = { ++}; ++ ++/* 88pm886 chip itself related */ ++int pm886_apply_patch(struct pm88x_chip *chip) ++{ ++ int ret, size; ++ ++ if (!chip || !chip->base_regmap || !chip->power_regmap || ++ !chip->gpadc_regmap || !chip->battery_regmap || ++ !chip->test_regmap) ++ return -EINVAL; ++ ++ size = ARRAY_SIZE(pm886_base_patch); ++ if (size == 0) ++ goto power; ++ ret = regmap_register_patch(chip->base_regmap, pm886_base_patch, size); ++ if (ret < 0) ++ return ret; ++ ++power: ++ size = ARRAY_SIZE(pm886_power_patch); ++ if (size == 0) ++ goto gpadc; ++ ret = regmap_register_patch(chip->power_regmap, pm886_power_patch, size); ++ if (ret < 0) ++ return ret; ++ ++gpadc: ++ size = ARRAY_SIZE(pm886_gpadc_patch); ++ if (size == 0) ++ goto battery; ++ ret = regmap_register_patch(chip->gpadc_regmap, pm886_gpadc_patch, size); ++ if (ret < 0) ++ return ret; ++battery: ++ size = ARRAY_SIZE(pm886_battery_patch); ++ if (size == 0) ++ goto test; ++ ret = regmap_register_patch(chip->battery_regmap, pm886_battery_patch, size); ++ if (ret < 0) ++ return ret; ++ ++test: ++ size = ARRAY_SIZE(pm886_test_patch); ++ if (size == 0) ++ goto out; ++ ret = regmap_register_patch(chip->test_regmap, pm886_test_patch, size); ++ if (ret < 0) ++ return ret; ++out: ++ return 0; ++} ++EXPORT_SYMBOL_GPL(pm886_apply_patch); +diff --git a/drivers/mfd/88pm88x-core.c b/drivers/mfd/88pm88x-core.c +new file mode 100644 +index 000000000000..343e0a0f3f8b +--- /dev/null ++++ b/drivers/mfd/88pm88x-core.c +@@ -0,0 +1,584 @@ ++/* ++ * Base driver for Marvell 88PM886/88PM880 PMIC ++ * ++ * Copyright (C) 2015 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "88pm88x.h" ++ ++#define PM88X_POWER_UP_LOG (0x17) ++#define PM88X_POWER_DOWN_LOG1 (0xe5) ++#define PM88X_POWER_DOWN_LOG2 (0xe6) ++#define PM88X_SW_PDOWN (1 << 5) ++ ++static const struct resource onkey_resources[] = { ++ CELL_IRQ_RESOURCE(PM88X_ONKEY_NAME, PM88X_IRQ_ONKEY), ++}; ++ ++static const struct resource rtc_resources[] = { ++ CELL_IRQ_RESOURCE(PM88X_RTC_NAME, PM88X_IRQ_RTC), ++}; ++ ++static const struct resource charger_resources[] = { ++ CELL_IRQ_RESOURCE("88pm88x-chg-fail", PM88X_IRQ_CHG_FAIL), ++ CELL_IRQ_RESOURCE("88pm88x-chg-done", PM88X_IRQ_CHG_DONE), ++ CELL_IRQ_RESOURCE("88pm88x-chg-good", PM88X_IRQ_CHG_GOOD), ++}; ++ ++static const struct resource battery_resources[] = { ++ CELL_IRQ_RESOURCE("88pm88x-bat-cc", PM88X_IRQ_CC), ++ CELL_IRQ_RESOURCE("88pm88x-bat-volt", PM88X_IRQ_VBAT), ++ CELL_IRQ_RESOURCE("88pm88x-bat-detect", PM88X_IRQ_BAT_DET), ++}; ++ ++static const struct resource headset_resources[] = { ++ CELL_IRQ_RESOURCE("88pm88x-headset-det", PM88X_IRQ_HS_DET), ++ CELL_IRQ_RESOURCE("88pm88x-mic-det", PM88X_IRQ_MIC_DET), ++}; ++ ++static const struct resource vbus_resources[] = { ++ CELL_IRQ_RESOURCE("88pm88x-vbus-det", PM88X_IRQ_VBUS), ++ CELL_IRQ_RESOURCE("88pm88x-gpadc0", PM88X_IRQ_GPADC0), ++ CELL_IRQ_RESOURCE("88pm88x-gpadc1", PM88X_IRQ_GPADC1), ++ CELL_IRQ_RESOURCE("88pm88x-gpadc2", PM88X_IRQ_GPADC2), ++ CELL_IRQ_RESOURCE("88pm88x-gpadc3", PM88X_IRQ_GPADC3), ++ CELL_IRQ_RESOURCE("88pm88x-otg-fail", PM88X_IRQ_OTG_FAIL), ++}; ++ ++static const struct resource leds_resources[] = { ++ CELL_IRQ_RESOURCE("88pm88x-cfd-fail", PM88X_IRQ_CFD_FAIL), ++}; ++ ++static const struct resource dvc_resources[] = { ++ { ++ .name = PM88X_DVC_NAME, ++ }, ++}; ++ ++static const struct resource rgb_resources[] = { ++ { ++ .name = PM88X_RGB_NAME, ++ }, ++}; ++ ++static const struct resource gpadc_resources[] = { ++ { ++ .name = PM88X_GPADC_NAME, ++ }, ++}; ++ ++static const struct mfd_cell common_cell_devs[] = { ++ CELL_DEV(PM88X_RTC_NAME, rtc_resources, "marvell,88pm88x-rtc", -1), ++ CELL_DEV(PM88X_ONKEY_NAME, onkey_resources, "marvell,88pm88x-onkey", -1), ++ CELL_DEV(PM88X_CHARGER_NAME, charger_resources, "marvell,88pm88x-charger", -1), ++ CELL_DEV(PM88X_BATTERY_NAME, battery_resources, "marvell,88pm88x-battery", -1), ++ CELL_DEV(PM88X_HEADSET_NAME, headset_resources, "marvell,88pm88x-headset", -1), ++ CELL_DEV(PM88X_VBUS_NAME, vbus_resources, "marvell,88pm88x-vbus", -1), ++ CELL_DEV(PM88X_CFD_NAME, leds_resources, "marvell,88pm88x-leds", PM88X_FLASH_LED), ++ CELL_DEV(PM88X_CFD_NAME, leds_resources, "marvell,88pm88x-leds", PM88X_TORCH_LED), ++ CELL_DEV(PM88X_DVC_NAME, dvc_resources, "marvell,88pm88x-dvc", -1), ++ CELL_DEV(PM88X_RGB_NAME, rgb_resources, "marvell,88pm88x-rgb0", PM88X_RGB_LED0), ++ CELL_DEV(PM88X_RGB_NAME, rgb_resources, "marvell,88pm88x-rgb1", PM88X_RGB_LED1), ++ CELL_DEV(PM88X_RGB_NAME, rgb_resources, "marvell,88pm88x-rgb2", PM88X_RGB_LED2), ++ CELL_DEV(PM88X_GPADC_NAME, gpadc_resources, "marvell,88pm88x-gpadc", -1), ++}; ++ ++const struct of_device_id pm88x_of_match[] = { ++ { .compatible = "marvell,88pm886", .data = (void *)PM886 }, ++ { .compatible = "marvell,88pm880", .data = (void *)PM880 }, ++ {}, ++}; ++ ++struct pm88x_chip *pm88x_init_chip(struct i2c_client *client) ++{ ++ struct pm88x_chip *chip; ++ ++ chip = devm_kzalloc(&client->dev, sizeof(struct pm88x_chip), GFP_KERNEL); ++ if (!chip) ++ return ERR_PTR(-ENOMEM); ++ ++ chip->client = client; ++ chip->irq = client->irq; ++ chip->dev = &client->dev; ++ chip->ldo_page_addr = client->addr + 1; ++ chip->power_page_addr = client->addr + 1; ++ chip->gpadc_page_addr = client->addr + 2; ++ chip->battery_page_addr = client->addr + 3; ++ chip->buck_page_addr = client->addr + 4; ++ chip->test_page_addr = client->addr + 7; ++ ++ dev_set_drvdata(chip->dev, chip); ++ i2c_set_clientdata(chip->client, chip); ++ ++ device_init_wakeup(&client->dev, 1); ++ ++ return chip; ++} ++ ++int pm88x_parse_dt(struct device_node *np, struct pm88x_chip *chip) ++{ ++ if (!chip) ++ return -EINVAL; ++ ++ chip->irq_mode = ++ !of_property_read_bool(np, "marvell,88pm88x-irq-write-clear"); ++ ++ return 0; ++} ++ ++ ++static void parse_powerup_down_log(struct pm88x_chip *chip) ++{ ++ int powerup, powerdown1, powerdown2, bit; ++ int powerup_bits, powerdown1_bits, powerdown2_bits; ++ static const char * const powerup_name[] = { ++ "ONKEY_WAKEUP ", ++ "CHG_WAKEUP ", ++ "EXTON_WAKEUP ", ++ "SMPL_WAKEUP ", ++ "ALARM_WAKEUP ", ++ "FAULT_WAKEUP ", ++ "BAT_WAKEUP ", ++ "WLCHG_WAKEUP ", ++ }; ++ static const char * const powerdown1_name[] = { ++ "OVER_TEMP ", ++ "UV_VANA5 ", ++ "SW_PDOWN ", ++ "FL_ALARM ", ++ "WD ", ++ "LONG_ONKEY", ++ "OV_VSYS ", ++ "RTC_RESET " ++ }; ++ static const char * const powerdown2_name[] = { ++ "HYB_DONE ", ++ "UV_VBAT ", ++ "HW_RESET2 ", ++ "PGOOD_PDOWN", ++ "LONKEY_RTC ", ++ "HW_RESET1 ", ++ }; ++ ++ regmap_read(chip->base_regmap, PM88X_POWER_UP_LOG, &powerup); ++ regmap_read(chip->base_regmap, PM88X_POWER_DOWN_LOG1, &powerdown1); ++ regmap_read(chip->base_regmap, PM88X_POWER_DOWN_LOG2, &powerdown2); ++ ++ /* ++ * mask reserved bits ++ * ++ * note: HYB_DONE and HW_RESET1 are kept, ++ * but should not be considered as power down events ++ */ ++ switch (chip->type) { ++ case PM886: ++ powerup &= 0x7f; ++ powerdown2 &= 0x1f; ++ powerup_bits = 7; ++ powerdown1_bits = 8; ++ powerdown2_bits = 5; ++ break; ++ case PM880: ++ powerdown2 &= 0x3f; ++ powerup_bits = 8; ++ powerdown1_bits = 8; ++ powerdown2_bits = 6; ++ break; ++ default: ++ return; ++ } ++ ++ /* keep globals for external usage */ ++ chip->powerup = powerup; ++ chip->powerdown1 = powerdown1; ++ chip->powerdown2 = powerdown2; ++ ++ /* power up log */ ++ dev_info(chip->dev, "powerup log 0x%x: 0x%x\n", ++ PM88X_POWER_UP_LOG, powerup); ++ dev_info(chip->dev, " ----------------------------\n"); ++ dev_info(chip->dev, "| name(power up) | status |\n"); ++ dev_info(chip->dev, "|-----------------|----------|\n"); ++ for (bit = 0; bit < powerup_bits; bit++) ++ dev_info(chip->dev, "| %s | %x |\n", ++ powerup_name[bit], (powerup >> bit) & 1); ++ dev_info(chip->dev, " ----------------------------\n"); ++ ++ /* power down log1 */ ++ dev_info(chip->dev, "PowerDW Log1 0x%x: 0x%x\n", ++ PM88X_POWER_DOWN_LOG1, powerdown1); ++ dev_info(chip->dev, " -------------------------------\n"); ++ dev_info(chip->dev, "| name(power down1) | status |\n"); ++ dev_info(chip->dev, "|--------------------|----------|\n"); ++ for (bit = 0; bit < powerdown1_bits; bit++) ++ dev_info(chip->dev, "| %s | %x |\n", ++ powerdown1_name[bit], (powerdown1 >> bit) & 1); ++ dev_info(chip->dev, " -------------------------------\n"); ++ ++ /* power down log2 */ ++ dev_info(chip->dev, "PowerDW Log2 0x%x: 0x%x\n", ++ PM88X_POWER_DOWN_LOG2, powerdown2); ++ dev_info(chip->dev, " -------------------------------\n"); ++ dev_info(chip->dev, "| name(power down2) | status |\n"); ++ dev_info(chip->dev, "|--------------------|----------|\n"); ++ for (bit = 0; bit < powerdown2_bits; bit++) ++ dev_info(chip->dev, "| %s | %x |\n", ++ powerdown2_name[bit], (powerdown2 >> bit) & 1); ++ dev_info(chip->dev, " -------------------------------\n"); ++ ++ /* write to clear power down log */ ++ regmap_write(chip->base_regmap, PM88X_POWER_DOWN_LOG1, 0xff); ++ regmap_write(chip->base_regmap, PM88X_POWER_DOWN_LOG2, 0xff); ++} ++ ++static const char *chip_stepping_to_string(unsigned int id) ++{ ++ switch (id) { ++ case 0xa1: ++ return "88pm886 A1"; ++ case 0xb1: ++ return "88pm880 A1"; ++ default: ++ return "Unknown"; ++ } ++} ++ ++int pm88x_post_init_chip(struct pm88x_chip *chip) ++{ ++ int ret; ++ unsigned int val; ++ ++ if (!chip || !chip->base_regmap || !chip->power_regmap || ++ !chip->gpadc_regmap || !chip->battery_regmap) ++ return -EINVAL; ++ ++ /* save chip stepping */ ++ ret = regmap_read(chip->base_regmap, PM88X_ID_REG, &val); ++ if (ret < 0) { ++ dev_err(chip->dev, "Failed to read chip ID: %d\n", ret); ++ return ret; ++ } ++ chip->chip_id = val; ++ ++ dev_info(chip->dev, "PM88X chip ID = 0x%x(%s)\n", val, ++ chip_stepping_to_string(chip->chip_id)); ++ ++ /* read before alarm wake up bit before initialize interrupt */ ++ ret = regmap_read(chip->base_regmap, PM88X_RTC_ALARM_CTRL1, &val); ++ if (ret < 0) { ++ dev_err(chip->dev, "Failed to read RTC register: %d\n", ret); ++ return ret; ++ } ++ chip->rtc_wakeup = !!(val & PM88X_ALARM_WAKEUP); ++ ++ parse_powerup_down_log(chip); ++ ++ return 0; ++} ++ ++int pm88x_init_pages(struct pm88x_chip *chip) ++{ ++ struct i2c_client *client = chip->client; ++ const struct regmap_config *base_regmap_config; ++ const struct regmap_config *power_regmap_config; ++ const struct regmap_config *gpadc_regmap_config; ++ const struct regmap_config *battery_regmap_config; ++ const struct regmap_config *test_regmap_config; ++ int ret = 0; ++ ++ if (!chip || !chip->power_page_addr || ++ !chip->gpadc_page_addr || !chip->battery_page_addr) ++ return -ENODEV; ++ ++ chip->type = pm88x_of_get_type(&client->dev); ++ switch (chip->type) { ++ case PM886: ++ base_regmap_config = &pm886_base_i2c_regmap; ++ power_regmap_config = &pm886_power_i2c_regmap; ++ gpadc_regmap_config = &pm886_gpadc_i2c_regmap; ++ battery_regmap_config = &pm886_battery_i2c_regmap; ++ test_regmap_config = &pm886_test_i2c_regmap; ++ break; ++ case PM880: ++ base_regmap_config = &pm880_base_i2c_regmap; ++ power_regmap_config = &pm880_power_i2c_regmap; ++ gpadc_regmap_config = &pm880_gpadc_i2c_regmap; ++ battery_regmap_config = &pm880_battery_i2c_regmap; ++ test_regmap_config = &pm880_test_i2c_regmap; ++ break; ++ default: ++ return -ENODEV; ++ } ++ ++ /* base page */ ++ chip->base_regmap = devm_regmap_init_i2c(client, base_regmap_config); ++ if (IS_ERR(chip->base_regmap)) { ++ dev_err(chip->dev, "Failed to init base_regmap: %d\n", ret); ++ ret = PTR_ERR(chip->base_regmap); ++ goto out; ++ } ++ ++ /* power page */ ++ chip->power_page = i2c_new_dummy(client->adapter, chip->power_page_addr); ++ if (!chip->power_page) { ++ dev_err(chip->dev, "Failed to new power_page: %d\n", ret); ++ ret = -ENODEV; ++ goto out; ++ } ++ chip->power_regmap = devm_regmap_init_i2c(chip->power_page, ++ power_regmap_config); ++ if (IS_ERR(chip->power_regmap)) { ++ dev_err(chip->dev, "Failed to init power_regmap: %d\n", ret); ++ ret = PTR_ERR(chip->power_regmap); ++ goto out; ++ } ++ ++ /* gpadc page */ ++ chip->gpadc_page = i2c_new_dummy(client->adapter, chip->gpadc_page_addr); ++ if (!chip->gpadc_page) { ++ dev_err(chip->dev, "Failed to new gpadc_page: %d\n", ret); ++ ret = -ENODEV; ++ goto out; ++ } ++ chip->gpadc_regmap = devm_regmap_init_i2c(chip->gpadc_page, ++ gpadc_regmap_config); ++ if (IS_ERR(chip->gpadc_regmap)) { ++ dev_err(chip->dev, "Failed to init gpadc_regmap: %d\n", ret); ++ ret = PTR_ERR(chip->gpadc_regmap); ++ goto out; ++ } ++ ++ /* battery page */ ++ chip->battery_page = i2c_new_dummy(client->adapter, chip->battery_page_addr); ++ if (!chip->battery_page) { ++ dev_err(chip->dev, "Failed to new gpadc_page: %d\n", ret); ++ ret = -ENODEV; ++ goto out; ++ } ++ chip->battery_regmap = devm_regmap_init_i2c(chip->battery_page, ++ battery_regmap_config); ++ if (IS_ERR(chip->battery_regmap)) { ++ dev_err(chip->dev, "Failed to init battery_regmap: %d\n", ret); ++ ret = PTR_ERR(chip->battery_regmap); ++ goto out; ++ } ++ ++ /* test page */ ++ chip->test_page = i2c_new_dummy(client->adapter, chip->test_page_addr); ++ if (!chip->test_page) { ++ dev_err(chip->dev, "Failed to new test_page: %d\n", ret); ++ ret = -ENODEV; ++ goto out; ++ } ++ chip->test_regmap = devm_regmap_init_i2c(chip->test_page, ++ test_regmap_config); ++ if (IS_ERR(chip->test_regmap)) { ++ dev_err(chip->dev, "Failed to init test_regmap: %d\n", ret); ++ ret = PTR_ERR(chip->test_regmap); ++ goto out; ++ } ++ ++ chip->type = pm88x_of_get_type(&client->dev); ++ switch (chip->type) { ++ case PM886: ++ /* ldo page */ ++ chip->ldo_page = chip->power_page; ++ chip->ldo_regmap = chip->power_regmap; ++ /* buck page */ ++ chip->buck_regmap = chip->power_regmap; ++ break; ++ case PM880: ++ /* ldo page */ ++ chip->ldo_page = chip->power_page; ++ chip->ldo_regmap = chip->power_regmap; ++ ++ /* buck page */ ++ chip->buck_page = i2c_new_dummy(client->adapter, ++ chip->buck_page_addr); ++ if (!chip->buck_page) { ++ dev_err(chip->dev, "Failed to new buck_page: %d\n", ret); ++ ret = -ENODEV; ++ goto out; ++ } ++ chip->buck_regmap = devm_regmap_init_i2c(chip->buck_page, ++ power_regmap_config); ++ if (IS_ERR(chip->buck_regmap)) { ++ dev_err(chip->dev, "Failed to init buck_regmap: %d\n", ret); ++ ret = PTR_ERR(chip->buck_regmap); ++ goto out; ++ } ++ ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++out: ++ return ret; ++} ++ ++void pm800_exit_pages(struct pm88x_chip *chip) ++{ ++ if (!chip) ++ return; ++ ++ if (chip->ldo_page) ++ i2c_unregister_device(chip->ldo_page); ++ if (chip->gpadc_page) ++ i2c_unregister_device(chip->gpadc_page); ++ if (chip->test_page) ++ i2c_unregister_device(chip->test_page); ++ /* no need to unregister ldo_page */ ++ switch (chip->type) { ++ case PM886: ++ break; ++ case PM880: ++ if (chip->buck_page) ++ i2c_unregister_device(chip->buck_page); ++ break; ++ default: ++ break; ++ } ++} ++ ++int pm88x_init_subdev(struct pm88x_chip *chip) ++{ ++ int ret; ++ if (!chip) ++ return -EINVAL; ++ ++ ret = mfd_add_devices(chip->dev, 0, common_cell_devs, ++ ARRAY_SIZE(common_cell_devs), NULL, 0, ++ regmap_irq_get_domain(chip->irq_data)); ++ if (ret < 0) ++ return ret; ++ ++ switch (chip->type) { ++ case PM886: ++ ret = mfd_add_devices(chip->dev, 0, pm886_cell_info.cells, ++ pm886_cell_info.cell_nr, NULL, 0, ++ regmap_irq_get_domain(chip->irq_data)); ++ break; ++ case PM880: ++ ret = mfd_add_devices(chip->dev, 0, pm880_cell_info.cells, ++ pm880_cell_info.cell_nr, NULL, 0, ++ regmap_irq_get_domain(chip->irq_data)); ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++ ++static int (*apply_to_chip)(struct pm88x_chip *chip); ++/* PMIC chip itself related */ ++int pm88x_apply_patch(struct pm88x_chip *chip) ++{ ++ if (!chip || !chip->client) ++ return -EINVAL; ++ ++ chip->type = pm88x_of_get_type(&chip->client->dev); ++ switch (chip->type) { ++ case PM886: ++ apply_to_chip = pm886_apply_patch; ++ break; ++ case PM880: ++ apply_to_chip = pm880_apply_patch; ++ break; ++ default: ++ break; ++ } ++ if (apply_to_chip) ++ apply_to_chip(chip); ++ return 0; ++} ++ ++int pm88x_stepping_fixup(struct pm88x_chip *chip) ++{ ++ if (!chip || !chip->client) ++ return -EINVAL; ++ ++ chip->type = pm88x_of_get_type(&chip->client->dev); ++ switch (chip->type) { ++ case PM886: ++ case PM880: ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++int pm88x_apply_board_fixup(struct pm88x_chip *chip, struct device_node *np) ++{ ++ /* add board design specific setting, parsed via device tree */ ++ return 0; ++} ++ ++long pm88x_of_get_type(struct device *dev) ++{ ++ const struct of_device_id *id = of_match_device(pm88x_of_match, dev); ++ ++ if (id) ++ return (long)id->data; ++ else ++ return 0; ++} ++ ++void pm88x_dev_exit(struct pm88x_chip *chip) ++{ ++ mfd_remove_devices(chip->dev); ++ pm88x_irq_exit(chip); ++} ++ ++void pm88x_power_off(void) ++{ ++ pr_info("powers off the system."); ++ /* TODO: implement later */ ++ ++ for (;;) ++ cpu_relax(); ++} ++ ++int pm88x_reboot_notifier_callback(struct notifier_block *this, ++ unsigned long code, void *unused) ++{ ++ struct pm88x_chip *chip = ++ container_of(this, struct pm88x_chip, reboot_notifier); ++ ++ switch (code) { ++ case SYS_HALT: ++ case SYS_POWER_OFF: ++ dev_info(chip->dev, "system is down.\n"); ++ break; ++ case SYS_RESTART: ++ default: ++ dev_info(chip->dev, "system will reboot.\n"); ++ break; ++ } ++ ++ return 0; ++} +diff --git a/drivers/mfd/88pm88x-i2c.c b/drivers/mfd/88pm88x-i2c.c +new file mode 100644 +index 000000000000..36842ed02e9a +--- /dev/null ++++ b/drivers/mfd/88pm88x-i2c.c +@@ -0,0 +1,167 @@ ++/* ++ * 88pm88x-i2c.c -- 88pm88x i2c bus interface ++ * ++ * Copyright (C) 2015 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int pm88x_i2c_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pm88x_chip *chip; ++ struct device_node *node = client->dev.of_node; ++ int ret = 0; ++ ++ chip = pm88x_init_chip(client); ++ if (IS_ERR(chip)) { ++ ret = PTR_ERR(chip); ++ dev_err(chip->dev, "initialize 88pm88x chip fails!\n"); ++ goto err; ++ } ++ ++ ret = pm88x_parse_dt(node, chip); ++ if (ret < 0) { ++ dev_err(chip->dev, "parse dt fails!\n"); ++ goto err; ++ } ++ ++ ret = pm88x_init_pages(chip); ++ if (ret) { ++ dev_err(chip->dev, "initialize 88pm88x pages fails!\n"); ++ goto err; ++ } ++ ++ ret = pm88x_post_init_chip(chip); ++ if (ret) { ++ dev_err(chip->dev, "post initialize 88pm88x fails!\n"); ++ goto err; ++ } ++ ++ ret = pm88x_irq_init(chip); ++ if (ret) { ++ dev_err(chip->dev, "initialize 88pm88x interrupt fails!\n"); ++ goto err_init_irq; ++ } ++ ++ ret = pm88x_init_subdev(chip); ++ if (ret) { ++ dev_err(chip->dev, "initialize 88pm88x sub-device fails\n"); ++ goto err_init_subdev; ++ } ++ ++ /* patch for PMIC chip itself */ ++ ret = pm88x_apply_patch(chip); ++ if (ret) { ++ dev_err(chip->dev, "apply 88pm88x register patch fails\n"); ++ goto err_apply_patch; ++ } ++ ++ /* fixup according PMIC stepping */ ++ ret = pm88x_stepping_fixup(chip); ++ if (ret) { ++ dev_err(chip->dev, "fixup according to chip stepping\n"); ++ goto err_apply_patch; ++ } ++ ++ /* patch for board configuration */ ++ ret = pm88x_apply_board_fixup(chip, node); ++ if (ret) { ++ dev_err(chip->dev, "apply 88pm88x register for board fails\n"); ++ goto err_apply_patch; ++ } ++ ++ pm_power_off = pm88x_power_off; ++ ++ chip->reboot_notifier.notifier_call = pm88x_reboot_notifier_callback; ++ register_reboot_notifier(&(chip->reboot_notifier)); ++ ++ return 0; ++ ++err_apply_patch: ++ mfd_remove_devices(chip->dev); ++err_init_subdev: ++ regmap_del_irq_chip(chip->irq, chip->irq_data); ++err_init_irq: ++ pm800_exit_pages(chip); ++err: ++ return ret; ++} ++ ++static int pm88x_i2c_remove(struct i2c_client *i2c) ++{ ++ struct pm88x_chip *chip = dev_get_drvdata(&i2c->dev); ++ pm88x_dev_exit(chip); ++ return 0; ++} ++ ++static const struct i2c_device_id pm88x_i2c_id[] = { ++ { "88pm886", PM886 }, ++ { "88pm880", PM880 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, pm88x_i2c_id); ++ ++static int pm88x_i2c_suspend(struct device *dev) ++{ ++ return 0; ++} ++ ++static int pm88x_i2c_resume(struct device *dev) ++{ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(pm88x_pm_ops, pm88x_i2c_suspend, pm88x_i2c_resume); ++ ++static struct i2c_driver pm88x_i2c_driver = { ++ .driver = { ++ .name = "88pm88x", ++ .owner = THIS_MODULE, ++ .pm = &pm88x_pm_ops, ++ .of_match_table = of_match_ptr(pm88x_of_match), ++ }, ++ .probe = pm88x_i2c_probe, ++ .remove = pm88x_i2c_remove, ++ .id_table = pm88x_i2c_id, ++}; ++ ++static int __init pm88x_i2c_init(void) ++{ ++ int ret; ++ ++ ret = i2c_add_driver(&pm88x_i2c_driver); ++ if (ret != 0) { ++ pr_err("88pm88x I2C registration failed %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++subsys_initcall(pm88x_i2c_init); ++ ++static void __exit pm88x_i2c_exit(void) ++{ ++ i2c_del_driver(&pm88x_i2c_driver); ++} ++module_exit(pm88x_i2c_exit); ++ ++MODULE_DESCRIPTION("88pm88x I2C bus interface"); ++MODULE_AUTHOR("Yi Zhang"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mfd/88pm88x-irq.c b/drivers/mfd/88pm88x-irq.c +new file mode 100644 +index 000000000000..0126df0231b8 +--- /dev/null ++++ b/drivers/mfd/88pm88x-irq.c +@@ -0,0 +1,171 @@ ++/* ++ * 88pm886 interrupt support ++ * ++ * Copyright (C) 2015 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* interrupt status registers */ ++#define PM88X_INT_STATUS1 (0x05) ++ ++#define PM88X_INT_ENA_1 (0x0a) ++#define PM88X_ONKEY_INT_ENA1 (1 << 0) ++#define PM88X_EXTON_INT_ENA1 (1 << 1) ++#define PM88X_CHG_INT_ENA1 (1 << 2) ++#define PM88X_BAT_INT_ENA1 (1 << 3) ++#define PM88X_RTC_INT_ENA1 (1 << 4) ++#define PM88X_CLASSD_INT_ENA1 (1 << 5) ++#define PM88X_XO_INT_ENA1 (1 << 6) ++#define PM88X_GPIO_INT_ENA1 (1 << 7) ++ ++#define PM88X_INT_ENA_2 (0x0b) ++#define PM88X_VBAT_INT_ENA2 (1 << 0) ++#define PM88X_RSVED1_INT_ENA2 (1 << 1) ++#define PM88X_VBUS_INT_ENA2 (1 << 2) ++#define PM88X_ITEMP_INT_ENA2 (1 << 3) ++#define PM88X_BUCK_PGOOD_INT_ENA2 (1 << 4) ++#define PM88X_LDO_PGOOD_INT_ENA2 (1 << 5) ++#define PM88X_RSVED6_INT_ENA2 (1 << 6) ++#define PM88X_RSVED7_INT_ENA2 (1 << 7) ++ ++#define PM88X_INT_ENA_3 (0x0c) ++#define PM88X_GPADC0_INT_ENA3 (1 << 0) ++#define PM88X_GPADC1_INT_ENA3 (1 << 1) ++#define PM88X_GPADC2_INT_ENA3 (1 << 2) ++#define PM88X_GPADC3_INT_ENA3 (1 << 3) ++#define PM88X_MIC_INT_ENA3 (1 << 4) ++#define PM88X_HS_INT_ENA3 (1 << 5) ++#define PM88X_GND_INT_ENA3 (1 << 6) ++#define PM88X_RSVED7_INT_ENA3 (1 << 7) ++ ++#define PM88X_INT_ENA_4 (0x0d) ++#define PM88X_CHG_FAIL_INT_ENA4 (1 << 0) ++#define PM88X_CHG_DONE_INT_ENA4 (1 << 1) ++#define PM88X_RSVED2_INT_ENA4 (1 << 2) ++#define PM88X_OTG_FAIL_INT_ENA4 (1 << 3) ++#define PM88X_RSVED4_INT_ENA4 (1 << 4) ++#define PM88X_CHG_ILIM_INT_ENA4 (1 << 5) ++#define PM88X_CC_INT_ENA4 (1 << 6) ++#define PM88X_RSVED7_INT_ENA4 (1 << 7) ++ ++#define PM88X_MISC_CONFIG2 (0x15) ++#define PM88X_INV_INT (1 << 0) ++#define PM88X_INT_CLEAR (1 << 1) ++#define PM88X_INT_RC (0 << 1) ++#define PM88X_INT_WC (1 << 1) ++#define PM88X_INT_MASK_MODE (1 << 2) ++ ++static const struct regmap_irq pm88x_irqs[] = { ++ /* INT0 */ ++ [PM88X_IRQ_ONKEY] = {.reg_offset = 0, .mask = PM88X_ONKEY_INT_ENA1,}, ++ [PM88X_IRQ_EXTON] = {.reg_offset = 0, .mask = PM88X_EXTON_INT_ENA1,}, ++ [PM88X_IRQ_CHG_GOOD] = {.reg_offset = 0, .mask = PM88X_CHG_INT_ENA1,}, ++ [PM88X_IRQ_BAT_DET] = {.reg_offset = 0, .mask = PM88X_BAT_INT_ENA1,}, ++ [PM88X_IRQ_RTC] = {.reg_offset = 0, .mask = PM88X_RTC_INT_ENA1,}, ++ [PM88X_IRQ_CLASSD] = { .reg_offset = 0, .mask = PM88X_CLASSD_INT_ENA1,}, ++ [PM88X_IRQ_XO] = {.reg_offset = 0, .mask = PM88X_XO_INT_ENA1,}, ++ [PM88X_IRQ_GPIO] = {.reg_offset = 0, .mask = PM88X_GPIO_INT_ENA1,}, ++ ++ /* INT1 */ ++ [PM88X_IRQ_VBAT] = {.reg_offset = 1, .mask = PM88X_VBAT_INT_ENA2,}, ++ [PM88X_IRQ_VBUS] = {.reg_offset = 1, .mask = PM88X_VBUS_INT_ENA2,}, ++ [PM88X_IRQ_ITEMP] = {.reg_offset = 1, .mask = PM88X_ITEMP_INT_ENA2,}, ++ [PM88X_IRQ_BUCK_PGOOD] = { ++ .reg_offset = 1, ++ .mask = PM88X_BUCK_PGOOD_INT_ENA2, ++ }, ++ [PM88X_IRQ_LDO_PGOOD] = { ++ .reg_offset = 1, ++ .mask = PM88X_LDO_PGOOD_INT_ENA2, ++ }, ++ /* INT2 */ ++ [PM88X_IRQ_GPADC0] = {.reg_offset = 2, .mask = PM88X_GPADC0_INT_ENA3,}, ++ [PM88X_IRQ_GPADC1] = {.reg_offset = 2, .mask = PM88X_GPADC1_INT_ENA3,}, ++ [PM88X_IRQ_GPADC2] = {.reg_offset = 2, .mask = PM88X_GPADC2_INT_ENA3,}, ++ [PM88X_IRQ_GPADC3] = {.reg_offset = 2, .mask = PM88X_GPADC3_INT_ENA3,}, ++ [PM88X_IRQ_MIC_DET] = {.reg_offset = 2, .mask = PM88X_MIC_INT_ENA3,}, ++ [PM88X_IRQ_HS_DET] = {.reg_offset = 2, .mask = PM88X_HS_INT_ENA3,}, ++ [PM88X_IRQ_GND_DET] = {.reg_offset = 2, .mask = PM88X_GND_INT_ENA3,}, ++ ++ /* INT3 */ ++ [PM88X_IRQ_CHG_FAIL] = { ++ .reg_offset = 3, ++ .mask = PM88X_CHG_FAIL_INT_ENA4, ++ }, ++ [PM88X_IRQ_CHG_DONE] = { ++ .reg_offset = 3, ++ .mask = PM88X_CHG_DONE_INT_ENA4, ++ }, ++ [PM88X_IRQ_OTG_FAIL] = { ++ .reg_offset = 3, ++ .mask = PM88X_OTG_FAIL_INT_ENA4, ++ }, ++ [PM88X_IRQ_CHG_ILIM] = { ++ .reg_offset = 3, ++ .mask = PM88X_CHG_ILIM_INT_ENA4, ++ }, ++ [PM88X_IRQ_CC] = {.reg_offset = 3, .mask = PM88X_CC_INT_ENA4,}, ++}; ++ ++struct regmap_irq_chip pm88x_irq_chip = { ++ .name = "88pm88x", ++ .irqs = pm88x_irqs, ++ .num_irqs = ARRAY_SIZE(pm88x_irqs), ++ ++ .num_regs = 4, ++ .status_base = PM88X_INT_STATUS1, ++ .mask_base = PM88X_INT_ENA_1, ++ .ack_base = PM88X_INT_STATUS1, ++ .mask_invert = 1, ++}; ++ ++int pm88x_irq_init(struct pm88x_chip *chip) ++{ ++ int mask, data, ret; ++ struct regmap *map; ++ ++ if (!chip || !chip->base_regmap || !chip->irq) { ++ pr_err("cannot initialize interrupt!\n"); ++ return -EINVAL; ++ } ++ map = chip->base_regmap; ++ ++ /* ++ * irq_mode defines the way of clearing interrupt. ++ * it's read-clear by default. ++ */ ++ mask = PM88X_INV_INT | PM88X_INT_CLEAR | PM88X_INT_MASK_MODE; ++ data = (chip->irq_mode) ? PM88X_INT_WC : PM88X_INT_RC; ++ ret = regmap_update_bits(map, PM88X_MISC_CONFIG2, mask, data); ++ if (ret < 0) { ++ dev_err(chip->dev, "cannot set interrupt mode!\n"); ++ return ret; ++ } ++ ++ ret = regmap_add_irq_chip(map, chip->irq, IRQF_ONESHOT, -1, ++ &pm88x_irq_chip, &chip->irq_data); ++ return ret; ++} ++ ++int pm88x_irq_exit(struct pm88x_chip *chip) ++{ ++ regmap_del_irq_chip(chip->irq, chip->irq_data); ++ return 0; ++} +diff --git a/drivers/mfd/88pm88x.h b/drivers/mfd/88pm88x.h +new file mode 100644 +index 000000000000..a85a48662197 +--- /dev/null ++++ b/drivers/mfd/88pm88x.h +@@ -0,0 +1,51 @@ ++#ifndef _MFD_88PM88X_H ++#define _MFD_88PM88X_H ++ ++#include ++#include ++#include ++#include ++ ++struct pmic_cell_info { ++ const struct mfd_cell *cells; ++ int cell_nr; ++}; ++ ++#define CELL_IRQ_RESOURCE(_name, _irq) { \ ++ .name = _name, \ ++ .start = _irq, .end = _irq, \ ++ .flags = IORESOURCE_IRQ, \ ++ } ++#define CELL_DEV(_name, _r, _compatible, _id) { \ ++ .name = _name, \ ++ .of_compatible = _compatible, \ ++ .num_resources = ARRAY_SIZE(_r), \ ++ .resources = _r, \ ++ .id = _id, \ ++ } ++ ++/* 88pm886 */ ++extern const struct regmap_config pm886_base_i2c_regmap; ++extern const struct regmap_config pm886_power_i2c_regmap; ++extern const struct regmap_config pm886_gpadc_i2c_regmap; ++extern const struct regmap_config pm886_battery_i2c_regmap; ++extern const struct regmap_config pm886_test_i2c_regmap; ++ ++extern const struct mfd_cell pm886_cell_devs[]; ++extern struct pmic_cell_info pm886_cell_info; ++ ++int pm886_apply_patch(struct pm88x_chip *chip); ++ ++/* 88pm880 */ ++extern const struct regmap_config pm880_base_i2c_regmap; ++extern const struct regmap_config pm880_power_i2c_regmap; ++extern const struct regmap_config pm880_gpadc_i2c_regmap; ++extern const struct regmap_config pm880_battery_i2c_regmap; ++extern const struct regmap_config pm880_test_i2c_regmap; ++ ++extern const struct mfd_cell pm880_cell_devs[]; ++extern struct pmic_cell_info pm880_cell_info; ++ ++int pm880_apply_patch(struct pm88x_chip *chip); ++ ++#endif +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index aea95745c73f..b80377b829e6 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -758,6 +758,18 @@ config MFD_KEMPLD + This driver can also be built as a module. If so, the module + will be called kempld-core. + ++config MFD_88PM88X ++ tristate "Marvell 88PM886/880 PMIC" ++ depends on I2C=y ++ select REGMAP_I2C ++ select MFD_CORE ++ help ++ This supports for Marvell 88PM88X Series Power Management IC: ++ 88pm886 and 88pm880; ++ This includes the I2C driver, the interrupt resource distribution ++ and the core APIs, for individual sub-device as voltage regulators, ++ RTC, charger, fuelgauge, etc, select under the corresponding menus. ++ + config MFD_88PM800 + tristate "Marvell 88PM800" + depends on I2C +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index c66f07edcd0e..576bad9e9b59 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -8,6 +8,9 @@ obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o + obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o + obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o + obj-$(CONFIG_MFD_ACT8945A) += act8945a.o ++88pm88x-objs := 88pm88x-core.o 88pm88x-i2c.o 88pm88x-irq.o 88pm886-table.o 88pm880-table.o ++obj-$(CONFIG_MFD_88PM88X) += 88pm88x.o ++ + obj-$(CONFIG_MFD_SM501) += sm501.o + obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o + obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o +diff --git a/include/linux/mfd/88pm880-reg.h b/include/linux/mfd/88pm880-reg.h +new file mode 100644 +index 000000000000..fdf23158bb37 +--- /dev/null ++++ b/include/linux/mfd/88pm880-reg.h +@@ -0,0 +1,98 @@ ++/* ++ * Marvell 88PM880 registers ++ * ++ * Copyright (C) 2014 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#ifndef __LINUX_MFD_88PM880_REG_H ++#define __LINUX_MFD_88PM880_REG_H ++ ++#define PM880_BUCK1_VOUT (0x28) ++ ++#define PM880_BUCK1A_VOUT (0x28) /* voltage 0 */ ++#define PM880_BUCK1A_1_VOUT (0x29) ++#define PM880_BUCK1A_2_VOUT (0x2a) ++#define PM880_BUCK1A_3_VOUT (0x2b) ++#define PM880_BUCK1A_4_VOUT (0x2c) ++#define PM880_BUCK1A_5_VOUT (0x2d) ++#define PM880_BUCK1A_6_VOUT (0x2e) ++#define PM880_BUCK1A_7_VOUT (0x2f) ++#define PM880_BUCK1A_8_VOUT (0x30) ++#define PM880_BUCK1A_9_VOUT (0x31) ++#define PM880_BUCK1A_10_VOUT (0x32) ++#define PM880_BUCK1A_11_VOUT (0x33) ++#define PM880_BUCK1A_12_VOUT (0x34) ++#define PM880_BUCK1A_13_VOUT (0x35) ++#define PM880_BUCK1A_14_VOUT (0x36) ++#define PM880_BUCK1A_15_VOUT (0x37) ++ ++#define PM880_BUCK1B_VOUT (0x40) ++#define PM880_BUCK1B_1_VOUT (0x41) ++#define PM880_BUCK1B_2_VOUT (0x42) ++#define PM880_BUCK1B_3_VOUT (0x43) ++#define PM880_BUCK1B_4_VOUT (0x44) ++#define PM880_BUCK1B_5_VOUT (0x45) ++#define PM880_BUCK1B_6_VOUT (0x46) ++#define PM880_BUCK1B_7_VOUT (0x47) ++#define PM880_BUCK1B_8_VOUT (0x48) ++#define PM880_BUCK1B_9_VOUT (0x49) ++#define PM880_BUCK1B_10_VOUT (0x4a) ++#define PM880_BUCK1B_11_VOUT (0x4b) ++#define PM880_BUCK1B_12_VOUT (0x4c) ++#define PM880_BUCK1B_13_VOUT (0x4d) ++#define PM880_BUCK1B_14_VOUT (0x4e) ++#define PM880_BUCK1B_15_VOUT (0x4f) ++ ++/* buck7 has dvc function */ ++#define PM880_BUCK7_VOUT (0xb8) /* voltage 0 */ ++#define PM880_BUCK7_1_VOUT (0xb9) ++#define PM880_BUCK7_2_VOUT (0xba) ++#define PM880_BUCK7_3_VOUT (0xbb) ++ ++/* ++ * buck sleep mode control registers: ++ * 00-disable, ++ * 01/10-sleep voltage, ++ * 11-active voltage ++ */ ++#define PM880_BUCK1A_SLP_CTRL (0x27) ++#define PM880_BUCK1B_SLP_CTRL (0x3c) ++#define PM880_BUCK2_SLP_CTRL (0x54) ++#define PM880_BUCK3_SLP_CTRL (0x6c) ++/* TODO: there are 7 controls bit for buck4~7 */ ++#define PM880_BUCK4_SLP_CTRL (0x84) ++#define PM880_BUCK5_SLP_CTRL (0x94) ++#define PM880_BUCK6_SLP_CTRL (0xa4) ++#define PM880_BUCK7_SLP_CTRL (0xb4) ++ ++/* ++ * ldo sleep mode control registers: ++ * 00-disable, ++ * 01/10-sleep voltage, ++ * 11-active voltage ++ */ ++#define PM880_LDO1_SLP_CTRL (0x21) ++#define PM880_LDO2_SLP_CTRL (0x27) ++#define PM880_LDO3_SLP_CTRL (0x2d) ++#define PM880_LDO4_SLP_CTRL (0x33) ++#define PM880_LDO5_SLP_CTRL (0x39) ++#define PM880_LDO6_SLP_CTRL (0x3f) ++#define PM880_LDO7_SLP_CTRL (0x45) ++#define PM880_LDO8_SLP_CTRL (0x4b) ++#define PM880_LDO9_SLP_CTRL (0x51) ++#define PM880_LDO10_SLP_CTRL (0x57) ++#define PM880_LDO11_SLP_CTRL (0x5d) ++#define PM880_LDO12_SLP_CTRL (0x63) ++#define PM880_LDO13_SLP_CTRL (0x69) ++#define PM880_LDO14_SLP_CTRL (0x6f) ++#define PM880_LDO15_SLP_CTRL (0x75) ++#define PM880_LDO16_SLP_CTRL (0x7b) ++#define PM880_LDO17_SLP_CTRL (0x81) ++#define PM880_LDO18_SLP_CTRL (0x87) ++ ++#endif /*__LINUX_MFD_88PM880_REG_H */ +diff --git a/include/linux/mfd/88pm880.h b/include/linux/mfd/88pm880.h +new file mode 100644 +index 000000000000..94b9e063918a +--- /dev/null ++++ b/include/linux/mfd/88pm880.h +@@ -0,0 +1,59 @@ ++/* ++ * Marvell 88PM880 Interface ++ * ++ * Copyright (C) 2015 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ * ++ * 88pm880 specific configuration: at present it's regulators and dvc part ++ */ ++ ++#ifndef __LINUX_MFD_88PM880_H ++#define __LINUX_MFD_88PM880_H ++ ++#include ++#include ++#include ++#include ++#include ++#include "88pm880-reg.h" ++ ++enum { ++ PM880_ID_BUCK1A = 0, ++ PM880_ID_BUCK2, ++ PM880_ID_BUCK3, ++ PM880_ID_BUCK4, ++ PM880_ID_BUCK5, ++ PM880_ID_BUCK6, ++ PM880_ID_BUCK7, ++ ++ PM880_ID_BUCK_MAX = 7, ++}; ++ ++enum { ++ PM880_ID_LDO1 = 0, ++ PM880_ID_LDO2, ++ PM880_ID_LDO3, ++ PM880_ID_LDO4, ++ PM880_ID_LDO5, ++ PM880_ID_LDO6, ++ PM880_ID_LDO7, ++ PM880_ID_LDO8, ++ PM880_ID_LDO9, ++ PM880_ID_LDO10, ++ PM880_ID_LDO11, ++ PM880_ID_LDO12, ++ PM880_ID_LDO13, ++ PM880_ID_LDO14 = 13, ++ PM880_ID_LDO15, ++ PM880_ID_LDO16 = 15, ++ ++ PM880_ID_LDO17 = 16, ++ PM880_ID_LDO18 = 17, ++ ++ PM880_ID_LDO_MAX = 18, ++}; ++#endif /* __LINUX_MFD_88PM880_H */ +diff --git a/include/linux/mfd/88pm886-reg.h b/include/linux/mfd/88pm886-reg.h +new file mode 100644 +index 000000000000..38a7ecdf8a5b +--- /dev/null ++++ b/include/linux/mfd/88pm886-reg.h +@@ -0,0 +1,59 @@ ++/* ++ * Marvell 88PM886 registers ++ * ++ * Copyright (C) 2014 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#ifndef __LINUX_MFD_88PM886_REG_H ++#define __LINUX_MFD_88PM886_REG_H ++ ++#define PM886_BUCK1_VOUT (0xa5) ++#define PM886_BUCK1_1_VOUT (0xa6) ++#define PM886_BUCK1_2_VOUT (0xa7) ++#define PM886_BUCK1_3_VOUT (0xa8) ++#define PM886_BUCK1_4_VOUT (0x9a) ++#define PM886_BUCK1_5_VOUT (0x9b) ++#define PM886_BUCK1_6_VOUT (0x9c) ++#define PM886_BUCK1_7_VOUT (0x9d) ++ ++/* ++ * buck sleep mode control registers: ++ * 00-disable, ++ * 01/10-sleep voltage, ++ * 11-active voltage ++ */ ++#define PM886_BUCK1_SLP_CTRL (0xa2) ++#define PM886_BUCK2_SLP_CTRL (0xb0) ++#define PM886_BUCK3_SLP_CTRL (0xbe) ++#define PM886_BUCK4_SLP_CTRL (0xcc) ++#define PM886_BUCK5_SLP_CTRL (0xda) ++ ++/* ++ * ldo sleep mode control registers: ++ * 00-disable, ++ * 01/10-sleep voltage, ++ * 11-active voltage ++ */ ++#define PM886_LDO1_SLP_CTRL (0x21) ++#define PM886_LDO2_SLP_CTRL (0x27) ++#define PM886_LDO3_SLP_CTRL (0x2d) ++#define PM886_LDO4_SLP_CTRL (0x33) ++#define PM886_LDO5_SLP_CTRL (0x39) ++#define PM886_LDO6_SLP_CTRL (0x3f) ++#define PM886_LDO7_SLP_CTRL (0x45) ++#define PM886_LDO8_SLP_CTRL (0x4b) ++#define PM886_LDO9_SLP_CTRL (0x51) ++#define PM886_LDO10_SLP_CTRL (0x57) ++#define PM886_LDO11_SLP_CTRL (0x5d) ++#define PM886_LDO12_SLP_CTRL (0x63) ++#define PM886_LDO13_SLP_CTRL (0x69) ++#define PM886_LDO14_SLP_CTRL (0x6f) ++#define PM886_LDO15_SLP_CTRL (0x75) ++#define PM886_LDO16_SLP_CTRL (0x7b) ++ ++#endif +diff --git a/include/linux/mfd/88pm886.h b/include/linux/mfd/88pm886.h +new file mode 100644 +index 000000000000..939040647702 +--- /dev/null ++++ b/include/linux/mfd/88pm886.h +@@ -0,0 +1,55 @@ ++/* ++ * Marvell 88PM886 Interface ++ * ++ * Copyright (C) 2015 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ * ++ * 88pm886 specific configuration: at present it's regulators and dvc part ++ */ ++ ++#ifndef __LINUX_MFD_88PM886_H ++#define __LINUX_MFD_88PM886_H ++ ++#include ++#include ++#include ++#include ++#include ++#include "88pm886-reg.h" ++ ++enum { ++ PM886_ID_BUCK1 = 0, ++ PM886_ID_BUCK2, ++ PM886_ID_BUCK3, ++ PM886_ID_BUCK4, ++ PM886_ID_BUCK5, ++ ++ PM886_ID_BUCK_MAX = 5, ++}; ++ ++enum { ++ PM886_ID_LDO1 = 0, ++ PM886_ID_LDO2, ++ PM886_ID_LDO3, ++ PM886_ID_LDO4, ++ PM886_ID_LDO5, ++ PM886_ID_LDO6, ++ PM886_ID_LDO7, ++ PM886_ID_LDO8, ++ PM886_ID_LDO9, ++ PM886_ID_LDO10, ++ PM886_ID_LDO11, ++ PM886_ID_LDO12, ++ PM886_ID_LDO13, ++ PM886_ID_LDO14, ++ PM886_ID_LDO15, ++ PM886_ID_LDO16 = 15, ++ ++ PM886_ID_LDO_MAX = 16, ++}; ++ ++#endif /* __LINUX_MFD_88PM886_H */ +diff --git a/include/linux/mfd/88pm88x-reg.h b/include/linux/mfd/88pm88x-reg.h +new file mode 100644 +index 000000000000..d767b3153a14 +--- /dev/null ++++ b/include/linux/mfd/88pm88x-reg.h +@@ -0,0 +1,118 @@ ++/* ++ * Marvell 88PM88X registers ++ * ++ * Copyright (C) 2014 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#ifndef __LINUX_MFD_88PM88X_REG_H ++#define __LINUX_MFD_88PM88X_REG_H ++/* ++ * This file is just used for the common registers, ++ * which are shared by sub-clients ++ */ ++ ++/*--base page:--------------------------------------------------------------*/ ++#define PM88X_ID_REG (0x0) ++ ++#define PM88X_STATUS1 (0x1) ++#define PM88X_CHG_DET (1 << 2) ++#define PM88X_BAT_DET (1 << 3) ++ ++#define PM88X_MISC_CONFIG1 (0x14) ++#define PM88X_LONKEY_RST (1 << 3) ++ ++#define PM88X_WDOG (0x1d) ++ ++#define PM88X_LOWPOWER2 (0x21) ++#define PM88X_LOWPOWER4 (0x23) ++ ++/* clk control register */ ++#define PM88X_CLK_CTRL1 (0x25) ++ ++/* gpio */ ++#define PM88X_GPIO_CTRL1 (0x30) ++#define PM88X_GPIO0_VAL_MSK (0x1 << 0) ++#define PM88X_GPIO0_MODE_MSK (0x7 << 1) ++#define PM88X_GPIO1_VAL_MSK (0x1 << 4) ++#define PM88X_GPIO1_MODE_MSK (0x7 << 5) ++#define PM88X_GPIO1_SET_DVC (0x2 << 5) ++ ++#define PM88X_GPIO_CTRL2 (0x31) ++#define PM88X_GPIO2_VAL_MSK (0x1 << 0) ++#define PM88X_GPIO2_MODE_MSK (0x7 << 1) ++ ++#define PM88X_GPIO_CTRL3 (0x32) ++ ++#define PM88X_GPIO_CTRL4 (0x33) ++#define PM88X_GPIO5V_1_VAL_MSK (0x1 << 0) ++#define PM88X_GPIO5V_1_MODE_MSK (0x7 << 1) ++#define PM88X_GPIO5V_2_VAL_MSK (0x1 << 4) ++#define PM88X_GPIO5V_2_MODE_MSK (0x7 << 5) ++ ++#define PM88X_BK_OSC_CTRL1 (0x50) ++#define PM88X_BK_OSC_CTRL3 (0x52) ++ ++#define PM88X_RTC_ALARM_CTRL1 (0xd0) ++#define PM88X_ALARM_WAKEUP (1 << 4) ++#define PM88X_USE_XO (1 << 7) ++ ++#define PM88X_AON_CTRL2 (0xe2) ++#define PM88X_AON_CTRL3 (0xe3) ++#define PM88X_AON_CTRL4 (0xe4) ++#define PM88X_AON_CTRL7 (0xe7) ++ ++/* 0xea, 0xeb, 0xec, 0xed are reserved by RTC */ ++#define PM88X_RTC_SPARE5 (0xee) ++#define PM88X_RTC_SPARE6 (0xef) ++/*-------------------------------------------------------------------------*/ ++ ++/*--power page:------------------------------------------------------------*/ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/*--gpadc page:------------------------------------------------------------*/ ++ ++#define PM88X_GPADC_CONFIG1 (0x1) ++ ++#define PM88X_GPADC_CONFIG2 (0x2) ++#define PM88X_GPADC0_MEAS_EN (1 << 2) ++#define PM88X_GPADC1_MEAS_EN (1 << 3) ++#define PM88X_GPADC2_MEAS_EN (1 << 4) ++#define PM88X_GPADC3_MEAS_EN (1 << 5) ++ ++#define PM88X_GPADC_CONFIG3 (0x3) ++ ++#define PM88X_GPADC_CONFIG6 (0x6) ++#define PM88X_GPADC_CONFIG8 (0x8) ++ ++#define PM88X_GPADC0_LOW_TH (0x20) ++#define PM88X_GPADC1_LOW_TH (0x21) ++#define PM88X_GPADC2_LOW_TH (0x22) ++#define PM88X_GPADC3_LOW_TH (0x23) ++ ++#define PM88X_GPADC0_UPP_TH (0x30) ++#define PM88X_GPADC1_UPP_TH (0x31) ++#define PM88X_GPADC2_UPP_TH (0x32) ++#define PM88X_GPADC3_UPP_TH (0x33) ++ ++#define PM88X_VBUS_MEAS1 (0x4A) ++#define PM88X_GPADC0_MEAS1 (0x54) ++#define PM88X_GPADC1_MEAS1 (0x56) ++#define PM88X_GPADC2_MEAS1 (0x58) ++#define PM88X_GPADC3_MEAS1 (0x5A) ++ ++ ++/*--charger page:------------------------------------------------------------*/ ++#define PM88X_CHG_CONFIG1 (0x28) ++#define PM88X_CHGBK_CONFIG6 (0x50) ++/*-------------------------------------------------------------------------*/ ++ ++/*--test page:-------------------------------------------------------------*/ ++ ++/*-------------------------------------------------------------------------*/ ++#endif +diff --git a/include/linux/mfd/88pm88x.h b/include/linux/mfd/88pm88x.h +new file mode 100644 +index 000000000000..efa2fe621ccd +--- /dev/null ++++ b/include/linux/mfd/88pm88x.h +@@ -0,0 +1,202 @@ ++/* ++ * Marvell 88PM88X PMIC Common Interface ++ * ++ * Copyright (C) 2014 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * ++ * This file configures the common part of the 88pm88x series PMIC ++ */ ++ ++#ifndef __LINUX_MFD_88PM88X_H ++#define __LINUX_MFD_88PM88X_H ++ ++#include ++#include ++#include ++#include ++#include ++#include "88pm88x-reg.h" ++#include "88pm886-reg.h" ++ ++#define PM88X_RTC_NAME "88pm88x-rtc" ++#define PM88X_ONKEY_NAME "88pm88x-onkey" ++#define PM88X_CHARGER_NAME "88pm88x-charger" ++#define PM88X_BATTERY_NAME "88pm88x-battery" ++#define PM88X_HEADSET_NAME "88pm88x-headset" ++#define PM88X_VBUS_NAME "88pm88x-vbus" ++#define PM88X_CFD_NAME "88pm88x-leds" ++#define PM88X_RGB_NAME "88pm88x-rgb" ++#define PM88X_GPADC_NAME "88pm88x-gpadc" ++#define PM88X_DVC_NAME "88pm88x-dvc" ++ ++enum pm88x_type { ++ PM886 = 1, ++ PM880 = 2, ++}; ++ ++enum pm88x_pages { ++ PM88X_BASE_PAGE = 0, ++ PM88X_LDO_PAGE, ++ PM88X_GPADC_PAGE, ++ PM88X_BATTERY_PAGE, ++ PM88X_BUCK_PAGE = 4, ++ PM88X_TEST_PAGE = 7, ++}; ++ ++enum pm88x_gpadc { ++ PM88X_NO_GPADC = -1, ++ PM88X_GPADC0 = 0, ++ PM88X_GPADC1, ++ PM88X_GPADC2, ++ PM88X_GPADC3, ++}; ++ ++/* interrupt number */ ++enum pm88x_irq_number { ++ PM88X_IRQ_ONKEY, /* EN1b0 *//* 0 */ ++ PM88X_IRQ_EXTON, /* EN1b1 */ ++ PM88X_IRQ_CHG_GOOD, /* EN1b2 */ ++ PM88X_IRQ_BAT_DET, /* EN1b3 */ ++ PM88X_IRQ_RTC, /* EN1b4 */ ++ PM88X_IRQ_CLASSD, /* EN1b5 *//* 5 */ ++ PM88X_IRQ_XO, /* EN1b6 */ ++ PM88X_IRQ_GPIO, /* EN1b7 */ ++ ++ PM88X_IRQ_VBAT, /* EN2b0 *//* 8 */ ++ /* EN2b1 */ ++ PM88X_IRQ_VBUS, /* EN2b2 */ ++ PM88X_IRQ_ITEMP, /* EN2b3 *//* 10 */ ++ PM88X_IRQ_BUCK_PGOOD, /* EN2b4 */ ++ PM88X_IRQ_LDO_PGOOD, /* EN2b5 */ ++ ++ PM88X_IRQ_GPADC0, /* EN3b0 */ ++ PM88X_IRQ_GPADC1, /* EN3b1 */ ++ PM88X_IRQ_GPADC2, /* EN3b2 *//* 15 */ ++ PM88X_IRQ_GPADC3, /* EN3b3 */ ++ PM88X_IRQ_MIC_DET, /* EN3b4 */ ++ PM88X_IRQ_HS_DET, /* EN3b5 */ ++ PM88X_IRQ_GND_DET, /* EN3b6 */ ++ ++ PM88X_IRQ_CHG_FAIL, /* EN4b0 *//* 20 */ ++ PM88X_IRQ_CHG_DONE, /* EN4b1 */ ++ /* EN4b2 */ ++ PM88X_IRQ_CFD_FAIL, /* EN4b3 */ ++ PM88X_IRQ_OTG_FAIL, /* EN4b4 */ ++ PM88X_IRQ_CHG_ILIM, /* EN4b5 *//* 25 */ ++ /* EN4b6 */ ++ PM88X_IRQ_CC, /* EN4b7 *//* 27 */ ++ ++ PM88X_MAX_IRQ, /* 28 */ ++}; ++ ++/* 3 rgb led indicators */ ++enum { ++ PM88X_RGB_LED0, ++ PM88X_RGB_LED1, ++ PM88X_RGB_LED2, ++}; ++ ++/* camera flash/torch */ ++enum { ++ PM88X_NO_LED = -1, ++ PM88X_FLASH_LED = 0, ++ PM88X_TORCH_LED, ++}; ++ ++struct pm88x_dvc_ops { ++ void (*level_to_reg)(u8 level); ++}; ++ ++struct pm88x_buck1_dvc_desc { ++ u8 current_reg; ++ int max_level; ++ int uV_step1; ++ int uV_step2; ++ int min_uV; ++ int mid_uV; ++ int max_uV; ++ int mid_reg_val; ++}; ++ ++struct pm88x_dvc { ++ struct device *dev; ++ struct pm88x_chip *chip; ++ struct pm88x_dvc_ops ops; ++ struct pm88x_buck1_dvc_desc desc; ++}; ++ ++struct pm88x_chip { ++ struct i2c_client *client; ++ struct device *dev; ++ ++ struct i2c_client *ldo_page; /* chip client for ldo page */ ++ struct i2c_client *power_page; /* chip client for power page */ ++ struct i2c_client *gpadc_page; /* chip client for gpadc page */ ++ struct i2c_client *battery_page;/* chip client for battery page */ ++ struct i2c_client *buck_page; /* chip client for buck page */ ++ struct i2c_client *test_page; /* chip client for test page */ ++ ++ struct regmap *base_regmap; ++ struct regmap *ldo_regmap; ++ struct regmap *power_regmap; ++ struct regmap *gpadc_regmap; ++ struct regmap *battery_regmap; ++ struct regmap *buck_regmap; ++ struct regmap *test_regmap; ++ struct regmap *codec_regmap; ++ ++ unsigned short ldo_page_addr; /* ldo page I2C address */ ++ unsigned short power_page_addr; /* power page I2C address */ ++ unsigned short gpadc_page_addr; /* gpadc page I2C address */ ++ unsigned short battery_page_addr;/* battery page I2C address */ ++ unsigned short buck_page_addr; /* buck page I2C address */ ++ unsigned short test_page_addr; /* test page I2C address */ ++ ++ unsigned int chip_id; ++ long type; /* specific chip */ ++ int irq; ++ ++ int irq_mode; /* write/read clear */ ++ struct regmap_irq_chip_data *irq_data; ++ ++ bool rtc_wakeup; /* is it powered up by expired alarm? */ ++ u8 powerdown1; /* save power down reason */ ++ u8 powerdown2; ++ u8 powerup; /* the reason of power on */ ++ ++ struct notifier_block reboot_notifier; ++ struct pm88x_dvc *dvc; ++}; ++ ++extern struct regmap_irq_chip pm88x_irq_chip; ++extern const struct of_device_id pm88x_of_match[]; ++ ++struct pm88x_chip *pm88x_init_chip(struct i2c_client *client); ++int pm88x_parse_dt(struct device_node *np, struct pm88x_chip *chip); ++ ++int pm88x_init_pages(struct pm88x_chip *chip); ++int pm88x_post_init_chip(struct pm88x_chip *chip); ++void pm800_exit_pages(struct pm88x_chip *chip); ++ ++int pm88x_init_subdev(struct pm88x_chip *chip); ++long pm88x_of_get_type(struct device *dev); ++void pm88x_dev_exit(struct pm88x_chip *chip); ++ ++int pm88x_irq_init(struct pm88x_chip *chip); ++int pm88x_irq_exit(struct pm88x_chip *chip); ++int pm88x_apply_patch(struct pm88x_chip *chip); ++int pm88x_stepping_fixup(struct pm88x_chip *chip); ++int pm88x_apply_board_fixup(struct pm88x_chip *chip, struct device_node *np); ++ ++struct pm88x_chip *pm88x_get_chip(void); ++void pm88x_set_chip(struct pm88x_chip *chip); ++void pm88x_power_off(void); ++int pm88x_reboot_notifier_callback(struct notifier_block *nb, ++ unsigned long code, void *unused); ++ ++#endif /* __LINUX_MFD_88PM88X_H */ +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0017-DONOTMERGE-fix-88pm88x-build.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0017-DONOTMERGE-fix-88pm88x-build.patch new file mode 100644 index 000000000..a8224dd70 --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0017-DONOTMERGE-fix-88pm88x-build.patch @@ -0,0 +1,220 @@ +From db98663bffbf33a89cc3286abb4f5c7844e78f79 Mon Sep 17 00:00:00 2001 +From: Karel Balej +Date: Mon, 14 Aug 2023 18:02:03 +0200 +Subject: [PATCH] DONOTMERGE: fix 88pm88x build + +--- + drivers/mfd/88pm880-table.c | 26 +++++++++++++------------- + drivers/mfd/88pm886-table.c | 34 +++++++++++++++++----------------- + drivers/mfd/88pm88x-core.c | 10 +++++----- + drivers/mfd/88pm88x-i2c.c | 6 ++---- + drivers/mfd/88pm88x-irq.c | 3 +-- + include/linux/mfd/88pm88x.h | 1 + + 6 files changed, 39 insertions(+), 41 deletions(-) + +diff --git a/drivers/mfd/88pm880-table.c b/drivers/mfd/88pm880-table.c +index 28ca86028905..03a19eb63632 100644 +--- a/drivers/mfd/88pm880-table.c ++++ b/drivers/mfd/88pm880-table.c +@@ -96,28 +96,28 @@ struct pmic_cell_info pm880_cell_info = { + .cell_nr = ARRAY_SIZE(pm880_cell_devs), + }; + +-static const struct reg_default pm880_base_patch[] = { +- {PM88X_WDOG, 0x1}, /* disable watchdog */ +- {PM88X_AON_CTRL2, 0x2a}, /* output 32kHZ from XO */ +- {PM88X_BK_OSC_CTRL1, 0x0f}, /* OSC_FREERUN = 1, to lock FLL */ +- {PM88X_LOWPOWER2, 0x20}, /* XO_LJ = 1, enable low jitter for 32kHZ */ ++static const struct reg_sequence pm880_base_patch[] = { ++ REG_SEQ0(PM88X_WDOG, 0x1), /* disable watchdog */ ++ REG_SEQ0(PM88X_AON_CTRL2, 0x2a), /* output 32kHZ from XO */ ++ REG_SEQ0(PM88X_BK_OSC_CTRL1, 0x0f), /* OSC_FREERUN = 1, to lock FLL */ ++ REG_SEQ0(PM88X_LOWPOWER2, 0x20), /* XO_LJ = 1, enable low jitter for 32kHZ */ + /* enable LPM for internal reference group in sleep */ +- {PM88X_LOWPOWER4, 0xc0}, +- {PM88X_BK_OSC_CTRL3, 0xc0}, /* set the duty cycle of charger DC/DC to max */ ++ REG_SEQ0(PM88X_LOWPOWER4, 0xc0), ++ REG_SEQ0(PM88X_BK_OSC_CTRL3, 0xc0), /* set the duty cycle of charger DC/DC to max */ + }; + +-static const struct reg_default pm880_power_patch[] = { ++static const struct reg_sequence pm880_power_patch[] = { + }; + +-static const struct reg_default pm880_gpadc_patch[] = { +- {PM88X_GPADC_CONFIG6, 0x03}, /* enable non-stop mode */ ++static const struct reg_sequence pm880_gpadc_patch[] = { ++ REG_SEQ0(PM88X_GPADC_CONFIG6, 0x03), /* enable non-stop mode */ + }; + +-static const struct reg_default pm880_battery_patch[] = { +- {PM88X_CHGBK_CONFIG6, 0xe1}, ++static const struct reg_sequence pm880_battery_patch[] = { ++ REG_SEQ0(PM88X_CHGBK_CONFIG6, 0xe1), + }; + +-static const struct reg_default pm880_test_patch[] = { ++static const struct reg_sequence pm880_test_patch[] = { + }; + + /* 88pm880 chip itself related */ +diff --git a/drivers/mfd/88pm886-table.c b/drivers/mfd/88pm886-table.c +index 897ee82a30c7..7558420ff3c5 100644 +--- a/drivers/mfd/88pm886-table.c ++++ b/drivers/mfd/88pm886-table.c +@@ -92,32 +92,32 @@ struct pmic_cell_info pm886_cell_info = { + .cell_nr = ARRAY_SIZE(pm886_cell_devs), + }; + +-static const struct reg_default pm886_base_patch[] = { +- {PM88X_WDOG, 0x1}, /* disable watchdog */ +- {PM88X_GPIO_CTRL1, 0x40}, /* gpio1: dvc , gpio0: input */ +- {PM88X_GPIO_CTRL2, 0x00}, /* , gpio2: input */ +- {PM88X_GPIO_CTRL3, 0x44}, /* dvc2 , dvc1 */ +- {PM88X_GPIO_CTRL4, 0x00}, /* gpio5v_1:input, gpio5v_2: input*/ +- {PM88X_AON_CTRL2, 0x2a}, /* output 32kHZ from XO */ +- {PM88X_BK_OSC_CTRL1, 0x0f}, /* OSC_FREERUN = 1, to lock FLL */ +- {PM88X_LOWPOWER2, 0x20}, /* XO_LJ = 1, enable low jitter for 32kHZ */ ++static const struct reg_sequence pm886_base_patch[] = { ++ REG_SEQ0(PM88X_WDOG, 0x1), /* disable watchdog */ ++ REG_SEQ0(PM88X_GPIO_CTRL1, 0x40), /* gpio1: dvc , gpio0: input */ ++ REG_SEQ0(PM88X_GPIO_CTRL2, 0x00), /* , gpio2: input */ ++ REG_SEQ0(PM88X_GPIO_CTRL3, 0x44), /* dvc2 , dvc1 */ ++ REG_SEQ0(PM88X_GPIO_CTRL4, 0x00), /* gpio5v_1:input, gpio5v_2: input*/ ++ REG_SEQ0(PM88X_AON_CTRL2, 0x2a), /* output 32kHZ from XO */ ++ REG_SEQ0(PM88X_BK_OSC_CTRL1, 0x0f), /* OSC_FREERUN = 1, to lock FLL */ ++ REG_SEQ0(PM88X_LOWPOWER2, 0x20), /* XO_LJ = 1, enable low jitter for 32kHZ */ + /* enable LPM for internal reference group in sleep */ +- {PM88X_LOWPOWER4, 0xc0}, +- {PM88X_BK_OSC_CTRL3, 0xc0}, /* set the duty cycle of charger DC/DC to max */ ++ REG_SEQ0(PM88X_LOWPOWER4, 0xc0), ++ REG_SEQ0(PM88X_BK_OSC_CTRL3, 0xc0), /* set the duty cycle of charger DC/DC to max */ + }; + +-static const struct reg_default pm886_power_patch[] = { ++static const struct reg_sequence pm886_power_patch[] = { + }; + +-static const struct reg_default pm886_gpadc_patch[] = { +- {PM88X_GPADC_CONFIG6, 0x03}, /* enable non-stop mode */ ++static const struct reg_sequence pm886_gpadc_patch[] = { ++ REG_SEQ0(PM88X_GPADC_CONFIG6, 0x03), /* enable non-stop mode */ + }; + +-static const struct reg_default pm886_battery_patch[] = { +- {PM88X_CHGBK_CONFIG6, 0xe1}, ++static const struct reg_sequence pm886_battery_patch[] = { ++ REG_SEQ0(PM88X_CHGBK_CONFIG6, 0xe1), + }; + +-static const struct reg_default pm886_test_patch[] = { ++static const struct reg_sequence pm886_test_patch[] = { + }; + + /* 88pm886 chip itself related */ +diff --git a/drivers/mfd/88pm88x-core.c b/drivers/mfd/88pm88x-core.c +index 343e0a0f3f8b..04409a2b0356 100644 +--- a/drivers/mfd/88pm88x-core.c ++++ b/drivers/mfd/88pm88x-core.c +@@ -342,7 +342,7 @@ int pm88x_init_pages(struct pm88x_chip *chip) + } + + /* power page */ +- chip->power_page = i2c_new_dummy(client->adapter, chip->power_page_addr); ++ chip->power_page = i2c_new_dummy_device(client->adapter, chip->power_page_addr); + if (!chip->power_page) { + dev_err(chip->dev, "Failed to new power_page: %d\n", ret); + ret = -ENODEV; +@@ -357,7 +357,7 @@ int pm88x_init_pages(struct pm88x_chip *chip) + } + + /* gpadc page */ +- chip->gpadc_page = i2c_new_dummy(client->adapter, chip->gpadc_page_addr); ++ chip->gpadc_page = i2c_new_dummy_device(client->adapter, chip->gpadc_page_addr); + if (!chip->gpadc_page) { + dev_err(chip->dev, "Failed to new gpadc_page: %d\n", ret); + ret = -ENODEV; +@@ -372,7 +372,7 @@ int pm88x_init_pages(struct pm88x_chip *chip) + } + + /* battery page */ +- chip->battery_page = i2c_new_dummy(client->adapter, chip->battery_page_addr); ++ chip->battery_page = i2c_new_dummy_device(client->adapter, chip->battery_page_addr); + if (!chip->battery_page) { + dev_err(chip->dev, "Failed to new gpadc_page: %d\n", ret); + ret = -ENODEV; +@@ -387,7 +387,7 @@ int pm88x_init_pages(struct pm88x_chip *chip) + } + + /* test page */ +- chip->test_page = i2c_new_dummy(client->adapter, chip->test_page_addr); ++ chip->test_page = i2c_new_dummy_device(client->adapter, chip->test_page_addr); + if (!chip->test_page) { + dev_err(chip->dev, "Failed to new test_page: %d\n", ret); + ret = -ENODEV; +@@ -416,7 +416,7 @@ int pm88x_init_pages(struct pm88x_chip *chip) + chip->ldo_regmap = chip->power_regmap; + + /* buck page */ +- chip->buck_page = i2c_new_dummy(client->adapter, ++ chip->buck_page = i2c_new_dummy_device(client->adapter, + chip->buck_page_addr); + if (!chip->buck_page) { + dev_err(chip->dev, "Failed to new buck_page: %d\n", ret); +diff --git a/drivers/mfd/88pm88x-i2c.c b/drivers/mfd/88pm88x-i2c.c +index 36842ed02e9a..7650014d9c90 100644 +--- a/drivers/mfd/88pm88x-i2c.c ++++ b/drivers/mfd/88pm88x-i2c.c +@@ -22,8 +22,7 @@ + #include + #include + +-static int pm88x_i2c_probe(struct i2c_client *client, +- const struct i2c_device_id *id) ++static int pm88x_i2c_probe(struct i2c_client *client) + { + struct pm88x_chip *chip; + struct device_node *node = client->dev.of_node; +@@ -104,11 +103,10 @@ static int pm88x_i2c_probe(struct i2c_client *client, + return ret; + } + +-static int pm88x_i2c_remove(struct i2c_client *i2c) ++static void pm88x_i2c_remove(struct i2c_client *i2c) + { + struct pm88x_chip *chip = dev_get_drvdata(&i2c->dev); + pm88x_dev_exit(chip); +- return 0; + } + + static const struct i2c_device_id pm88x_i2c_id[] = { +diff --git a/drivers/mfd/88pm88x-irq.c b/drivers/mfd/88pm88x-irq.c +index 0126df0231b8..ea9f6636e700 100644 +--- a/drivers/mfd/88pm88x-irq.c ++++ b/drivers/mfd/88pm88x-irq.c +@@ -131,9 +131,8 @@ struct regmap_irq_chip pm88x_irq_chip = { + + .num_regs = 4, + .status_base = PM88X_INT_STATUS1, +- .mask_base = PM88X_INT_ENA_1, ++ .unmask_base = PM88X_INT_ENA_1, + .ack_base = PM88X_INT_STATUS1, +- .mask_invert = 1, + }; + + int pm88x_irq_init(struct pm88x_chip *chip) +diff --git a/include/linux/mfd/88pm88x.h b/include/linux/mfd/88pm88x.h +index efa2fe621ccd..91a84b551d15 100644 +--- a/include/linux/mfd/88pm88x.h ++++ b/include/linux/mfd/88pm88x.h +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include "88pm88x-reg.h" + #include "88pm886-reg.h" + +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0018-DONOTMERGE-add-downstream-regulator-driver.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0018-DONOTMERGE-add-downstream-regulator-driver.patch new file mode 100644 index 000000000..5183496b5 --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0018-DONOTMERGE-add-downstream-regulator-driver.patch @@ -0,0 +1,2176 @@ +From 511728c3b8f0957fb0e6a3f31b447428c852dbc1 Mon Sep 17 00:00:00 2001 +From: Karel Balej +Date: Sun, 24 Sep 2023 12:40:26 +0200 +Subject: [PATCH] DONOTMERGE: add downstream regulator driver + +--- + drivers/regulator/88pm88x-buck.c | 714 ++++++++++++++++++++++++++++++ + drivers/regulator/88pm88x-ldo.c | 726 +++++++++++++++++++++++++++++++ + drivers/regulator/88pm88x-vr.c | 666 ++++++++++++++++++++++++++++ + drivers/regulator/Kconfig | 10 + + drivers/regulator/Makefile | 3 + + 5 files changed, 2119 insertions(+) + create mode 100644 drivers/regulator/88pm88x-buck.c + create mode 100644 drivers/regulator/88pm88x-ldo.c + create mode 100644 drivers/regulator/88pm88x-vr.c + +diff --git a/drivers/regulator/88pm88x-buck.c b/drivers/regulator/88pm88x-buck.c +new file mode 100644 +index 000000000000..7546e0fb9d87 +--- /dev/null ++++ b/drivers/regulator/88pm88x-buck.c +@@ -0,0 +1,714 @@ ++/* ++ * Buck driver for Marvell 88PM88X ++ * ++ * Copyright (C) 2014 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* max current in sleep */ ++#define MAX_SLEEP_CURRENT 5000 ++ ++/* BUCK enable2 register offset relative to enable1 register */ ++#define PM88X_BUCK_EN2_OFF (0x06) ++/* ------------- 88pm886 buck registers --------------- */ ++ ++/* buck voltage */ ++#define PM886_BUCK2_VOUT (0xb3) ++#define PM886_BUCK3_VOUT (0xc1) ++#define PM886_BUCK4_VOUT (0xcf) ++#define PM886_BUCK5_VOUT (0xdd) ++ ++/* set buck sleep voltage */ ++#define PM886_BUCK1_SET_SLP (0xa3) ++#define PM886_BUCK2_SET_SLP (0xb1) ++#define PM886_BUCK3_SET_SLP (0xbf) ++#define PM886_BUCK4_SET_SLP (0xcd) ++#define PM886_BUCK5_SET_SLP (0xdb) ++ ++/* control section */ ++#define PM886_BUCK_EN (0x08) ++ ++/* ------------- 88pm880 buck registers --------------- */ ++/* buck voltage */ ++#define PM880_BUCK2_VOUT (0x58) ++#define PM880_BUCK3_VOUT (0x70) ++#define PM880_BUCK4_VOUT (0x88) ++#define PM880_BUCK5_VOUT (0x98) ++#define PM880_BUCK6_VOUT (0xa8) ++ ++/* set buck sleep voltage */ ++#define PM880_BUCK1_SET_SLP (0x27) ++#define PM880_BUCK1A_SET_SLP (0x27) ++#define PM880_BUCK1B_SET_SLP (0x3c) ++ ++#define PM880_BUCK2_SET_SLP (0x56) ++#define PM880_BUCK3_SET_SLP (0x6e) ++#define PM880_BUCK4_SET_SLP (0x86) ++#define PM880_BUCK5_SET_SLP (0x96) ++#define PM880_BUCK6_SET_SLP (0xa6) ++#define PM880_BUCK7_SET_SLP (0xb6) ++ ++/* control section */ ++#define PM880_BUCK_EN (0x08) ++ ++/* ++ * vreg - the buck regs string. ++ * ebit - the bit number in the enable register. ++ * amax - the current ++ * Buck has 2 kinds of voltage steps. It is easy to find voltage by ranges, ++ * not the constant voltage table. ++ */ ++#define PM88X_BUCK(_pmic, vreg, ebit, amax, volt_ranges, n_volt, slp_en_msk, slp_en_off) \ ++{ \ ++ .desc = { \ ++ .name = #vreg, \ ++ .ops = &pm88x_volt_buck_ops, \ ++ .type = REGULATOR_VOLTAGE, \ ++ .id = _pmic##_ID_##vreg, \ ++ .owner = THIS_MODULE, \ ++ .n_voltages = n_volt, \ ++ .linear_ranges = volt_ranges, \ ++ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ ++ .vsel_reg = _pmic##_##vreg##_VOUT, \ ++ .vsel_mask = 0x7f, \ ++ .enable_reg = _pmic##_BUCK_EN, \ ++ .enable_mask = 1 << (ebit), \ ++ }, \ ++ .max_ua = (amax), \ ++ .sleep_vsel_reg = _pmic##_##vreg##_SET_SLP, \ ++ .sleep_vsel_mask = 0x7f, \ ++ .sleep_enable_reg = _pmic##_##vreg##_SLP_CTRL, \ ++ .sleep_enable_mask = (slp_en_msk << slp_en_off), \ ++ .sleep_enable_off = (slp_en_off), \ ++} ++ ++#define PM886_BUCK(vreg, ebit, amax, volt_ranges, n_volt) \ ++ PM88X_BUCK(PM886, vreg, ebit, amax, volt_ranges, n_volt, 0x3, 4) ++ ++#define PM880_BUCK(vreg, ebit, amax, volt_ranges, n_volt) \ ++ PM88X_BUCK(PM880, vreg, ebit, amax, volt_ranges, n_volt, 0x3, 4) ++ ++#define PM886_BUCK_AUDIO(vreg, ebit, amax, volt_ranges, n_volt) \ ++ PM88X_BUCK(PM886, vreg, ebit, amax, volt_ranges, n_volt, 0x1, 7) ++ ++#define PM880_BUCK_AUDIO(vreg, ebit, amax, volt_ranges, n_volt) \ ++ PM88X_BUCK(PM880, vreg, ebit, amax, volt_ranges, n_volt, 0x1, 7) ++ ++/* ++ * 88pm886 buck1 and 88pm880 buck1. both have dvc function ++ * from 0x00 to 0x4F: step is 12.5mV, range is from 0.6V to 1.6V ++ * from 0x50 to 0x3F step is 50mV, range is from 1.6V to 1.8V ++ */ ++static const struct regulator_linear_range buck_volt_range1[] = { ++ REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), ++ REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000), ++}; ++ ++/* ++ * 88pm886 buck 2-5, and 88pm880 buck 2-7 ++ * from 0x00 to 0x4F VOUT step is 12.5mV, range is from 0.6V to 1.6V ++ * from 0x50 to 0x72 step is 50mV, range is from 1.6V to 3.3V ++ */ ++static const struct regulator_linear_range buck_volt_range2[] = { ++ REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), ++ REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x72, 50000), ++}; ++ ++struct pm88x_buck_info { ++ struct regulator_desc desc; ++ int max_ua; ++ u8 sleep_enable_mask; ++ u8 sleep_enable_reg; ++ u8 sleep_enable_off; ++ u8 sleep_vsel_reg; ++ u8 sleep_vsel_mask; ++}; ++ ++struct pm88x_regulators { ++ struct regulator_dev *rdev; ++ struct pm88x_chip *chip; ++ struct regmap *map; ++}; ++ ++struct pm88x_buck_print { ++ char name[15]; ++ char enable[15]; ++ char slp_mode[15]; ++ char set_slp[15]; ++ char volt[10]; ++ char audio_en[15]; ++ char audio[10]; ++}; ++ ++struct pm88x_buck_extra { ++ const char *name; ++ bool dvc; ++ u8 audio_enable_reg; ++ u8 audio_enable_mask; ++ u8 audio_enable_off; ++ u8 audio_vsel_reg; ++ u8 audio_vsel_mask; ++}; ++ ++#define PM88X_BUCK_EXTRA(_name, _dvc, _areg, _amsk, _aoff, _vreg, _vmsk) \ ++{ \ ++ .name = _name, \ ++ .dvc = _dvc, \ ++ .audio_enable_reg = _areg, \ ++ .audio_enable_mask = _amsk, \ ++ .audio_enable_off = _aoff, \ ++ .audio_vsel_reg = _vreg, \ ++ .audio_vsel_mask = _vmsk \ ++} ++ ++static struct pm88x_buck_extra pm886_buck_extra_info[] = { ++ PM88X_BUCK_EXTRA("BUCK1", 1, 0xa4, 0x80, 0x07, 0xa4, 0x7f), ++ PM88X_BUCK_EXTRA("BUCK2", 0, 0xb2, 0x80, 0x07, 0xb2, 0x7f), ++ PM88X_BUCK_EXTRA("BUCK3", 0, 0xc0, 0x80, 0x07, 0xc0, 0x7f), ++ PM88X_BUCK_EXTRA("BUCK4", 0, 0, 0, 0, 0, 0), ++ PM88X_BUCK_EXTRA("BUCK5", 0, 0, 0, 0, 0, 0), ++}; ++ ++static struct pm88x_buck_extra pm880_buck_extra_info[] = { ++ PM88X_BUCK_EXTRA("BUCK1A", 1, 0x27, 0x80, 0x07, 0x27, 0x7f), ++ PM88X_BUCK_EXTRA("BUCK2", 0, 0x57, 0x80, 0x07, 0x57, 0x7f), ++ PM88X_BUCK_EXTRA("BUCK3", 0, 0x6f, 0x80, 0x07, 0x6f, 0x7f), ++ PM88X_BUCK_EXTRA("BUCK4", 0, 0, 0, 0, 0, 0), ++ PM88X_BUCK_EXTRA("BUCK5", 0, 0, 0, 0, 0, 0), ++ PM88X_BUCK_EXTRA("BUCK6", 0, 0, 0, 0, 0, 0), ++ PM88X_BUCK_EXTRA("BUCK7", 1, 0, 0, 0, 0, 0), ++}; ++ ++#define BUCK_OFF (0x0) ++#define BUCK_ACTIVE_VOLT_SLP (0x1) ++#define BUCK_SLP_VOLT_SLP (0x2) ++#define BUCK_ACTIVE_VOLT_ACTIVE (0x3) ++#define BUCK_AUDIO_MODE_EN (0x1) ++ ++int pm88x_buck_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode) ++{ ++ struct pm88x_buck_info *info = rdev_get_drvdata(rdev); ++ u8 val; ++ int ret, rid; ++ ++ if (!info) ++ return -EINVAL; ++ ++ rid = rdev_get_id(rdev); ++ /* we enabled buck1 audio mode enable/disable for 88pm886 and 88pm880 */ ++ if (rid == PM880_ID_BUCK1A) { ++ switch (mode) { ++ case REGULATOR_MODE_NORMAL: ++ val = 0; ++ break; ++ case REGULATOR_MODE_IDLE: ++ val = BUCK_AUDIO_MODE_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } else { ++ switch (mode) { ++ case REGULATOR_MODE_NORMAL: ++ /* regulator will be active with normal voltage */ ++ val = BUCK_ACTIVE_VOLT_ACTIVE; ++ break; ++ case REGULATOR_MODE_IDLE: ++ /* regulator will be in sleep with sleep voltage */ ++ val = BUCK_SLP_VOLT_SLP; ++ break; ++ case REGULATOR_MODE_STANDBY: ++ /* regulator will be off */ ++ val = BUCK_OFF; ++ break; ++ default: ++ /* regulator will be active with sleep voltage */ ++ val = BUCK_ACTIVE_VOLT_SLP; ++ break; ++ } ++ } ++ ++ ret = regmap_update_bits(rdev->regmap, info->sleep_enable_reg, ++ info->sleep_enable_mask, (val << info->sleep_enable_off)); ++ return ret; ++} ++ ++static unsigned int pm88x_buck_get_optimum_mode(struct regulator_dev *rdev, ++ int input_uV, int output_uV, ++ int output_uA) ++{ ++ struct pm88x_buck_info *info = rdev_get_drvdata(rdev); ++ if (!info) ++ return REGULATOR_MODE_IDLE; ++ ++ if (output_uA < 0) { ++ dev_err(rdev_get_dev(rdev), "current needs to be > 0.\n"); ++ return REGULATOR_MODE_IDLE; ++ } ++ ++ return (output_uA < MAX_SLEEP_CURRENT) ? ++ REGULATOR_MODE_IDLE : REGULATOR_MODE_NORMAL; ++} ++ ++static int pm88x_buck_get_current_limit(struct regulator_dev *rdev) ++{ ++ struct pm88x_buck_info *info = rdev_get_drvdata(rdev); ++ if (!info) ++ return 0; ++ return info->max_ua; ++} ++ ++static int pm88x_buck_set_suspend_voltage(struct regulator_dev *rdev, int uv) ++{ ++ int ret, sel; ++ struct pm88x_buck_info *info = rdev_get_drvdata(rdev); ++ if (!info || !info->desc.ops) ++ return -EINVAL; ++ if (!info->desc.ops->set_suspend_mode) ++ return 0; ++ /* ++ * two steps: ++ * 1) set the suspend voltage to *_set_slp registers ++ * 2) set regulator mode via set_suspend_mode() interface to enable output ++ */ ++ /* the suspend voltage mapping is the same as active */ ++ sel = regulator_map_voltage_linear_range(rdev, uv, uv); ++ if (sel < 0) ++ return -EINVAL; ++ ++ sel <<= ffs(info->sleep_vsel_mask) - 1; ++ ++ ret = regmap_update_bits(rdev->regmap, info->sleep_vsel_reg, ++ info->sleep_vsel_mask, sel); ++ if (ret < 0) ++ return -EINVAL; ++ ++ /* TODO: do we need this? */ ++ ret = pm88x_buck_set_suspend_mode(rdev, REGULATOR_MODE_IDLE); ++ return ret; ++} ++ ++/* ++ * about the get_optimum_mode()/set_suspend_mode()/set_suspend_voltage() interface: ++ * - 88pm88x has two sets of registers to set and enable/disable regulators ++ * in active and suspend(sleep) status: ++ * the following focues on the sleep part: ++ * - there are two control bits: 00-disable, ++ * 01/10-use sleep voltage, ++ * 11-use active voltage, ++ *- in most of the scenario, these registers are configured when the whole PMIC ++ * initialized, when the system enters into suspend(sleep) mode, the regulator ++ * works according to the setting or disabled; ++ *- there is also case that the device driver needs to: ++ * - set the sleep voltage; ++ * - choose to use sleep voltage or active voltage depends on the load; ++ * so: ++ * set_suspend_voltage() is used to manipulate the registers to set sleep volt; ++ * set_suspend_mode() is used to switch between sleep voltage and active voltage ++ * get_optimum_mode() is used to get right mode ++ */ ++static struct regulator_ops pm88x_volt_buck_ops = { ++ .list_voltage = regulator_list_voltage_linear_range, ++ .map_voltage = regulator_map_voltage_linear_range, ++ .set_voltage_sel = regulator_set_voltage_sel_regmap, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .enable = regulator_enable_regmap, ++ .disable = regulator_disable_regmap, ++ .is_enabled = regulator_is_enabled_regmap, ++ .get_current_limit = pm88x_buck_get_current_limit, ++ .get_optimum_mode = pm88x_buck_get_optimum_mode, ++ .set_suspend_mode = pm88x_buck_set_suspend_mode, ++ .set_suspend_voltage = pm88x_buck_set_suspend_voltage, ++}; ++ ++/* The array is indexed by id(PM886_ID_BUCK*) */ ++static struct pm88x_buck_info pm886_buck_configs[] = { ++ PM886_BUCK(BUCK1, 0, 3000000, buck_volt_range1, 0x55), ++ PM886_BUCK(BUCK2, 1, 1200000, buck_volt_range2, 0x73), ++ PM886_BUCK(BUCK3, 2, 1200000, buck_volt_range2, 0x73), ++ PM886_BUCK(BUCK4, 3, 1200000, buck_volt_range2, 0x73), ++ PM886_BUCK(BUCK5, 4, 1200000, buck_volt_range2, 0x73), ++}; ++ ++/* The array is indexed by id(PM880_ID_BUCK*) */ ++static struct pm88x_buck_info pm880_buck_configs[] = { ++ PM880_BUCK_AUDIO(BUCK1A, 0, 3000000, buck_volt_range1, 0x55), ++ PM880_BUCK(BUCK2, 2, 1200000, buck_volt_range2, 0x73), ++ PM880_BUCK(BUCK3, 3, 1200000, buck_volt_range2, 0x73), ++ PM880_BUCK(BUCK4, 4, 1200000, buck_volt_range2, 0x73), ++ PM880_BUCK(BUCK5, 5, 1200000, buck_volt_range2, 0x73), ++ PM880_BUCK(BUCK6, 6, 1200000, buck_volt_range2, 0x73), ++ PM880_BUCK(BUCK7, 7, 1200000, buck_volt_range2, 0x73), ++}; ++ ++#define PM88X_BUCK_OF_MATCH(_pmic, id, comp, label) \ ++ { \ ++ .compatible = comp, \ ++ .data = &_pmic##_buck_configs[id##_##label], \ ++ } ++#define PM886_BUCK_OF_MATCH(comp, label) \ ++ PM88X_BUCK_OF_MATCH(pm886, PM886_ID, comp, label) ++ ++#define PM880_BUCK_OF_MATCH(comp, label) \ ++ PM88X_BUCK_OF_MATCH(pm880, PM880_ID, comp, label) ++ ++static const struct of_device_id pm88x_bucks_of_match[] = { ++ PM886_BUCK_OF_MATCH("marvell,88pm886-buck1", BUCK1), ++ PM886_BUCK_OF_MATCH("marvell,88pm886-buck2", BUCK2), ++ PM886_BUCK_OF_MATCH("marvell,88pm886-buck3", BUCK3), ++ PM886_BUCK_OF_MATCH("marvell,88pm886-buck4", BUCK4), ++ PM886_BUCK_OF_MATCH("marvell,88pm886-buck5", BUCK5), ++ ++ PM880_BUCK_OF_MATCH("marvell,88pm880-buck1a", BUCK1A), ++ PM880_BUCK_OF_MATCH("marvell,88pm880-buck2", BUCK2), ++ PM880_BUCK_OF_MATCH("marvell,88pm880-buck3", BUCK3), ++ PM880_BUCK_OF_MATCH("marvell,88pm880-buck4", BUCK4), ++ PM880_BUCK_OF_MATCH("marvell,88pm880-buck5", BUCK5), ++ PM880_BUCK_OF_MATCH("marvell,88pm880-buck6", BUCK6), ++ PM880_BUCK_OF_MATCH("marvell,88pm880-buck7", BUCK7), ++}; ++ ++/* ++ * The function convert the buck voltage register value ++ * to a real voltage value (in uV) according to the voltage table. ++ */ ++static int pm88x_get_vbuck_vol(unsigned int val, struct pm88x_buck_info *info) ++{ ++ const struct regulator_linear_range *range; ++ int i, volt = -EINVAL; ++ ++ /* get the voltage via the register value */ ++ for (i = 0; i < info->desc.n_linear_ranges; i++) { ++ range = &info->desc.linear_ranges[i]; ++ if (!range) ++ return -EINVAL; ++ ++ if (val >= range->min_sel && val <= range->max_sel) { ++ volt = (val - range->min_sel) * range->uV_step + range->min_uV; ++ break; ++ } ++ } ++ return volt; ++} ++ ++/* The function check if the regulator register is configured to enable/disable */ ++static int pm88x_check_en(struct pm88x_chip *chip, unsigned int reg, unsigned int mask, ++ unsigned int reg2) ++{ ++ struct regmap *map = chip->buck_regmap; ++ int ret, value; ++ unsigned int enable1, enable2; ++ ++ ret = regmap_read(map, reg, &enable1); ++ if (ret < 0) ++ return ret; ++ ++ ret = regmap_read(map, reg2, &enable2); ++ if (ret < 0) ++ return ret; ++ ++ value = (enable1 | enable2) & mask; ++ ++ return value; ++} ++ ++/* The function check the regulator sleep mode as configured in his register */ ++static int pm88x_check_slp_mode(struct regmap *map, unsigned int reg, int off) ++{ ++ int ret; ++ unsigned int slp_mode; ++ ++ ret = regmap_read(map, reg, &slp_mode); ++ if (ret < 0) ++ return ret; ++ ++ slp_mode = (slp_mode >> off) & 0x3; ++ ++ return slp_mode; ++} ++ ++/* The function return the value in the regulator voltage register */ ++static unsigned int pm88x_check_vol(struct regmap *map, unsigned int reg, unsigned int mask) ++{ ++ int ret; ++ unsigned int vol_val; ++ ++ ret = regmap_bulk_read(map, reg, &vol_val, 1); ++ if (ret < 0) ++ return ret; ++ ++ /* mask and shift the relevant value from the register */ ++ vol_val = (vol_val & mask) >> (ffs(mask) - 1); ++ ++ return vol_val; ++} ++ ++static int pm88x_update_print(struct pm88x_chip *chip, struct pm88x_buck_info *info, ++ struct pm88x_buck_extra *extra, struct pm88x_buck_print *print_temp, ++ int index, int buck_num) ++{ ++ int ret, volt; ++ struct regmap *map = chip->buck_regmap; ++ char *slp_mode_str[] = {"off", "active_slp", "sleep", "active"}; ++ int slp_mode_num = ARRAY_SIZE(slp_mode_str); ++ ++ sprintf(print_temp->name, "%s", info[index].desc.name); ++ ++ /* check enable/disable */ ++ ret = pm88x_check_en(chip, info[index].desc.enable_reg, info[index].desc.enable_mask, ++ info[index].desc.enable_reg + PM88X_BUCK_EN2_OFF); ++ if (ret < 0) ++ return ret; ++ else if (ret) ++ strcpy(print_temp->enable, "enable"); ++ else ++ strcpy(print_temp->enable, "disable"); ++ ++ if (!strcmp(print_temp->name, "BUCK1A")) { ++ sprintf(print_temp->slp_mode, " VR"); ++ sprintf(print_temp->set_slp, " VR"); ++ } else { ++ /* check sleep mode */ ++ ret = pm88x_check_slp_mode(map, info[index].sleep_enable_reg, ++ info[index].sleep_enable_off); ++ if (ret < 0) ++ return ret; ++ if (ret < slp_mode_num) ++ strcpy(print_temp->slp_mode, slp_mode_str[ret]); ++ else ++ strcpy(print_temp->slp_mode, "unknown"); ++ ++ /* print sleep voltage */ ++ ret = pm88x_check_vol(map, info[index].sleep_vsel_reg, info[index].sleep_vsel_mask); ++ if (ret < 0) ++ return ret; ++ ++ volt = pm88x_get_vbuck_vol(ret, &info[index]); ++ if (volt < 0) ++ return volt; ++ else ++ sprintf(print_temp->set_slp, "%4d", volt/1000); ++ } ++ ++ /* print active voltage(s) */ ++ if (extra[index].dvc) { ++ sprintf(print_temp->volt, " DVC "); ++ } else { ++ ret = pm88x_check_vol(map, info[index].desc.vsel_reg, ++ info[index].desc.vsel_mask); ++ if (ret < 0) ++ return ret; ++ ++ volt = pm88x_get_vbuck_vol(ret, &info[index]); ++ if (volt < 0) ++ return volt; ++ else ++ sprintf(print_temp->volt, "%4d", volt/1000); ++ } ++ ++ /* print audio voltage */ ++ if (extra[index].audio_enable_reg) { ++ ret = pm88x_check_en(chip, extra[index].audio_enable_reg, ++ extra[index].audio_enable_mask, ++ extra[index].audio_enable_reg); ++ if (ret < 0) ++ return ret; ++ else if (ret) ++ strcpy(print_temp->audio_en, "enable"); ++ else ++ strcpy(print_temp->audio_en, "disable"); ++ ++ ret = pm88x_check_vol(map, extra[index].audio_vsel_reg, ++ extra[index].audio_vsel_mask); ++ if (ret < 0) ++ return ret; ++ ++ volt = pm88x_get_vbuck_vol(ret, &info[index]); ++ if (volt < 0) ++ return volt; ++ else ++ sprintf(print_temp->audio, "%4d", volt/1000); ++ } else { ++ strcpy(print_temp->audio_en, " - "); ++ sprintf(print_temp->audio, " -"); ++ } ++ ++ return 0; ++} ++ ++int pm88x_display_buck(struct pm88x_chip *chip, char *buf) ++{ ++ struct pm88x_buck_print *print_temp; ++ struct pm88x_buck_info *info; ++ struct pm88x_buck_extra *extra; ++ int buck_num, i, len = 0; ++ ssize_t ret; ++ ++ switch (chip->type) { ++ case PM886: ++ info = pm886_buck_configs; ++ extra = pm886_buck_extra_info; ++ buck_num = ARRAY_SIZE(pm886_buck_configs); ++ break; ++ case PM880: ++ info = pm880_buck_configs; ++ extra = pm880_buck_extra_info; ++ buck_num = ARRAY_SIZE(pm880_buck_configs); ++ break; ++ default: ++ pr_err("%s: Cannot find chip type.\n", __func__); ++ return -ENODEV; ++ } ++ ++ print_temp = kmalloc(sizeof(struct pm88x_buck_print), GFP_KERNEL); ++ if (!print_temp) { ++ pr_err("%s: Cannot allocate print template.\n", __func__); ++ return -ENOMEM; ++ } ++ ++ len += sprintf(buf + len, "\nBUCK"); ++ len += sprintf(buf + len, "\n-----------------------------------"); ++ len += sprintf(buf + len, "-------------------------------------\n"); ++ len += sprintf(buf + len, "| name | status | slp_mode |slp_volt"); ++ len += sprintf(buf + len, "| volt | audio_en| audio |\n"); ++ len += sprintf(buf + len, "------------------------------------"); ++ len += sprintf(buf + len, "------------------------------------\n"); ++ ++ for (i = 0; i < buck_num; i++) { ++ ret = pm88x_update_print(chip, info, extra, print_temp, i, buck_num); ++ if (ret < 0) { ++ pr_err("Print of regulator %s failed\n", print_temp->name); ++ goto out_print; ++ } ++ len += sprintf(buf + len, "| %-8s |", print_temp->name); ++ len += sprintf(buf + len, " %-7s |", print_temp->enable); ++ len += sprintf(buf + len, " %-10s|", print_temp->slp_mode); ++ len += sprintf(buf + len, " %-5s |", print_temp->set_slp); ++ len += sprintf(buf + len, " %-5s |", print_temp->volt); ++ len += sprintf(buf + len, " %-7s |", print_temp->audio_en); ++ len += sprintf(buf + len, " %-5s |\n", print_temp->audio); ++ } ++ ++ len += sprintf(buf + len, "------------------------------------"); ++ len += sprintf(buf + len, "------------------------------------\n"); ++ ++ ret = len; ++out_print: ++ kfree(print_temp); ++ return ret; ++} ++ ++static int pm88x_buck_probe(struct platform_device *pdev) ++{ ++ struct pm88x_chip *chip = dev_get_drvdata(pdev->dev.parent); ++ struct pm88x_regulators *data; ++ struct regulator_config config = { }; ++ struct regulator_init_data *init_data; ++ struct regulation_constraints *c; ++ const struct of_device_id *match; ++ const struct pm88x_buck_info *const_info; ++ struct pm88x_buck_info *info; ++ int ret; ++ ++ match = of_match_device(pm88x_bucks_of_match, &pdev->dev); ++ if (match) { ++ const_info = match->data; ++ init_data = of_get_regulator_init_data(&pdev->dev, ++ pdev->dev.of_node); ++ } else { ++ dev_err(&pdev->dev, "parse dts fails!\n"); ++ return -EINVAL; ++ } ++ ++ info = kmemdup(const_info, sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(struct pm88x_regulators), ++ GFP_KERNEL); ++ if (!data) { ++ dev_err(&pdev->dev, "failed to allocate pm88x_regualtors"); ++ return -ENOMEM; ++ } ++ data->map = chip->buck_regmap; ++ data->chip = chip; ++ ++ /* add regulator config */ ++ config.dev = &pdev->dev; ++ config.init_data = init_data; ++ config.driver_data = info; ++ config.regmap = data->map; ++ config.of_node = pdev->dev.of_node; ++ ++ data->rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); ++ if (IS_ERR(data->rdev)) { ++ dev_err(&pdev->dev, "cannot register %s\n", info->desc.name); ++ ret = PTR_ERR(data->rdev); ++ return ret; ++ } ++ ++ c = data->rdev->constraints; ++ c->valid_ops_mask |= REGULATOR_CHANGE_DRMS | REGULATOR_CHANGE_MODE ++ | REGULATOR_CHANGE_VOLTAGE; ++ c->valid_modes_mask |= REGULATOR_MODE_NORMAL ++ | REGULATOR_MODE_IDLE; ++ c->input_uV = 1000; ++ ++ platform_set_drvdata(pdev, data); ++ ++ return 0; ++} ++ ++static int pm88x_buck_remove(struct platform_device *pdev) ++{ ++ struct pm88x_regulators *data = platform_get_drvdata(pdev); ++ devm_kfree(&pdev->dev, data); ++ return 0; ++} ++ ++static struct platform_driver pm88x_buck_driver = { ++ .driver = { ++ .name = "88pm88x-buck", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(pm88x_bucks_of_match), ++ }, ++ .probe = pm88x_buck_probe, ++ .remove = pm88x_buck_remove, ++}; ++ ++static int pm88x_buck_init(void) ++{ ++ return platform_driver_register(&pm88x_buck_driver); ++} ++subsys_initcall(pm88x_buck_init); ++ ++static void pm88x_buck_exit(void) ++{ ++ platform_driver_unregister(&pm88x_buck_driver); ++} ++module_exit(pm88x_buck_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Yi Zhang"); ++MODULE_DESCRIPTION("Buck for Marvell 88PM88X PMIC"); ++MODULE_ALIAS("platform:88pm88x-buck"); +diff --git a/drivers/regulator/88pm88x-ldo.c b/drivers/regulator/88pm88x-ldo.c +new file mode 100644 +index 000000000000..d2bf731e2dcc +--- /dev/null ++++ b/drivers/regulator/88pm88x-ldo.c +@@ -0,0 +1,726 @@ ++/* ++ * LDO driver for Marvell 88PM88X ++ * ++ * Copyright (C) 2014 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* max current in sleep */ ++#define MAX_SLEEP_CURRENT 5000 ++ ++/* ------------- 88pm886 ldo registers --------------- */ ++/* control section */ ++#define PM886_LDO_EN1 (0x09) ++#define PM886_LDO_EN2 (0x0a) ++ ++/* LDO enable2 register offset relative to enable1 register */ ++#define PM88X_LDO_EN2_OFF (0x06) ++ ++/* ++ * 88pm886 ldo voltage: ++ * ldox_set_slp[7: 4] ldox_set [3: 0] ++ */ ++#define PM886_LDO1_VOUT (0x20) ++#define PM886_LDO2_VOUT (0x26) ++#define PM886_LDO3_VOUT (0x2c) ++#define PM886_LDO4_VOUT (0x32) ++#define PM886_LDO5_VOUT (0x38) ++#define PM886_LDO6_VOUT (0x3e) ++#define PM886_LDO7_VOUT (0x44) ++#define PM886_LDO8_VOUT (0x4a) ++#define PM886_LDO9_VOUT (0x50) ++#define PM886_LDO10_VOUT (0x56) ++#define PM886_LDO11_VOUT (0x5c) ++#define PM886_LDO12_VOUT (0x62) ++#define PM886_LDO13_VOUT (0x68) ++#define PM886_LDO14_VOUT (0x6e) ++#define PM886_LDO15_VOUT (0x74) ++#define PM886_LDO16_VOUT (0x7a) ++ ++/* ------------- 88pm880 ldo registers --------------- */ ++/* control section */ ++#define PM880_LDO_EN1 (0x09) ++#define PM880_LDO_EN2 (0x0a) ++#define PM880_LDO_EN3 (0x0b) ++ ++/* ++ * 88pm880 ldo voltage: ++ * ldox_set_slp[7: 4] ldox_set [3: 0] ++ */ ++#define PM880_LDO1_VOUT (0x20) ++#define PM880_LDO2_VOUT (0x26) ++#define PM880_LDO3_VOUT (0x2c) ++#define PM880_LDO4_VOUT (0x32) ++#define PM880_LDO5_VOUT (0x38) ++#define PM880_LDO6_VOUT (0x3e) ++#define PM880_LDO7_VOUT (0x44) ++#define PM880_LDO8_VOUT (0x4a) ++#define PM880_LDO9_VOUT (0x50) ++#define PM880_LDO10_VOUT (0x56) ++#define PM880_LDO11_VOUT (0x5c) ++#define PM880_LDO12_VOUT (0x62) ++#define PM880_LDO13_VOUT (0x68) ++#define PM880_LDO14_VOUT (0x6e) ++#define PM880_LDO15_VOUT (0x74) ++#define PM880_LDO16_VOUT (0x7a) ++#define PM880_LDO17_VOUT (0x80) ++#define PM880_LDO18_VOUT (0x86) ++ ++/* ++ * set ldo sleep voltage register is the same as the active registers; ++ * only the mask is not the same: ++ * bit [7 : 4] --> to set sleep voltage ++ * bit [3 : 0] --> to set active voltage ++ * no need to give definition here ++ */ ++ ++/* ++ * vreg - the LDO regs string ++ * ebit - the bit number in the enable register. ++ * ereg - the enable register ++ * amax - the current ++ * volt_table - the LDO voltage table ++ * For all the LDOes, there are too many ranges. Using volt_table will be ++ * simpler and faster. ++ */ ++#define PM88X_LDO(_pmic, vreg, ereg, ebit, amax, ldo_volt_table) \ ++{ \ ++ .desc = { \ ++ .name = #vreg, \ ++ .ops = &pm88x_volt_ldo_ops, \ ++ .type = REGULATOR_VOLTAGE, \ ++ .id = _pmic##_ID_##vreg, \ ++ .owner = THIS_MODULE, \ ++ .n_voltages = ARRAY_SIZE(ldo_volt_table), \ ++ .vsel_reg = _pmic##_##vreg##_VOUT, \ ++ .vsel_mask = 0xf, \ ++ .enable_reg = _pmic##_LDO_##ereg, \ ++ .enable_mask = 1 << (ebit), \ ++ .volt_table = ldo_volt_table, \ ++ }, \ ++ .max_ua = (amax), \ ++ .sleep_vsel_reg = _pmic##_##vreg##_VOUT, \ ++ .sleep_vsel_mask = (0xf << 4), \ ++ .sleep_enable_reg = _pmic##_##vreg##_SLP_CTRL, \ ++ .sleep_enable_mask = (0x3 << 4), \ ++} ++ ++#define PM886_LDO(vreg, ereg, ebit, amax, ldo_volt_table) \ ++ PM88X_LDO(PM886, vreg, ereg, ebit, amax, ldo_volt_table) ++ ++#define PM880_LDO(vreg, ereg, ebit, amax, ldo_volt_table) \ ++ PM88X_LDO(PM880, vreg, ereg, ebit, amax, ldo_volt_table) ++ ++/* 88pm886 ldo1~3, 88pm880 ldo1-3 */ ++static const unsigned int ldo_volt_table1[] = { ++ 1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000, ++}; ++/* 88pm886 ldo4~15, 88pm880 ldo4-17 */ ++static const unsigned int ldo_volt_table2[] = { ++ 1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000, ++ 2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000, ++}; ++/* 88pm886 ldo16, 88pm880 ldo18 */ ++static const unsigned int ldo_volt_table3[] = { ++ 1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000, ++}; ++ ++struct pm88x_ldo_info { ++ struct regulator_desc desc; ++ int max_ua; ++ u8 sleep_enable_mask; ++ u8 sleep_enable_reg; ++ u8 sleep_vsel_reg; ++ u8 sleep_vsel_mask; ++}; ++ ++struct pm88x_ldos { ++ struct regulator_dev *rdev; ++ struct pm88x_chip *chip; ++ struct regmap *map; ++}; ++ ++struct pm88x_ldo_print { ++ char name[15]; ++ char enable[15]; ++ char slp_mode[15]; ++ char set_slp[15]; ++ char volt[10]; ++ char audio_en[15]; ++ char audio[10]; ++}; ++ ++struct pm88x_ldo_extra { ++ const char *name; ++ u8 audio_enable_reg; ++ u8 audio_enable_mask; ++ u8 audio_enable_off; ++ u8 audio_vsel_reg; ++ u8 audio_vsel_mask; ++}; ++ ++#define PM88X_LDO_EXTRA(_name, _areg, _amsk, _aoff, _vreg, _vmsk) \ ++{ \ ++ .name = _name, \ ++ .audio_enable_reg = _areg, \ ++ .audio_enable_mask = _amsk, \ ++ .audio_enable_off = _aoff, \ ++ .audio_vsel_reg = _vreg, \ ++ .audio_vsel_mask = _vmsk \ ++} ++ ++static struct pm88x_ldo_extra pm88x_ldo_extra_info[] = { ++ PM88X_LDO_EXTRA("LDO2", 0x28, 0x10, 0x04, 0x28, 0x0f), ++}; ++ ++#define LDO_OFF (0x0 << 4) ++#define LDO_ACTIVE_VOLT_SLP (0x1 << 4) ++#define LDO_SLP_VOLT_SLP (0x2 << 4) ++#define LDO_ACTIVE_VOLT_ACTIVE (0x3 << 4) ++ ++int pm88x_ldo_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode) ++{ ++ struct pm88x_ldo_info *info = rdev_get_drvdata(rdev); ++ u8 val; ++ int ret; ++ ++ if (!info) ++ return -EINVAL; ++ ++ switch (mode) { ++ case REGULATOR_MODE_NORMAL: ++ /* regulator will be active with normal voltage */ ++ val = LDO_ACTIVE_VOLT_ACTIVE; ++ break; ++ case REGULATOR_MODE_IDLE: ++ /* regulator will be in sleep with sleep voltage */ ++ val = LDO_SLP_VOLT_SLP; ++ break; ++ case REGULATOR_MODE_STANDBY: ++ /* regulator will be off */ ++ val = LDO_OFF; ++ break; ++ default: ++ /* regulator will be active with sleep voltage */ ++ val = LDO_ACTIVE_VOLT_SLP; ++ break; ++ } ++ ++ ret = regmap_update_bits(rdev->regmap, info->sleep_enable_reg, ++ info->sleep_enable_mask, val); ++ return ret; ++} ++ ++static unsigned int pm88x_ldo_get_optimum_mode(struct regulator_dev *rdev, ++ int input_uV, int output_uV, ++ int output_uA) ++{ ++ struct pm88x_ldo_info *info = rdev_get_drvdata(rdev); ++ if (!info) ++ return REGULATOR_MODE_IDLE; ++ ++ if (output_uA < 0) { ++ dev_err(rdev_get_dev(rdev), "current needs to be > 0.\n"); ++ return REGULATOR_MODE_IDLE; ++ } ++ ++ return (output_uA < MAX_SLEEP_CURRENT) ? ++ REGULATOR_MODE_IDLE : REGULATOR_MODE_NORMAL; ++} ++ ++static int pm88x_ldo_get_current_limit(struct regulator_dev *rdev) ++{ ++ struct pm88x_ldo_info *info = rdev_get_drvdata(rdev); ++ if (!info) ++ return 0; ++ return info->max_ua; ++} ++ ++static int pm88x_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uv) ++{ ++ int ret, sel; ++ struct pm88x_ldo_info *info = rdev_get_drvdata(rdev); ++ if (!info || !info->desc.ops) ++ return -EINVAL; ++ if (!info->desc.ops->set_suspend_mode) ++ return 0; ++ /* ++ * two steps: ++ * 1) set the suspend voltage to *_set_slp registers ++ * 2) set regulator mode via set_suspend_mode() interface to enable output ++ */ ++ /* the suspend voltage mapping is the same as active */ ++ sel = regulator_map_voltage_iterate(rdev, uv, uv); ++ if (sel < 0) ++ return -EINVAL; ++ ++ sel <<= ffs(info->sleep_vsel_mask) - 1; ++ ++ ret = regmap_update_bits(rdev->regmap, info->sleep_vsel_reg, ++ info->sleep_vsel_mask, sel); ++ if (ret < 0) ++ return -EINVAL; ++ ++ /* TODO: do we need this? */ ++ ret = pm88x_ldo_set_suspend_mode(rdev, REGULATOR_MODE_IDLE); ++ return ret; ++} ++ ++/* ++ * about the get_optimum_mode()/set_suspend_mode()/set_suspend_voltage() interface: ++ * - 88pm88x has two sets of registers to set and enable/disable regulators ++ * in active and suspend(sleep) status: ++ * the following focues on the sleep part: ++ * - there are two control bits: 00-disable, ++ * 01/10-use sleep voltage, ++ * 11-use active voltage, ++ *- in most of the scenario, these registers are configured when the whole PMIC ++ * initialized, when the system enters into suspend(sleep) mode, the regulator ++ * works according to the setting or disabled; ++ *- there is also case that the device driver needs to: ++ * - set the sleep voltage; ++ * - choose to use sleep voltage or active voltage depends on the load; ++ * so: ++ * set_suspend_voltage() is used to manipulate the registers to set sleep volt; ++ * set_suspend_mode() is used to switch between sleep voltage and active voltage ++ * get_optimum_mode() is used to get right mode ++ */ ++static struct regulator_ops pm88x_volt_ldo_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ .map_voltage = regulator_map_voltage_iterate, ++ .set_voltage_sel = regulator_set_voltage_sel_regmap, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .enable = regulator_enable_regmap, ++ .disable = regulator_disable_regmap, ++ .is_enabled = regulator_is_enabled_regmap, ++ .get_current_limit = pm88x_ldo_get_current_limit, ++ .get_optimum_mode = pm88x_ldo_get_optimum_mode, ++ .set_suspend_mode = pm88x_ldo_set_suspend_mode, ++ .set_suspend_voltage = pm88x_ldo_set_suspend_voltage, ++}; ++ ++/* The array is indexed by id(PM886_ID_LDO*) */ ++static struct pm88x_ldo_info pm886_ldo_configs[] = { ++ /* 88pm886 ldo */ ++ PM886_LDO(LDO1, EN1, 0, 100000, ldo_volt_table1), ++ PM886_LDO(LDO2, EN1, 1, 100000, ldo_volt_table1), ++ PM886_LDO(LDO3, EN1, 2, 100000, ldo_volt_table1), ++ PM886_LDO(LDO4, EN1, 3, 400000, ldo_volt_table2), ++ PM886_LDO(LDO5, EN1, 4, 400000, ldo_volt_table2), ++ PM886_LDO(LDO6, EN1, 5, 400000, ldo_volt_table2), ++ PM886_LDO(LDO7, EN1, 6, 400000, ldo_volt_table2), ++ PM886_LDO(LDO8, EN1, 7, 400000, ldo_volt_table2), ++ PM886_LDO(LDO9, EN2, 0, 400000, ldo_volt_table2), ++ PM886_LDO(LDO10, EN2, 1, 200000, ldo_volt_table2), ++ PM886_LDO(LDO11, EN2, 2, 200000, ldo_volt_table2), ++ PM886_LDO(LDO12, EN2, 3, 200000, ldo_volt_table2), ++ PM886_LDO(LDO13, EN2, 4, 200000, ldo_volt_table2), ++ PM886_LDO(LDO14, EN2, 5, 200000, ldo_volt_table2), ++ PM886_LDO(LDO15, EN2, 6, 200000, ldo_volt_table2), ++ PM886_LDO(LDO16, EN2, 7, 200000, ldo_volt_table3), ++}; ++ ++/* The array is indexed by id(PM880_ID_LDO*) */ ++static struct pm88x_ldo_info pm880_ldo_configs[] = { ++ /* 88pm880 ldo */ ++ PM880_LDO(LDO1, EN1, 0, 100000, ldo_volt_table1), ++ PM880_LDO(LDO2, EN1, 1, 100000, ldo_volt_table1), ++ PM880_LDO(LDO3, EN1, 2, 100000, ldo_volt_table1), ++ PM880_LDO(LDO4, EN1, 3, 400000, ldo_volt_table2), ++ PM880_LDO(LDO5, EN1, 4, 400000, ldo_volt_table2), ++ PM880_LDO(LDO6, EN1, 5, 400000, ldo_volt_table2), ++ PM880_LDO(LDO7, EN1, 6, 400000, ldo_volt_table2), ++ PM880_LDO(LDO8, EN1, 7, 400000, ldo_volt_table2), ++ PM880_LDO(LDO9, EN2, 0, 400000, ldo_volt_table2), ++ PM880_LDO(LDO10, EN2, 1, 200000, ldo_volt_table2), ++ PM880_LDO(LDO11, EN2, 2, 200000, ldo_volt_table2), ++ PM880_LDO(LDO12, EN2, 3, 200000, ldo_volt_table2), ++ PM880_LDO(LDO13, EN2, 4, 200000, ldo_volt_table2), ++ PM880_LDO(LDO14, EN2, 5, 200000, ldo_volt_table2), ++ PM880_LDO(LDO15, EN2, 6, 200000, ldo_volt_table2), ++ PM880_LDO(LDO16, EN2, 7, 200000, ldo_volt_table2), ++ PM880_LDO(LDO17, EN3, 0, 200000, ldo_volt_table2), ++ PM880_LDO(LDO18, EN3, 1, 200000, ldo_volt_table3), ++}; ++ ++#define PM88X_LDO_OF_MATCH(_pmic, id, comp, label) \ ++ { \ ++ .compatible = comp, \ ++ .data = &_pmic##_ldo_configs[id##_##label], \ ++ } ++ ++#define PM886_LDO_OF_MATCH(comp, label) \ ++ PM88X_LDO_OF_MATCH(pm886, PM886_ID, comp, label) ++ ++#define PM880_LDO_OF_MATCH(comp, label) \ ++ PM88X_LDO_OF_MATCH(pm880, PM880_ID, comp, label) ++ ++static const struct of_device_id pm88x_ldos_of_match[] = { ++ /* 88pm886 */ ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo1", LDO1), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo2", LDO2), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo3", LDO3), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo4", LDO4), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo5", LDO5), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo6", LDO6), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo7", LDO7), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo8", LDO8), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo9", LDO9), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo10", LDO10), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo11", LDO11), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo12", LDO12), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo13", LDO13), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo14", LDO14), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo15", LDO15), ++ PM886_LDO_OF_MATCH("marvell,88pm886-ldo16", LDO16), ++ /* 88pm880 */ ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo1", LDO1), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo2", LDO2), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo3", LDO3), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo4", LDO4), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo5", LDO5), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo6", LDO6), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo7", LDO7), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo8", LDO8), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo9", LDO9), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo10", LDO10), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo11", LDO11), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo12", LDO12), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo13", LDO13), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo14", LDO14), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo15", LDO15), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo16", LDO16), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo17", LDO17), ++ PM880_LDO_OF_MATCH("marvell,88pm880-ldo18", LDO18), ++}; ++ ++/* ++ * The function convert the ldo voltage register value ++ * to a real voltage value (in uV) according to the voltage table. ++ */ ++static int pm88x_get_vldo_vol(unsigned int val, struct pm88x_ldo_info *info) ++{ ++ int volt = -EINVAL; ++ ++ /* get the voltage via the register value */ ++ volt = info->desc.volt_table[val]; ++ return volt; ++} ++ ++/* The function check if the regulator register is configured to enable/disable */ ++static int pm88x_check_en(struct pm88x_chip *chip, unsigned int reg, unsigned int mask, ++ unsigned int reg2) ++{ ++ struct regmap *map = chip->ldo_regmap; ++ int ret, value; ++ unsigned int enable1, enable2; ++ ++ ret = regmap_read(map, reg, &enable1); ++ if (ret < 0) ++ return ret; ++ ++ ret = regmap_read(map, reg2, &enable2); ++ if (ret < 0) ++ return ret; ++ ++ value = (enable1 | enable2) & mask; ++ ++ return value; ++} ++ ++/* The function check the regulator sleep mode as configured in his register */ ++static int pm88x_check_slp_mode(struct regmap *map, unsigned int reg, int mask) ++{ ++ int ret; ++ unsigned int slp_mode; ++ ++ ret = regmap_read(map, reg, &slp_mode); ++ if (ret < 0) ++ return ret; ++ ++ slp_mode = (slp_mode & mask) >> (ffs(mask) - 1); ++ ++ return slp_mode; ++} ++ ++/* The function return the value in the regulator voltage register */ ++static unsigned int pm88x_check_vol(struct regmap *map, unsigned int reg, unsigned int mask) ++{ ++ int ret; ++ unsigned int vol_val; ++ ++ ret = regmap_bulk_read(map, reg, &vol_val, 1); ++ if (ret < 0) ++ return ret; ++ ++ /* mask and shift the relevant value from the register */ ++ vol_val = (vol_val & mask) >> (ffs(mask) - 1); ++ ++ return vol_val; ++} ++ ++static int pm88x_update_print(struct pm88x_chip *chip, struct pm88x_ldo_info *info, ++ struct pm88x_ldo_extra *extra, struct pm88x_ldo_print *print_temp, ++ int index, int ldo_num, int extra_info_num) ++{ ++ int i, ret, volt, flag = 0; ++ struct regmap *map = chip->ldo_regmap; ++ char *slp_mode_str[] = {"off", "active_slp", "sleep", "active"}; ++ int slp_mode_num = sizeof(slp_mode_str)/sizeof(slp_mode_str[0]); ++ ++ sprintf(print_temp->name, "%s", info[index].desc.name); ++ ++ /* check enable/disable */ ++ ret = pm88x_check_en(chip, info[index].desc.enable_reg, info[index].desc.enable_mask, ++ info[index].desc.enable_reg + PM88X_LDO_EN2_OFF); ++ if (ret < 0) ++ return ret; ++ else if (ret) ++ strcpy(print_temp->enable, "enable"); ++ else ++ strcpy(print_temp->enable, "disable"); ++ ++ /* check sleep mode */ ++ ret = pm88x_check_slp_mode(map, info[index].sleep_enable_reg, ++ info[index].sleep_enable_mask); ++ if (ret < 0) ++ return ret; ++ if (ret < slp_mode_num) ++ strcpy(print_temp->slp_mode, slp_mode_str[ret]); ++ else ++ strcpy(print_temp->slp_mode, "unknown"); ++ ++ /* print sleep voltage */ ++ ret = pm88x_check_vol(map, info[index].sleep_vsel_reg, info[index].sleep_vsel_mask); ++ if (ret < 0) ++ return ret; ++ ++ volt = pm88x_get_vldo_vol(ret, &info[index]); ++ if (volt < 0) ++ return volt; ++ else ++ sprintf(print_temp->set_slp, "%4d", volt/1000); ++ ++ /* print active voltage(s) */ ++ ret = pm88x_check_vol(map, info[index].desc.vsel_reg, ++ info[index].desc.vsel_mask); ++ if (ret < 0) ++ return ret; ++ ++ volt = pm88x_get_vldo_vol(ret, &info[index]); ++ if (volt < 0) ++ return volt; ++ else ++ sprintf(print_temp->volt, "%4d", volt/1000); ++ ++ for (i = 0; i < extra_info_num; i++) { ++ /* print audio voltage */ ++ if (!strcmp(print_temp->name, extra[i].name) && extra[i].audio_enable_reg) { ++ ret = pm88x_check_en(chip, extra[i].audio_enable_reg, ++ extra[i].audio_enable_mask, ++ extra[i].audio_enable_reg); ++ if (ret < 0) ++ return ret; ++ else if (ret) ++ strcpy(print_temp->audio_en, "enable"); ++ else ++ strcpy(print_temp->audio_en, "disable"); ++ ret = pm88x_check_vol(map, extra[i].audio_vsel_reg, ++ extra[i].audio_vsel_mask); ++ if (ret < 0) ++ return ret; ++ ++ volt = pm88x_get_vldo_vol(ret, &info[index]); ++ if (volt < 0) ++ return volt; ++ else ++ sprintf(print_temp->audio, "%4d", volt/1000); ++ flag = 1; ++ } ++ } ++ if (!flag) { ++ strcpy(print_temp->audio_en, " - "); ++ sprintf(print_temp->audio, " -"); ++ flag = 0; ++ } ++ return 0; ++} ++ ++int pm88x_display_ldo(struct pm88x_chip *chip, char *buf) ++{ ++ struct pm88x_ldo_print *print_temp; ++ struct pm88x_ldo_info *info; ++ struct pm88x_ldo_extra *extra; ++ int ldo_num, extra_info_num, i, len = 0; ++ ssize_t ret; ++ ++ switch (chip->type) { ++ case PM886: ++ info = pm886_ldo_configs; ++ ldo_num = sizeof(pm886_ldo_configs) / sizeof(pm886_ldo_configs[0]); ++ extra = pm88x_ldo_extra_info; ++ extra_info_num = sizeof(pm88x_ldo_extra_info) / sizeof(pm88x_ldo_extra_info[0]); ++ break; ++ case PM880: ++ info = pm880_ldo_configs; ++ ldo_num = sizeof(pm880_ldo_configs) / sizeof(pm880_ldo_configs[0]); ++ extra = pm88x_ldo_extra_info; ++ extra_info_num = sizeof(pm88x_ldo_extra_info) / sizeof(pm88x_ldo_extra_info[0]); ++ break; ++ default: ++ pr_err("%s: Cannot find chip type.\n", __func__); ++ return -ENODEV; ++ } ++ ++ print_temp = kmalloc(sizeof(struct pm88x_ldo_print), GFP_KERNEL); ++ if (!print_temp) { ++ pr_err("%s: Cannot allocate print template.\n", __func__); ++ return -ENOMEM; ++ } ++ ++ len += sprintf(buf + len, "\nLDO"); ++ len += sprintf(buf + len, "\n-----------------------------------"); ++ len += sprintf(buf + len, "-------------------------------------\n"); ++ len += sprintf(buf + len, "| name | status | slp_mode |slp_volt"); ++ len += sprintf(buf + len, "| volt | audio_en| audio |\n"); ++ len += sprintf(buf + len, "------------------------------------"); ++ len += sprintf(buf + len, "------------------------------------\n"); ++ ++ for (i = 0; i < ldo_num; i++) { ++ ret = pm88x_update_print(chip, info, extra, print_temp, i, ldo_num, extra_info_num); ++ if (ret < 0) { ++ pr_err("Print of regulator %s failed\n", print_temp->name); ++ goto out_print; ++ } ++ len += sprintf(buf + len, "| %-8s |", print_temp->name); ++ len += sprintf(buf + len, " %-7s |", print_temp->enable); ++ len += sprintf(buf + len, " %-10s|", print_temp->slp_mode); ++ len += sprintf(buf + len, " %-5s |", print_temp->set_slp); ++ len += sprintf(buf + len, " %-5s |", print_temp->volt); ++ len += sprintf(buf + len, " %-7s |", print_temp->audio_en); ++ len += sprintf(buf + len, " %-5s |\n", print_temp->audio); ++ } ++ ++ len += sprintf(buf + len, "------------------------------------"); ++ len += sprintf(buf + len, "------------------------------------\n"); ++ ++ ret = len; ++out_print: ++ kfree(print_temp); ++ return ret; ++} ++ ++static int pm88x_ldo_probe(struct platform_device *pdev) ++{ ++ struct pm88x_chip *chip = dev_get_drvdata(pdev->dev.parent); ++ struct pm88x_ldos *data; ++ struct regulator_config config = { }; ++ struct regulator_init_data *init_data; ++ struct regulation_constraints *c; ++ const struct of_device_id *match; ++ const struct pm88x_ldo_info *const_info; ++ struct pm88x_ldo_info *info; ++ int ret; ++ ++ match = of_match_device(pm88x_ldos_of_match, &pdev->dev); ++ if (match) { ++ const_info = match->data; ++ init_data = of_get_regulator_init_data(&pdev->dev, ++ pdev->dev.of_node); ++ } else { ++ dev_err(&pdev->dev, "parse dts fails!\n"); ++ return -EINVAL; ++ } ++ ++ info = kmemdup(const_info, sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(struct pm88x_ldos), ++ GFP_KERNEL); ++ if (!data) { ++ dev_err(&pdev->dev, "failed to allocate pm88x_regualtors"); ++ return -ENOMEM; ++ } ++ data->map = chip->ldo_regmap; ++ data->chip = chip; ++ ++ /* add regulator config */ ++ config.dev = &pdev->dev; ++ config.init_data = init_data; ++ config.driver_data = info; ++ config.regmap = data->map; ++ config.of_node = pdev->dev.of_node; ++ ++ data->rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); ++ if (IS_ERR(data->rdev)) { ++ dev_err(&pdev->dev, "cannot register %s\n", info->desc.name); ++ ret = PTR_ERR(data->rdev); ++ return ret; ++ } ++ ++ c = data->rdev->constraints; ++ c->valid_ops_mask |= REGULATOR_CHANGE_DRMS | REGULATOR_CHANGE_MODE ++ | REGULATOR_CHANGE_VOLTAGE; ++ c->valid_modes_mask |= REGULATOR_MODE_NORMAL ++ | REGULATOR_MODE_IDLE; ++ c->input_uV = 1000; ++ ++ platform_set_drvdata(pdev, data); ++ ++ return 0; ++} ++ ++static int pm88x_ldo_remove(struct platform_device *pdev) ++{ ++ struct pm88x_ldos *data = platform_get_drvdata(pdev); ++ devm_kfree(&pdev->dev, data); ++ return 0; ++} ++ ++static struct platform_driver pm88x_ldo_driver = { ++ .driver = { ++ .name = "88pm88x-ldo", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(pm88x_ldos_of_match), ++ }, ++ .probe = pm88x_ldo_probe, ++ .remove = pm88x_ldo_remove, ++}; ++ ++static int pm88x_ldo_init(void) ++{ ++ return platform_driver_register(&pm88x_ldo_driver); ++} ++subsys_initcall(pm88x_ldo_init); ++ ++static void pm88x_ldo_exit(void) ++{ ++ platform_driver_unregister(&pm88x_ldo_driver); ++} ++module_exit(pm88x_ldo_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Yi Zhang"); ++MODULE_DESCRIPTION("LDO Driver for Marvell 88PM88X PMIC"); ++MODULE_ALIAS("platform:88pm88x-ldo"); +diff --git a/drivers/regulator/88pm88x-vr.c b/drivers/regulator/88pm88x-vr.c +new file mode 100644 +index 000000000000..2175859b8727 +--- /dev/null ++++ b/drivers/regulator/88pm88x-vr.c +@@ -0,0 +1,666 @@ ++/* ++ * virtual regulator driver for Marvell 88PM88X ++ * ++ * Copyright (C) 2015 Marvell International Ltd. ++ * Yi Zhang ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PM88X_VR_EN (0x28) ++ ++#define PM886_BUCK1_SLP_VOUT (0xa3) ++#define PM886_BUCK1_SLP_EN (0xa2) ++ ++#define PM880_BUCK1A_SLP_VOUT (0x26) ++#define PM880_BUCK1A_SLP_EN (0x24) ++#define PM880_BUCK1B_SLP_VOUT (0x3e) ++#define PM880_BUCK1B_SLP_EN (0x3c) ++ ++#define PM880_BUCK1A_AUDIO_VOUT (0x27) ++#define PM880_BUCK1A_AUDIO_EN (0x27) ++#define PM880_BUCK1B_AUDIO_EN (0x3f) ++#define PM880_BUCK1B_AUDIO_VOUT (0x3f) ++ ++#define PM88X_VR(vreg, ebit, nr) \ ++{ \ ++ .desc = { \ ++ .name = #vreg, \ ++ .ops = &pm88x_virtual_regulator_ops, \ ++ .type = REGULATOR_VOLTAGE, \ ++ .id = PM88X##_ID_##vreg, \ ++ .owner = THIS_MODULE, \ ++ .enable_reg = PM88X##_VR_EN, \ ++ .enable_mask = 1 << (ebit), \ ++ }, \ ++ .page_nr = nr, \ ++} ++ ++#define PM88X_BUCK_SLP(_pmic, vreg, ebit, nr, volt_ranges, n_volt) \ ++{ \ ++ .desc = { \ ++ .name = #vreg, \ ++ .ops = &pm88x_buck_slp_ops, \ ++ .type = REGULATOR_VOLTAGE, \ ++ .id = _pmic##_ID_##vreg, \ ++ .owner = THIS_MODULE, \ ++ .n_voltages = n_volt, \ ++ .linear_ranges = volt_ranges, \ ++ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ ++ .vsel_reg = _pmic##_##vreg##_VOUT, \ ++ .vsel_mask = 0x7f, \ ++ .enable_reg = _pmic##_##vreg##_EN, \ ++ .enable_mask = (0x3) << (ebit), \ ++ }, \ ++ .page_nr = nr, \ ++} ++ ++#define PM88X_BUCK_AUDIO(_pmic, vreg, ebit, nr, volt_ranges, n_volt) \ ++{ \ ++ .desc = { \ ++ .name = #vreg, \ ++ .ops = &pm88x_buck_audio_ops, \ ++ .type = REGULATOR_VOLTAGE, \ ++ .id = _pmic##_ID_##vreg, \ ++ .owner = THIS_MODULE, \ ++ .n_voltages = n_volt, \ ++ .linear_ranges = volt_ranges, \ ++ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ ++ .vsel_reg = _pmic##_##vreg##_VOUT, \ ++ .vsel_mask = 0x7f, \ ++ .enable_reg = _pmic##_##vreg##_EN, \ ++ .enable_mask = (0x1) << (ebit), \ ++ }, \ ++ .page_nr = nr, \ ++} ++ ++#define PM880_BUCK_SLP(vreg, ebit, nr, volt_ranges, n_volt) \ ++ PM88X_BUCK_SLP(PM880, vreg, ebit, nr, volt_ranges, n_volt) ++ ++#define PM886_BUCK_SLP(vreg, ebit, nr, volt_ranges, n_volt) \ ++ PM88X_BUCK_SLP(PM886, vreg, ebit, nr, volt_ranges, n_volt) ++ ++#define PM880_BUCK_AUDIO(vreg, ebit, nr, volt_ranges, n_volt) \ ++ PM88X_BUCK_AUDIO(PM880, vreg, ebit, nr, volt_ranges, n_volt) ++ ++#define PM88X_VR_OF_MATCH(comp, label) \ ++ { \ ++ .compatible = comp, \ ++ .data = &pm88x_vr_configs[PM88X_ID##_##label], \ ++ } ++ ++#define PM88X_BUCK_SLP_OF_MATCH(_pmic, id, comp, label) \ ++ { \ ++ .compatible = comp, \ ++ .data = &_pmic##_buck_slp_configs[id##_##label], \ ++ } ++ ++#define PM88X_BUCK_AUDIO_OF_MATCH(_pmic, id, comp, label) \ ++ { \ ++ .compatible = comp, \ ++ .data = &_pmic##_buck_audio_configs[id##_##label], \ ++ } ++ ++#define PM880_BUCK_SLP_OF_MATCH(comp, label) \ ++ PM88X_BUCK_SLP_OF_MATCH(pm880, PM880_ID, comp, label) ++ ++#define PM886_BUCK_SLP_OF_MATCH(comp, label) \ ++ PM88X_BUCK_SLP_OF_MATCH(pm886, PM886_ID, comp, label) ++ ++#define PM880_BUCK_AUDIO_OF_MATCH(comp, label) \ ++ PM88X_BUCK_AUDIO_OF_MATCH(pm880, PM880_ID, comp, label) ++ ++static const struct regulator_linear_range buck_slp_volt_range1[] = { ++ REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), ++ REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000), ++}; ++ ++static const struct regulator_linear_range buck_audio_volt_range1[] = { ++ REGULATOR_LINEAR_RANGE(600000, 0, 0x54, 12500), ++}; ++ ++struct pm88x_vr_info { ++ struct regulator_desc desc; ++ unsigned int page_nr; ++}; ++ ++struct pm88x_buck_slp_info { ++ struct regulator_desc desc; ++ unsigned int page_nr; ++}; ++ ++struct pm88x_buck_audio_info { ++ struct regulator_desc desc; ++ unsigned int page_nr; ++}; ++ ++struct pm88x_regulators { ++ struct regulator_dev *rdev; ++ struct pm88x_chip *chip; ++ struct regmap *map; ++}; ++ ++struct pm88x_vr_print { ++ char name[15]; ++ char enable[15]; ++ char slp_mode[15]; ++ char set_slp[15]; ++ char volt[10]; ++ char audio_en[15]; ++ char audio[10]; ++}; ++ ++static struct regulator_ops pm88x_virtual_regulator_ops = { ++ .enable = regulator_enable_regmap, ++ .disable = regulator_disable_regmap, ++ .is_enabled = regulator_is_enabled_regmap, ++}; ++ ++static int pm88x_buck_slp_enable(struct regulator_dev *rdev) ++{ ++ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, ++ rdev->desc->enable_mask, 0x2); ++} ++ ++static int pm88x_buck_slp_disable(struct regulator_dev *rdev) ++{ ++ dev_info(&rdev->dev, "%s: this buck is _off_ in suspend.\n", __func__); ++ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, ++ rdev->desc->enable_mask, 0x0); ++} ++ ++static int pm88x_buck_slp_is_enabled(struct regulator_dev *rdev) ++{ ++ unsigned int val; ++ int ret; ++ ++ ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); ++ if (ret != 0) ++ return ret; ++ ++ return !!((val & rdev->desc->enable_mask) == (0x2 << 5)); ++} ++ ++static int pm88x_buck_slp_map_voltage(struct regulator_dev *rdev, ++ int min_uV, int max_uV) ++{ ++ /* use higest voltage */ ++ if (max_uV >= 1600000) ++ return 0x50 + (max_uV - 1600000) / 50000; ++ else ++ return (max_uV - 600000) / 12500; ++ ++ return -EINVAL; ++} ++ ++static struct regulator_ops pm88x_buck_slp_ops = { ++ .enable = pm88x_buck_slp_enable, ++ .disable = pm88x_buck_slp_disable, ++ .is_enabled = pm88x_buck_slp_is_enabled, ++ .set_voltage_sel = regulator_set_voltage_sel_regmap, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .list_voltage = regulator_list_voltage_linear_range, ++ .map_voltage = pm88x_buck_slp_map_voltage, ++}; ++ ++static int pm88x_buck_audio_enable(struct regulator_dev *rdev) ++{ ++ dev_info(&rdev->dev, "%s is empty.\n", __func__); ++ return 0; ++} ++ ++static int pm88x_buck_audio_disable(struct regulator_dev *rdev) ++{ ++ dev_info(&rdev->dev, "%s is empty.\n", __func__); ++ return 0; ++} ++ ++static int pm88x_buck_audio_is_enabled(struct regulator_dev *rdev) ++{ ++ dev_info(&rdev->dev, "%s is empty.\n", __func__); ++ return 0; ++} ++ ++static struct regulator_ops pm88x_buck_audio_ops = { ++ .enable = pm88x_buck_audio_enable, ++ .disable = pm88x_buck_audio_disable, ++ .is_enabled = pm88x_buck_audio_is_enabled, ++ .set_voltage_sel = regulator_set_voltage_sel_regmap, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .list_voltage = regulator_list_voltage_linear_range, ++}; ++ ++static struct pm88x_vr_info pm88x_vr_configs[] = { ++ PM88X_VR(VOTG, 7, 3), ++}; ++ ++static struct pm88x_buck_slp_info pm880_buck_slp_configs[] = { ++ PM880_BUCK_SLP(BUCK1A_SLP, 4, 4, buck_slp_volt_range1, 0x55), ++ PM880_BUCK_SLP(BUCK1B_SLP, 4, 4, buck_slp_volt_range1, 0x55), ++}; ++ ++static struct pm88x_buck_slp_info pm886_buck_slp_configs[] = { ++ PM886_BUCK_SLP(BUCK1_SLP, 4, 1, buck_slp_volt_range1, 0x55), ++}; ++ ++static struct pm88x_buck_audio_info pm880_buck_audio_configs[] = { ++ PM880_BUCK_AUDIO(BUCK1A_AUDIO, 7, 4, buck_audio_volt_range1, 0x50), ++ PM880_BUCK_AUDIO(BUCK1B_AUDIO, 7, 4, buck_audio_volt_range1, 0x50), ++}; ++ ++static const struct of_device_id pm88x_vrs_of_match[] = { ++ PM88X_VR_OF_MATCH("marvell,88pm88x-votg", VOTG), ++ ++ PM886_BUCK_SLP_OF_MATCH("marvell,88pm886-buck1-slp", BUCK1_SLP), ++ ++ PM880_BUCK_SLP_OF_MATCH("marvell,88pm880-buck1a-slp", BUCK1A_SLP), ++ PM880_BUCK_SLP_OF_MATCH("marvell,88pm880-buck1b-slp", BUCK1B_SLP), ++ ++ PM880_BUCK_AUDIO_OF_MATCH("marvell,88pm880-buck1a-audio", BUCK1A_AUDIO), ++ PM880_BUCK_AUDIO_OF_MATCH("marvell,88pm880-buck1b-audio", BUCK1B_AUDIO), ++}; ++ ++static struct regmap *nr_to_regmap(struct pm88x_chip *chip, unsigned int nr) ++{ ++ switch (nr) { ++ case 0: ++ return chip->base_regmap; ++ case 1: ++ return chip->ldo_regmap; ++ case 2: ++ return chip->gpadc_regmap; ++ case 3: ++ return chip->battery_regmap; ++ case 4: ++ return chip->buck_regmap; ++ case 7: ++ return chip->test_regmap; ++ default: ++ pr_err("unsupported pages.\n"); ++ return NULL; ++ } ++} ++ ++static int of_get_legacy_init_data(struct device *dev, ++ struct regulator_init_data **init_data) ++{ ++ struct device_node *node = dev->of_node; ++ struct regulator_consumer_supply *consumer_supplies; ++ int len, num, ret, i; ++ ++ len = of_property_count_strings(node, "marvell,consumer-supplies"); ++ if (len <= 0) ++ return 0; ++ ++ /* format: marvell,consumer-supplies = "supply-name", "dev-name" */ ++ if (len % 2 != 0) { ++ dev_err(dev, ++ "format should be: marvell,consumer-supplies = supply-name, dev-name\n"); ++ ++ return -EINVAL; ++ } ++ ++ num = len / 2; ++ consumer_supplies = devm_kzalloc(dev, ++ sizeof(struct regulator_consumer_supply) * num, ++ GFP_KERNEL); ++ if (!consumer_supplies) { ++ dev_err(dev, "alloc memory fails.\n"); ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < num; i++) { ++ ret = of_property_read_string_index(node, ++ "marvell,consumer-supplies", ++ i * 2, ++ &consumer_supplies[i].supply); ++ if (ret) { ++ dev_err(dev, "read property fails.\n"); ++ devm_kfree(dev, consumer_supplies); ++ return ret; ++ } ++ ++ ret = of_property_read_string_index(node, ++ "marvell,consumer-supplies", ++ i * 2 + 1, ++ &consumer_supplies[i].dev_name); ++ if (ret) { ++ dev_err(dev, "read property fails.\n"); ++ devm_kfree(dev, consumer_supplies); ++ return ret; ++ } ++ ++ if (!strcmp((consumer_supplies[i].dev_name), "nameless")) ++ consumer_supplies[i].dev_name = NULL; ++ ++ } ++ ++ (*init_data)->consumer_supplies = consumer_supplies; ++ (*init_data)->num_consumer_supplies = num; ++ ++ return 0; ++} ++ ++/* ++ * The function convert the vr voltage register value ++ * to a real voltage value (in uV) according to the voltage table. ++ */ ++static int pm88x_get_vvr_vol(unsigned int val, unsigned int n_linear_ranges, ++ const struct regulator_linear_range *ranges) ++{ ++ const struct regulator_linear_range *range; ++ int i, volt = -EINVAL; ++ ++ /* get the voltage via the register value */ ++ for (i = 0; i < n_linear_ranges; i++) { ++ range = &ranges[i]; ++ if (!range) ++ return -EINVAL; ++ ++ if (val >= range->min_sel && val <= range->max_sel) { ++ volt = (val - range->min_sel) * range->uV_step + range->min_uV; ++ break; ++ } ++ } ++ return volt; ++} ++ ++/* The function check if the regulator register is configured to enable/disable */ ++static int pm88x_check_en(struct regmap *map, unsigned int reg, unsigned int mask) ++{ ++ int ret, value; ++ unsigned int enable1; ++ ++ ret = regmap_read(map, reg, &enable1); ++ if (ret < 0) ++ return ret; ++ ++ value = enable1 & mask; ++ ++ return value; ++} ++ ++/* The function return the value in the regulator voltage register */ ++static unsigned int pm88x_check_vol(struct regmap *map, unsigned int reg, unsigned int mask) ++{ ++ int ret; ++ unsigned int vol_val; ++ ++ ret = regmap_bulk_read(map, reg, &vol_val, 1); ++ if (ret < 0) ++ return ret; ++ ++ /* mask and shift the relevant value from the register */ ++ vol_val = (vol_val & mask) >> (ffs(mask) - 1); ++ ++ return vol_val; ++} ++ ++static int pm88x_update_print(struct pm88x_chip *chip, struct regmap *map, ++ struct regulator_desc *desc, struct pm88x_vr_print *print_temp, ++ int index, int num) ++{ ++ int ret, volt; ++ ++ sprintf(print_temp->name, "%s", desc->name); ++ ++ /* check enable/disable */ ++ ret = pm88x_check_en(map, desc->enable_reg, desc->enable_mask); ++ if (ret < 0) ++ return ret; ++ else if (ret) ++ strcpy(print_temp->enable, "enable"); ++ else ++ strcpy(print_temp->enable, "disable"); ++ ++ /* no sleep mode */ ++ strcpy(print_temp->slp_mode, " -"); ++ ++ /* no sleep voltage */ ++ sprintf(print_temp->set_slp, " -"); ++ ++ /* print active voltage(s) */ ++ ret = pm88x_check_vol(map, desc->vsel_reg, desc->vsel_mask); ++ if (ret < 0) ++ return ret; ++ ++ if (desc->n_linear_ranges) { ++ volt = pm88x_get_vvr_vol(ret, desc->n_linear_ranges, desc->linear_ranges); ++ if (volt < 0) ++ return volt; ++ else ++ sprintf(print_temp->volt, "%4d", volt/1000); ++ } else { ++ sprintf(print_temp->volt, " -"); ++ } ++ /* no audio mode*/ ++ strcpy(print_temp->audio_en, " - "); ++ sprintf(print_temp->audio, " -"); ++ ++ return 0; ++} ++ ++int pm88x_display_vr(struct pm88x_chip *chip, char *buf) ++{ ++ struct pm88x_vr_print *print_temp; ++ struct pm88x_buck_slp_info *slp_info = NULL; ++ struct pm88x_buck_audio_info *audio_info = NULL; ++ struct pm88x_vr_info *vr_info = NULL; ++ struct regmap *map; ++ int slp_num, audio_num, vr_num, i, len = 0; ++ ssize_t ret; ++ ++ switch (chip->type) { ++ case PM886: ++ slp_info = pm886_buck_slp_configs; ++ slp_num = ARRAY_SIZE(pm886_buck_slp_configs); ++ vr_info = pm88x_vr_configs; ++ vr_num = ARRAY_SIZE(pm88x_vr_configs); ++ break; ++ case PM880: ++ slp_info = pm880_buck_slp_configs; ++ slp_num = ARRAY_SIZE(pm880_buck_slp_configs); ++ audio_info = pm880_buck_audio_configs; ++ audio_num = ARRAY_SIZE(pm880_buck_audio_configs); ++ vr_info = pm88x_vr_configs; ++ vr_num = ARRAY_SIZE(pm88x_vr_configs); ++ break; ++ default: ++ pr_err("%s: Cannot find chip type.\n", __func__); ++ return -ENODEV; ++ } ++ ++ print_temp = kmalloc(sizeof(struct pm88x_vr_print), GFP_KERNEL); ++ if (!print_temp) { ++ pr_err("%s: Cannot allocate print template.\n", __func__); ++ return -ENOMEM; ++ } ++ ++ len += sprintf(buf + len, "\nVirtual Regulator"); ++ len += sprintf(buf + len, "\n------------------------------------"); ++ len += sprintf(buf + len, "--------------------------------------\n"); ++ len += sprintf(buf + len, "| name | status | slp_mode |slp_volt"); ++ len += sprintf(buf + len, "| volt | audio_en| audio |\n"); ++ len += sprintf(buf + len, "-------------------------------------"); ++ len += sprintf(buf + len, "-------------------------------------\n"); ++ ++ if (slp_info) { ++ map = nr_to_regmap(chip, slp_info->page_nr); ++ for (i = 0; i < slp_num; i++) { ++ ret = pm88x_update_print(chip, map, &slp_info[i].desc, ++ print_temp, i, slp_num); ++ if (ret < 0) { ++ pr_err("Print of regulator %s failed\n", print_temp->name); ++ goto out_print; ++ } ++ len += sprintf(buf + len, "|%-12s|", print_temp->name); ++ len += sprintf(buf + len, " %-7s |", print_temp->enable); ++ len += sprintf(buf + len, " %-10s|", print_temp->slp_mode); ++ len += sprintf(buf + len, " %-5s |", print_temp->set_slp); ++ len += sprintf(buf + len, " %-5s |", print_temp->volt); ++ len += sprintf(buf + len, " %-7s |", print_temp->audio_en); ++ len += sprintf(buf + len, " %-5s |\n", print_temp->audio); ++ } ++ } ++ ++ if (audio_info) { ++ map = nr_to_regmap(chip, audio_info->page_nr); ++ for (i = 0; i < audio_num; i++) { ++ ret = pm88x_update_print(chip, map, &audio_info[i].desc, ++ print_temp, i, audio_num); ++ if (ret < 0) { ++ pr_err("Print of regulator %s failed\n", print_temp->name); ++ goto out_print; ++ } ++ len += sprintf(buf + len, "|%-12s|", print_temp->name); ++ len += sprintf(buf + len, " %-7s |", print_temp->enable); ++ len += sprintf(buf + len, " %-10s|", print_temp->slp_mode); ++ len += sprintf(buf + len, " %-5s |", print_temp->set_slp); ++ len += sprintf(buf + len, " %-5s |", print_temp->volt); ++ len += sprintf(buf + len, " %-7s |", print_temp->audio_en); ++ len += sprintf(buf + len, " %-5s |\n", print_temp->audio); ++ } ++ } ++ ++ if (vr_info) { ++ map = nr_to_regmap(chip, vr_info->page_nr); ++ for (i = 0; i < vr_num; i++) { ++ ret = pm88x_update_print(chip, map, &vr_info[i].desc, ++ print_temp, i, vr_num); ++ if (ret < 0) { ++ pr_err("Print of regulator %s failed\n", print_temp->name); ++ goto out_print; ++ } ++ len += sprintf(buf + len, "|%-12s|", print_temp->name); ++ len += sprintf(buf + len, " %-7s |", print_temp->enable); ++ len += sprintf(buf + len, " %-10s|", print_temp->slp_mode); ++ len += sprintf(buf + len, " %-5s |", print_temp->set_slp); ++ len += sprintf(buf + len, " %-5s |", print_temp->volt); ++ len += sprintf(buf + len, " %-7s |", print_temp->audio_en); ++ len += sprintf(buf + len, " %-5s |\n", print_temp->audio); ++ } ++ } ++ ++ len += sprintf(buf + len, "-------------------------------------"); ++ len += sprintf(buf + len, "-------------------------------------\n"); ++ ++ ret = len; ++out_print: ++ kfree(print_temp); ++ return ret; ++} ++ ++static int pm88x_virtual_regulator_probe(struct platform_device *pdev) ++{ ++ struct pm88x_chip *chip = dev_get_drvdata(pdev->dev.parent); ++ struct pm88x_regulators *data; ++ struct regulator_config config = { }; ++ struct regulator_init_data *init_data; ++ struct regulation_constraints *c; ++ const struct of_device_id *match; ++ const struct pm88x_vr_info *const_info; ++ struct pm88x_vr_info *info; ++ int ret; ++ ++ match = of_match_device(pm88x_vrs_of_match, &pdev->dev); ++ if (match) { ++ const_info = match->data; ++ init_data = of_get_regulator_init_data(&pdev->dev, ++ pdev->dev.of_node); ++ ret = of_get_legacy_init_data(&pdev->dev, &init_data); ++ if (ret < 0) ++ return ret; ++ } else { ++ dev_err(&pdev->dev, "parse dts fails!\n"); ++ return -EINVAL; ++ } ++ ++ info = kmemdup(const_info, sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(struct pm88x_regulators), ++ GFP_KERNEL); ++ if (!data) { ++ dev_err(&pdev->dev, "failed to allocate pm88x_regualtors"); ++ return -ENOMEM; ++ } ++ data->map = nr_to_regmap(chip, info->page_nr); ++ data->chip = chip; ++ ++ /* add regulator config */ ++ config.dev = &pdev->dev; ++ config.init_data = init_data; ++ config.driver_data = info; ++ config.regmap = data->map; ++ config.of_node = pdev->dev.of_node; ++ ++ data->rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); ++ if (IS_ERR(data->rdev)) { ++ dev_err(&pdev->dev, "cannot register %s\n", info->desc.name); ++ ret = PTR_ERR(data->rdev); ++ return ret; ++ } ++ ++ c = data->rdev->constraints; ++ if (info->desc.ops->enable) ++ c->valid_ops_mask |= REGULATOR_CHANGE_STATUS; ++ if (info->desc.ops->set_voltage_sel) ++ c->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; ++ ++ platform_set_drvdata(pdev, data); ++ ++ return 0; ++} ++ ++static int pm88x_virtual_regulator_remove(struct platform_device *pdev) ++{ ++ struct pm88x_regulators *data = platform_get_drvdata(pdev); ++ devm_kfree(&pdev->dev, data); ++ return 0; ++} ++ ++static struct platform_driver pm88x_virtual_regulator_driver = { ++ .driver = { ++ .name = "88pm88x-virtual-regulator", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(pm88x_vrs_of_match), ++ }, ++ .probe = pm88x_virtual_regulator_probe, ++ .remove = pm88x_virtual_regulator_remove, ++}; ++ ++static int pm88x_virtual_regulator_init(void) ++{ ++ return platform_driver_register(&pm88x_virtual_regulator_driver); ++} ++subsys_initcall(pm88x_virtual_regulator_init); ++ ++static void pm88x_virtual_regulator_exit(void) ++{ ++ platform_driver_unregister(&pm88x_virtual_regulator_driver); ++} ++module_exit(pm88x_virtual_regulator_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Yi Zhang "); ++MODULE_DESCRIPTION("for virtual supply in Marvell 88PM88X PMIC"); ++MODULE_ALIAS("platform:88pm88x-vr"); +diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig +index 965d4f0c18a6..484baabf3c41 100644 +--- a/drivers/regulator/Kconfig ++++ b/drivers/regulator/Kconfig +@@ -1663,4 +1663,14 @@ config REGULATOR_QCOM_LABIBB + boost regulator and IBB can be used as a negative boost regulator + for LCD display panel. + ++config REGULATOR_88PM88X ++ tristate "Marvell 88PM88X Power regulators" ++ depends on MFD_88PM88X ++ depends on I2C ++ help ++ This driver supports Marvell 88PM88X voltage regulator chips. ++ It delivers digitally programmable output, the voltage is ++ programmed via I2C interface. ++ It has 5 bucks and 16 ldos. Buck1 has DVC feature ++ + endif +diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile +index 23074714a81a..8a1e6f454760 100644 +--- a/drivers/regulator/Makefile ++++ b/drivers/regulator/Makefile +@@ -63,6 +63,9 @@ obj-$(CONFIG_REGULATOR_LP873X) += lp873x-regulator.o + obj-$(CONFIG_REGULATOR_LP87565) += lp87565-regulator.o + obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o + obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o ++obj-$(CONFIG_REGULATOR_88PM88X) += 88pm88x-ldo.o ++obj-$(CONFIG_REGULATOR_88PM88X) += 88pm88x-buck.o ++obj-$(CONFIG_REGULATOR_88PM88X) += 88pm88x-vr.o + obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o + obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o + obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0019-DONOTMERGE-fix-build-for-the-88pm88x-regulator-drive.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0019-DONOTMERGE-fix-build-for-the-88pm88x-regulator-drive.patch new file mode 100644 index 000000000..3176de7b2 --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0019-DONOTMERGE-fix-build-for-the-88pm88x-regulator-drive.patch @@ -0,0 +1,208 @@ +From f613c321a4e37bce1603f1b2e8ffac01c7c0fb25 Mon Sep 17 00:00:00 2001 +From: Karel Balej +Date: Sun, 24 Sep 2023 13:01:20 +0200 +Subject: [PATCH] DONOTMERGE: fix build for the 88pm88x regulator driver + +--- + drivers/regulator/88pm88x-buck.c | 10 +++++----- + drivers/regulator/88pm88x-ldo.c | 2 +- + drivers/regulator/88pm88x-vr.c | 12 ++++++------ + include/linux/mfd/88pm880.h | 10 ++++++++++ + include/linux/mfd/88pm886.h | 4 ++++ + include/linux/mfd/88pm88x.h | 20 +++++++++++++------- + 6 files changed, 39 insertions(+), 19 deletions(-) + +diff --git a/drivers/regulator/88pm88x-buck.c b/drivers/regulator/88pm88x-buck.c +index 7546e0fb9d87..1e0c29bfdce1 100644 +--- a/drivers/regulator/88pm88x-buck.c ++++ b/drivers/regulator/88pm88x-buck.c +@@ -119,7 +119,7 @@ + * from 0x00 to 0x4F: step is 12.5mV, range is from 0.6V to 1.6V + * from 0x50 to 0x3F step is 50mV, range is from 1.6V to 1.8V + */ +-static const struct regulator_linear_range buck_volt_range1[] = { ++static const struct linear_range buck_volt_range1[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), + REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000), + }; +@@ -129,7 +129,7 @@ static const struct regulator_linear_range buck_volt_range1[] = { + * from 0x00 to 0x4F VOUT step is 12.5mV, range is from 0.6V to 1.6V + * from 0x50 to 0x72 step is 50mV, range is from 1.6V to 3.3V + */ +-static const struct regulator_linear_range buck_volt_range2[] = { ++static const struct linear_range buck_volt_range2[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), + REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x72, 50000), + }; +@@ -394,7 +394,7 @@ static const struct of_device_id pm88x_bucks_of_match[] = { + */ + static int pm88x_get_vbuck_vol(unsigned int val, struct pm88x_buck_info *info) + { +- const struct regulator_linear_range *range; ++ const struct linear_range *range; + int i, volt = -EINVAL; + + /* get the voltage via the register value */ +@@ -404,7 +404,7 @@ static int pm88x_get_vbuck_vol(unsigned int val, struct pm88x_buck_info *info) + return -EINVAL; + + if (val >= range->min_sel && val <= range->max_sel) { +- volt = (val - range->min_sel) * range->uV_step + range->min_uV; ++ volt = (val - range->min_sel) * range->step + range->min; + break; + } + } +@@ -634,7 +634,7 @@ static int pm88x_buck_probe(struct platform_device *pdev) + if (match) { + const_info = match->data; + init_data = of_get_regulator_init_data(&pdev->dev, +- pdev->dev.of_node); ++ pdev->dev.of_node, &const_info->desc); + } else { + dev_err(&pdev->dev, "parse dts fails!\n"); + return -EINVAL; +diff --git a/drivers/regulator/88pm88x-ldo.c b/drivers/regulator/88pm88x-ldo.c +index d2bf731e2dcc..2d3d14f4f78f 100644 +--- a/drivers/regulator/88pm88x-ldo.c ++++ b/drivers/regulator/88pm88x-ldo.c +@@ -646,7 +646,7 @@ static int pm88x_ldo_probe(struct platform_device *pdev) + if (match) { + const_info = match->data; + init_data = of_get_regulator_init_data(&pdev->dev, +- pdev->dev.of_node); ++ pdev->dev.of_node, &const_info->desc); + } else { + dev_err(&pdev->dev, "parse dts fails!\n"); + return -EINVAL; +diff --git a/drivers/regulator/88pm88x-vr.c b/drivers/regulator/88pm88x-vr.c +index 2175859b8727..dacac878eaa2 100644 +--- a/drivers/regulator/88pm88x-vr.c ++++ b/drivers/regulator/88pm88x-vr.c +@@ -128,12 +128,12 @@ + #define PM880_BUCK_AUDIO_OF_MATCH(comp, label) \ + PM88X_BUCK_AUDIO_OF_MATCH(pm880, PM880_ID, comp, label) + +-static const struct regulator_linear_range buck_slp_volt_range1[] = { ++static const struct linear_range buck_slp_volt_range1[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), + REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000), + }; + +-static const struct regulator_linear_range buck_audio_volt_range1[] = { ++static const struct linear_range buck_audio_volt_range1[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 0x54, 12500), + }; + +@@ -364,9 +364,9 @@ static int of_get_legacy_init_data(struct device *dev, + * to a real voltage value (in uV) according to the voltage table. + */ + static int pm88x_get_vvr_vol(unsigned int val, unsigned int n_linear_ranges, +- const struct regulator_linear_range *ranges) ++ const struct linear_range *ranges) + { +- const struct regulator_linear_range *range; ++ const struct linear_range *range; + int i, volt = -EINVAL; + + /* get the voltage via the register value */ +@@ -376,7 +376,7 @@ static int pm88x_get_vvr_vol(unsigned int val, unsigned int n_linear_ranges, + return -EINVAL; + + if (val >= range->min_sel && val <= range->max_sel) { +- volt = (val - range->min_sel) * range->uV_step + range->min_uV; ++ volt = (val - range->min_sel) * range->step + range->min; + break; + } + } +@@ -584,7 +584,7 @@ static int pm88x_virtual_regulator_probe(struct platform_device *pdev) + if (match) { + const_info = match->data; + init_data = of_get_regulator_init_data(&pdev->dev, +- pdev->dev.of_node); ++ pdev->dev.of_node, &const_info->desc); + ret = of_get_legacy_init_data(&pdev->dev, &init_data); + if (ret < 0) + return ret; +diff --git a/include/linux/mfd/88pm880.h b/include/linux/mfd/88pm880.h +index 94b9e063918a..3952f8d29c32 100644 +--- a/include/linux/mfd/88pm880.h ++++ b/include/linux/mfd/88pm880.h +@@ -33,6 +33,16 @@ enum { + PM880_ID_BUCK_MAX = 7, + }; + ++enum { ++ PM880_ID_BUCK1A_SLP = 0, ++ PM880_ID_BUCK1B_SLP, ++}; ++ ++enum { ++ PM880_ID_BUCK1A_AUDIO = 0, ++ PM880_ID_BUCK1B_AUDIO, ++}; ++ + enum { + PM880_ID_LDO1 = 0, + PM880_ID_LDO2, +diff --git a/include/linux/mfd/88pm886.h b/include/linux/mfd/88pm886.h +index 939040647702..9db077be1f79 100644 +--- a/include/linux/mfd/88pm886.h ++++ b/include/linux/mfd/88pm886.h +@@ -52,4 +52,8 @@ enum { + PM886_ID_LDO_MAX = 16, + }; + ++enum { ++ PM886_ID_BUCK1_SLP = 0, ++}; ++ + #endif /* __LINUX_MFD_88PM886_H */ +diff --git a/include/linux/mfd/88pm88x.h b/include/linux/mfd/88pm88x.h +index 91a84b551d15..ceffd976d3b7 100644 +--- a/include/linux/mfd/88pm88x.h ++++ b/include/linux/mfd/88pm88x.h +@@ -32,14 +32,27 @@ + #define PM88X_VBUS_NAME "88pm88x-vbus" + #define PM88X_CFD_NAME "88pm88x-leds" + #define PM88X_RGB_NAME "88pm88x-rgb" ++#define PM88X_DEBUGFS_NAME "88pm88x-debugfs" + #define PM88X_GPADC_NAME "88pm88x-gpadc" ++#define PM88X_HWMON_NAME "88pm88x-hwmon" + #define PM88X_DVC_NAME "88pm88x-dvc" ++#define PM88X_VIRTUAL_REGULATOR_NAME "88pm88x-vr" + + enum pm88x_type { + PM886 = 1, + PM880 = 2, + }; + ++enum { ++ PM88X_ID_VOTG = 0, ++}; ++ ++enum { ++ PM88X_RGB_LED0, ++ PM88X_RGB_LED1, ++ PM88X_RGB_LED2, ++}; ++ + enum pm88x_pages { + PM88X_BASE_PAGE = 0, + PM88X_LDO_PAGE, +@@ -95,13 +108,6 @@ enum pm88x_irq_number { + PM88X_MAX_IRQ, /* 28 */ + }; + +-/* 3 rgb led indicators */ +-enum { +- PM88X_RGB_LED0, +- PM88X_RGB_LED1, +- PM88X_RGB_LED2, +-}; +- + /* camera flash/torch */ + enum { + PM88X_NO_LED = -1, +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0020-DONOTMERGE-add-88pm88x-DT-bindings.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0020-DONOTMERGE-add-88pm88x-DT-bindings.patch new file mode 100644 index 000000000..6f63180a0 --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0020-DONOTMERGE-add-88pm88x-DT-bindings.patch @@ -0,0 +1,306 @@ +From 8cde8feee2afae8f509b52ec14474a51a72a8991 Mon Sep 17 00:00:00 2001 +From: Karel Balej +Date: Mon, 14 Aug 2023 18:58:13 +0200 +Subject: [PATCH] DONOTMERGE: add 88pm88x DT bindings + +--- + arch/arm64/boot/dts/marvell/88pm886.dtsi | 151 ++++++++++++++++++ + arch/arm64/boot/dts/marvell/88pm88x.dtsi | 66 ++++++++ + .../pxa1908-samsung-coreprimevelte.dts | 39 +++++ + 3 files changed, 256 insertions(+) + create mode 100644 arch/arm64/boot/dts/marvell/88pm886.dtsi + create mode 100644 arch/arm64/boot/dts/marvell/88pm88x.dtsi + +diff --git a/arch/arm64/boot/dts/marvell/88pm886.dtsi b/arch/arm64/boot/dts/marvell/88pm886.dtsi +new file mode 100644 +index 000000000000..084e922f4e4c +--- /dev/null ++++ b/arch/arm64/boot/dts/marvell/88pm886.dtsi +@@ -0,0 +1,151 @@ ++/* ++ * Copyright (C) 2014 Marvell ++ * Yi Zhang ++ */ ++ ++/* ++ * Integrated Power Management Chip ++ * header file for Marvell PMIC: 88pm886 ++ */ ++ ++&pmic0 { ++ compatible = "marvell,88pm886"; ++ /* ---buck--- */ ++ vccmain: regulator-buck1 { ++ compatible = "marvell,88pm886-buck1"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ buck2: regulator-buck2 { ++ compatible = "marvell,88pm886-buck2"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ vddr: regulator-buck3 { ++ compatible = "marvell,88pm886-buck3"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ buck4: regulator-buck4 { ++ compatible = "marvell,88pm886-buck4"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ buck5: regulator-buck5 { ++ compatible = "marvell,88pm886-buck5"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ /* ---ldo--- */ ++ /* ++ ldo1: regulator-ldo1 { ++ compatible = "marvell,88pm886-ldo1"; ++ regulator-min-microvolt = <1700000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ */ ++ ldo2: regulator-ldo2 { ++ compatible = "marvell,88pm886-ldo2"; ++ regulator-min-microvolt = <1700000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ /* ++ ldo3: regulator-ldo3 { ++ compatible = "marvell,88pm886-ldo3"; ++ regulator-min-microvolt = <1700000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo4: regulator-ldo4 { ++ compatible = "marvell,88pm886-ldo4"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo5: regulator-ldo5 { ++ compatible = "marvell,88pm886-ldo5"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo6: regulator-ldo6 { ++ compatible = "marvell,88pm886-ldo6"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo7: regulator-ldo7 { ++ compatible = "marvell,88pm886-ldo7"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo8: regulator-ldo8 { ++ compatible = "marvell,88pm886-ldo8"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo9: regulator-ldo9 { ++ compatible = "marvell,88pm886-ldo9"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo10: regulator-ldo10 { ++ compatible = "marvell,88pm886-ldo10"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo11: regulator-ldo11 { ++ compatible = "marvell,88pm886-ldo11"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo12: regulator-ldo12 { ++ compatible = "marvell,88pm886-ldo12"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo13: regulator-ldo13 { ++ compatible = "marvell,88pm886-ldo13"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo14: regulator-ldo14 { ++ compatible = "marvell,88pm886-ldo14"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo15: regulator-ldo15 { ++ compatible = "marvell,88pm886-ldo15"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ldo16: regulator-ldo16 { ++ compatible = "marvell,88pm886-ldo16"; ++ regulator-min-microvolt = <1700000>; ++ regulator-max-microvolt = <2800000>; ++ }; ++ */ ++ ++ /* virtual regulator */ ++ buck1slp: regulator-buck1-slp { ++ compatible = "marvell,88pm886-buck1-slp"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ marvell,consumer-supplies = "buck1slp", "nameless"; ++ }; ++ ++ gpadc: gpadc{ ++ compatible = "marvell,88pm886-gpadc"; ++ #io-channel-cells = <1>; ++ io-channel-ranges; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/marvell/88pm88x.dtsi b/arch/arm64/boot/dts/marvell/88pm88x.dtsi +new file mode 100644 +index 000000000000..39f3943b9f6c +--- /dev/null ++++ b/arch/arm64/boot/dts/marvell/88pm88x.dtsi +@@ -0,0 +1,66 @@ ++/* ++ * Copyright (C) 2014 Marvell ++ * Yi Zhang ++ */ ++ ++/* ++ * Integrated Power Management Chip ++ * common header file for Marvell PMIC: 88pm88x ++ */ ++ ++&pmic0 { ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ marvell,88pm88x-irq-write-clear; ++ ++ onkey { ++ compatible = "marvell,88pm88x-onkey"; ++ /* marvell,pm886-onkey-gpio-number = <1>; */ ++ }; ++ ++ vbus { ++ compatible = "marvell,88pm88x-vbus"; ++ }; ++ ++ rtc { ++ compatible = "marvell,88pm88x-rtc"; ++ }; ++ ++ charger { ++ compatible = "marvell,88pm88x-charger"; ++ }; ++ ++ battery { ++ compatible = "marvell,88pm88x-battery"; ++ }; ++ ++ dvc { ++ compatible = "marvell,88pm88x-dvc"; ++ }; ++ ++ headset { ++ compatible = "marvell,88pm88x-headset"; ++ status = "disabled"; ++ }; ++ ++ led { ++ compatible = "marvell,88pm88x-leds"; ++ }; ++ ++ red: led-rgb0 { ++ compatible = "marvell,88pm88x-rgb0"; ++ }; ++ green: led-rgb1 { ++ compatible = "marvell,88pm88x-rgb1"; ++ }; ++ blue: led-rgb2 { ++ compatible = "marvell,88pm88x-rgb2"; ++ }; ++ ++ gpadc: gpadc{ ++ compatible = "marvell,88pm88x-gpadc"; ++ #io-channel-cells = <1>; ++ io-channel-ranges; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts +index bd69358fd069..b1ae358c5778 100644 +--- a/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts ++++ b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts +@@ -2,6 +2,8 @@ + #include "pxa1908.dtsi" + #include + #include ++// FIXME ++#define IRQF_TRIGGER_HIGH 0x00000004 + + / { + pxa,rev-id = <3928 2>; +@@ -305,6 +307,41 @@ &twsi1 { + + &twsi2 { + status = "okay"; ++ pmic0: 88pm886@30 { ++ compatible = "marvell,88pm886"; ++ reg = <0x30>; ++ interrupts = <0 4 IRQF_TRIGGER_HIGH>; ++ interrupt-parent = <&gic>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ marvell,88pm88x-irq-write-clear; ++ ++ onkey { ++ marvell,pm88x-onkey-gpio-number = <0>; ++ }; ++ ++ vbus { ++ gpadc-number = <1>; ++ }; ++ ++ battery { ++ bat-software-battery-detection; ++ /* bat-ntc-support; */ ++ bat-ntc-support; ++ gpadc-det-no = <2>; ++ gpadc-temp-no = <3>; ++ }; ++ }; ++ pmic2: 88pm860@38 { ++ compatible = "marvell,88pm860"; ++ reg = <0x38>; ++ marvell,pmic-type = <1>; ++ pm860_codec: pm860_codec { ++ compatible = "marvell,88pm860-codec"; ++ #dailink-cells = <1>; ++ }; ++ }; + }; + + &twsi3 { +@@ -342,3 +379,5 @@ &sdh0 { + bus-width = <4>; + wp-inverted; + }; ++#include "88pm886.dtsi" ++#include "88pm88x.dtsi" +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/0021-set-touchscreen-VDD-regulator-to-3.1V.patch b/device/testing/linux-samsung-coreprimevelte-mainline/0021-set-touchscreen-VDD-regulator-to-3.1V.patch new file mode 100644 index 000000000..0e5b9219f --- /dev/null +++ b/device/testing/linux-samsung-coreprimevelte-mainline/0021-set-touchscreen-VDD-regulator-to-3.1V.patch @@ -0,0 +1,25 @@ +From cd329af16a6e443bc0c43628dfe7949758c5191e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Duje=20Mihanovi=C4=87?= +Date: Thu, 28 Sep 2023 18:33:07 +0200 +Subject: [PATCH] set touchscreen VDD regulator to 3.1V + +--- + arch/arm64/boot/dts/marvell/88pm886.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/marvell/88pm886.dtsi b/arch/arm64/boot/dts/marvell/88pm886.dtsi +index 084e922f4e4c..f5c6084673e4 100644 +--- a/arch/arm64/boot/dts/marvell/88pm886.dtsi ++++ b/arch/arm64/boot/dts/marvell/88pm886.dtsi +@@ -57,7 +57,7 @@ ldo1: regulator-ldo1 { + */ + ldo2: regulator-ldo2 { + compatible = "marvell,88pm886-ldo2"; +- regulator-min-microvolt = <1700000>; ++ regulator-min-microvolt = <3100000>; + regulator-max-microvolt = <3300000>; + }; + /* +-- +2.42.0 + diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/APKBUILD b/device/testing/linux-samsung-coreprimevelte-mainline/APKBUILD index 85aa2a036..72c9b1802 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/APKBUILD +++ b/device/testing/linux-samsung-coreprimevelte-mainline/APKBUILD @@ -2,7 +2,7 @@ _flavor=samsung-coreprimevelte-mainline pkgname=linux-$_flavor -pkgver=6.5_rc4 +pkgver=6.6_rc3 pkgrel=0 pkgdesc="Samsung Galaxy Core Prime VE LTE mainline kernel" arch="aarch64" @@ -20,17 +20,27 @@ _config="config-$_flavor.$arch" source=" linux-$_tag.tar.gz::$url/archive/refs/tags/v$_tag.tar.gz $_config - 0001-tty-serial-8250-Define-earlycon-for-mrvl-mmp-uart.patch - 0002-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch - 0003-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch - 0004-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch - 0005-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch - 0006-dt-bindings-marvell-Document-PXA1908-SoC.patch - 0007-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch - 0008-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch - 0009-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch + 0001-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch + 0002-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch + 0003-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch + 0004-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch + 0005-dt-bindings-marvell-Document-PXA1908-SoC.patch + 0006-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch + 0007-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch + 0008-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch + 0009-DONOTMERGE-Enable-AArch64-system-timer-properly.patch 0010-DONOTMERGE-Add-pxa-rev-id-to-board-dts.patch - 0011-DONOTMERGE-Enable-AArch64-system-timer-properly.patch + 0011-input-generalize-the-Imagis-touchscreen-driver.patch + 0012-Documentation-imagis-document-IST3032C-support.patch + 0013-input-Imagis-add-support-for-IST3032C-touchscreen.patch + 0014-arm64-dts-add-touchscreen-bindings-for-samsung-corep.patch + 0015-mfd-add-Marvell-88pm88x-description.patch + 0016-mfd-88pm88x-initialize-88pm886-88pm880-base-support.patch + 0017-DONOTMERGE-fix-88pm88x-build.patch + 0018-DONOTMERGE-add-downstream-regulator-driver.patch + 0019-DONOTMERGE-fix-build-for-the-88pm88x-regulator-drive.patch + 0020-DONOTMERGE-add-88pm88x-DT-bindings.patch + 0021-set-touchscreen-VDD-regulator-to-3.1V.patch " builddir="$srcdir/linux-$_tag" @@ -64,17 +74,27 @@ package() { } sha512sums=" -f30138f99c65bb4d96ed3b59e0fc741a1364601632c6dbec9ffec999d20f41b8eaa8d2636eee440ea8c61fe12d5971bbb3a1d0e540165b974c4e3f03d11f829e linux-6.5-rc4.tar.gz -67bef68d9f89c6b713e75785899d889013cf07ba648a10db1a4b613070ac0ea293520d215158e0c1dd4a27695d6072e62943ad105bc7782f853c032533b258c2 config-samsung-coreprimevelte-mainline.aarch64 -0b091733e12dd68d5286751e1cc8673211adb679f05b97f276956badc199b287c0325fad9ada455e7e00bbfcd1ce1a854e669fbe2644f33de1997bfb8d2a2ce1 0001-tty-serial-8250-Define-earlycon-for-mrvl-mmp-uart.patch -e4b1519678367799022b0543449dbd2f6ebed0c6cd23cf246b27242d77201a9a728e9feb48cb35874522918236d8e6809b22ae2cb269722deea72302c6ad0b9a 0002-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch -6a71af9fdfd9cdded2ef798ec1b54149acc0152014d708ea3e59b9254aeff7f9bcec4c8dcefe36f3299dcf65867bf50ac8487ccf1d4fbb6522da61406a971baa 0003-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch -8b41a273f21c2c7dfdaaebeac60d0b95ff3e3ac152d30254250cf479a8b0483ae974737e33e1e8c60a16aa0da9fb8fec450383f010dbd67b7416e1f761d97dbd 0004-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch -741b27c644128b655bc9b1bc25ae9d7a7e6e6b1e26300b597eb8a787e8e23c4584eb1cacd0528c7e5b0531b794a8eab2080d4404348dfc305c99703e55bbcdb0 0005-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch -cd120ad2ee70a86c6de367b446e2e2cf4bc44ccb6c660978a72e27c55237be0e7eecb61310162c44461afbf66e378beac4e6429b9aed7b9a3c47db6180122430 0006-dt-bindings-marvell-Document-PXA1908-SoC.patch -b06e721b18490512a35d22af0c266f084835b85f29fc2b84e9e3cd4ac7e30f7bcd7454295cc51c14679f6a9cd640323be6f2544541649c795ea287858dd28a48 0007-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch -00fbda0b7e26bec4664fd391b8dd57fed315cd254f28287a85e6174f14a08274204f5441bdd1a32ba8a8855dd5ad139081a4e65718387d75481759276f9bd7ec 0008-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch -be476ac6ea0bf11c7415ac8849ad796c51041b96c93a744015a613e561a0dcdfb65642abeee3674639387c7276fcb8b83dda1f8c20e3461c14f198c410bb96ee 0009-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch -1ba1bb05696364f3790e68c37ba75e3b83ae7f13e11ca0f52e03036da29c6e9caed93b7cbb675ff82b2e2ec337a5c416b863abe2cba7d5ae9be68ad74c798d86 0010-DONOTMERGE-Add-pxa-rev-id-to-board-dts.patch -cab9434b485c63077b22ba65c7ca160e413bc10a60e971a76c84f1df21140a2475b406a4c4c8c7e97c0292795b2a2786035663a8632e7915d2c69031d5255197 0011-DONOTMERGE-Enable-AArch64-system-timer-properly.patch +59dfaf0d49d898c0f00019364845271f58ad4401f7f2a6fe3e2b3718a29a5e183a356b5400f4936967bc215471dbe87278ec5c3ab6e9e52643d7e869233b3833 linux-6.6-rc3.tar.gz +e2b61e3c9de6f15db3cf6ea116f9466755c783d40c7085ab01fb4f6ae02e813524b137ad6f0fd2c0624457559778c32f8b22031238ab4353702cd15c33bf4a16 config-samsung-coreprimevelte-mainline.aarch64 +0069e76bf9695da6a944e43aff6b21c928d3816765eee483135cc523b19668fa8a3da547565a55b39adcd9f01e125b48e22f1eafb78cbb4d97b39f8c3bd8f80a 0001-gpio-pxa-disable-pinctrl-calls-for-MMP_GPIO.patch +2ef0a47ba941202c3ed61063c781ae73dcb2b05ab229c4863c610f809716bd9159cae58468fcd1559913fcba6f2de4f940df58104687cfebb631fe2ee5cd7e33 0002-clk-mmp-Switch-to-use-struct-u32_fract-instead-of-cu.patch +841d1df7e18e58893c82f5a0a48e06d82954721b1392b9c36ef555150ef3d82fa7d3b33c1b30ebf7b1cf55a6fcc9e3f032667bc30f664176e046d6f9756da238 0003-dt-bindings-clock-Add-Marvell-PXA1908-clock-bindings.patch +b0e5e538ab7837351a8c2feb32a6c6f81cb8f37edafd4ea68ed3a74c6d6b27745a54b4bd1b8839bb4f84daa5635cbbf62453cc1f17c59216e562442bc1833eb2 0004-clk-mmp-Add-Marvell-PXA1908-clock-driver.patch +22472dfd020364bf32e7e9d350f91ea07761e4f8c291cfde37e5c8d334a88290565320b167264d1a5f51a257702d7c41cafb6d0ae15baf37a32defee21170fe8 0005-dt-bindings-marvell-Document-PXA1908-SoC.patch +84ab5f554ae9d8a41d1baa9743c9f066e0ac7c3183d9ab53ab8225c381ff5e19cce73f4ec1a567f6a8b9ba962318bd323f1f117bb553cf3ef628b572bb7fd585 0006-arm64-Kconfig.platforms-Add-config-for-Marvell-PXA19.patch +7305a9275ba74718932f5bb409d0d1b3eb029ecc620c3878b58091994f6da400203c58ce535f877bd4d06f86d9cdc1e8512cef073e4d1118fa8ccb54f254129c 0007-arm64-dts-Add-DTS-for-Marvell-PXA1908-and-samsung-co.patch +16588e84d9650d405b2cf23edc0648de29b4b74869648e29c84a83ebda776a5ba2c6b97039a9d73c1c5683040ad77b470ea73fd9fe151a2d333a47b54bac34b6 0008-MAINTAINERS-add-myself-as-Marvell-PXA1908-maintainer.patch +fc5cd8a5de0c4c7e177673535de98377059ac2a905492c095bb1b292447a97acc0df681970cdfd327a0e39ff9c95955d258095965513555cd310a0d58fa0b272 0009-DONOTMERGE-Enable-AArch64-system-timer-properly.patch +d73005b5581d5e0b5a7c73b5f67be209a0032f605955775e83737c0250aeb13157e97bfe93f7a9ec77c49f040478b15bde9ca715b4c5fa2f3f900f5c1c83ec0c 0010-DONOTMERGE-Add-pxa-rev-id-to-board-dts.patch +39ceaf8cada08dcc5e43b97dfc56e4370308c78faa01ce8f8ccaf955c26717ea783014f5b6e3263d07d5f1bb8997206209cd97ca67918d6f8747f27d35feeaf5 0011-input-generalize-the-Imagis-touchscreen-driver.patch +7a2c2b5251a9cc0687c6e9cde4079532d75ae9dc76bad96acae95879b031560fe63568b359948fe08a6a224c1c0a3c8a96766f89bb9aabce5fc4c3b531449930 0012-Documentation-imagis-document-IST3032C-support.patch +0bd27a665556a329dc8c009ba37cc10395c570a150380317ad103984da9d53240b3221c0f471113783d56863e0afa6e1dc2ed9f152f9c9be339f9d75763d106b 0013-input-Imagis-add-support-for-IST3032C-touchscreen.patch +631682ed29640028cb8de8278578140a9538a954e5bcf22614fd513caebfe33bc280e06b08f784bb8c9414c4e2b0ac5672a8df19ef1526af58f9d0d25070668a 0014-arm64-dts-add-touchscreen-bindings-for-samsung-corep.patch +b70b301d33b3703543e097aecfd4dc2c428039d58ed99b5977927bb2857cb9d8038d9bfe16effc857aa2a8a520498b13e5ebfbf0340b0f1140f97815bbf6adcd 0015-mfd-add-Marvell-88pm88x-description.patch +b4bbc5f90f10335129e1e6ff23895a5bce05fa7d7e943d0f57ec5889e56572847e756a4d44b0a0c4fc18e78fbb0a4b0f8b6ffa58421f6147d75d069741d7175e 0016-mfd-88pm88x-initialize-88pm886-88pm880-base-support.patch +e2a1c8dbbe96b5c4df48273c82f7974d06d009e39c0602e4daafb3b920cb825ad65f8378ecaac53f0730eb0a3aaf303ffd0edd20a5d19806e605b651a94a8549 0017-DONOTMERGE-fix-88pm88x-build.patch +0db0c7c0919470cc8e3ea13a6eb9b992562a023b67ffb1445a203bcf65f8658ae4771b23af27b8e21c4da133a863db80186a7cd382027c56c89024947bcb6a9a 0018-DONOTMERGE-add-downstream-regulator-driver.patch +c65a7ab9e3dd5bf44358ef9963d31224abe5d1d47d74c796fe30b478d13bbef78db54b3ede9875751399d12667b8ea7c6392d7e5a3ee2ffc35f8c223db8565e1 0019-DONOTMERGE-fix-build-for-the-88pm88x-regulator-drive.patch +0db204bc989a0db2f2da1fd6f7a8190219abda36da7d8e45363cdf1563816b3036306a36e563661774279a7fd2976808df149320e19c377a05ec8ff65442de79 0020-DONOTMERGE-add-88pm88x-DT-bindings.patch +68badc34bf07c63785f9a34bbf9e2cf02c419fafae299d7ab3b0eb17cb1dd5da703308720ba987b6cc7cb8db17f893f59fc6710daec1a3e0dba96d36aa5756bb 0021-set-touchscreen-VDD-regulator-to-3.1V.patch " diff --git a/device/testing/linux-samsung-coreprimevelte-mainline/config-samsung-coreprimevelte-mainline.aarch64 b/device/testing/linux-samsung-coreprimevelte-mainline/config-samsung-coreprimevelte-mainline.aarch64 index 9c072c5dd..9352dbe1f 100644 --- a/device/testing/linux-samsung-coreprimevelte-mainline/config-samsung-coreprimevelte-mainline.aarch64 +++ b/device/testing/linux-samsung-coreprimevelte-mainline/config-samsung-coreprimevelte-mainline.aarch64 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 6.5.0-rc3 Kernel Configuration +# Linux/arm64 6.6.0-rc3 Kernel Configuration # CONFIG_CC_VERSION_TEXT="aarch64-alpine-linux-musl-gcc (Alpine 13.1.1_git20230722) 13.1.1 20230722" CONFIG_CC_IS_GCC=y @@ -150,6 +150,7 @@ CONFIG_GENERIC_SCHED_CLOCK=y # end of Scheduler features CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y CONFIG_CC_HAS_INT128=y CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" CONFIG_GCC11_NO_ARRAY_BOUNDS=y @@ -239,7 +240,6 @@ CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_KCMP=y CONFIG_RSEQ=y CONFIG_CACHESTAT_SYSCALL=y -# CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y CONFIG_GUEST_PERF_EVENTS=y @@ -251,6 +251,17 @@ CONFIG_PERF_EVENTS=y # end of Kernel Performance Events And Counters CONFIG_PROFILING=y + +# +# Kexec and crash features +# +CONFIG_CRASH_CORE=y +CONFIG_KEXEC_CORE=y +CONFIG_KEXEC=y +CONFIG_KEXEC_FILE=y +# CONFIG_KEXEC_SIG is not set +CONFIG_CRASH_DUMP=y +# end of Kexec and crash features # end of General setup CONFIG_ARM64=y @@ -273,7 +284,6 @@ CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CSUM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y CONFIG_SMP=y CONFIG_KERNEL_MODE_NEON=y CONFIG_FIX_EARLYCON_MEM=y @@ -409,10 +419,13 @@ CONFIG_HW_PERF_EVENTS=y CONFIG_CC_HAVE_SHADOW_CALL_STACK=y CONFIG_PARAVIRT=y # CONFIG_PARAVIRT_TIME_ACCOUNTING is not set -CONFIG_KEXEC=y -CONFIG_KEXEC_FILE=y -# CONFIG_KEXEC_SIG is not set -CONFIG_CRASH_DUMP=y +CONFIG_ARCH_SUPPORTS_KEXEC=y +CONFIG_ARCH_SUPPORTS_KEXEC_FILE=y +CONFIG_ARCH_SELECTS_KEXEC_FILE=y +CONFIG_ARCH_SUPPORTS_KEXEC_SIG=y +CONFIG_ARCH_SUPPORTS_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_SUPPORTS_CRASH_DUMP=y CONFIG_TRANS_TABLE=y CONFIG_XEN_DOM0=y CONFIG_XEN=y @@ -432,7 +445,6 @@ CONFIG_KUSER_HELPERS=y # CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_PAN=y -CONFIG_AS_HAS_LDAPR=y CONFIG_AS_HAS_LSE_ATOMICS=y CONFIG_ARM64_LSE_ATOMICS=y CONFIG_ARM64_USE_LSE_ATOMICS=y @@ -457,6 +469,7 @@ CONFIG_CC_HAS_BRANCH_PROT_PAC_RET=y CONFIG_CC_HAS_SIGN_RETURN_ADDRESS=y CONFIG_AS_HAS_ARMV8_3=y CONFIG_AS_HAS_CFI_NEGATE_RA_STATE=y +CONFIG_AS_HAS_LDAPR=y # end of ARMv8.3 architectural features # @@ -596,7 +609,6 @@ CONFIG_KVM_MMIO=y CONFIG_HAVE_KVM_MSI=y CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y CONFIG_KVM_VFIO=y -CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL=y CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y CONFIG_HAVE_KVM_IRQ_BYPASS=y CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y @@ -609,8 +621,6 @@ CONFIG_KVM=y # # General architecture-dependent options # -CONFIG_CRASH_CORE=y -CONFIG_KEXEC_CORE=y CONFIG_ARCH_HAS_SUBPAGE_FAULTS=y CONFIG_HOTPLUG_CORE_SYNC=y CONFIG_HOTPLUG_CORE_SYNC_DEAD=y @@ -678,6 +688,7 @@ CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y CONFIG_HAVE_ARCH_HUGE_VMAP=y CONFIG_HAVE_ARCH_HUGE_VMALLOC=y CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_WANT_PMD_MKWRITE=y CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_MODULES_USE_ELF_RELA=y CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y @@ -833,6 +844,7 @@ CONFIG_SLAB_MERGE_DEFAULT=y # CONFIG_SLAB_FREELIST_HARDENED is not set # CONFIG_SLUB_STATS is not set CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_RANDOM_KMALLOC_CACHES is not set # end of SLAB allocator options # CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set @@ -848,6 +860,7 @@ CONFIG_EXCLUSIVE_SYSTEM_RAM=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y # CONFIG_MEMORY_HOTPLUG is not set +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y CONFIG_COMPACTION=y @@ -894,6 +907,7 @@ CONFIG_VM_EVENT_COUNTERS=y # CONFIG_GUP_TEST is not set # CONFIG_DMAPOOL_TEST is not set CONFIG_ARCH_HAS_PTE_SPECIAL=y +CONFIG_MEMFD_CREATE=y CONFIG_SECRETMEM=y # CONFIG_ANON_VMA_NAME is not set # CONFIG_USERFAULTFD is not set @@ -912,6 +926,7 @@ CONFIG_LOCK_MM_AND_FIND_VMA=y CONFIG_NET=y CONFIG_NET_INGRESS=y CONFIG_NET_EGRESS=y +CONFIG_NET_XGRESS=y CONFIG_SKB_EXTENSIONS=y # @@ -1337,6 +1352,11 @@ CONFIG_MHI_BUS=m # CONFIG_MHI_BUS_EP is not set # end of Bus devices +# +# Cache Drivers +# +# end of Cache Drivers + # CONFIG_CONNECTOR is not set # @@ -1477,6 +1497,7 @@ CONFIG_SCSI_MOD=y # CONFIG_ATA is not set CONFIG_MD=y # CONFIG_BLK_DEV_MD is not set +CONFIG_MD_BITMAP_FILE=y # CONFIG_BCACHE is not set CONFIG_BLK_DEV_DM_BUILTIN=y CONFIG_BLK_DEV_DM=y @@ -1648,7 +1669,7 @@ CONFIG_TOUCHSCREEN_GOODIX=m # CONFIG_TOUCHSCREEN_MSG2638 is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_NOVATEK_NVT_TS is not set -# CONFIG_TOUCHSCREEN_IMAGIS is not set +CONFIG_TOUCHSCREEN_IMAGIS=m # CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set # CONFIG_TOUCHSCREEN_INEXIO is not set # CONFIG_TOUCHSCREEN_PENMOUNT is not set @@ -1673,6 +1694,7 @@ CONFIG_TOUCHSCREEN_EDT_FT5X06=m # CONFIG_TOUCHSCREEN_ZFORCE is not set # CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set # CONFIG_TOUCHSCREEN_IQS5XX is not set +# CONFIG_TOUCHSCREEN_IQS7211 is not set # CONFIG_TOUCHSCREEN_ZINITIX is not set # CONFIG_TOUCHSCREEN_HIMAX_HX83112B is not set # CONFIG_INPUT_MISC is not set @@ -1944,6 +1966,7 @@ CONFIG_GPIO_PXA=y # # CONFIG_GPIO_ADNP is not set # CONFIG_GPIO_FXL6408 is not set +# CONFIG_GPIO_DS4520 is not set # CONFIG_GPIO_GW_PLD is not set # CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set @@ -2077,6 +2100,7 @@ CONFIG_SENSORS_ARM_SCPI=y # CONFIG_SENSORS_G762 is not set CONFIG_SENSORS_GPIO_FAN=m # CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_HS3001 is not set # CONFIG_SENSORS_IBMAEM is not set # CONFIG_SENSORS_IBMPEX is not set # CONFIG_SENSORS_IT87 is not set @@ -2155,7 +2179,6 @@ CONFIG_SENSORS_LM90=m # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_STTS751 is not set -# CONFIG_SENSORS_SMM665 is not set # CONFIG_SENSORS_ADC128D818 is not set # CONFIG_SENSORS_ADS7828 is not set # CONFIG_SENSORS_AMC6821 is not set @@ -2228,6 +2251,7 @@ CONFIG_MFD_CORE=y CONFIG_MFD_BD9571MWV=y CONFIG_MFD_AXP20X=y CONFIG_MFD_AXP20X_I2C=y +# CONFIG_MFD_CS42L43_I2C is not set # CONFIG_MFD_MADERA is not set # CONFIG_MFD_MAX5970 is not set # CONFIG_PMIC_DA903X is not set @@ -2243,6 +2267,7 @@ CONFIG_MFD_AXP20X_I2C=y CONFIG_MFD_HI6421_PMIC=y # CONFIG_MFD_IQS62X is not set # CONFIG_MFD_KEMPLD is not set +CONFIG_MFD_88PM88X=y CONFIG_MFD_88PM800=y # CONFIG_MFD_88PM805 is not set # CONFIG_MFD_88PM860X is not set @@ -2332,6 +2357,7 @@ CONFIG_REGULATOR_88PM800=y # CONFIG_REGULATOR_ACT8865 is not set # CONFIG_REGULATOR_AD5398 is not set # CONFIG_REGULATOR_ARM_SCMI is not set +# CONFIG_REGULATOR_AW37503 is not set # CONFIG_REGULATOR_AXP20X is not set # CONFIG_REGULATOR_BD718XX is not set # CONFIG_REGULATOR_BD9571MWV is not set @@ -2353,6 +2379,7 @@ CONFIG_REGULATOR_88PM800=y # CONFIG_REGULATOR_LTC3676 is not set # CONFIG_REGULATOR_MAX1586 is not set # CONFIG_REGULATOR_MAX77620 is not set +# CONFIG_REGULATOR_MAX77857 is not set # CONFIG_REGULATOR_MAX8649 is not set # CONFIG_REGULATOR_MAX8660 is not set # CONFIG_REGULATOR_MAX8893 is not set @@ -2393,6 +2420,7 @@ CONFIG_REGULATOR_88PM800=y # CONFIG_REGULATOR_RTQ2134 is not set # CONFIG_REGULATOR_RTMV20 is not set # CONFIG_REGULATOR_RTQ6752 is not set +# CONFIG_REGULATOR_RTQ2208 is not set # CONFIG_REGULATOR_S2MPA01 is not set # CONFIG_REGULATOR_S2MPS11 is not set # CONFIG_REGULATOR_S5M8767 is not set @@ -2410,6 +2438,7 @@ CONFIG_REGULATOR_88PM800=y # CONFIG_REGULATOR_VCTRL is not set # CONFIG_REGULATOR_VEXPRESS is not set # CONFIG_REGULATOR_WM8994 is not set +CONFIG_REGULATOR_88PM88X=y # CONFIG_RC_CORE is not set # @@ -2426,6 +2455,7 @@ CONFIG_REGULATOR_88PM800=y CONFIG_APERTURE_HELPERS=y CONFIG_VIDEO_CMDLINE=y CONFIG_VIDEO_NOMODESET=y +# CONFIG_AUXDISPLAY is not set CONFIG_DRM=y # CONFIG_DRM_DEBUG_MM is not set CONFIG_DRM_KMS_HELPER=y @@ -2531,23 +2561,7 @@ CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y # # Frame buffer Devices # -CONFIG_FB_NOTIFY=y CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FB_SYS_FILLRECT=y -CONFIG_FB_SYS_COPYAREA=y -CONFIG_FB_SYS_IMAGEBLIT=y -# CONFIG_FB_FOREIGN_ENDIAN is not set -CONFIG_FB_SYS_FOPS=y -CONFIG_FB_DEFERRED_IO=y -CONFIG_FB_SYS_HELPERS=y -CONFIG_FB_SYS_HELPERS_DEFERRED=y -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# # CONFIG_FB_ARMCLCD is not set # CONFIG_FB_OPENCORES is not set # CONFIG_FB_S1D13XXX is not set @@ -2558,6 +2572,20 @@ CONFIG_FB_SYS_HELPERS_DEFERRED=y # CONFIG_XEN_FBDEV_FRONTEND is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_SSD1307 is not set +CONFIG_FB_CORE=y +CONFIG_FB_NOTIFY=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_DEVICE=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_SYSMEM_HELPERS=y +CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set # end of Frame buffer Devices # @@ -2629,6 +2657,7 @@ CONFIG_HID_EZKEY=y # CONFIG_HID_GFRM is not set # CONFIG_HID_GLORIOUS is not set # CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GOOGLE_STADIA_FF is not set # CONFIG_HID_VIVALDI is not set # CONFIG_HID_GT683R is not set # CONFIG_HID_KEYTOUCH is not set @@ -2975,6 +3004,7 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_LP8860 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PCA995X is not set # CONFIG_LEDS_REGULATOR is not set # CONFIG_LEDS_BD2606MVV is not set # CONFIG_LEDS_BD2802 is not set @@ -3001,6 +3031,7 @@ CONFIG_LEDS_SYSCON=y # # RGB LED drivers # +# CONFIG_LEDS_GROUP_MULTICOLOR is not set # # LED Triggers @@ -3122,7 +3153,6 @@ CONFIG_RTC_DRV_PCF2127=m # CONFIG_RTC_DRV_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set # CONFIG_RTC_DRV_MSM6242 is not set -# CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_RP5C01 is not set # CONFIG_RTC_DRV_OPTEE is not set # CONFIG_RTC_DRV_ZYNQMP is not set @@ -3190,9 +3220,9 @@ CONFIG_SYNC_FILE=y # CONFIG_DMABUF_SYSFS_STATS is not set # end of DMABUF options -# CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set CONFIG_VFIO=y +CONFIG_VFIO_GROUP=y CONFIG_VFIO_CONTAINER=y CONFIG_VFIO_IOMMU_TYPE1=y # CONFIG_VFIO_NOIOMMU is not set @@ -3272,6 +3302,7 @@ CONFIG_COMMON_CLK=y # CONFIG_COMMON_CLK_XGENE is not set # CONFIG_COMMON_CLK_RS9_PCIE is not set # CONFIG_COMMON_CLK_SI521XX is not set +# CONFIG_COMMON_CLK_VC3 is not set # CONFIG_COMMON_CLK_VC5 is not set # CONFIG_COMMON_CLK_VC7 is not set # CONFIG_COMMON_CLK_BD718XX is not set @@ -3477,6 +3508,8 @@ CONFIG_PHY_PXA_USB=y # CONFIG_PHY_OCELOT_SERDES is not set # CONFIG_PHY_QCOM_USB_HS is not set # CONFIG_PHY_QCOM_USB_HSIC is not set +# CONFIG_PHY_RTK_RTD_USB2PHY is not set +# CONFIG_PHY_RTK_RTD_USB3PHY is not set # CONFIG_PHY_TUSB1210 is not set # end of PHY Subsystem @@ -3490,6 +3523,7 @@ CONFIG_PHY_PXA_USB=y # CONFIG_ARM_CCN is not set # CONFIG_ARM_CMN is not set CONFIG_ARM_PMU=y +# CONFIG_ARM_SMMU_V3_PMU is not set CONFIG_ARM_PMUV3=y # CONFIG_ARM_DSU_PMU is not set # CONFIG_ARM_SPE_PMU is not set @@ -3547,6 +3581,7 @@ CONFIG_PM_OPP=y CONFIG_DCACHE_WORD_ACCESS=y # CONFIG_VALIDATE_FS_PARSER is not set CONFIG_FS_IOMAP=y +CONFIG_BUFFER_HEAD=y CONFIG_LEGACY_DIRECT_IO=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set @@ -3589,7 +3624,6 @@ CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set # CONFIG_QFMT_V2 is not set CONFIG_QUOTACTL=y -CONFIG_AUTOFS4_FS=y CONFIG_AUTOFS_FS=y CONFIG_FUSE_FS=m CONFIG_CUSE=m @@ -3600,6 +3634,7 @@ CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y # CONFIG_OVERLAY_FS_INDEX is not set # CONFIG_OVERLAY_FS_XINO_AUTO is not set # CONFIG_OVERLAY_FS_METACOPY is not set +# CONFIG_OVERLAY_FS_DEBUG is not set # # Caches @@ -3644,10 +3679,10 @@ CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_TMPFS_XATTR=y # CONFIG_TMPFS_INODE64 is not set +# CONFIG_TMPFS_QUOTA is not set CONFIG_ARCH_SUPPORTS_HUGETLBFS=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y -CONFIG_MEMFD_CREATE=y CONFIG_ARCH_HAS_GIGANTIC_PAGE=y CONFIG_CONFIGFS_FS=y # end of Pseudo filesystems @@ -3689,12 +3724,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_ROMFS_FS is not set CONFIG_PSTORE=y CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 -# CONFIG_PSTORE_DEFLATE_COMPRESS is not set -# CONFIG_PSTORE_LZO_COMPRESS is not set -# CONFIG_PSTORE_LZ4_COMPRESS is not set -# CONFIG_PSTORE_LZ4HC_COMPRESS is not set -# CONFIG_PSTORE_842_COMPRESS is not set -# CONFIG_PSTORE_ZSTD_COMPRESS is not set +CONFIG_PSTORE_COMPRESS=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_PMSG=y CONFIG_PSTORE_RAM=y @@ -3818,6 +3848,13 @@ CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y # CONFIG_ZERO_CALL_USED_REGS is not set # end of Memory initialization +# +# Hardening of kernel data structures +# +# CONFIG_LIST_HARDENED is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# end of Hardening of kernel data structures + CONFIG_RANDSTRUCT_NONE=y # CONFIG_RANDSTRUCT_FULL is not set # CONFIG_RANDSTRUCT_PERFORMANCE is not set @@ -4112,7 +4149,7 @@ CONFIG_XXHASH=y CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y # CONFIG_RANDOM32_SELFTEST is not set CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m +CONFIG_ZLIB_DEFLATE=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y CONFIG_LZ4_COMPRESS=m @@ -4159,13 +4196,14 @@ CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y CONFIG_SWIOTLB=y +# CONFIG_SWIOTLB_DYNAMIC is not set CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y # CONFIG_DMA_RESTRICTED_POOL is not set CONFIG_DMA_NONCOHERENT_MMAP=y CONFIG_DMA_COHERENT_POOL=y CONFIG_DMA_DIRECT_REMAP=y CONFIG_DMA_CMA=y -CONFIG_DMA_PERNUMA_CMA=y +# CONFIG_DMA_NUMA_CMA is not set # # Default contiguous memory area size: @@ -4381,7 +4419,6 @@ CONFIG_STACKTRACE=y # CONFIG_DEBUG_PLIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_BUG_ON_DATA_CORRUPTION is not set # CONFIG_DEBUG_MAPLE_TREE is not set # end of Debug kernel data structures