* [PATCH v4 23/27] arm64: dts: qcom: starqltechn: add display PMIC
From: Dzmitry Sankouski @ 2024-09-13 15:08 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add support for s2dos05 display / touchscreen PMIC
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
.../boot/dts/qcom/sdm845-samsung-starqltechn.dts | 77 ++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
index 865253d8f0c7..5e5684f84ffb 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -39,6 +39,9 @@ framebuffer: framebuffer@9d400000 {
height = <2960>;
stride = <(1440 * 4)>;
format = "a8r8g8b8";
+ vci-supply = <&s2dos05_ldo4>;
+ vddr-supply = <&s2dos05_buck1>;
+ vdd3-supply = <&s2dos05_ldo1>;
};
};
@@ -101,6 +104,66 @@ key-wink {
};
};
+ i2c21 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&tlmm 127 GPIO_ACTIVE_HIGH>;
+ scl-gpios = <&tlmm 128 GPIO_ACTIVE_HIGH>;
+ i2c-gpio,delay-us = <2>;
+ pinctrl-0 = <&i2c21_sda_state &i2c21_scl_state>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@60 {
+ compatible = "samsung,s2dos05";
+ reg = <0x60>;
+
+ regulators {
+ s2dos05_ldo1: ldo1 {
+ regulator-active-discharge = <1>;
+ regulator-enable-ramp-delay = <12000>;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-name = "s2dos05-ldo1";
+ };
+
+ s2dos05_ldo2: ldo2 {
+ regulator-active-discharge = <1>;
+ regulator-boot-on;
+ regulator-enable-ramp-delay = <12000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "s2dos05-ldo2";
+ };
+
+ s2dos05_ldo3: ldo3 {
+ regulator-active-discharge = <1>;
+ regulator-boot-on;
+ regulator-enable-ramp-delay = <12000>;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-name = "s2dos05-ldo3";
+ };
+
+ s2dos05_ldo4: ldo4 {
+ regulator-active-discharge = <1>;
+ regulator-enable-ramp-delay = <12000>;
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3775000>;
+ regulator-name = "s2dos05-ldo4";
+ };
+
+ s2dos05_buck1: buck1 {
+ regulator-active-discharge = <1>;
+ regulator-enable-ramp-delay = <12000>;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-name = "s2dos05-buck1";
+ };
+ };
+ };
+ };
+
vib_regulator: gpio-regulator {
compatible = "regulator-fixed";
regulator-name = "haptic";
@@ -588,4 +651,18 @@ motor_pwm_suspend_state: motor-pwm-suspend-state {
bias-disable;
output-low;
};
+
+ i2c21_sda_state: i2c21-sda-state {
+ pins = "gpio127";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ i2c21_scl_state: i2c21-scl-state {
+ pins = "gpio128";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
};
--
2.39.2
^ permalink raw reply related
* [PATCH v4 22/27] arm64: dts: qcom: starqltechn: add max77705 PMIC
From: Dzmitry Sankouski @ 2024-09-13 15:08 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add support for max77705 MFD device. Supported sub-devices:
charger, fuelgauge, haptic, led
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
.../boot/dts/qcom/sdm845-samsung-starqltechn.dts | 103 +++++++++++++++++++++
1 file changed, 103 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
index a3bd5231569d..865253d8f0c7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -18,6 +18,16 @@ / {
model = "Samsung Galaxy S9 SM-G9600";
compatible = "samsung,starqltechn", "qcom,sdm845";
+ battery: battery {
+ compatible = "simple-battery";
+ constant-charge-current-max-microamp = <2150000>;
+ charge-full-design-microamp-hours = <3000000>;
+
+ over-voltage-threshold-microvolt = <4500000>;
+ voltage-min-design-microvolt = <3400000>;
+ voltage-max-design-microvolt = <4350000>;
+ };
+
chosen {
#address-cells = <2>;
#size-cells = <2>;
@@ -90,6 +100,27 @@ key-wink {
debounce-interval = <15>;
};
};
+
+ vib_regulator: gpio-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "haptic";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ enable-active-high;
+ gpio = <&pm8998_gpios 18 GPIO_ACTIVE_HIGH>;
+ };
+
+ vib_pwm: pwm {
+ #pwm-cells = <2>;
+ compatible = "clk-pwm";
+ clocks = <&gcc GCC_GP1_CLK>;
+ assigned-clock-parents = <&rpmhcc RPMH_CXO_CLK>;
+ assigned-clocks = <&gcc GCC_GP1_CLK_SRC>;
+ pinctrl-0 = <&motor_pwm_default_state>;
+ pinctrl-1 = <&motor_pwm_suspend_state>;
+ pinctrl-names = "default", "suspend";
+ };
};
@@ -385,10 +416,66 @@ &qupv3_id_1 {
status = "okay";
};
+&gpi_dma1 {
+ status = "okay";
+};
+
&uart9 {
status = "okay";
};
+&i2c14 {
+ status = "okay";
+
+ pmic@66 {
+ compatible = "maxim,max77705";
+ reg = <0x66>;
+ interrupt-parent = <&pm8998_gpios>;
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&chg_int_default>;
+ pinctrl-names = "default";
+
+ leds {
+ compatible = "maxim,max77705-led";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ label = "red:usr1";
+ };
+
+ led@2 {
+ reg = <2>;
+ label = "green:usr2";
+ };
+
+ led@3 {
+ reg = <3>;
+ label = "blue:usr3";
+ };
+ };
+
+ max77705_charger: charger {
+ compatible = "maxim,max77705-charger";
+ monitored-battery = <&battery>;
+ };
+
+ fuel_gauge {
+ compatible = "maxim,max77705-fuel-gauge";
+ monitored-battery = <&battery>;
+ power-supplies = <&max77705_charger>;
+ shunt-resistor-micro-ohms = <5000>;
+ };
+
+ haptic {
+ compatible = "maxim,max77705-haptic";
+ haptic-supply = <&vib_regulator>;
+ pwms = <&vib_pwm 0 100000>;
+ };
+ };
+};
+
&ufs_mem_hc {
reset-gpios = <&tlmm 150 GPIO_ACTIVE_LOW>;
vcc-supply = <&vreg_l20a_2p95>;
@@ -485,4 +572,20 @@ sd_card_det_n_state: sd-card-det-n-state {
function = "gpio";
bias-pull-up;
};
+
+ motor_pwm_default_state: motor-pwm-active-state {
+ pins = "gpio57";
+ function = "gcc_gp1";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ motor_pwm_suspend_state: motor-pwm-suspend-state {
+ pins = "gpio57";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
};
--
2.39.2
^ permalink raw reply related
* [PATCH v4 21/27] arm64: dts: qcom: starqltechn: add gpio keys
From: Dzmitry Sankouski @ 2024-09-13 15:08 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add support for phone buttons.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
.../boot/dts/qcom/sdm845-samsung-starqltechn.dts | 36 ++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
index 5948b401165c..a3bd5231569d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -7,9 +7,11 @@
/dts-v1/;
+#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "sdm845.dtsi"
+#include "pm8998.dtsi"
/ {
chassis-type = "handset";
@@ -69,6 +71,25 @@ memory@a1300000 {
pmsg-size = <0x40000>;
};
};
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ autorepeat;
+
+ key-vol-up {
+ label = "volume_up";
+ gpios = <&pm8998_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <15>;
+ };
+
+ key-wink {
+ label = "key_wink";
+ gpios = <&pm8998_gpios 19 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_ENTER>;
+ debounce-interval = <15>;
+ };
+ };
};
@@ -417,6 +438,21 @@ &usb_1_qmpphy {
status = "okay";
};
+&pm8998_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&pm8998_gpios {
+ chg_int_default: chg-int-default-state {
+ pins = "gpio11";
+ function = "normal";
+ input-enable;
+ bias-disable;
+ power-source = <0>;
+ };
+};
+
&tlmm {
gpio-reserved-ranges = <27 4>, /* SPI (eSE - embedded Secure Element) */
<85 4>; /* SPI (fingerprint reader) */
--
2.39.2
^ permalink raw reply related
* [PATCH v4 20/27] arm64: dts: qcom: starqltechn: remove excess reserved gpios
From: Dzmitry Sankouski @ 2024-09-13 15:08 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Starqltechn has 2 reserved gpio ranges <27 4>, <85 4>.
<27 4> is spi for eSE(embedded Secure Element).
<85 4> is spi for fingerprint.
Remove excess reserved gpio regions.
Fixes: d711b22eee55 ("arm64: dts: qcom: starqltechn: add initial device tree for starqltechn")
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
index 8a0d63bd594b..5948b401165c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -418,7 +418,8 @@ &usb_1_qmpphy {
};
&tlmm {
- gpio-reserved-ranges = <0 4>, <27 4>, <81 4>, <85 4>;
+ gpio-reserved-ranges = <27 4>, /* SPI (eSE - embedded Secure Element) */
+ <85 4>; /* SPI (fingerprint reader) */
sdc2_clk_state: sdc2-clk-state {
pins = "sdc2_clk";
--
2.39.2
^ permalink raw reply related
* [PATCH v4 19/27] arm64: dts: qcom: starqltechn: refactor node order
From: Dzmitry Sankouski @ 2024-09-13 15:08 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Fixes: d711b22eee55 ("arm64: dts: qcom: starqltechn: add initial device tree for starqltechn")
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
index f3f2b25883d8..8a0d63bd594b 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -382,8 +382,8 @@ &ufs_mem_phy {
};
&sdhc_2 {
- pinctrl-names = "default";
pinctrl-0 = <&sdc2_clk_state &sdc2_cmd_state &sdc2_data_state &sd_card_det_n_state>;
+ pinctrl-names = "default";
cd-gpios = <&tlmm 126 GPIO_ACTIVE_LOW>;
vmmc-supply = <&vreg_l21a_2p95>;
vqmmc-supply = <&vddpx_2>;
--
2.39.2
^ permalink raw reply related
* [PATCH v4 18/27] arm64: dts: qcom: starqltechn: fix usb regulator mistake
From: Dzmitry Sankouski @ 2024-09-13 15:08 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Usb regulator was wrongly pointed to vreg_l1a_0p875.
However, on starqltechn it's powered from vreg_l5a_0p8.
Fixes: d711b22eee55 ("arm64: dts: qcom: starqltechn: add initial device tree for starqltechn")
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
index 6fc30fd1262b..f3f2b25883d8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -135,8 +135,6 @@ vdda_pll_cc_ebi23:
vdda_sp_sensor:
vdda_ufs1_core:
vdda_ufs2_core:
- vdda_usb1_ss_core:
- vdda_usb2_ss_core:
vreg_l1a_0p875: ldo1 {
regulator-min-microvolt = <880000>;
regulator-max-microvolt = <880000>;
@@ -157,6 +155,7 @@ vreg_l3a_1p0: ldo3 {
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+ vdda_usb1_ss_core:
vdd_wcss_cx:
vdd_wcss_mx:
vdda_wcss_pll:
--
2.39.2
^ permalink raw reply related
* [PATCH v4 17/27] arm64: dts: qcom: starqltechn: remove wifi
From: Dzmitry Sankouski @ 2024-09-13 15:08 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Starqltechn has broadcom chip for wifi, so sdm845 wifi part
can be disabled.
Fixes: d711b22eee55 ("arm64: dts: qcom: starqltechn: add initial device tree for starqltechn")
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts | 8 --------
1 file changed, 8 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
index d37a433130b9..6fc30fd1262b 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -418,14 +418,6 @@ &usb_1_qmpphy {
status = "okay";
};
-&wifi {
- vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
- vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
- vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
- vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
- status = "okay";
-};
-
&tlmm {
gpio-reserved-ranges = <0 4>, <27 4>, <81 4>, <85 4>;
--
2.39.2
^ permalink raw reply related
* [PATCH v4 16/27] arm64: dts: qcom: sdm845: enable gmu
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Leave gmu enabled, because it's only probed when
GPU is.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi | 4 ----
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 ----
arch/arm64/boot/dts/qcom/sdm845-mtp.dts | 4 ----
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi | 4 ----
arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts | 4 ----
arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi | 4 ----
arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi | 4 ----
arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts | 4 ----
arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 --
9 files changed, 34 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
index e8276db9eabb..a5149a384167 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
@@ -741,10 +741,6 @@ touchscreen@10 {
};
};
-&gmu {
- status = "okay";
-};
-
&gpu {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
index 9a6d3d0c0ee4..59cb6e6e434c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
@@ -444,10 +444,6 @@ &gcc {
<GCC_LPASS_SWAY_CLK>;
};
-&gmu {
- status = "okay";
-};
-
&gpi_dma0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
index 2391f842c903..d31efad8a321 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
@@ -414,10 +414,6 @@ &gcc {
<GCC_LPASS_SWAY_CLK>;
};
-&gmu {
- status = "okay";
-};
-
&gpu {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
index 46e25c53829a..8a0f154bffc3 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
@@ -345,10 +345,6 @@ &gcc {
<GCC_LPASS_SWAY_CLK>;
};
-&gmu {
- status = "okay";
-};
-
&gpu {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
index 486ce175e6bc..87fc4021e024 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
@@ -419,10 +419,6 @@ &gcc {
<GCC_LPASS_SWAY_CLK>;
};
-&gmu {
- status = "okay";
-};
-
&gpu {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
index b02a1dc5fecd..a3a304e1ac87 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
@@ -415,10 +415,6 @@ &gcc {
<GCC_LPASS_SWAY_CLK>;
};
-&gmu {
- status = "okay";
-};
-
&gpi_dma0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
index 617b17b2d7d9..f790eb73abdd 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
@@ -239,10 +239,6 @@ &gcc {
<GCC_LPASS_SWAY_CLK>;
};
-&gmu {
- status = "okay";
-};
-
&gpu {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
index e386b504e978..501575c9beda 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
@@ -381,10 +381,6 @@ &gcc {
<GCC_LPASS_SWAY_CLK>;
};
-&gmu {
- status = "okay";
-};
-
&gpi_dma0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 54077549b9da..fe154216f138 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -4948,8 +4948,6 @@ gmu: gmu@506a000 {
operating-points-v2 = <&gmu_opp_table>;
- status = "disabled";
-
gmu_opp_table: opp-table {
compatible = "operating-points-v2";
--
2.39.2
^ permalink raw reply related
* [PATCH v4 15/27] regulator: add s2dos05 regulator support
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
S2dos05 has 1 buck and 4 LDO regulators, used for powering
panel/touchscreen.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes in v4:
- remove excessive linux/module.h import
- use generic regulator helpers
- use of_match
- use devm_* for mem allocations
- use // style comment
- drop all junk Samsung code
- adjust to depend on sec-core
---
MAINTAINERS | 1 +
drivers/regulator/Kconfig | 8 ++
drivers/regulator/Makefile | 1 +
drivers/regulator/s2dos05-regulator.c | 176 ++++++++++++++++++++++++++++++++++
include/linux/regulator/s2dos05.h | 73 ++++++++++++++
5 files changed, 259 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 444cc855a01e..25dcce07180a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20476,6 +20476,7 @@ F: Documentation/devicetree/bindings/regulator/samsung,s2m*.yaml
F: Documentation/devicetree/bindings/regulator/samsung,s5m*.yaml
F: drivers/clk/clk-s2mps11.c
F: drivers/mfd/sec*.c
+F: drivers/regulator/s2dos*.c
F: drivers/regulator/s2m*.c
F: drivers/regulator/s5m*.c
F: drivers/rtc/rtc-s5m.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 4b411a09c1a6..63085d73cf74 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1322,6 +1322,14 @@ config REGULATOR_RTQ2208
and two ldos. It features wide output voltage range from 0.4V to 2.05V
and the capability to configure the corresponding power stages.
+config REGULATOR_S2DOS05
+ tristate "SLSI S2DOS05 regulator"
+ depends on MFD_SEC_CORE || COMPILE_TEST
+ help
+ This driver provides support for the voltage regulators of the S2DOS05.
+ The S2DOS05 is a companion power management IC for the smart phones.
+ The S2DOS05 has 4 LDOs and 1 BUCK outputs.
+
config REGULATOR_S2MPA01
tristate "Samsung S2MPA01 voltage regulator"
depends on MFD_SEC_CORE || COMPILE_TEST
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index a61fa42b13c4..d26e0db7c825 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -154,6 +154,7 @@ obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o
obj-$(CONFIG_REGULATOR_RTQ2134) += rtq2134-regulator.o
obj-$(CONFIG_REGULATOR_RTQ6752) += rtq6752-regulator.o
obj-$(CONFIG_REGULATOR_RTQ2208) += rtq2208-regulator.o
+obj-$(CONFIG_REGULATOR_S2DOS05) += s2dos05-regulator.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
diff --git a/drivers/regulator/s2dos05-regulator.c b/drivers/regulator/s2dos05-regulator.c
new file mode 100644
index 000000000000..1325c8311b08
--- /dev/null
+++ b/drivers/regulator/s2dos05-regulator.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// s2dos05.c - Regulator driver for the Samsung s2dos05
+//
+// Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.com>
+
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/regulator/s2dos05.h>
+#include <linux/i2c.h>
+
+struct s2dos05_data {
+ struct regmap *regmap;
+ struct device *dev;
+};
+
+static const struct regulator_ops s2dos05_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+#define _BUCK(macro) S2DOS05_BUCK##macro
+#define _buck_ops(num) s2dos05_ops##num
+
+#define _LDO(macro) S2DOS05_LDO##macro
+#define _REG(ctrl) S2DOS05_REG##ctrl
+#define _ldo_ops(num) s2dos05_ops##num
+#define _MASK(macro) S2DOS05_ENABLE_MASK##macro
+#define _TIME(macro) S2DOS05_ENABLE_TIME##macro
+
+#define BUCK_DESC(_name, _id, _ops, m, s, v, e, em, t, a) { \
+ .name = _name, \
+ .id = _id, \
+ .ops = _ops, \
+ .of_match = of_match_ptr(_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = m, \
+ .uV_step = s, \
+ .n_voltages = S2DOS05_BUCK_N_VOLTAGES, \
+ .vsel_reg = v, \
+ .vsel_mask = S2DOS05_BUCK_VSEL_MASK, \
+ .enable_reg = e, \
+ .enable_mask = em, \
+ .enable_time = t, \
+ .active_discharge_off = 0, \
+ .active_discharge_on = S2DOS05_BUCK_FD_MASK, \
+ .active_discharge_reg = a, \
+ .active_discharge_mask = S2DOS05_BUCK_FD_MASK \
+}
+
+#define LDO_DESC(_name, _id, _ops, m, s, v, e, em, t, a) { \
+ .name = _name, \
+ .id = _id, \
+ .ops = _ops, \
+ .of_match = of_match_ptr(_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = m, \
+ .uV_step = s, \
+ .n_voltages = S2DOS05_LDO_N_VOLTAGES, \
+ .vsel_reg = v, \
+ .vsel_mask = S2DOS05_LDO_VSEL_MASK, \
+ .enable_reg = e, \
+ .enable_mask = em, \
+ .enable_time = t, \
+ .active_discharge_off = 0, \
+ .active_discharge_on = S2DOS05_LDO_FD_MASK, \
+ .active_discharge_reg = a, \
+ .active_discharge_mask = S2DOS05_LDO_FD_MASK \
+}
+
+static struct regulator_desc regulators[S2DOS05_REGULATOR_MAX] = {
+ // name, id, ops, min_uv, uV_step, vsel_reg, enable_reg
+ LDO_DESC("ldo1", _LDO(1), &_ldo_ops(), _LDO(_MIN1),
+ _LDO(_STEP1), _REG(_LDO1_CFG),
+ _REG(_EN), _MASK(_L1), _TIME(_LDO), _REG(_LDO1_CFG)),
+ LDO_DESC("ldo2", _LDO(2), &_ldo_ops(), _LDO(_MIN1),
+ _LDO(_STEP1), _REG(_LDO2_CFG),
+ _REG(_EN), _MASK(_L2), _TIME(_LDO), _REG(_LDO2_CFG)),
+ LDO_DESC("ldo3", _LDO(3), &_ldo_ops(), _LDO(_MIN2),
+ _LDO(_STEP1), _REG(_LDO3_CFG),
+ _REG(_EN), _MASK(_L3), _TIME(_LDO), _REG(_LDO3_CFG)),
+ LDO_DESC("ldo4", _LDO(4), &_ldo_ops(), _LDO(_MIN2),
+ _LDO(_STEP1), _REG(_LDO4_CFG),
+ _REG(_EN), _MASK(_L4), _TIME(_LDO), _REG(_LDO4_CFG)),
+ BUCK_DESC("buck1", _BUCK(1), &_buck_ops(), _BUCK(_MIN1),
+ _BUCK(_STEP1), _REG(_BUCK_VOUT),
+ _REG(_EN), _MASK(_B1), _TIME(_BUCK), _REG(_BUCK_CFG)),
+};
+
+static int s2dos05_pmic_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct of_regulator_match *rdata = NULL;
+ struct s2dos05_data *s2dos05;
+ struct regulator_config config = { };
+ unsigned int rdev_num = ARRAY_SIZE(regulators);
+ int i, ret;
+
+ s2dos05 = devm_kzalloc(dev, sizeof(struct s2dos05_data),
+ GFP_KERNEL);
+ if (!s2dos05)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, s2dos05);
+
+ rdata = devm_kcalloc(dev, rdev_num, sizeof(*rdata), GFP_KERNEL);
+ if (!rdata)
+ return -ENOMEM;
+
+ for (i = 0; i < rdev_num; i++)
+ rdata[i].name = regulators[i].name;
+
+ s2dos05->regmap = iodev->regmap_pmic;
+ s2dos05->dev = dev;
+ if (!dev->of_node)
+ dev->of_node = dev->parent->of_node;
+
+ for (i = 0; i < rdev_num; i++) {
+ struct regulator_dev *regulator;
+
+ config.init_data = rdata[i].init_data;
+ config.of_node = rdata[i].of_node;
+ config.dev = dev;
+ config.driver_data = s2dos05;
+ regulator = devm_regulator_register(&pdev->dev,
+ ®ulators[i], &config);
+ if (IS_ERR(regulator)) {
+ ret = PTR_ERR(regulator);
+ dev_err(&pdev->dev, "regulator init failed for %d\n",
+ i);
+ }
+ }
+
+ return ret;
+}
+
+static const struct platform_device_id s2dos05_pmic_id[] = {
+ { "s2dos05-regulator" },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, s2dos05_pmic_id);
+
+static struct platform_driver s2dos05_platform_driver = {
+ .driver = {
+ .name = "s2dos05",
+ },
+ .probe = s2dos05_pmic_probe,
+ .id_table = s2dos05_pmic_id,
+};
+module_platform_driver(s2dos05_platform_driver);
+
+MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>");
+MODULE_DESCRIPTION("SAMSUNG s2dos05 Regulator Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/regulator/s2dos05.h b/include/linux/regulator/s2dos05.h
new file mode 100644
index 000000000000..2e89fcbce769
--- /dev/null
+++ b/include/linux/regulator/s2dos05.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+// s2dos05.h
+//
+// Copyright (c) 2016 Samsung Electronics Co., Ltd
+// http://www.samsung.com
+// Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.com>
+
+#ifndef __LINUX_S2DOS05_H
+#define __LINUX_S2DOS05_H
+
+// S2DOS05 registers
+// Slave Addr : 0xC0
+enum S2DOS05_reg {
+ S2DOS05_REG_DEV_ID,
+ S2DOS05_REG_TOPSYS_STAT,
+ S2DOS05_REG_STAT,
+ S2DOS05_REG_EN,
+ S2DOS05_REG_LDO1_CFG,
+ S2DOS05_REG_LDO2_CFG,
+ S2DOS05_REG_LDO3_CFG,
+ S2DOS05_REG_LDO4_CFG,
+ S2DOS05_REG_BUCK_CFG,
+ S2DOS05_REG_BUCK_VOUT,
+ S2DOS05_REG_IRQ_MASK = 0x0D,
+ S2DOS05_REG_SSD_TSD = 0x0E,
+ S2DOS05_REG_OCL = 0x10,
+ S2DOS05_REG_IRQ = 0x11
+};
+
+// S2DOS05 regulator ids
+enum S2DOS05_regulators {
+ S2DOS05_LDO1,
+ S2DOS05_LDO2,
+ S2DOS05_LDO3,
+ S2DOS05_LDO4,
+ S2DOS05_BUCK1,
+ S2DOS05_REG_MAX,
+};
+
+#define S2DOS05_IRQ_PWRMT_MASK BIT(5)
+#define S2DOS05_IRQ_TSD_MASK BIT(4)
+#define S2DOS05_IRQ_SSD_MASK BIT(3)
+#define S2DOS05_IRQ_SCP_MASK BIT(2)
+#define S2DOS05_IRQ_UVLO_MASK BIT(1)
+#define S2DOS05_IRQ_OCD_MASK BIT(0)
+
+#define S2DOS05_BUCK_MIN1 506250
+#define S2DOS05_LDO_MIN1 1500000
+#define S2DOS05_LDO_MIN2 2700000
+#define S2DOS05_BUCK_STEP1 6250
+#define S2DOS05_LDO_STEP1 25000
+#define S2DOS05_LDO_VSEL_MASK 0x7F
+#define S2DOS05_LDO_FD_MASK 0x80
+#define S2DOS05_BUCK_VSEL_MASK 0xFF
+#define S2DOS05_BUCK_FD_MASK 0x08
+
+#define S2DOS05_ENABLE_MASK_L1 BIT(0)
+#define S2DOS05_ENABLE_MASK_L2 BIT(1)
+#define S2DOS05_ENABLE_MASK_L3 BIT(2)
+#define S2DOS05_ENABLE_MASK_L4 BIT(3)
+#define S2DOS05_ENABLE_MASK_B1 BIT(4)
+
+#define S2DOS05_RAMP_DELAY 12000
+
+#define S2DOS05_ENABLE_TIME_LDO 50
+#define S2DOS05_ENABLE_TIME_BUCK 350
+
+#define S2DOS05_LDO_N_VOLTAGES (S2DOS05_LDO_VSEL_MASK + 1)
+#define S2DOS05_BUCK_N_VOLTAGES (S2DOS05_BUCK_VSEL_MASK + 1)
+
+#define S2DOS05_REGULATOR_MAX (S2DOS05_REG_MAX)
+
+#endif // __LINUX_S2DOS05_H
--
2.39.2
^ permalink raw reply related
* [PATCH v4 14/27] mfd: sec-core: add s2dos05 support
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
S2dos05 is a panel/touchscreen PMIC, often found in
Samsung phones. We define 2 sub-devices for which drivers will
be added in subsequent patches.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
drivers/mfd/sec-core.c | 11 +++++++++++
include/linux/mfd/samsung/core.h | 1 +
2 files changed, 12 insertions(+)
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index a6b0d7300b2d..cdfe738e1d76 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -34,6 +34,10 @@ static const struct mfd_cell s5m8767_devs[] = {
},
};
+static const struct mfd_cell s2dos05_devs[] = {
+ { .name = "s2dos05-regulator", },
+};
+
static const struct mfd_cell s2mps11_devs[] = {
{ .name = "s2mps11-regulator", },
{ .name = "s2mps14-rtc", },
@@ -83,6 +87,9 @@ static const struct of_device_id sec_dt_match[] = {
{
.compatible = "samsung,s5m8767-pmic",
.data = (void *)S5M8767X,
+ }, {
+ .compatible = "samsung,s2dos05",
+ .data = (void *)S2DOS05,
}, {
.compatible = "samsung,s2mps11-pmic",
.data = (void *)S2MPS11X,
@@ -339,6 +346,10 @@ static int sec_pmic_probe(struct i2c_client *i2c)
sec_devs = s5m8767_devs;
num_sec_devs = ARRAY_SIZE(s5m8767_devs);
break;
+ case S2DOS05:
+ sec_devs = s2dos05_devs;
+ num_sec_devs = ARRAY_SIZE(s2dos05_devs);
+ break;
case S2MPA01:
sec_devs = s2mpa01_devs;
num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index a212b9f72bc9..750274d41fc0 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -37,6 +37,7 @@ struct gpio_desc;
enum sec_device_type {
S5M8767X,
+ S2DOS05,
S2MPA01,
S2MPS11X,
S2MPS13X,
--
2.39.2
^ permalink raw reply related
* [PATCH v4 13/27] leds: max77705: Add LEDs support
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
This adds basic support for LEDs for the max77705 PMIC.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes in v4:
- inline BLINK_(ON|OFF) macro
- remove camel case
- drop backwards compatibility(new driver)
- drop module alias
---
MAINTAINERS | 1 +
drivers/leds/Kconfig | 6 ++
drivers/leds/Makefile | 1 +
drivers/leds/leds-max77705.c | 158 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 166 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 716e66bb7982..444cc855a01e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14073,6 +14073,7 @@ F: drivers/*/max14577*.c
F: drivers/*/max77686*.c
F: drivers/*/max77693*.c
F: drivers/*/max77705*.c
+F: drivers/leds/leds-max77705.c
F: drivers/clk/clk-max77686.c
F: drivers/extcon/extcon-max14577.c
F: drivers/extcon/extcon-max77693.c
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index b784bb74a837..292f9f1a237e 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -753,6 +753,12 @@ config LEDS_MAX77650
help
LEDs driver for MAX77650 family of PMICs from Maxim Integrated.
+config LEDS_MAX77705
+ tristate "LED support for Maxim MAX77705 RGB"
+ depends on MFD_MAX77705 && LEDS_CLASS && I2C
+ help
+ LED driver for MAX77705 MFD chip from Maxim Integrated.
+
config LEDS_MAX8997
tristate "LED support for MAX8997 PMIC"
depends on LEDS_CLASS && MFD_MAX8997
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 18afbb5a23ee..096bf244527d 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o
obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o
obj-$(CONFIG_LEDS_MAX5970) += leds-max5970.o
obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o
+obj-$(CONFIG_LEDS_MAX77705) += leds-max77705.o
obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o
obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o
diff --git a/drivers/leds/leds-max77705.c b/drivers/leds/leds-max77705.c
new file mode 100644
index 000000000000..6190c010b039
--- /dev/null
+++ b/drivers/leds/leds-max77705.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Based on leds-max77650 driver:
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// LED driver for MAXIM 77705 MFD.
+// Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.org>
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/mfd/max77705-private.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MAX77705_LED_NUM_LEDS 4
+#define MAX77705_LED_EN_MASK GENMASK(1, 0)
+#define MAX77705_LED_MAX_BRIGHTNESS 0xff
+
+struct max77705_led {
+ struct led_classdev cdev;
+ struct regmap *regmap;
+ unsigned int en_shift;
+ unsigned int reg_brightness;
+};
+
+static struct max77705_led *max77705_to_led(struct led_classdev *cdev)
+{
+ return container_of(cdev, struct max77705_led, cdev);
+}
+
+static int max77705_rgb_blink(struct led_classdev *cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct max77705_led *led = max77705_to_led(cdev);
+ int value, on_value, off_value;
+
+ on_value = (((*delay_on < 100) ? 0 :
+ (*delay_on < 500) ? *delay_on/100 - 1 :
+ (*delay_on < 3250) ? (*delay_on - 500) / 250 + 4 : 15) << 4);
+ off_value = ((*delay_off < 1) ? 0x00 :
+ (*delay_off < 500) ? 0x01 :
+ (*delay_off < 5000) ? *delay_off / 500 :
+ (*delay_off < 8000) ? (*delay_off - 5000) / 1000 + 10 :
+ (*delay_off < 12000) ? (*delay_off - 8000) / 2000 + 13 : 15);
+ value = on_value | off_value;
+ return regmap_write(led->regmap, MAX77705_RGBLED_REG_LEDBLNK, value);
+}
+
+static int max77705_led_brightness_set(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ struct max77705_led *led = max77705_to_led(cdev);
+ int ret;
+ unsigned long blink_default = 0;
+
+ if (brightness == LED_OFF) {
+ // Flash OFF
+ ret = regmap_update_bits(led->regmap,
+ MAX77705_RGBLED_REG_LEDEN,
+ MAX77705_LED_EN_MASK << led->en_shift, 0);
+ max77705_rgb_blink(cdev, &blink_default, &blink_default);
+ } else {
+ // Set current
+ ret = regmap_write(led->regmap,
+ led->reg_brightness, brightness);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(led->regmap,
+ MAX77705_RGBLED_REG_LEDEN, LED_ON << led->en_shift,
+ MAX77705_LED_EN_MASK << led->en_shift);
+ }
+
+ return ret;
+}
+
+static int max77705_led_probe(struct platform_device *pdev)
+{
+ struct fwnode_handle *child;
+ struct max77705_led *leds, *led;
+ struct device *dev;
+ struct regmap *map;
+ int rv, num_leds;
+ u32 reg;
+
+ dev = &pdev->dev;
+
+ leds = devm_kcalloc(dev, sizeof(*leds),
+ MAX77705_LED_NUM_LEDS, GFP_KERNEL);
+ if (!leds)
+ return -ENOMEM;
+
+ map = dev_get_regmap(dev->parent, NULL);
+ if (!map)
+ return -ENODEV;
+
+ num_leds = device_get_child_node_count(dev);
+ if (!num_leds || num_leds > MAX77705_LED_NUM_LEDS)
+ return -ENODEV;
+
+ device_for_each_child_node(dev, child) {
+ struct led_init_data init_data = {};
+
+ rv = fwnode_property_read_u32(child, "reg", ®);
+ if (rv || reg >= MAX77705_LED_NUM_LEDS) {
+ rv = -EINVAL;
+ goto err_node_put;
+ }
+
+ led = &leds[reg];
+ led->regmap = map;
+ led->reg_brightness = MAX77705_RGBLED_REG_LED0BRT + reg;
+ led->en_shift = 2 * reg;
+ led->cdev.brightness_set_blocking = max77705_led_brightness_set;
+ led->cdev.blink_set = max77705_rgb_blink;
+ led->cdev.max_brightness = MAX77705_LED_MAX_BRIGHTNESS;
+
+ init_data.fwnode = child;
+ init_data.devicename = "max77705";
+
+ rv = devm_led_classdev_register_ext(dev, &led->cdev,
+ &init_data);
+ if (rv)
+ goto err_node_put;
+
+ rv = max77705_led_brightness_set(&led->cdev, LED_OFF);
+ if (rv)
+ goto err_node_put;
+ }
+
+ return 0;
+err_node_put:
+ fwnode_handle_put(child);
+ return rv;
+}
+
+static const struct of_device_id max77705_led_of_match[] = {
+ { .compatible = "maxim,max77705-led" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max77705_led_of_match);
+
+static struct platform_driver max77705_led_driver = {
+ .driver = {
+ .name = "max77705-led",
+ .of_match_table = max77705_led_of_match,
+ },
+ .probe = max77705_led_probe,
+};
+module_platform_driver(max77705_led_driver);
+
+MODULE_DESCRIPTION("MAXIM 77705 LED driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>");
+MODULE_LICENSE("GPL");
--
2.39.2
^ permalink raw reply related
* [PATCH v4 12/27] power: supply: max77705: Add fuel gauge driver for Maxim 77705
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add driver for Maxim 77705 fuel gauge (part of max77705
MFD driver) providing power supply class information to userspace.
The driver is configured through DTS (battery and system related
settings).
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes for V4:
- rework driver from scratch
- change word delimiters in filenames to "_"
- remove debugfs code
- cleanup header
---
drivers/power/supply/Kconfig | 7 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/max77705_fuel_gauge.c | 348 +++++++++++++++++++++++++++++
include/linux/power/max77705_fuelgauge.h | 65 ++++++
4 files changed, 421 insertions(+)
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index fe84d2004f57..0b2da9d88a80 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -579,6 +579,13 @@ config CHARGER_MAX77705
help
Say Y to enable support for the Maxim MAX77705 battery charger.
+config FUEL_GAUGE_MAX77705
+ tristate "MAX77705 fuel gauge driver"
+ depends on MFD_MAX77705
+ default n
+ help
+ Say Y to enable support for MAXIM MAX77705 fuel gauge driver.
+
config CHARGER_MAX77976
tristate "Maxim MAX77976 battery charger driver"
depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index daa9228fa04b..b949600a6207 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -80,6 +80,7 @@ obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o
obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
obj-$(CONFIG_CHARGER_MAX77705) += max77705_charger.o
+obj-$(CONFIG_FUEL_GAUGE_MAX77705) += max77705_fuel_gauge.o
obj-$(CONFIG_CHARGER_MAX77976) += max77976_charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
diff --git a/drivers/power/supply/max77705_fuel_gauge.c b/drivers/power/supply/max77705_fuel_gauge.c
new file mode 100644
index 000000000000..90d695bfdf9f
--- /dev/null
+++ b/drivers/power/supply/max77705_fuel_gauge.c
@@ -0,0 +1,348 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.org>
+//
+// Fuel gauge driver for MAXIM 77705 charger/power-supply.
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max77693-common.h>
+#include <linux/mfd/max77705-private.h>
+#include <linux/power/max77705_fuelgauge.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+
+static const char *max77705_fuelgauge_model = "max77705";
+static const char *max77705_fuelgauge_manufacturer = "Maxim Integrated";
+
+static enum power_supply_property max77705_fuelgauge_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_OCV,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+};
+
+static int max77705_fg_read_reg(struct max77705_fuelgauge_data *fuelgauge,
+ unsigned int reg, unsigned int *val)
+{
+ struct regmap *regmap = fuelgauge->regmap;
+ u8 data[2];
+ int ret;
+
+ ret = regmap_noinc_read(regmap, reg, data, sizeof(data));
+ if (ret < 0)
+ return ret;
+
+ *val = (data[1] << 8) + data[0];
+
+ return 0;
+}
+
+static int max77705_fg_read_temp(struct max77705_fuelgauge_data *fuelgauge,
+ int *val)
+{
+ struct regmap *regmap = fuelgauge->regmap;
+ u8 data[2] = { 0, 0 };
+ int ret, temperature = 0;
+
+ ret = regmap_noinc_read(regmap, TEMPERATURE_REG, data, sizeof(data));
+ if (ret < 0)
+ return ret;
+
+ if (data[1] & BIT(7))
+ temperature = ((~(data[1])) & 0xFF) + 1;
+ else
+ temperature = data[1] & 0x7f;
+
+ temperature *= 10;
+ temperature += data[0] * 10 / 256;
+ *val = temperature;
+
+ return 0;
+}
+
+static int max77705_fg_check_battery_present(struct max77705_fuelgauge_data
+ *fuelgauge, int *val)
+{
+ struct regmap *regmap = fuelgauge->regmap;
+ u8 status_data[2];
+ int ret;
+
+ ret = regmap_noinc_read(regmap, STATUS_REG, status_data, sizeof(status_data));
+ if (ret < 0)
+ return ret;
+
+ *val = !(status_data[0] & MAX77705_BAT_ABSENT_MASK);
+
+ return 0;
+}
+
+static int max77705_battery_get_status(struct max77705_fuelgauge_data *fuelgauge,
+ int *val)
+{
+ int current_now;
+ int am_i_supplied;
+ int ret;
+ unsigned int soc_rep;
+
+ am_i_supplied = power_supply_am_i_supplied(fuelgauge->psy_fg);
+ if (am_i_supplied) {
+ if (am_i_supplied == -ENODEV) {
+ dev_err(fuelgauge->dev,
+ "power supply not found, fall back to current-based status checking\n");
+ } else {
+ *val = POWER_SUPPLY_STATUS_CHARGING;
+ return 0;
+ }
+ }
+ ret = max77705_fg_read_reg(fuelgauge, SOCREP_REG, &soc_rep);
+ if (ret)
+ return ret;
+
+ if (soc_rep < 100) {
+ ret = max77705_fg_read_reg(fuelgauge, CURRENT_REG, ¤t_now);
+ if (ret)
+ return ret;
+
+ if (current_now > 0)
+ *val = POWER_SUPPLY_STATUS_CHARGING;
+ else if (current_now < 0)
+ *val = POWER_SUPPLY_STATUS_DISCHARGING;
+ else
+ *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ *val = POWER_SUPPLY_STATUS_FULL;
+ }
+
+ return 0;
+}
+
+static void max77705_unit_adjustment(struct max77705_fuelgauge_data *fuelgauge,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ const unsigned int base_unit_conversion = 1000;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ case POWER_SUPPLY_PROP_VOLTAGE_OCV:
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ val->intval = max77705_fg_vs_convert(val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ val->intval = max77705_fg_cs_convert(val->intval,
+ fuelgauge->rsense_conductance);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval *= base_unit_conversion;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = min(val->intval, 100);
+ break;
+ default:
+ dev_dbg(fuelgauge->dev,
+ "%s: no need for unit conversion %d\n", __func__, psp);
+ }
+}
+
+static int max77705_fg_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max77705_fuelgauge_data *fuelgauge =
+ power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ ret = max77705_battery_get_status(fuelgauge, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ ret = max77705_fg_check_battery_present(fuelgauge, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = max77705_fg_read_reg(fuelgauge, VCELL_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_OCV:
+ ret = max77705_fg_read_reg(fuelgauge, VFOCV_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ ret = max77705_fg_read_reg(fuelgauge, AVR_VCELL_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = max77705_fg_read_reg(fuelgauge, CURRENT_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ ret = max77705_fg_read_reg(fuelgauge, AVG_CURRENT_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ ret = max77705_fg_read_reg(fuelgauge, REMCAP_REP_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ ret = max77705_fg_read_reg(fuelgauge, FULLCAP_REP_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ ret = max77705_fg_read_reg(fuelgauge, DESIGNCAP_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = max77705_fg_read_reg(fuelgauge, SOCREP_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ ret = max77705_fg_read_temp(fuelgauge, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+ ret = max77705_fg_read_reg(fuelgauge, TIME_TO_EMPTY_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
+ ret = max77705_fg_read_reg(fuelgauge, TIME_TO_FULL_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CYCLE_COUNT:
+ ret = max77705_fg_read_reg(fuelgauge, CYCLES_REG, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = max77705_fuelgauge_model;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = max77705_fuelgauge_manufacturer;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ret)
+ return ret;
+
+ max77705_unit_adjustment(fuelgauge, psp, val);
+
+ return 0;
+}
+
+static const struct power_supply_desc max77705_fg_desc = {
+ .name = "max77705-fuel-gauge",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = max77705_fuelgauge_props,
+ .num_properties = ARRAY_SIZE(max77705_fuelgauge_props),
+ .get_property = max77705_fg_get_property,
+};
+
+static int max77705_fg_set_charge_design(struct regmap *regmap, int value)
+{
+ u8 data[2];
+ int value_mah;
+
+ value_mah = value / 1000;
+ data[0] = value_mah & 0xFF;
+ data[1] = (value_mah >> 8) & 0xFF;
+
+ return regmap_noinc_write(regmap, DESIGNCAP_REG, data, sizeof(data));
+}
+
+static int max77705_battery_settings(struct max77705_fuelgauge_data *fuelgauge)
+{
+ struct power_supply_battery_info *info;
+ struct regmap *regmap = fuelgauge->regmap;
+ int ret;
+
+ ret = power_supply_get_battery_info(fuelgauge->psy_fg, &info);
+ if (ret)
+ return ret;
+
+ fuelgauge->bat_info = info;
+
+ if (info->energy_full_design_uwh != info->charge_full_design_uah) {
+ if (info->charge_full_design_uah == -EINVAL)
+ dev_warn(fuelgauge->dev, "missing battery:charge-full-design-microamp-hours\n");
+ ret = max77705_fg_set_charge_design(regmap, info->charge_full_design_uah);
+ }
+
+ return ret;
+}
+
+static int max77705_fuelgauge_parse_dt(struct max77705_fuelgauge_data
+ *fuelgauge)
+{
+ struct device *dev = fuelgauge->dev;
+ struct device_node *np = dev->of_node;
+ int ret;
+ unsigned int rsense;
+
+ if (!np) {
+ dev_err(dev, "no fuelgauge OF node\n");
+ return -EINVAL;
+ }
+ ret = of_property_read_u32(np, "shunt-resistor-micro-ohms",
+ &rsense);
+ if (ret < 0) {
+ dev_warn(dev, "No shunt-resistor-micro-ohms property, assume default\n");
+ fuelgauge->rsense_conductance = 100;
+ } else
+ fuelgauge->rsense_conductance = 1000000 / rsense; /* rsense conductance in Ohm^-1 */
+
+ return 0;
+}
+
+static int max77705_fuelgauge_probe(struct platform_device *pdev)
+{
+ struct max77693_dev *max77705 = dev_get_drvdata(pdev->dev.parent);
+ struct max77705_fuelgauge_data *fuelgauge;
+ struct power_supply_config fuelgauge_cfg = { };
+ struct device *dev = &pdev->dev;
+ int ret = 0;
+
+ fuelgauge = devm_kzalloc(dev, sizeof(*fuelgauge), GFP_KERNEL);
+ if (!fuelgauge)
+ return -ENOMEM;
+
+ fuelgauge->dev = dev;
+ fuelgauge->regmap = max77705->regmap_fg;
+
+ ret = max77705_fuelgauge_parse_dt(fuelgauge);
+ if (ret < 0)
+ return ret;
+
+ fuelgauge_cfg.drv_data = fuelgauge;
+ fuelgauge_cfg.of_node = fuelgauge->dev->of_node;
+
+ fuelgauge->psy_fg = devm_power_supply_register(&pdev->dev,
+ &max77705_fg_desc,
+ &fuelgauge_cfg);
+
+ if (IS_ERR(fuelgauge->psy_fg))
+ return PTR_ERR(fuelgauge->psy_fg);
+
+ return max77705_battery_settings(fuelgauge);
+}
+
+static const struct of_device_id max77705_fg_of_match[] = {
+ { .compatible = "maxim,max77705-fuel-gauge" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max77705_fg_of_match);
+
+static struct platform_driver max77705_fuelgauge_driver = {
+ .driver = {
+ .name = "max77705-fuel-gauge",
+ .of_match_table = max77705_fg_of_match,
+ },
+ .probe = max77705_fuelgauge_probe,
+};
+module_platform_driver(max77705_fuelgauge_driver);
+
+MODULE_DESCRIPTION("Samsung max77705 Fuel Gauge Driver");
+MODULE_AUTHOR("Samsung Electronics");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/power/max77705_fuelgauge.h b/include/linux/power/max77705_fuelgauge.h
new file mode 100644
index 000000000000..599b3fb5a7e4
--- /dev/null
+++ b/include/linux/power/max77705_fuelgauge.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+//
+// Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.org>
+//
+// Fuel gauge driver header for MAXIM 77705 charger/power-supply.
+
+#ifndef __MAX77705_FUELGAUGE_H
+#define __MAX77705_FUELGAUGE_H __FILE__
+
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#define ALERT_EN 0x04
+#define CAPACITY_SCALE_DEFAULT_CURRENT 1000
+#define CAPACITY_SCALE_HV_CURRENT 600
+// Current and capacity values are displayed as a voltage
+// and must be divided by the sense resistor to determine Amps or Amp-hours.
+// This should be applied to all current, charge, energy registers,
+// except ModelGauge m5 Algorithm related ones.
+// current sense resolution
+#define MAX77705_FG_CS_ADC_RESOLUTION 15625 // 1.5625 microvolts
+// voltage sense resolution
+#define MAX77705_FG_VS_ADC_RESOLUTION 78125 // 78.125 microvolts
+// CONFIG_REG register
+#define MAX77705_SOC_ALERT_EN_MASK BIT(2)
+// When set to 1, external temperature measurements should be written from the host
+#define MAX77705_TEX_MASK BIT(8)
+// Enable Thermistor
+#define MAX77705_ETHRM_MASK BIT(5)
+// CONFIG2_REG register
+#define MAX77705_AUTO_DISCHARGE_EN_MASK BIT(9)
+// STATUS_REG register
+#define MAX77705_BAT_ABSENT_MASK BIT(3)
+
+// @brief Convert voltage register value to micro volts
+// @param reg_val - register value
+// @return voltage in micro Volts
+inline u64 max77705_fg_vs_convert(u16 reg_val)
+{
+ u64 result = (u64)reg_val * MAX77705_FG_VS_ADC_RESOLUTION;
+
+ return result / 1000;
+}
+
+// @brief Convert current register value to micro volts
+// @param reg_val - register value
+// @param rsense_conductance - current sense resistor conductance in Ohm^-1
+// @return voltage in micro Volts
+inline s32 max77705_fg_cs_convert(s16 reg_val, u32 rsense_conductance)
+{
+ s64 result = (s64)reg_val * rsense_conductance * MAX77705_FG_CS_ADC_RESOLUTION;
+
+ return result / 10000;
+}
+
+struct max77705_fuelgauge_data {
+ struct device *dev;
+ struct regmap *regmap;
+ struct power_supply *psy_fg;
+ struct power_supply_battery_info *bat_info;
+ u32 rsense_conductance;
+};
+
+#endif // __MAX77705_FUELGAUGE_H
--
2.39.2
^ permalink raw reply related
* [PATCH v4 11/27] power: supply: max77705: Add charger driver for Maxim 77705
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add driver for Maxim 77705 switch-mode charger (part of max77705
MFD driver) providing power supply class information to userspace.
The driver is configured through DTS (battery and system related
settings).
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes for V4:
- start from scratch
- change word delimiters in filenames to '_'
- use GENMASK in header
- remove debugfs code
- migrate to regmap_add_irq_chip
- fix property getters to follow the same style
---
drivers/power/supply/Kconfig | 6 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/max77705_charger.c | 585 ++++++++++++++++++++++++++++++++
include/linux/mfd/max77705_charger.h | 215 ++++++++++++
4 files changed, 807 insertions(+)
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index bcfa63fb9f1e..fe84d2004f57 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -573,6 +573,12 @@ config CHARGER_MAX77693
help
Say Y to enable support for the Maxim MAX77693 battery charger.
+config CHARGER_MAX77705
+ tristate "Maxim MAX77705 battery charger driver"
+ depends on MFD_MAX77705
+ help
+ Say Y to enable support for the Maxim MAX77705 battery charger.
+
config CHARGER_MAX77976
tristate "Maxim MAX77976 battery charger driver"
depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 8dcb41545317..daa9228fa04b 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o
obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
+obj-$(CONFIG_CHARGER_MAX77705) += max77705_charger.o
obj-$(CONFIG_CHARGER_MAX77976) += max77976_charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
new file mode 100644
index 000000000000..2d82c6663002
--- /dev/null
+++ b/drivers/power/supply/max77705_charger.c
@@ -0,0 +1,585 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Based on max77650-charger.c:
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.org>
+//
+// Battery charger driver for MAXIM 77705 charger/power-supply.
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max77693-common.h>
+#include <linux/mfd/max77705-private.h>
+#include <linux/mfd/max77705_charger.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+
+static const char *max77705_charger_model = "max77705";
+static const char *max77705_charger_manufacturer = "Maxim Integrated";
+
+static enum power_supply_property max77705_charger_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+};
+
+static int max77705_chgin_irq(void *irq_drv_data)
+{
+ struct max77705_charger_data *charger = irq_drv_data;
+
+ queue_work(charger->wqueue, &charger->chgin_work);
+
+ return 0;
+}
+
+static const struct regmap_irq max77705_charger_irqs[] = {
+ { .mask = MAX77705_BYP_IM, },
+ { .mask = MAX77705_INP_LIMIT_IM, },
+ { .mask = MAX77705_BATP_IM, },
+ { .mask = MAX77705_BAT_IM, },
+ { .mask = MAX77705_CHG_IM, },
+ { .mask = MAX77705_WCIN_IM, },
+ { .mask = MAX77705_CHGIN_IM, },
+ { .mask = MAX77705_AICL_IM, },
+};
+
+static const struct regmap_irq_chip max77705_charger_irq_chip = {
+ .name = "max77705-charger",
+ .status_base = MAX77705_CHG_REG_INT,
+ .mask_base = MAX77705_CHG_REG_INT_MASK,
+ .handle_post_irq = max77705_chgin_irq,
+ .num_regs = 1,
+ .irqs = max77705_charger_irqs,
+ .num_irqs = ARRAY_SIZE(max77705_charger_irqs),
+};
+
+static int max77705_charger_enable(struct max77705_charger_data *chg)
+{
+ int rv;
+
+ rv = regmap_update_bits(chg->regmap, MAX77705_CHG_REG_CNFG_09,
+ MAX77705_CHG_EN_MASK, MAX77705_CHG_EN_MASK);
+ if (rv)
+ dev_err(chg->dev, "unable to enable the charger: %d\n", rv);
+
+ return rv;
+}
+
+static void max77705_charger_disable(struct max77705_charger_data *chg)
+{
+ int rv;
+
+ rv = regmap_update_bits(chg->regmap,
+ MAX77705_CHG_REG_CNFG_09,
+ MAX77705_CHG_EN_MASK,
+ MAX77705_CHG_DISABLE);
+ if (rv)
+ dev_err(chg->dev, "unable to disable the charger: %d\n", rv);
+}
+
+static int max77705_get_online(struct regmap *regmap, int *val)
+{
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(regmap, MAX77705_CHG_REG_INT_OK, &data);
+ if (ret < 0)
+ return ret;
+
+ *val = !!(data & MAX77705_CHGIN_OK);
+
+ return 0;
+}
+
+static int max77705_check_battery(struct max77705_charger_data *charger, int *val)
+{
+ unsigned int reg_data;
+ unsigned int reg_data2;
+ struct regmap *regmap = charger->regmap;
+
+
+ regmap_read(regmap, MAX77705_CHG_REG_INT_OK, ®_data);
+
+ dev_dbg(charger->dev, "CHG_INT_OK(0x%x)\n", reg_data);
+
+ regmap_read(regmap,
+ MAX77705_CHG_REG_DETAILS_00, ®_data2);
+
+ dev_dbg(charger->dev, "CHG_DETAILS00(0x%x)\n", reg_data2);
+
+ if ((reg_data & MAX77705_BATP_OK) || !(reg_data2 & MAX77705_BATP_DTLS))
+ *val = true;
+ else
+ *val = false;
+
+ return 0;
+}
+
+static int max77705_get_charge_type(struct max77705_charger_data *charger, int *val)
+{
+ struct regmap *regmap = charger->regmap;
+ unsigned int reg_data;
+
+ regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data);
+ if (!MAX77705_CHARGER_CHG_CHARGING(reg_data)) {
+ *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ return 0;
+ }
+
+ regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, ®_data);
+ reg_data &= MAX77705_CHG_DTLS;
+
+ switch (reg_data) {
+ case 0x0:
+ case MAX77705_CHARGER_CONSTANT_CURRENT:
+ case MAX77705_CHARGER_CONSTANT_VOLTAGE:
+ *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
+ return 0;
+ default:
+ *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ return 0;
+ }
+
+ return 0;
+}
+
+static int max77705_get_status(struct max77705_charger_data *charger, int *val)
+{
+ struct regmap *regmap = charger->regmap;
+ unsigned int reg_data;
+
+ regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data);
+ if (!MAX77705_CHARGER_CHG_CHARGING(reg_data)) {
+ *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ return 0;
+ }
+
+ regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, ®_data);
+ reg_data &= MAX77705_CHG_DTLS;
+
+ switch (reg_data) {
+ case 0x0:
+ case MAX77705_CHARGER_CONSTANT_CURRENT:
+ case MAX77705_CHARGER_CONSTANT_VOLTAGE:
+ *val = POWER_SUPPLY_STATUS_CHARGING;
+ return 0;
+ case MAX77705_CHARGER_END_OF_CHARGE:
+ case MAX77705_CHARGER_DONE:
+ *val = POWER_SUPPLY_STATUS_FULL;
+ return 0;
+ // those values hard coded as in vendor kernel, because of
+ // failure to determine it's actual meaning.
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ return 0;
+ case 0x08:
+ case 0xA:
+ case 0xB:
+ *val = POWER_SUPPLY_STATUS_DISCHARGING;
+ return 0;
+ default:
+ *val = POWER_SUPPLY_STATUS_UNKNOWN;
+ return 0;
+ }
+
+ return 0;
+}
+
+static int max77705_get_vbus_state(struct regmap *regmap, int *value)
+{
+ int ret;
+ unsigned int charge_dtls;
+
+ ret = regmap_read(regmap, MAX77705_CHG_REG_DETAILS_00, &charge_dtls);
+ if (ret)
+ return ret;
+
+ charge_dtls = ((charge_dtls & MAX77705_CHGIN_DTLS) >>
+ MAX77705_CHGIN_DTLS_SHIFT);
+
+ switch (charge_dtls) {
+ case 0x00:
+ *value = POWER_SUPPLY_HEALTH_UNDERVOLTAGE;
+ break;
+ case 0x01:
+ *value = POWER_SUPPLY_HEALTH_UNDERVOLTAGE;
+ break;
+ case 0x02:
+ *value = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ break;
+ case 0x03:
+ *value = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+static int max77705_get_battery_health(struct max77705_charger_data *charger,
+ int *value)
+{
+ struct regmap *regmap = charger->regmap;
+ unsigned int bat_dtls;
+
+ regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, &bat_dtls);
+ bat_dtls = ((bat_dtls & MAX77705_BAT_DTLS) >> MAX77705_BAT_DTLS_SHIFT);
+
+ switch (bat_dtls) {
+ case MAX77705_BATTERY_NOBAT:
+ dev_dbg(charger->dev, "%s: No battery and the charger is suspended\n",
+ __func__);
+ *value = POWER_SUPPLY_HEALTH_NO_BATTERY;
+ break;
+ case MAX77705_BATTERY_PREQUALIFICATION:
+ dev_dbg(charger->dev, "%s: battery is okay but its voltage is low(~VPQLB)\n",
+ __func__);
+ break;
+ case MAX77705_BATTERY_DEAD:
+ dev_dbg(charger->dev, "%s: battery dead\n", __func__);
+ *value = POWER_SUPPLY_HEALTH_DEAD;
+ break;
+ case MAX77705_BATTERY_GOOD:
+ case MAX77705_BATTERY_LOWVOLTAGE:
+ *value = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ case MAX77705_BATTERY_OVERVOLTAGE:
+ dev_dbg(charger->dev, "%s: battery ovp\n", __func__);
+ *value = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ break;
+ default:
+ dev_dbg(charger->dev, "%s: battery unknown\n", __func__);
+ *value = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ break;
+ }
+
+ return 0;
+}
+
+static int max77705_get_health(struct max77705_charger_data *charger, int *val)
+{
+ struct regmap *regmap = charger->regmap;
+ int ret, is_online = 0;
+
+ ret = max77705_get_online(regmap, &is_online);
+ if (ret)
+ return ret;
+ if (is_online) {
+ ret = max77705_get_vbus_state(regmap, val);
+ if (ret || (*val != POWER_SUPPLY_HEALTH_GOOD))
+ return ret;
+ }
+ return max77705_get_battery_health(charger, val);
+}
+
+static int max77705_get_input_current(struct max77705_charger_data *charger,
+ int *val)
+{
+ unsigned int reg_data;
+ int get_current = 0;
+ struct regmap *regmap = charger->regmap;
+
+ regmap_read(regmap,
+ MAX77705_CHG_REG_CNFG_09, ®_data);
+
+ reg_data &= MAX77705_CHG_CHGIN_LIM_MASK;
+
+ if (reg_data <= 3)
+ get_current = 100;
+ else if (reg_data >= MAX77705_CHG_CHGIN_LIM_MASK)
+ get_current = MAX77705_CURRENT_CHGIN_MAX;
+ else
+ get_current = (reg_data + 1) * 25;
+
+ *val = get_current;
+
+ return 0;
+}
+
+static int max77705_get_charge_current(struct max77705_charger_data *charger,
+ int *val)
+{
+ unsigned int reg_data;
+ struct regmap *regmap = charger->regmap;
+
+
+ regmap_read(regmap, MAX77705_CHG_REG_CNFG_02, ®_data);
+ reg_data &= MAX77705_CHG_CC;
+
+ *val = reg_data <= 0x2 ? 100 : reg_data * 50;
+
+ return 0;
+}
+
+static int max77705_set_float_voltage(struct max77705_charger_data *charger,
+ int float_voltage)
+{
+ int float_voltage_mv;
+ unsigned int reg_data = 0;
+ struct regmap *regmap = charger->regmap;
+
+ float_voltage_mv = float_voltage / 1000;
+ reg_data = float_voltage_mv <= 4000 ? 0x0 :
+ float_voltage_mv >= 4500 ? 0x23 :
+ (float_voltage_mv <= 4200) ? (float_voltage_mv - 4000) / 50 :
+ (((float_voltage_mv - 4200) / 10) + 0x04);
+
+ return regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_04,
+ MAX77705_CHG_CV_PRM_MASK,
+ (reg_data << MAX77705_CHG_CV_PRM_SHIFT));
+}
+
+static int max77705_get_float_voltage(struct max77705_charger_data *charger,
+ int *val)
+{
+ unsigned int reg_data = 0;
+ struct regmap *regmap = charger->regmap;
+
+ regmap_read(regmap, MAX77705_CHG_REG_CNFG_04, ®_data);
+ reg_data &= MAX77705_CHG_PRM_MASK;
+ *val = reg_data <= 0x04 ? reg_data * 50 + 4000 :
+ (reg_data - 4) * 10 + 4200;
+
+ return 0;
+}
+
+static int max77705_chg_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max77705_charger_data *charger = power_supply_get_drvdata(psy);
+ struct regmap *regmap = charger->regmap;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ return max77705_get_online(regmap, &val->intval);
+ case POWER_SUPPLY_PROP_PRESENT:
+ return max77705_check_battery(charger, &val->intval);
+ case POWER_SUPPLY_PROP_STATUS:
+ return max77705_get_status(charger, &val->intval);
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ return max77705_get_charge_type(charger, &val->intval);
+ case POWER_SUPPLY_PROP_HEALTH:
+ return max77705_get_health(charger, &val->intval);
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return max77705_get_input_current(charger, &val->intval);
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ return max77705_get_charge_current(charger, &val->intval);
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ return max77705_get_float_voltage(charger, &val->intval);
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = charger->bat_info->voltage_max_design_uv;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = max77705_charger_model;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = max77705_charger_manufacturer;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const struct power_supply_desc max77705_charger_psy_desc = {
+ .name = "max77705-charger",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = max77705_charger_props,
+ .num_properties = ARRAY_SIZE(max77705_charger_props),
+ .get_property = max77705_chg_get_property,
+};
+
+static void max77705_chgin_isr_work(struct work_struct *work)
+{
+ struct max77705_charger_data *charger =
+ container_of(work, struct max77705_charger_data, chgin_work);
+ power_supply_changed(charger->psy_chg);
+}
+
+static void max77705_charger_initialize(struct max77705_charger_data *chg)
+{
+ u8 reg_data;
+ struct power_supply_battery_info *info;
+ struct regmap *regmap = chg->regmap;
+
+ if (power_supply_get_battery_info(chg->psy_chg, &info) < 0)
+ return;
+
+ chg->bat_info = info;
+
+ // unlock charger setting protect
+ // slowest LX slope
+ reg_data = MAX77705_CHGPROT_MASK | MAX77705_SLOWEST_LX_SLOPE;
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_06, reg_data,
+ reg_data);
+
+ // fast charge timer disable
+ // restart threshold disable
+ // pre-qual charge disable
+ reg_data = (MAX77705_FCHGTIME_DISABLE << MAX77705_FCHGTIME_SHIFT) |
+ (MAX77705_CHG_RSTRT_DISABLE << MAX77705_CHG_RSTRT_SHIFT) |
+ (MAX77705_CHG_PQEN_DISABLE << MAX77705_PQEN_SHIFT);
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_01,
+ (MAX77705_FCHGTIME_MASK |
+ MAX77705_CHG_RSTRT_MASK |
+ MAX77705_PQEN_MASK),
+ reg_data);
+
+ // OTG off(UNO on), boost off
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
+ MAX77705_OTG_CTRL, 0);
+
+ // charge current 450mA(default)
+ // otg current limit 900mA
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_02,
+ MAX77705_OTG_ILIM_MASK,
+ MAX77705_OTG_ILIM_900 << MAX77705_OTG_ILIM_SHIFT);
+
+ // BAT to SYS OCP 4.80A
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_05,
+ MAX77705_REG_B2SOVRC_MASK,
+ MAX77705_B2SOVRC_4_8A << MAX77705_REG_B2SOVRC_SHIFT);
+ // top off current 150mA
+ // top off timer 30min
+ reg_data = (MAX77705_TO_ITH_150MA << MAX77705_TO_ITH_SHIFT) |
+ (MAX77705_TO_TIME_30M << MAX77705_TO_TIME_SHIFT) |
+ (MAX77705_SYS_TRACK_DISABLE << MAX77705_SYS_TRACK_DIS_SHIFT);
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_03,
+ (MAX77705_TO_ITH_MASK |
+ MAX77705_TO_TIME_MASK |
+ MAX77705_SYS_TRACK_DIS_MASK), reg_data);
+
+ // cv voltage 4.2V or 4.35V
+ // MINVSYS 3.6V(default)
+ if (info->voltage_max_design_uv < 0) {
+ dev_warn(chg->dev, "missing battery:voltage-max-design-microvolt\n");
+ max77705_set_float_voltage(chg, 4200000);
+ } else {
+ max77705_set_float_voltage(chg, info->voltage_max_design_uv);
+ }
+
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12,
+ MAX77705_VCHGIN_REG_MASK, MAX77705_VCHGIN_4_5);
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12,
+ MAX77705_WCIN_REG_MASK, MAX77705_WCIN_4_5);
+
+ // Watchdog timer
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
+ MAX77705_WDTEN_MASK, 0);
+
+ // Active Discharge Enable
+ regmap_update_bits(regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1);
+
+ // VBYPSET=5.0V
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_11, MAX77705_VBYPSET_MASK, 0);
+
+ // Switching Frequency : 1.5MHz
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_08, MAX77705_REG_FSW_MASK,
+ (MAX77705_CHG_FSW_1_5MHz << MAX77705_REG_FSW_SHIFT));
+
+ // Auto skip mode
+ regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12, MAX77705_REG_DISKIP_MASK,
+ (MAX77705_AUTO_SKIP << MAX77705_REG_DISKIP_SHIFT));
+}
+
+static int max77705_charger_probe(struct platform_device *pdev)
+{
+ struct power_supply_config pscfg = {};
+ struct max77693_dev *max77705;
+ struct max77705_charger_data *chg;
+ struct device *dev, *parent;
+ struct regmap_irq_chip_data *irq_data;
+ int ret;
+
+ dev = &pdev->dev;
+ parent = dev->parent;
+ max77705 = dev_get_drvdata(parent);
+
+ chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL);
+ if (!chg)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, chg);
+
+ chg->regmap = max77705->regmap_chg;
+ if (!chg->regmap)
+ return -ENODEV;
+
+ chg->dev = dev;
+
+ max77705_charger_irq_chip.irq_drv_data = chg;
+ ret = devm_regmap_add_irq_chip(chg->dev, chg->regmap, max77705->irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ &max77705_charger_irq_chip,
+ &irq_data);
+ if (ret) {
+ dev_err(dev, "failed to add irq chip: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_update_bits(chg->regmap,
+ MAX77705_CHG_REG_INT_MASK,
+ MAX77705_CHGIN_IM, 0);
+
+ if (ret)
+ return ret;
+
+ chg->wqueue = create_singlethread_workqueue(dev_name(dev));
+ if (IS_ERR(chg->wqueue)) {
+ dev_err(dev, "failed to create workqueue\n");
+ return PTR_ERR(chg->wqueue);
+ }
+ INIT_WORK(&chg->chgin_work, max77705_chgin_isr_work);
+
+ pscfg.of_node = dev->of_node;
+ pscfg.drv_data = chg;
+
+ chg->psy_chg = devm_power_supply_register(dev, &max77705_charger_psy_desc,
+ &pscfg);
+ if (IS_ERR(chg->psy_chg))
+ return PTR_ERR(chg->psy_chg);
+
+ max77705_charger_initialize(chg);
+
+ return max77705_charger_enable(chg);
+}
+
+static void max77705_charger_remove(struct platform_device *pdev)
+{
+ struct max77705_charger_data *chg = platform_get_drvdata(pdev);
+
+ max77705_charger_disable(chg);
+}
+
+static const struct of_device_id max77705_charger_of_match[] = {
+ { .compatible = "maxim,max77705-charger" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max77705_charger_of_match);
+
+static struct platform_driver max77705_charger_driver = {
+ .driver = {
+ .name = "max77705-charger",
+ .of_match_table = max77705_charger_of_match,
+ },
+ .probe = max77705_charger_probe,
+ .remove_new = max77705_charger_remove,
+};
+module_platform_driver(max77705_charger_driver);
+
+MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>");
+MODULE_DESCRIPTION("Maxim 77705 charger driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/max77705_charger.h b/include/linux/mfd/max77705_charger.h
new file mode 100644
index 000000000000..72614d7575a3
--- /dev/null
+++ b/include/linux/mfd/max77705_charger.h
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+//
+// Maxim MAX77705 definitions.
+//
+// Copyright (C) 2015 Samsung Electronics, Inc.
+// Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.com>
+
+#ifndef __MAX77705_CHARGER_H
+#define __MAX77705_CHARGER_H __FILE__
+
+// MAX77705_CHG_REG_CHG_INT
+#define MAX77705_BYP_I BIT(0)
+#define MAX77705_INP_LIMIT_I BIT(1)
+#define MAX77705_BATP_I BIT(2)
+#define MAX77705_BAT_I BIT(3)
+#define MAX77705_CHG_I BIT(4)
+#define MAX77705_WCIN_I BIT(5)
+#define MAX77705_CHGIN_I BIT(6)
+#define MAX77705_AICL_I BIT(7)
+
+// MAX77705_CHG_REG_CHG_INT_MASK
+#define MAX77705_BYP_IM BIT(0)
+#define MAX77705_INP_LIMIT_IM BIT(1)
+#define MAX77705_BATP_IM BIT(2)
+#define MAX77705_BAT_IM BIT(3)
+#define MAX77705_CHG_IM BIT(4)
+#define MAX77705_WCIN_IM BIT(5)
+#define MAX77705_CHGIN_IM BIT(6)
+#define MAX77705_AICL_IM BIT(7)
+
+// MAX77705_CHG_REG_CHG_INT_OK
+#define MAX77705_BYP_OK BIT(0)
+#define MAX77705_DISQBAT_OK BIT(1)
+#define MAX77705_BATP_OK BIT(2)
+#define MAX77705_BAT_OK BIT(3)
+#define MAX77705_CHG_OK BIT(4)
+#define MAX77705_WCIN_OK BIT(5)
+#define MAX77705_CHGIN_OK BIT(6)
+#define MAX77705_AICL_OK BIT(7)
+
+// MAX77705_CHG_REG_DETAILS_00
+#define MAX77705_BATP_DTLS BIT(0)
+#define MAX77705_WCIN_DTLS GENMASK(4, 3)
+#define MAX77705_WCIN_DTLS_SHIFT 3
+#define MAX77705_CHGIN_DTLS GENMASK(6, 5)
+#define MAX77705_CHGIN_DTLS_SHIFT 5
+
+// MAX77705_CHG_REG_DETAILS_01
+#define MAX77705_CHG_DTLS GENMASK(3, 0)
+#define MAX77705_CHG_DTLS_SHIFT 0
+#define MAX77705_BAT_DTLS GENMASK(6, 4)
+#define MAX77705_BAT_DTLS_SHIFT 4
+
+// MAX77705_CHG_REG_DETAILS_02
+#define MAX77705_BYP_DTLS GENMASK(3, 0)
+#define MAX77705_BYP_DTLS_SHIFT 0
+
+// MAX77705_CHG_REG_CNFG_00
+#define MAX77705_CHG_SHIFT 0
+#define MAX77705_UNO_SHIFT 1
+#define MAX77705_OTG_SHIFT 1
+#define MAX77705_BUCK_SHIFT 2
+#define MAX77705_BOOST_SHIFT 3
+#define MAX77705_WDTEN_SHIFT 4
+#define MAX77705_MODE_MASK GENMASK(3, 0)
+#define MAX77705_CHG_MASK BIT(MAX77705_CHG_SHIFT)
+#define MAX77705_UNO_MASK BIT(MAX77705_UNO_SHIFT)
+#define MAX77705_OTG_MASK BIT(MAX77705_OTG_SHIFT)
+#define MAX77705_BUCK_MASK BIT(MAX77705_BUCK_SHIFT)
+#define MAX77705_BOOST_MASK BIT(MAX77705_BOOST_SHIFT)
+#define MAX77705_WDTEN_MASK BIT(MAX77705_WDTEN_SHIFT)
+#define MAX77705_UNO_CTRL (MAX77705_UNO_MASK | MAX77705_BOOST_MASK)
+#define MAX77705_OTG_CTRL (MAX77705_OTG_MASK | MAX77705_BOOST_MASK)
+
+// MAX77705_CHG_REG_CNFG_01
+#define MAX77705_FCHGTIME_SHIFT 0
+#define MAX77705_FCHGTIME_MASK GENMASK(2, 0)
+#define MAX77705_CHG_RSTRT_SHIFT 4
+#define MAX77705_CHG_RSTRT_MASK GENMASK(5, 4)
+#define MAX77705_FCHGTIME_DISABLE 0
+#define MAX77705_CHG_RSTRT_DISABLE 0x3
+
+#define MAX77705_PQEN_SHIFT 7
+#define MAX77705_PQEN_MASK BIT(7)
+#define MAX77705_CHG_PQEN_DISABLE 0
+#define MAX77705_CHG_PQEN_ENABLE 1
+
+// MAX77705_CHG_REG_CNFG_02
+#define MAX77705_OTG_ILIM_SHIFT 6
+#define MAX77705_OTG_ILIM_MASK GENMASK(7, 6)
+#define MAX77705_OTG_ILIM_500 0
+#define MAX77705_OTG_ILIM_900 1
+#define MAX77705_OTG_ILIM_1200 2
+#define MAX77705_OTG_ILIM_1500 3
+#define MAX77705_CHG_CC GENMASK(5, 0)
+
+// MAX77705_CHG_REG_CNFG_03
+#define MAX77705_TO_ITH_SHIFT 0
+#define MAX77705_TO_ITH_MASK GENMASK(2, 0)
+#define MAX77705_TO_TIME_SHIFT 3
+#define MAX77705_TO_TIME_MASK GENMASK(5, 3)
+#define MAX77705_SYS_TRACK_DIS_SHIFT 7
+#define MAX77705_SYS_TRACK_DIS_MASK BIT(7)
+#define MAX77705_TO_ITH_150MA 0
+#define MAX77705_TO_TIME_30M 3
+#define MAX77705_SYS_TRACK_ENABLE 0
+#define MAX77705_SYS_TRACK_DISABLE 1
+
+// MAX77705_CHG_REG_CNFG_04
+#define MAX77705_CHG_MINVSYS_SHIFT 6
+#define MAX77705_CHG_MINVSYS_MASK GENMASK(7, 6)
+#define MAX77705_CHG_PRM_SHIFT 0
+#define MAX77705_CHG_PRM_MASK GENMASK(5, 0)
+
+#define MAX77705_CHG_CV_PRM_SHIFT 0
+#define MAX77705_CHG_CV_PRM_MASK GENMASK(5, 0)
+
+// MAX77705_CHG_REG_CNFG_05
+#define MAX77705_REG_B2SOVRC_SHIFT 0
+#define MAX77705_REG_B2SOVRC_MASK GENMASK(3, 0)
+#define MAX77705_B2SOVRC_DISABLE 0
+#define MAX77705_B2SOVRC_4_5A 6
+#define MAX77705_B2SOVRC_4_8A 8
+#define MAX77705_B2SOVRC_5_0A 9
+
+// MAX77705_CHG_CNFG_06
+#define MAX77705_WDTCLR_SHIFT 0
+#define MAX77705_WDTCLR_MASK GENMASK(1, 0)
+#define MAX77705_WDTCLR 1
+#define MAX77705_CHGPROT_MASK GENMASK(3, 2)
+#define MAX77705_CHGPROT_UNLOCKED GENMASK(3, 2)
+#define MAX77705_SLOWEST_LX_SLOPE GENMASK(6, 5)
+
+// MAX77705_CHG_REG_CNFG_07
+#define MAX77705_CHG_FMBST 4
+#define MAX77705_REG_FMBST_SHIFT 2
+#define MAX77705_REG_FMBST_MASK BIT(MAX77705_REG_FMBST_SHIFT)
+#define MAX77705_REG_FGSRC_SHIFT 1
+#define MAX77705_REG_FGSRC_MASK BIT(MAX77705_REG_FGSRC_SHIFT)
+
+// MAX77705_CHG_REG_CNFG_08
+#define MAX77705_REG_FSW_SHIFT 0
+#define MAX77705_REG_FSW_MASK GENMASK(1, 0)
+#define MAX77705_CHG_FSW_3MHz 0
+#define MAX77705_CHG_FSW_2MHz 1
+#define MAX77705_CHG_FSW_1_5MHz 2
+
+// MAX77705_CHG_REG_CNFG_09
+#define MAX77705_CHG_CHGIN_LIM_MASK GENMASK(6, 0)
+#define MAX77705_CHG_EN_MASK BIT(7)
+#define MAX77705_CHG_DISABLE 0
+#define MAX77705_CHARGER_CHG_CHARGING(_reg) \
+ (((_reg) & MAX77705_CHG_EN_MASK) > 1)
+
+
+// MAX77705_CHG_REG_CNFG_10
+#define MAX77705_CHG_WCIN_LIM GENMASK(5, 0)
+
+// MAX77705_CHG_REG_CNFG_11
+#define MAX77705_VBYPSET_SHIFT 0
+#define MAX77705_VBYPSET_MASK GENMASK(6, 0)
+
+// MAX77705_CHG_REG_CNFG_12
+#define MAX77705_CHGINSEL_SHIFT 5
+#define MAX77705_CHGINSEL_MASK BIT(MAX77705_CHGINSEL_SHIFT)
+#define MAX77705_WCINSEL_SHIFT 6
+#define MAX77705_WCINSEL_MASK BIT(MAX77705_WCINSEL_SHIFT)
+#define MAX77705_VCHGIN_REG_MASK GENMASK(4, 3)
+#define MAX77705_WCIN_REG_MASK GENMASK(2, 1)
+#define MAX77705_REG_DISKIP_SHIFT 0
+#define MAX77705_REG_DISKIP_MASK BIT(MAX77705_REG_DISKIP_SHIFT)
+// REG=4.5V, UVLO=4.7V
+#define MAX77705_VCHGIN_4_5 0
+// REG=4.5V, UVLO=4.7V
+#define MAX77705_WCIN_4_5 0
+#define MAX77705_DISABLE_SKIP 1
+#define MAX77705_AUTO_SKIP 0
+
+// mA
+#define MAX77705_CURRENT_STEP 25
+#define MAX77705_CURRENT_WCIN_MAX 1600
+#define MAX77705_CURRENT_CHGIN_MAX 3200
+
+/* Convert current in mA to corresponding CNFG09 value */
+inline u8 max77705_convert_ma_to_chgin_ilim_value(unsigned int cur)
+{
+ if (cur < MAX77705_CURRENT_STEP)
+ return 0;
+ if (cur < MAX77705_CURRENT_CHGIN_MAX)
+ return (cur / MAX77705_CURRENT_STEP) - 1;
+ else
+ return (MAX77705_CURRENT_CHGIN_MAX / MAX77705_CURRENT_STEP) - 1;
+}
+
+/* Convert current in mA to corresponding CNFG10 value */
+inline u8 max77705_convert_ma_to_wcin_ilim_value(unsigned int cur)
+{
+ if (cur < MAX77705_CURRENT_STEP)
+ return 0;
+ if (cur < MAX77705_CURRENT_WCIN_MAX)
+ return (cur / MAX77705_CURRENT_STEP) - 1;
+ else
+ return (MAX77705_CURRENT_WCIN_MAX / MAX77705_CURRENT_STEP) - 1;
+}
+
+struct max77705_charger_data {
+ struct device *dev;
+ struct regmap *regmap;
+ struct power_supply_battery_info *bat_info;
+ struct workqueue_struct *wqueue;
+ struct work_struct chgin_work;
+ struct power_supply *psy_chg;
+};
+
+#endif // __MAX77705_CHARGER_H
--
2.39.2
^ permalink raw reply related
* [PATCH v4 10/27] input: max77693: add max77705 haptic support
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add support for haptic controller on MAX77705 Multifunction
device.
This driver supports external pwm and LRA (Linear Resonant Actuator) motor.
User can control the haptic device via force feedback framework.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes in v4:
- add max77705 haptic support to max77693 driver
- delete max77705-haptic
---
drivers/input/misc/Kconfig | 4 ++--
drivers/input/misc/Makefile | 1 +
drivers/input/misc/max77693-haptic.c | 15 ++++++++++++++-
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 6a852c76331b..b4515c4e5cf6 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -241,11 +241,11 @@ config INPUT_MAX77650_ONKEY
config INPUT_MAX77693_HAPTIC
tristate "MAXIM MAX77693/MAX77843 haptic controller support"
- depends on (MFD_MAX77693 || MFD_MAX77843) && PWM
+ depends on (MFD_MAX77693 || MFD_MAX77705 || MFD_MAX77843) && PWM
select INPUT_FF_MEMLESS
help
This option enables support for the haptic controller on
- MAXIM MAX77693 and MAX77843 chips.
+ MAXIM MAX77693, MAX77705 and MAX77843 chips.
To compile this driver as module, choose M here: the
module will be called max77693-haptic.
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 4f7f736831ba..3e3532b27990 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
obj-$(CONFIG_INPUT_MAX77650_ONKEY) += max77650-onkey.o
obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o
+obj-$(CONFIG_INPUT_MAX77705_HAPTIC) += max77705-haptic.o
obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o
obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o
diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
index 0e646f1b257b..c3b9d33608d7 100644
--- a/drivers/input/misc/max77693-haptic.c
+++ b/drivers/input/misc/max77693-haptic.c
@@ -23,6 +23,7 @@
#include <linux/mfd/max77693.h>
#include <linux/mfd/max77693-common.h>
#include <linux/mfd/max77693-private.h>
+#include <linux/mfd/max77705-private.h>
#include <linux/mfd/max77843-private.h>
#define MAX_MAGNITUDE_SHIFT 16
@@ -115,6 +116,13 @@ static int max77693_haptic_configure(struct max77693_haptic *haptic,
MAX77693_HAPTIC_PWM_DIVISOR_128);
config_reg = MAX77693_HAPTIC_REG_CONFIG2;
break;
+ case TYPE_MAX77705:
+ value = ((haptic->type << MAX77693_CONFIG2_MODE) |
+ (enable << MAX77693_CONFIG2_MEN) |
+ (haptic->mode << MAX77693_CONFIG2_HTYP) |
+ MAX77693_HAPTIC_PWM_DIVISOR_128);
+ config_reg = MAX77705_PMIC_REG_MCONFIG;
+ break;
case TYPE_MAX77843:
value = (haptic->type << MCONFIG_MODE_SHIFT) |
(enable << MCONFIG_MEN_SHIFT) |
@@ -312,6 +320,9 @@ static int max77693_haptic_probe(struct platform_device *pdev)
case TYPE_MAX77693:
haptic->regmap_haptic = max77693->regmap_haptic;
break;
+ case TYPE_MAX77705:
+ haptic->regmap_haptic = max77693->regmap;
+ break;
case TYPE_MAX77843:
haptic->regmap_haptic = max77693->regmap;
break;
@@ -407,6 +418,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops,
static const struct platform_device_id max77693_haptic_id[] = {
{ "max77693-haptic", },
+ { "max77705-haptic", },
{ "max77843-haptic", },
{},
};
@@ -414,6 +426,7 @@ MODULE_DEVICE_TABLE(platform, max77693_haptic_id);
static const struct of_device_id of_max77693_haptic_dt_match[] = {
{ .compatible = "maxim,max77693-haptic", },
+ { .compatible = "maxim,max77705-haptic", },
{ .compatible = "maxim,max77843-haptic", },
{ /* sentinel */ },
};
@@ -432,5 +445,5 @@ module_platform_driver(max77693_haptic_driver);
MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
-MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver");
+MODULE_DESCRIPTION("MAXIM 77693/77705/77843 Haptic driver");
MODULE_LICENSE("GPL");
--
2.39.2
^ permalink raw reply related
* [PATCH v4 09/27] mfd: Add new driver for MAX77705 PMIC
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add the core MFD driver for max77705 PMIC. We define five sub-devices
for which the drivers will be added in subsequent patches.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes for V4:
- rework driver from scratch
- migrate to regmap_add_irq_chip, remove max77705-irq.c,
rename max77705-core.c to max77705.c
- cleanup headers
- remove debugfs code
- migrate to use max77693_dev structure
- remove max77705.h
---
MAINTAINERS | 2 +
drivers/mfd/Kconfig | 12 ++
drivers/mfd/Makefile | 2 +
drivers/mfd/max77705.c | 248 +++++++++++++++++++++++++++++++++++
include/linux/mfd/max77693-common.h | 6 +-
include/linux/mfd/max77705-private.h | 180 +++++++++++++++++++++++++
6 files changed, 449 insertions(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 65cb2511ba22..716e66bb7982 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14072,6 +14072,7 @@ F: drivers/*/*max77843.c
F: drivers/*/max14577*.c
F: drivers/*/max77686*.c
F: drivers/*/max77693*.c
+F: drivers/*/max77705*.c
F: drivers/clk/clk-max77686.c
F: drivers/extcon/extcon-max14577.c
F: drivers/extcon/extcon-max77693.c
@@ -14079,6 +14080,7 @@ F: drivers/rtc/rtc-max77686.c
F: include/linux/mfd/max14577*.h
F: include/linux/mfd/max77686*.h
F: include/linux/mfd/max77693*.h
+F: include/linux/mfd/max77705*.h
MAXIRADIO FM RADIO RECEIVER DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f9325bcce1b9..785aac4cb64b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -904,6 +904,18 @@ config MFD_MAX77693
additional drivers must be enabled in order to use the functionality
of the device.
+config MFD_MAX77705
+ tristate "Maxim Semiconductor MAX77705 PMIC Support"
+ depends on I2C
+ select MFD_CORE
+ help
+ Say yes here to add support for Maxim Semiconductor MAX77705.
+ This is a Power Management IC with Charger, safe LDOs, Flash, Haptic
+ and MUIC controls on chip.
+ This driver provides common support for accessing the device;
+ additional drivers must be enabled in order to use the functionality
+ of the device.
+
config MFD_MAX77714
tristate "Maxim Semiconductor MAX77714 PMIC Support"
depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 2a9f91e81af8..3dc5742c6aeb 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -167,6 +167,7 @@ obj-$(CONFIG_MFD_MAX77620) += max77620.o
obj-$(CONFIG_MFD_MAX77650) += max77650.o
obj-$(CONFIG_MFD_MAX77686) += max77686.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o
+obj-$(CONFIG_MFD_MAX77705) += max77705.o
obj-$(CONFIG_MFD_MAX77714) += max77714.o
obj-$(CONFIG_MFD_MAX77843) += max77843.o
obj-$(CONFIG_MFD_MAX8907) += max8907.o
@@ -232,6 +233,7 @@ obj-$(CONFIG_MFD_RK8XX_I2C) += rk8xx-i2c.o
obj-$(CONFIG_MFD_RK8XX_SPI) += rk8xx-spi.o
obj-$(CONFIG_MFD_RN5T618) += rn5t618.o
obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
+obj-$(CONFIG_MFD_S2DOS05) += s2dos05.o
obj-$(CONFIG_MFD_SYSCON) += syscon.o
obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o
obj-$(CONFIG_MFD_VEXPRESS_SYSREG) += vexpress-sysreg.o
diff --git a/drivers/mfd/max77705.c b/drivers/mfd/max77705.c
new file mode 100644
index 000000000000..2c6a5520964e
--- /dev/null
+++ b/drivers/mfd/max77705.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// max77705.c - mfd core driver for the MAX77705
+//
+// Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.com>
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max77705-private.h>
+#include <linux/mfd/max77693-common.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+#define I2C_ADDR_CHG (0xD2 >> 1)
+#define I2C_ADDR_FG (0x6C >> 1)
+
+static struct mfd_cell max77705_devs[] = {
+ {
+ .name = "leds-max77705-rgb",
+ .of_compatible = "maxim,max77705-led",
+ },
+ {
+ .name = "max77705-fuel-gauge",
+ .of_compatible = "maxim,max77705-fuel-gauge",
+ },
+ {
+ .name = "max77705-charger",
+ .of_compatible = "maxim,max77705-charger",
+ },
+ {
+ .name = "max77705-haptic",
+ .of_compatible = "maxim,max77705-haptic",
+ },
+};
+
+static const struct regmap_range max77705_readable_ranges[] = {
+ regmap_reg_range(MAX77705_PMIC_REG_PMICID1, MAX77705_PMIC_REG_BSTOUT_MASK),
+ regmap_reg_range(MAX77705_PMIC_REG_INTSRC, MAX77705_PMIC_REG_RESERVED_29),
+ regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1, MAX77705_PMIC_REG_BOOSTCONTROL1),
+ regmap_reg_range(MAX77705_PMIC_REG_MCONFIG, MAX77705_PMIC_REG_MCONFIG2),
+ regmap_reg_range(MAX77705_PMIC_REG_FORCE_EN_MASK, MAX77705_PMIC_REG_FORCE_EN_MASK),
+ regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1, MAX77705_PMIC_REG_BOOSTCONTROL1),
+ regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL2, MAX77705_PMIC_REG_BOOSTCONTROL2),
+ regmap_reg_range(MAX77705_PMIC_REG_SW_RESET, MAX77705_PMIC_REG_USBC_RESET),
+};
+
+static const struct regmap_range max77705_writable_ranges[] = {
+ regmap_reg_range(MAX77705_PMIC_REG_MAINCTRL1, MAX77705_PMIC_REG_BSTOUT_MASK),
+ regmap_reg_range(MAX77705_PMIC_REG_INTSRC, MAX77705_PMIC_REG_RESERVED_29),
+ regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1, MAX77705_PMIC_REG_BOOSTCONTROL1),
+ regmap_reg_range(MAX77705_PMIC_REG_MCONFIG, MAX77705_PMIC_REG_MCONFIG2),
+ regmap_reg_range(MAX77705_PMIC_REG_FORCE_EN_MASK, MAX77705_PMIC_REG_FORCE_EN_MASK),
+ regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1, MAX77705_PMIC_REG_BOOSTCONTROL1),
+ regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL2, MAX77705_PMIC_REG_BOOSTCONTROL2),
+ regmap_reg_range(MAX77705_PMIC_REG_SW_RESET, MAX77705_PMIC_REG_USBC_RESET),
+
+};
+
+static const struct regmap_access_table max77705_readable_table = {
+ .yes_ranges = max77705_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(max77705_readable_ranges),
+};
+
+static const struct regmap_access_table max77705_writable_table = {
+ .yes_ranges = max77705_writable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(max77705_writable_ranges),
+};
+
+static const struct regmap_config max77705_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .rd_table = &max77705_readable_table,
+ .wr_table = &max77705_writable_table,
+ .max_register = MAX77705_PMIC_REG_USBC_RESET,
+};
+
+static const struct regmap_config max77705_leds_regmap_config = {
+ .reg_base = MAX77705_RGBLED_REG_BASE,
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX77705_LED_REG_END,
+};
+
+static const struct regmap_config max77705_chg_regmap_config = {
+ .reg_base = MAX77705_CHG_REG_BASE,
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX77705_CHG_REG_SAFEOUT_CTRL,
+};
+
+static const struct regmap_config max77705_fg_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX77705_FG_END,
+};
+
+static const struct regmap_irq max77705_topsys_irqs[] = {
+ { .mask = MAX77705_SYSTEM_IRQ_BSTEN_INT, },
+ { .mask = MAX77705_SYSTEM_IRQ_SYSUVLO_INT, },
+ { .mask = MAX77705_SYSTEM_IRQ_SYSOVLO_INT, },
+ { .mask = MAX77705_SYSTEM_IRQ_TSHDN_INT, },
+ { .mask = MAX77705_SYSTEM_IRQ_TM_INT, },
+};
+
+static const struct regmap_irq_chip max77705_topsys_irq_chip = {
+ .name = "max77705-topsys",
+ .status_base = MAX77705_PMIC_REG_SYSTEM_INT,
+ .mask_base = MAX77705_PMIC_REG_SYSTEM_INT_MASK,
+ .num_regs = 1,
+ .irqs = max77705_topsys_irqs,
+ .num_irqs = ARRAY_SIZE(max77705_topsys_irqs),
+};
+
+static int max77705_i2c_probe(struct i2c_client *i2c)
+{
+ struct max77693_dev *max77705;
+ struct i2c_client *i2c_chg;
+ struct i2c_client *i2c_fg;
+ struct regmap_irq_chip_data *irq_data;
+ struct irq_domain *domain;
+ int ret;
+ unsigned int pmic_rev_value;
+ u8 pmic_ver, pmic_rev;
+
+
+ max77705 = devm_kzalloc(&i2c->dev, sizeof(struct max77693_dev),
+ GFP_KERNEL);
+ if (!max77705)
+ return -ENOMEM;
+
+ max77705->dev = &i2c->dev;
+ max77705->irq = i2c->irq;
+ max77705->type = TYPE_MAX77705;
+ i2c_set_clientdata(i2c, max77705);
+
+ max77705->regmap = devm_regmap_init_i2c(i2c, &max77705_regmap_config);
+ if (IS_ERR(max77705->regmap))
+ return PTR_ERR(max77705->regmap);
+
+ if (regmap_read(max77705->regmap, MAX77705_PMIC_REG_PMICREV, &pmic_rev_value) < 0)
+ return -ENODEV;
+
+ pmic_rev = (pmic_rev_value & MAX77705_REVISION_MASK);
+ pmic_ver = ((pmic_rev_value & MAX77705_VERSION_MASK) >> MAX77705_VERSION_SHIFT);
+ dev_dbg(max77705->dev, "device found: rev.0x%x, ver.0x%x\n",
+ pmic_rev, pmic_ver);
+ if (pmic_rev != MAX77705_PASS3) {
+ dev_err(max77705->dev, "rev.0x%x is not tested",
+ pmic_rev);
+ return -ENODEV;
+ }
+
+ max77705->regmap_leds = devm_regmap_init_i2c(i2c, &max77705_leds_regmap_config);
+ if (IS_ERR(max77705->regmap_leds))
+ return PTR_ERR(max77705->regmap_leds);
+
+ i2c_chg = devm_i2c_new_dummy_device(max77705->dev,
+ i2c->adapter, I2C_ADDR_CHG);
+ max77705->regmap_chg = devm_regmap_init_i2c(i2c_chg,
+ &max77705_chg_regmap_config);
+ if (IS_ERR(max77705->regmap_chg))
+ return PTR_ERR(max77705->regmap_chg);
+
+ i2c_fg = devm_i2c_new_dummy_device(max77705->dev, i2c->adapter,
+ I2C_ADDR_FG);
+ max77705->regmap_fg = devm_regmap_init_i2c(i2c_fg,
+ &max77705_fg_regmap_config);
+ if (IS_ERR(max77705->regmap_fg))
+ return PTR_ERR(max77705->regmap_fg);
+
+ ret = devm_regmap_add_irq_chip(max77705->dev, max77705->regmap,
+ max77705->irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ &max77705_topsys_irq_chip,
+ &irq_data);
+ if (ret)
+ dev_err(max77705->dev, "failed to add irq chip: %d\n", ret);
+
+ /* Unmask interrupts from all blocks in interrupt source register */
+ ret = regmap_update_bits(max77705->regmap,
+ MAX77705_PMIC_REG_INTSRC_MASK,
+ MAX77705_SRC_IRQ_ALL, (unsigned int)~MAX77705_SRC_IRQ_ALL);
+ if (ret < 0)
+ dev_err(max77705->dev,
+ "Could not unmask interrupts in INTSRC: %d\n", ret);
+
+ domain = regmap_irq_get_domain(irq_data);
+ ret = devm_mfd_add_devices(max77705->dev, PLATFORM_DEVID_NONE,
+ max77705_devs, ARRAY_SIZE(max77705_devs),
+ NULL, 0, domain);
+ if (ret) {
+ dev_err(max77705->dev, "failed to add MFD devices: %d\n", ret);
+ return ret;
+ }
+
+ device_init_wakeup(max77705->dev, true);
+
+ return 0;
+}
+
+static int max77705_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct max77693_dev *max77705 = i2c_get_clientdata(i2c);
+
+ disable_irq(max77705->irq);
+ if (device_may_wakeup(dev))
+ enable_irq_wake(max77705->irq);
+
+ return 0;
+}
+
+static int max77705_resume(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct max77693_dev *max77705 = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(max77705->irq);
+ enable_irq(max77705->irq);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_DEV_PM_OPS(max77705_pm_ops, max77705_suspend, max77705_resume);
+
+static const struct of_device_id max77705_i2c_dt_ids[] = {
+ { .compatible = "maxim,max77705" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, max77705_i2c_dt_ids);
+
+static struct i2c_driver max77705_i2c_driver = {
+ .driver = {
+ .name = "max77705",
+ .of_match_table = max77705_i2c_dt_ids,
+ .pm = pm_sleep_ptr(&max77705_pm_ops),
+ .suppress_bind_attrs = true,
+ },
+ .probe = max77705_i2c_probe,
+};
+module_i2c_driver(max77705_i2c_driver);
+
+MODULE_DESCRIPTION("MAXIM 77705 multi-function core driver");
+MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/max77693-common.h b/include/linux/mfd/max77693-common.h
index a5bce099f1ed..1b87b1ada21c 100644
--- a/include/linux/mfd/max77693-common.h
+++ b/include/linux/mfd/max77693-common.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Common data shared between Maxim 77693 and 77843 drivers
+ * Common data shared between Maxim 77693, 77705 and 77843 drivers
*
* Copyright (C) 2015 Samsung Electronics
*/
@@ -11,6 +11,7 @@
enum max77693_types {
TYPE_MAX77693_UNKNOWN,
TYPE_MAX77693,
+ TYPE_MAX77705,
TYPE_MAX77843,
TYPE_MAX77693_NUM,
@@ -25,6 +26,7 @@ struct max77693_dev {
struct i2c_client *i2c_muic; /* 0x4A , MUIC */
struct i2c_client *i2c_haptic; /* MAX77693: 0x90 , Haptic */
struct i2c_client *i2c_chg; /* MAX77843: 0xD2, Charger */
+ struct i2c_client *i2c_fg; /* MAX77843: 0xD2, Charger */
enum max77693_types type;
@@ -32,6 +34,8 @@ struct max77693_dev {
struct regmap *regmap_muic;
struct regmap *regmap_haptic; /* Only MAX77693 */
struct regmap *regmap_chg; /* Only MAX77843 */
+ struct regmap *regmap_fg; /* Only MAX77705 */
+ struct regmap *regmap_leds; /* Only MAX77705 */
struct regmap_irq_chip_data *irq_data_led;
struct regmap_irq_chip_data *irq_data_topsys;
diff --git a/include/linux/mfd/max77705-private.h b/include/linux/mfd/max77705-private.h
new file mode 100644
index 000000000000..2fbc1c345724
--- /dev/null
+++ b/include/linux/mfd/max77705-private.h
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+//
+// Maxim MAX77705 definitions.
+//
+// Copyright (C) 2015 Samsung Electronics, Inc.
+// Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.com>
+
+#ifndef __LINUX_MFD_MAX77705_PRIV_H
+#define __LINUX_MFD_MAX77705_PRIV_H
+
+#include <linux/pm.h>
+
+#define MAX77705_SRC_IRQ_CHG BIT(0)
+#define MAX77705_SRC_IRQ_TOP BIT(1)
+#define MAX77705_SRC_IRQ_FG BIT(2)
+#define MAX77705_SRC_IRQ_USBC BIT(3)
+#define MAX77705_SRC_IRQ_ALL (MAX77705_SRC_IRQ_CHG | MAX77705_SRC_IRQ_TOP | \
+ MAX77705_SRC_IRQ_FG | MAX77705_SRC_IRQ_USBC)
+
+// MAX77705_PMIC_REG_PMICREV register
+#define MAX77705_VERSION_SHIFT 3
+#define MAX77705_REVISION_MASK GENMASK(2, 0)
+#define MAX77705_VERSION_MASK GENMASK(7, MAX77705_VERSION_SHIFT)
+// MAX77705_PMIC_REG_MAINCTRL1 register
+#define MAX77705_MAINCTRL1_BIASEN_SHIFT 7
+#define MAX77705_MAINCTRL1_BIASEN_MASK BIT(MAX77705_MAINCTRL1_BIASEN_SHIFT)
+// MAX77705_PMIC_REG_MCONFIG2 (haptics) register
+#define MAX77705_CONFIG2_MEN_SHIFT 6
+#define MAX77705_CONFIG2_MODE_SHIFT 7
+#define MAX77705_CONFIG2_HTYP_SHIFT 5
+// MAX77705_PMIC_REG_SYSTEM_INT_MASK register
+#define MAX77705_SYSTEM_IRQ_BSTEN_INT BIT(3)
+#define MAX77705_SYSTEM_IRQ_SYSUVLO_INT BIT(4)
+#define MAX77705_SYSTEM_IRQ_SYSOVLO_INT BIT(5)
+#define MAX77705_SYSTEM_IRQ_TSHDN_INT BIT(6)
+#define MAX77705_SYSTEM_IRQ_TM_INT BIT(7)
+
+enum max77705_hw_rev {
+ MAX77705_PASS1 = 1,
+ MAX77705_PASS2,
+ MAX77705_PASS3,
+};
+
+enum max77705_reg {
+ MAX77705_PMIC_REG_PMICID1 = 0x00,
+ MAX77705_PMIC_REG_PMICREV = 0x01,
+ MAX77705_PMIC_REG_MAINCTRL1 = 0x02,
+ MAX77705_PMIC_REG_BSTOUT_MASK = 0x03,
+ MAX77705_PMIC_REG_FORCE_EN_MASK = 0x08,
+ MAX77705_PMIC_REG_MCONFIG = 0x10,
+ MAX77705_PMIC_REG_MCONFIG2 = 0x11,
+ MAX77705_PMIC_REG_INTSRC = 0x22,
+ MAX77705_PMIC_REG_INTSRC_MASK = 0x23,
+ MAX77705_PMIC_REG_SYSTEM_INT = 0x24,
+ MAX77705_PMIC_REG_RESERVED_25 = 0x25,
+ MAX77705_PMIC_REG_SYSTEM_INT_MASK = 0x26,
+ MAX77705_PMIC_REG_RESERVED_27 = 0x27,
+ MAX77705_PMIC_REG_RESERVED_28 = 0x28,
+ MAX77705_PMIC_REG_RESERVED_29 = 0x29,
+ MAX77705_PMIC_REG_BOOSTCONTROL1 = 0x4C,
+ MAX77705_PMIC_REG_BOOSTCONTROL2 = 0x4F,
+ MAX77705_PMIC_REG_SW_RESET = 0x50,
+ MAX77705_PMIC_REG_USBC_RESET = 0x51,
+
+ MAX77705_PMIC_REG_END,
+};
+
+enum max77705_chg_reg {
+ MAX77705_CHG_REG_BASE = 0xB0,
+ MAX77705_CHG_REG_INT = 0,
+ MAX77705_CHG_REG_INT_MASK,
+ MAX77705_CHG_REG_INT_OK,
+ MAX77705_CHG_REG_DETAILS_00,
+ MAX77705_CHG_REG_DETAILS_01,
+ MAX77705_CHG_REG_DETAILS_02,
+ MAX77705_CHG_REG_DTLS_03,
+ MAX77705_CHG_REG_CNFG_00,
+ MAX77705_CHG_REG_CNFG_01,
+ MAX77705_CHG_REG_CNFG_02,
+ MAX77705_CHG_REG_CNFG_03,
+ MAX77705_CHG_REG_CNFG_04,
+ MAX77705_CHG_REG_CNFG_05,
+ MAX77705_CHG_REG_CNFG_06,
+ MAX77705_CHG_REG_CNFG_07,
+ MAX77705_CHG_REG_CNFG_08,
+ MAX77705_CHG_REG_CNFG_09,
+ MAX77705_CHG_REG_CNFG_10,
+ MAX77705_CHG_REG_CNFG_11,
+ MAX77705_CHG_REG_CNFG_12,
+ MAX77705_CHG_REG_CNFG_13,
+ MAX77705_CHG_REG_CNFG_14,
+ MAX77705_CHG_REG_SAFEOUT_CTRL,
+};
+
+enum max77705_fuelgauge_reg {
+ STATUS_REG = 0x00,
+ VALRT_THRESHOLD_REG = 0x01,
+ TALRT_THRESHOLD_REG = 0x02,
+ SALRT_THRESHOLD_REG = 0x03,
+ REMCAP_REP_REG = 0x05,
+ SOCREP_REG = 0x06,
+ TEMPERATURE_REG = 0x08,
+ VCELL_REG = 0x09,
+ TIME_TO_EMPTY_REG = 0x11,
+ FULLSOCTHR_REG = 0x13,
+ CURRENT_REG = 0x0A,
+ AVG_CURRENT_REG = 0x0B,
+ SOCMIX_REG = 0x0D,
+ SOCAV_REG = 0x0E,
+ REMCAP_MIX_REG = 0x0F,
+ FULLCAP_REG = 0x10,
+ RFAST_REG = 0x15,
+ AVR_TEMPERATURE_REG = 0x16,
+ CYCLES_REG = 0x17,
+ DESIGNCAP_REG = 0x18,
+ AVR_VCELL_REG = 0x19,
+ TIME_TO_FULL_REG = 0x20,
+ CONFIG_REG = 0x1D,
+ ICHGTERM_REG = 0x1E,
+ REMCAP_AV_REG = 0x1F,
+ FULLCAP_NOM_REG = 0x23,
+ LEARN_CFG_REG = 0x28,
+ FILTER_CFG_REG = 0x29,
+ MISCCFG_REG = 0x2B,
+ QRTABLE20_REG = 0x32,
+ FULLCAP_REP_REG = 0x35,
+ RCOMP_REG = 0x38,
+ VEMPTY_REG = 0x3A,
+ FSTAT_REG = 0x3D,
+ DISCHARGE_THRESHOLD_REG = 0x40,
+ QRTABLE30_REG = 0x42,
+ ISYS_REG = 0x43,
+ DQACC_REG = 0x45,
+ DPACC_REG = 0x46,
+ AVGISYS_REG = 0x4B,
+ QH_REG = 0x4D,
+ VSYS_REG = 0xB1,
+ TALRTTH2_REG = 0xB2,
+ VBYP_REG = 0xB3,
+ CONFIG2_REG = 0xBB,
+ IIN_REG = 0xD0,
+ OCV_REG = 0xEE,
+ VFOCV_REG = 0xFB,
+ VFSOC_REG = 0xFF,
+
+ MAX77705_FG_END,
+};
+
+enum max77705_led_reg {
+ MAX77705_RGBLED_REG_BASE = 0x30,
+ MAX77705_RGBLED_REG_LEDEN = 0,
+ MAX77705_RGBLED_REG_LED0BRT,
+ MAX77705_RGBLED_REG_LED1BRT,
+ MAX77705_RGBLED_REG_LED2BRT,
+ MAX77705_RGBLED_REG_LED3BRT,
+ MAX77705_RGBLED_REG_LEDRMP,
+ MAX77705_RGBLED_REG_LEDBLNK,
+ MAX77705_LED_REG_END
+};
+
+enum max77705_charger_battery_state {
+ MAX77705_BATTERY_NOBAT,
+ MAX77705_BATTERY_PREQUALIFICATION,
+ MAX77705_BATTERY_DEAD,
+ MAX77705_BATTERY_GOOD,
+ MAX77705_BATTERY_LOWVOLTAGE,
+ MAX77705_BATTERY_OVERVOLTAGE,
+ MAX77705_BATTERY_RESERVED,
+};
+
+enum max77705_charger_charge_type {
+ MAX77705_CHARGER_CONSTANT_CURRENT = 1,
+ MAX77705_CHARGER_CONSTANT_VOLTAGE,
+ MAX77705_CHARGER_END_OF_CHARGE,
+ MAX77705_CHARGER_DONE,
+};
+
+extern const struct dev_pm_ops max77705_pm_ops;
+
+#endif /* __LINUX_MFD_MAX77705_PRIV_H */
--
2.39.2
^ permalink raw reply related
* [PATCH v4 08/27] mfd: max77693: remove unused declarations
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Remove `enum max77693_irq_source` declaration because unused.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
include/linux/mfd/max77693-private.h | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h
index 20c5e02ed9da..c324d548619e 100644
--- a/include/linux/mfd/max77693-private.h
+++ b/include/linux/mfd/max77693-private.h
@@ -419,17 +419,6 @@ enum max77693_haptic_reg {
#define MAX77693_CONFIG2_MEN 6
#define MAX77693_CONFIG2_HTYP 5
-enum max77693_irq_source {
- LED_INT = 0,
- TOPSYS_INT,
- CHG_INT,
- MUIC_INT1,
- MUIC_INT2,
- MUIC_INT3,
-
- MAX77693_IRQ_GROUP_NR,
-};
-
#define SRC_IRQ_CHARGER BIT(0)
#define SRC_IRQ_TOP BIT(1)
#define SRC_IRQ_FLASH BIT(2)
--
2.39.2
^ permalink raw reply related
* [PATCH v4 07/27] drm/panel: Add support for S6E3HA8 panel driver
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add support for MIPI-DSI based S6E3HA8 AMOLED panel
driver. This panel has 1440x2960 resolution, 5.8-inch physical
size, and can be found in starqltechn device.
Brightness regulation is not yet supported.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
Changes in v4:
- inline power related functions
- rework driver using new mipi_dsi_dcs_write_seq_multi macro
- use drm_connector_helper_get_modes_fixed for modes
- remove excessive compression setting
---
MAINTAINERS | 1 +
drivers/gpu/drm/panel/Kconfig | 7 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-samsung-s6e3ha8.c | 350 ++++++++++++++++++++++++++
4 files changed, 359 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 92135252264a..65cb2511ba22 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7385,6 +7385,7 @@ DRM DRIVER FOR SAMSUNG S6E3HA8 PANELS
M: Dzmitry Sankouski <dsankouski@gmail.com>
S: Maintained
F: Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml
+F: drivers/gpu/drm/panel/panel-samsung-s6e3ha8.c
DRM DRIVER FOR SITRONIX ST7586 PANELS
M: David Lechner <david@lechnology.com>
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index d3a9a9fafe4e..65fb3a466e39 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -689,6 +689,13 @@ config DRM_PANEL_SAMSUNG_S6E3HA2
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
+config DRM_PANEL_SAMSUNG_S6E3HA8
+ tristate "Samsung S6E3HA8 DSI video mode panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ select VIDEOMODE_HELPERS
+
config DRM_PANEL_SAMSUNG_S6E63J0X03
tristate "Samsung S6E63J0X03 DSI command mode panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 987a08702410..8ee28f5a2213 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D27A1) += panel-samsung-s6d27a1.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D7AA0) += panel-samsung-s6d7aa0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FA7) += panel-samsung-s6e3fa7.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA8) += panel-samsung-s6e3ha8.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_SPI) += panel-samsung-s6e63m0-spi.o
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3ha8.c b/drivers/gpu/drm/panel/panel-samsung-s6e3ha8.c
new file mode 100644
index 000000000000..e69943f0527e
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha8.c
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+// Copyright (c) 2013, The Linux Foundation. All rights reserved.
+// Copyright (c) 2024 Dzmitry Sankouski <dsankouski@gmail.com>
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/display/drm_dsc.h>
+#include <drm/display/drm_dsc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_panel.h>
+
+struct s6e3ha8 {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct drm_dsc_config dsc;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[3];
+};
+
+static inline
+struct s6e3ha8 *to_s6e3ha8_amb577px01_wqhd(struct drm_panel *panel)
+{
+ return container_of(panel, struct s6e3ha8, panel);
+}
+
+#define s6e3ha8_test_key_on_lvl2(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0x5a, 0x5a)
+#define s6e3ha8_test_key_off_lvl2(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0xa5, 0xa5)
+#define s6e3ha8_test_key_on_lvl3(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfc, 0x5a, 0x5a)
+#define s6e3ha8_test_key_off_lvl3(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfc, 0xa5, 0xa5)
+#define s6e3ha8_test_key_on_lvl1(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9f, 0xa5, 0xa5)
+#define s6e3ha8_test_key_off_lvl1(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9f, 0x5a, 0x5a)
+#define s6e3ha8_afc_off(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xe2, 0x00, 0x00)
+
+static void s6e3ha8_amb577px01_wqhd_reset(struct s6e3ha8 *priv)
+{
+ gpiod_set_value_cansleep(priv->reset_gpio, 1);
+ usleep_range(5000, 6000);
+ gpiod_set_value_cansleep(priv->reset_gpio, 0);
+ usleep_range(5000, 6000);
+ gpiod_set_value_cansleep(priv->reset_gpio, 1);
+ usleep_range(5000, 6000);
+}
+
+static int s6e3ha8_amb577px01_wqhd_on(struct s6e3ha8 *priv)
+{
+ struct mipi_dsi_device *dsi = priv->dsi;
+ struct device *dev = &dsi->dev;
+ struct mipi_dsi_multi_context ctx = { .dsi = dsi };
+ int ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ s6e3ha8_test_key_on_lvl1(&ctx);
+ s6e3ha8_test_key_on_lvl2(&ctx);
+
+ ret = mipi_dsi_compression_mode(dsi, true);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set compression mode: %d\n", ret);
+ return ret;
+ }
+
+ s6e3ha8_test_key_off_lvl2(&ctx);
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+ usleep_range(5000, 6000);
+
+ s6e3ha8_test_key_on_lvl2(&ctx);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf2, 0x13);
+ s6e3ha8_test_key_off_lvl2(&ctx);
+
+ usleep_range(10000, 11000);
+
+ s6e3ha8_test_key_on_lvl2(&ctx);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf2, 0x13);
+ s6e3ha8_test_key_off_lvl2(&ctx);
+
+ /* OMOK setting 1 (Initial setting) - Scaler Latch Setting Guide */
+ s6e3ha8_test_key_on_lvl2(&ctx);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x07);
+ /* latch setting 1 : Scaler on/off & address setting & PPS setting -> Image update latch */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf2, 0x3c, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0b);
+ /* latch setting 2 : Ratio change mode -> Image update latch */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf2, 0x30);
+ /* OMOK setting 2 - Seamless setting guide : WQHD */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x00, 0x00, 0x05, 0x9f); /* CASET */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00, 0x00, 0x0b, 0x8f); /* PASET */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x01); /* scaler setup : scaler off */
+ s6e3ha8_test_key_off_lvl2(&ctx);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x00); /* TE Vsync ON */
+ s6e3ha8_test_key_on_lvl2(&ctx);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xed, 0x4c); /* ERR_FG */
+ s6e3ha8_test_key_off_lvl2(&ctx);
+ s6e3ha8_test_key_on_lvl3(&ctx);
+ /* FFC Setting 897.6Mbps */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x0d, 0x10, 0xb4, 0x3e, 0x01);
+ s6e3ha8_test_key_off_lvl3(&ctx);
+ s6e3ha8_test_key_on_lvl2(&ctx);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9,
+ 0x00, 0xb0, 0x81, 0x09, 0x00, 0x00, 0x00,
+ 0x11, 0x03); /* TSP HSYNC Setting */
+ s6e3ha8_test_key_off_lvl2(&ctx);
+ s6e3ha8_test_key_on_lvl2(&ctx);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf6, 0x43);
+ s6e3ha8_test_key_off_lvl2(&ctx);
+ s6e3ha8_test_key_on_lvl2(&ctx);
+ /* Brightness condition set */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca,
+ 0x07, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0x0c); /* AID Set : 0% */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5,
+ 0x19, 0xdc, 0x16, 0x01, 0x34, 0x67, 0x9a,
+ 0xcd, 0x01, 0x22, 0x33, 0x44, 0x00, 0x00,
+ 0x05, 0x55, 0xcc, 0x0c, 0x01, 0x11, 0x11,
+ 0x10); /* MPS/ELVSS Setting */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf4, 0xeb, 0x28); /* VINT */
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf7, 0x03); /* Gamma, LTPS(AID) update */
+ s6e3ha8_test_key_off_lvl2(&ctx);
+ s6e3ha8_test_key_off_lvl1(&ctx);
+
+ return 0;
+}
+
+static int s6e3ha8_enable(struct drm_panel *panel)
+{
+ struct s6e3ha8 *priv = to_s6e3ha8_amb577px01_wqhd(panel);
+ struct mipi_dsi_device *dsi = priv->dsi;
+ struct mipi_dsi_multi_context ctx = { .dsi = dsi };
+
+ s6e3ha8_test_key_on_lvl1(&ctx);
+ ctx.accum_err = mipi_dsi_dcs_set_display_on(dsi);
+ s6e3ha8_test_key_off_lvl1(&ctx);
+
+ return ctx.accum_err;
+}
+
+static int s6e3ha8_disable(struct drm_panel *panel)
+{
+ struct s6e3ha8 *priv = to_s6e3ha8_amb577px01_wqhd(panel);
+ struct mipi_dsi_device *dsi = priv->dsi;
+ struct mipi_dsi_multi_context ctx = { .dsi = dsi };
+
+ s6e3ha8_test_key_on_lvl1(&ctx);
+ ctx.accum_err = mipi_dsi_dcs_set_display_off(dsi);
+ s6e3ha8_test_key_off_lvl1(&ctx);
+ msleep(20);
+
+ s6e3ha8_test_key_on_lvl2(&ctx);
+ s6e3ha8_afc_off(&ctx);
+ s6e3ha8_test_key_off_lvl2(&ctx);
+
+ msleep(160);
+
+ return 0;
+}
+
+static int s6e3ha8_amb577px01_wqhd_prepare(struct drm_panel *panel)
+{
+ struct s6e3ha8 *priv = to_s6e3ha8_amb577px01_wqhd(panel);
+ struct mipi_dsi_device *dsi = priv->dsi;
+ struct device *dev = &dsi->dev;
+ struct mipi_dsi_multi_context ctx = { .dsi = dsi };
+ struct drm_dsc_picture_parameter_set pps;
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+ if (ret < 0)
+ return ret;
+ msleep(120);
+ s6e3ha8_amb577px01_wqhd_reset(priv);
+ ret = s6e3ha8_amb577px01_wqhd_on(priv);
+
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(priv->reset_gpio, 1);
+ goto err;
+ }
+
+ drm_dsc_pps_payload_pack(&pps, &priv->dsc);
+
+ s6e3ha8_test_key_on_lvl1(&ctx);
+ ret = mipi_dsi_picture_parameter_set(priv->dsi, &pps);
+ if (ret < 0) {
+ dev_err(panel->dev, "failed to transmit PPS: %d\n", ret);
+ return ret;
+ }
+ s6e3ha8_test_key_off_lvl1(&ctx);
+
+ msleep(28);
+
+ return 0;
+err:
+ regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+ return ret;
+}
+
+static int s6e3ha8_amb577px01_wqhd_unprepare(struct drm_panel *panel)
+{
+ struct s6e3ha8 *priv = to_s6e3ha8_amb577px01_wqhd(panel);
+
+ return regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+}
+
+static const struct drm_display_mode s6e3ha8_amb577px01_wqhd_mode = {
+ .clock = (1440 + 116 + 44 + 120) * (2960 + 120 + 80 + 124) * 60 / 1000,
+ .hdisplay = 1440,
+ .hsync_start = 1440 + 116,
+ .hsync_end = 1440 + 116 + 44,
+ .htotal = 1440 + 116 + 44 + 120,
+ .vdisplay = 2960,
+ .vsync_start = 2960 + 120,
+ .vsync_end = 2960 + 120 + 80,
+ .vtotal = 2960 + 120 + 80 + 124,
+ .width_mm = 64,
+ .height_mm = 132,
+};
+
+static int s6e3ha8_amb577px01_wqhd_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ return drm_connector_helper_get_modes_fixed(connector, &s6e3ha8_amb577px01_wqhd_mode);
+}
+
+static const struct drm_panel_funcs s6e3ha8_amb577px01_wqhd_panel_funcs = {
+ .prepare = s6e3ha8_amb577px01_wqhd_prepare,
+ .unprepare = s6e3ha8_amb577px01_wqhd_unprepare,
+ .get_modes = s6e3ha8_amb577px01_wqhd_get_modes,
+ .enable = s6e3ha8_enable,
+ .disable = s6e3ha8_disable,
+};
+
+static int s6e3ha8_amb577px01_wqhd_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct s6e3ha8 *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->supplies[0].supply = "vdd3";
+ priv->supplies[1].supply = "vci";
+ priv->supplies[2].supply = "vddr";
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
+ priv->supplies);
+ if (ret < 0) {
+ dev_err(dev, "failed to get regulators: %d\n", ret);
+ return ret;
+ }
+
+ priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(priv->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ priv->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, priv);
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
+ MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP |
+ MIPI_DSI_MODE_VIDEO_NO_HSA | MIPI_DSI_MODE_NO_EOT_PACKET;
+
+ drm_panel_init(&priv->panel, dev, &s6e3ha8_amb577px01_wqhd_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ priv->panel.prepare_prev_first = true;
+
+ drm_panel_add(&priv->panel);
+
+ /* This panel only supports DSC; unconditionally enable it */
+ dsi->dsc = &priv->dsc;
+
+ priv->dsc.dsc_version_major = 1;
+ priv->dsc.dsc_version_minor = 1;
+
+ priv->dsc.slice_height = 40;
+ priv->dsc.slice_width = 720;
+ WARN_ON(1440 % priv->dsc.slice_width);
+ priv->dsc.slice_count = 1440 / priv->dsc.slice_width;
+ priv->dsc.bits_per_component = 8;
+ priv->dsc.bits_per_pixel = 8 << 4; /* 4 fractional bits */
+ priv->dsc.block_pred_enable = true;
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+ drm_panel_remove(&priv->panel);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void s6e3ha8_amb577px01_wqhd_remove(struct mipi_dsi_device *dsi)
+{
+ struct s6e3ha8 *priv = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&priv->panel);
+}
+
+static const struct of_device_id s6e3ha8_amb577px01_wqhd_of_match[] = {
+ { .compatible = "samsung,s6e3ha8" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s6e3ha8_amb577px01_wqhd_of_match);
+
+static struct mipi_dsi_driver s6e3ha8_amb577px01_wqhd_driver = {
+ .probe = s6e3ha8_amb577px01_wqhd_probe,
+ .remove = s6e3ha8_amb577px01_wqhd_remove,
+ .driver = {
+ .name = "panel-s6e3ha8",
+ .of_match_table = s6e3ha8_amb577px01_wqhd_of_match,
+ },
+};
+module_mipi_dsi_driver(s6e3ha8_amb577px01_wqhd_driver);
+
+MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>");
+MODULE_DESCRIPTION("DRM driver for S6E3HA8 panel");
+MODULE_LICENSE("GPL");
--
2.39.2
^ permalink raw reply related
* [PATCH v4 06/27] dt-bindings: mfd: add samsung,s2dos05
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add samsung,s2dos05 MFD module binding.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes in v4:
- split long(>80) lines
- fix indentation
- merge with regulators binding
- drop pmic suffix
- drop unused labels in example
- correct description
---
.../devicetree/bindings/mfd/samsung,s2dos05.yaml | 99 ++++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 100 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2dos05.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2dos05.yaml
new file mode 100644
index 000000000000..534434002045
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/samsung,s2dos05.yaml
@@ -0,0 +1,99 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/samsung,s2dos05.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S2DOS05 Power Management IC
+
+maintainers:
+ - Dzmitry Sankouski <dsankouski@gmail.com>
+
+description:
+ This is a device tree bindings for S2DOS family of Power Management IC (PMIC).
+
+ The S2DOS05 is a companion power management IC for the panel and touchscreen
+ in smart phones. Provides voltage regulators and
+ ADC for power/current measurements.
+
+ Regulator section has 4 LDO and 1 BUCK regulators and also
+ provides ELVDD, ELVSS, AVDD lines.
+
+properties:
+ compatible:
+ const: samsung,s2dos05
+
+ reg:
+ maxItems: 1
+
+ regulators:
+ patternProperties:
+ "^buck1|ldo[1-4]$":
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
+
+ required:
+ - regulator-name
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - regulators
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@60 {
+ compatible = "samsung,s2dos05";
+ reg = <0x60>;
+
+ regulators {
+ ldo1 {
+ regulator-name = "s2dos05-ldo1";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-active-discharge = <0x1>;
+ };
+
+ ldo2 {
+ regulator-name = "s2dos05-ldo2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-active-discharge = <0x1>;
+ regulator-boot-on;
+ };
+
+ ldo3 {
+ regulator-name = "s2dos05-ldo3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-active-discharge = <0x1>;
+ regulator-boot-on;
+ };
+
+ ldo4 {
+ regulator-name = "s2dos05-ldo4";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3775000>;
+ regulator-active-discharge = <0x1>;
+ };
+
+ buck1 {
+ regulator-name = "s2dos05-buck1";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-active-discharge = <0x1>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 59d027591e34..92135252264a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20465,6 +20465,7 @@ L: linux-samsung-soc@vger.kernel.org
S: Maintained
B: mailto:linux-samsung-soc@vger.kernel.org
F: Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml
+F: Documentation/devicetree/bindings/mfd/samsung,s2dos*.yaml
F: Documentation/devicetree/bindings/mfd/samsung,s2m*.yaml
F: Documentation/devicetree/bindings/mfd/samsung,s5m*.yaml
F: Documentation/devicetree/bindings/regulator/samsung,s2m*.yaml
--
2.39.2
^ permalink raw reply related
* [PATCH v4 05/27] dt-bindings: mfd: add maxim,max77705
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add maxim,max77705 core binding part.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes in v4:
- change dts example intendation from tabs
to spaces
- remove interrupt-names property
- remove obvious reg description
- split long(>80) lines
---
.../devicetree/bindings/mfd/maxim,max77705.yaml | 169 +++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 170 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77705.yaml b/Documentation/devicetree/bindings/mfd/maxim,max77705.yaml
new file mode 100644
index 000000000000..40a67d15e312
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/maxim,max77705.yaml
@@ -0,0 +1,169 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/maxim,max77705.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX77705 Companion Power Management IC and USB Type-C interface IC
+
+maintainers:
+ - Dzmitry Sankouski <dsankouski@gmail.com>
+
+description: |
+ This is a part of device tree bindings for Maxim MAX77705 multi functional
+ device.
+
+ The Maxim MAX77705 is a Companion Power Management and Type-C
+ interface IC which includes charger, fuelgauge, LED, haptic motor driver and
+ Type-C management IC.
+
+properties:
+ compatible:
+ const: maxim,max77705
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ charger:
+ $ref: /schemas/power/supply/power-supply.yaml
+ additionalProperties: true
+ properties:
+ compatible:
+ const: maxim,max77705-charger
+
+ required:
+ - compatible
+ - monitored-battery
+
+ fuel_gauge:
+ $ref: /schemas/power/supply/power-supply.yaml
+ type: object
+ additionalProperties: true
+ description: MAX77705 fuel gauge with ModelGauge m5 EZ algorithm support.
+ properties:
+ compatible:
+ const: maxim,max77705-fuel-gauge
+
+ shunt-resistor-micro-ohms:
+ description: |
+ The value of current sense resistor in microohms.
+
+ required:
+ - compatible
+ - shunt-resistor-micro-ohms
+ - monitored-battery
+ - power-supplies
+
+ haptic:
+ type: object
+ additionalProperties: false
+ properties:
+ compatible:
+ const: maxim,max77705-haptic
+
+ haptic-supply: true
+
+ pwms:
+ maxItems: 1
+
+ required:
+ - compatible
+ - haptic-supply
+ - pwms
+
+ leds:
+ type: object
+ additionalProperties: false
+ description:
+ Up to 4 LEDs supported. One LED is represented by one child node.
+ properties:
+ compatible:
+ const: maxim,max77705-led
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ patternProperties:
+ "^led@[0-3]$":
+ type: object
+ $ref: /schemas/leds/common.yaml#
+ properties:
+ reg:
+ description:
+ LED index.
+ unevaluatedProperties: false
+ required:
+ - reg
+
+ required:
+ - compatible
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/leds/common.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@66 {
+ compatible = "maxim,max77705";
+ reg = <0x66>;
+ interrupt-parent = <&pm8998_gpios>;
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&chg_int_default>;
+ pinctrl-names = "default";
+
+ leds {
+ compatible = "maxim,max77705-led";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ label = "red:usr1";
+ };
+
+ led@2 {
+ reg = <2>;
+ label = "green:usr2";
+ };
+
+ led@3 {
+ reg = <3>;
+ label = "blue:usr3";
+ };
+ };
+
+ max77705_charger: charger {
+ compatible = "maxim,max77705-charger";
+ monitored-battery = <&battery>;
+ };
+
+ fuel_gauge {
+ compatible = "maxim,max77705-fuel-gauge";
+ monitored-battery = <&battery>;
+ power-supplies = <&max77705_charger>;
+ rsense = <5>;
+ };
+
+
+ haptic {
+ compatible = "maxim,max77705-haptic";
+ haptic-supply = <&vib_regulator>;
+ pwms = <&vib_pwm 0 50000>;
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index b65cfa1d322d..59d027591e34 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14064,6 +14064,7 @@ B: mailto:linux-samsung-soc@vger.kernel.org
F: Documentation/devicetree/bindings/*/maxim,max14577.yaml
F: Documentation/devicetree/bindings/*/maxim,max77686.yaml
F: Documentation/devicetree/bindings/*/maxim,max77693.yaml
+F: Documentation/devicetree/bindings/*/maxim,max77705*.yaml
F: Documentation/devicetree/bindings/*/maxim,max77843.yaml
F: Documentation/devicetree/bindings/clock/maxim,max77686.txt
F: drivers/*/*max77843.c
--
2.39.2
^ permalink raw reply related
* [PATCH v4 04/27] dt-bindings: panel: add Samsung s6e3ha8
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add binding for the Samsung s6e3ha8 panel found in the Samsung S9.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes in v4:
- change dts example intendation from tabs
to spaces
- remove reset-gpios description
---
.../bindings/display/panel/samsung,s6e3ha8.yaml | 75 ++++++++++++++++++++++
MAINTAINERS | 5 ++
2 files changed, 80 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml
new file mode 100644
index 000000000000..94c812e07571
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/samsung,s6e3ha8.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung s6e3ha8 AMOLED DSI panel
+
+description: The s6e3ha8 is a 1440x2960 DPI display panel from Samsung Mobile
+ Displays (SMD).
+
+maintainers:
+ - Dzmitry Sankouski <dsankouski@gmail.com>
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ const: samsung,s6e3ha8
+
+ reg:
+ maxItems: 1
+
+ reset-gpios: true
+
+ port: true
+
+ vdd3-supply:
+ description: VDD regulator
+
+ vci-supply:
+ description: VCI regulator
+
+ vddr-supply:
+ description: VDDR regulator
+
+required:
+ - compatible
+ - reset-gpios
+ - vdd3-supply
+ - vddr-supply
+ - vci-supply
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "samsung,s6e3ha8";
+ reg = <0>;
+ vci-supply = <&s2dos05_ldo4>;
+ vddr-supply = <&s2dos05_buck1>;
+ vdd3-supply = <&s2dos05_ldo1>;
+ te-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&sde_dsi_active &sde_te_active_sleep>;
+ pinctrl-1 = <&sde_dsi_suspend &sde_te_active_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 52b72d212c18..b65cfa1d322d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7381,6 +7381,11 @@ S: Maintained
F: Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml
F: drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c
+DRM DRIVER FOR SAMSUNG S6E3HA8 PANELS
+M: Dzmitry Sankouski <dsankouski@gmail.com>
+S: Maintained
+F: Documentation/devicetree/bindings/display/panel/samsung,s6e3ha8.yaml
+
DRM DRIVER FOR SITRONIX ST7586 PANELS
M: David Lechner <david@lechnology.com>
S: Maintained
--
2.39.2
^ permalink raw reply related
* [PATCH v4 03/27] gcc-sdm845: Add general purpose clock ops
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
SDM845 has "General Purpose" clocks that can be muxed to
SoC pins to clock various external devices.
Those clocks may be used as e.g. PWM sources for external peripherals.
GPCLK can in theory have arbitrary value depending on the use case, so
the concept of frequency tables, used in rcg2 clock driver, is not
efficient, because it allows only defined frequencies.
Introduce clk_rcg2_gp_ops, which automatically calculate clock
mnd values for arbitrary clock rate. The calculation done as follows:
- upon determine rate request, we calculate m/n/pre_div as follows:
- find parent(from our client's assigned-clock-parent) rate
- find scaled rates by dividing rates on its greatest common divisor
- assign requested scaled rate to m
- factorize scaled parent rate, put multipliers to n till max value
(determined by mnd_width)
- validate calculated values with *_width:
- if doesn't fit, delete divisor and multiplier by 2 until fit
- return determined rate
Limitations:
- The driver doesn't select a parent clock (it may be selected by client
in device tree with assigned-clocks, assigned-clock-parents properties)
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
drivers/clk/qcom/clk-rcg.h | 1 +
drivers/clk/qcom/clk-rcg2.c | 192 ++++++++++++++++++++++++++++++++++++++++--
drivers/clk/qcom/gcc-sdm845.c | 21 ++---
3 files changed, 193 insertions(+), 21 deletions(-)
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 8e0f3372dc7a..8817d14bbda4 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -189,6 +189,7 @@ struct clk_rcg2_gfx3d {
container_of(to_clk_rcg2(_hw), struct clk_rcg2_gfx3d, rcg)
extern const struct clk_ops clk_rcg2_ops;
+extern const struct clk_ops clk_rcg2_gp_ops;
extern const struct clk_ops clk_rcg2_floor_ops;
extern const struct clk_ops clk_rcg2_fm_ops;
extern const struct clk_ops clk_rcg2_mux_closest_ops;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index df491540ef39..1397cbd39bdb 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -8,11 +8,13 @@
#include <linux/err.h>
#include <linux/bug.h>
#include <linux/export.h>
+#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/rational.h>
#include <linux/regmap.h>
#include <linux/math64.h>
+#include <linux/gcd.h>
#include <linux/minmax.h>
#include <linux/slab.h>
@@ -32,6 +34,7 @@
#define CFG_REG 0x4
#define CFG_SRC_DIV_SHIFT 0
+#define CFG_SRC_DIV_LENGTH 8
#define CFG_SRC_SEL_SHIFT 8
#define CFG_SRC_SEL_MASK (0x7 << CFG_SRC_SEL_SHIFT)
#define CFG_MODE_SHIFT 12
@@ -148,6 +151,14 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
return update_config(rcg);
}
+// Converts divisors to corresponding clock register values.
+// @param f - Frequency table with pure m/n/pre_div parameters.
+static void convert_to_reg_val(struct freq_tbl *f)
+{
+ f->pre_div *= 2;
+ f->pre_div -= 1;
+}
+
/*
* Calculate m/n:d rate
*
@@ -400,16 +411,116 @@ static int clk_rcg2_fm_determine_rate(struct clk_hw *hw,
return _freq_tbl_fm_determine_rate(hw, rcg->freq_multi_tbl, req);
}
-static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f,
- u32 *_cfg)
+// Split multiplier that doesn't fit in n neither in pre_div.
+//
+// @param multiplier - multiplier to split between n and pre_div
+// @param pre_div_pure - pointer to pre divisor value
+// @param n - pointer to n divisor value
+// @param hid_max - pre divisor maximum value
+//
+static inline void clk_rcg2_split_div(int multiplier, unsigned int *pre_div_pure,
+ u16 *n, unsigned int hid_max)
+{
+ *n = mult_frac(multiplier * *n, *pre_div_pure, hid_max);
+ *pre_div_pure = hid_max;
+}
+
+static void clk_rcg2_calc_mnd(u64 parent_rate, u64 rate, struct freq_tbl *f,
+ unsigned int mnd_max, unsigned int hid_max)
+{
+ int i = 2, count = 0;
+ unsigned int pre_div_pure = 1;
+ unsigned long rates_gcd, scaled_parent_rate;
+ u16 m, n = 1, n_candidate = 1, n_max;
+
+ rates_gcd = gcd(parent_rate, rate);
+ m = rate / rates_gcd;
+ scaled_parent_rate = parent_rate / rates_gcd;
+ while (scaled_parent_rate > (mnd_max + m) * hid_max) {
+ // we're exceeding divisor's range, trying lower scale.
+ if (m > 1) {
+ m--;
+ scaled_parent_rate = mult_frac(scaled_parent_rate, m, (m + 1));
+ } else {
+ f->n = mnd_max + m;
+ f->pre_div = hid_max;
+ f->m = m;
+ }
+ }
+
+ n_max = m + mnd_max;
+
+ while (scaled_parent_rate > 1) {
+ while (scaled_parent_rate % i == 0) {
+ n_candidate *= i;
+ if (n_candidate < n_max)
+ n = n_candidate;
+ else if (pre_div_pure * i < hid_max)
+ pre_div_pure *= i;
+ else
+ clk_rcg2_split_div(i, &pre_div_pure, &n, hid_max);
+
+ scaled_parent_rate /= i;
+ }
+ i++;
+ count++;
+ }
+
+ f->m = m;
+ f->n = n;
+ f->pre_div = pre_div_pure > 1 ? pre_div_pure : 0;
+}
+
+static int clk_rcg2_determine_gp_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+ struct freq_tbl *f;
+ int mnd_max = BIT(rcg->mnd_width) - 1;
+ int hid_max = BIT(rcg->hid_width) - 1;
+ struct clk_hw *parent;
+ u64 parent_rate;
+
+ parent = clk_hw_get_parent(hw);
+ parent_rate = clk_get_rate(parent->clk);
+ if (!parent_rate)
+ return -EINVAL;
+
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
+
+ if (!f)
+ return -ENOMEM;
+
+ clk_rcg2_calc_mnd(parent_rate, req->rate, f, mnd_max, hid_max / 2);
+ convert_to_reg_val(f);
+ req->rate = calc_rate(parent_rate, f->m, f->n, f->n, f->pre_div);
+
+ kfree(f);
+
+ return 0;
+}
+
+static int __clk_rcg2_configure_parent(struct clk_rcg2 *rcg, u8 src, u32 *_cfg)
{
- u32 cfg, mask, d_val, not2d_val, n_minus_m;
struct clk_hw *hw = &rcg->clkr.hw;
- int ret, index = qcom_find_src_index(hw, rcg->parent_map, f->src);
+ u32 mask = CFG_SRC_SEL_MASK;
+ int index = qcom_find_src_index(hw, rcg->parent_map, src);
if (index < 0)
return index;
+ *_cfg &= ~mask;
+ *_cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
+
+ return 0;
+}
+
+static int __clk_rcg2_configure_mnd(struct clk_rcg2 *rcg, const struct freq_tbl *f,
+ u32 *_cfg)
+{
+ u32 cfg, mask, d_val, not2d_val, n_minus_m;
+ int ret;
+
if (rcg->mnd_width && f->n) {
mask = BIT(rcg->mnd_width) - 1;
ret = regmap_update_bits(rcg->clkr.regmap,
@@ -438,9 +549,8 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f,
}
mask = BIT(rcg->hid_width) - 1;
- mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK | CFG_HW_CLK_CTRL_MASK;
+ mask |= CFG_MODE_MASK | CFG_HW_CLK_CTRL_MASK;
cfg = f->pre_div << CFG_SRC_DIV_SHIFT;
- cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
if (rcg->mnd_width && f->n && (f->m != f->n))
cfg |= CFG_MODE_DUAL_EDGE;
if (rcg->hw_clk_ctrl)
@@ -452,6 +562,22 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f,
return 0;
}
+static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f,
+ u32 *_cfg)
+{
+ int ret;
+
+ ret = __clk_rcg2_configure_parent(rcg, f->src, _cfg);
+ if (ret)
+ return ret;
+
+ ret = __clk_rcg2_configure_mnd(rcg, f, _cfg);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
{
u32 cfg;
@@ -472,6 +598,26 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
return update_config(rcg);
}
+static int clk_rcg2_configure_gp(struct clk_rcg2 *rcg, const struct freq_tbl *f)
+{
+ u32 cfg;
+ int ret;
+
+ ret = regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg);
+ if (ret)
+ return ret;
+
+ ret = __clk_rcg2_configure_mnd(rcg, f, &cfg);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), cfg);
+ if (ret)
+ return ret;
+
+ return update_config(rcg);
+}
+
static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
enum freq_policy policy)
{
@@ -525,6 +671,28 @@ static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
return __clk_rcg2_set_rate(hw, rate, CEIL);
}
+static int clk_rcg2_set_gp_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+ int mnd_max = BIT(rcg->mnd_width) - 1;
+ int hid_max = BIT(rcg->hid_width) - 1;
+ struct freq_tbl *f;
+ int ret;
+
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
+
+ if (!f)
+ return -ENOMEM;
+
+ clk_rcg2_calc_mnd(parent_rate, rate, f, mnd_max, hid_max / 2);
+ convert_to_reg_val(f);
+ ret = clk_rcg2_configure_gp(rcg, f);
+ kfree(f);
+
+ return ret;
+}
+
static int clk_rcg2_set_floor_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
@@ -652,6 +820,18 @@ const struct clk_ops clk_rcg2_ops = {
};
EXPORT_SYMBOL_GPL(clk_rcg2_ops);
+const struct clk_ops clk_rcg2_gp_ops = {
+ .is_enabled = clk_rcg2_is_enabled,
+ .get_parent = clk_rcg2_get_parent,
+ .set_parent = clk_rcg2_set_parent,
+ .recalc_rate = clk_rcg2_recalc_rate,
+ .determine_rate = clk_rcg2_determine_gp_rate,
+ .set_rate = clk_rcg2_set_gp_rate,
+ .get_duty_cycle = clk_rcg2_get_duty_cycle,
+ .set_duty_cycle = clk_rcg2_set_duty_cycle,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_gp_ops);
+
const struct clk_ops clk_rcg2_floor_ops = {
.is_enabled = clk_rcg2_is_enabled,
.get_parent = clk_rcg2_get_parent,
diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
index dc3aa7014c3e..82da8138b766 100644
--- a/drivers/clk/qcom/gcc-sdm845.c
+++ b/drivers/clk/qcom/gcc-sdm845.c
@@ -283,26 +283,17 @@ static struct clk_rcg2 gcc_sdm670_cpuss_rbcpr_clk_src = {
},
};
-static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
- F(19200000, P_BI_TCXO, 1, 0, 0),
- F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
- F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
- F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
- F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
- { }
-};
-
static struct clk_rcg2 gcc_gp1_clk_src = {
.cmd_rcgr = 0x64004,
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_parent_map_1,
- .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .freq_tbl = {},
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_gp1_clk_src",
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_gp_ops,
},
};
@@ -311,12 +302,12 @@ static struct clk_rcg2 gcc_gp2_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_parent_map_1,
- .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .freq_tbl = {},
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_gp2_clk_src",
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_gp_ops,
},
};
@@ -325,12 +316,12 @@ static struct clk_rcg2 gcc_gp3_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_parent_map_1,
- .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .freq_tbl = {},
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_gp3_clk_src",
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_gp_ops,
},
};
--
2.39.2
^ permalink raw reply related
* [PATCH v4 02/27] clk: qcom: clk-rcg2: name refactoring
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
clk-rcg2.c uses 2 variable names for pre divisor register value:
pre_div and hid_div.
Replace hid_div with pre_div. Update calc_rate docs to reflect, that
pre_div is not pure divisor, but a register value, and requires conversion.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
drivers/clk/qcom/clk-rcg2.c | 51 ++++++++++++++++++++++++++-------------------
1 file changed, 29 insertions(+), 22 deletions(-)
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index bf26c5448f00..df491540ef39 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -153,13 +153,20 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
*
* parent_rate m
* rate = ----------- x ---
- * hid_div n
+ * pre_div_pure n
+ *
+ * @param rate - Parent rate.
+ * @param m - Multiplier.
+ * @param n - Divisor.
+ * @param mode - Use zero to ignore m/n calculation.
+ * @param pre_div - Pre divisor register value. Pure pre divisor value
+ * related to pre_div as pre_div_pure = (pre_div + 1) / 2
*/
static unsigned long
-calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div)
+calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 pre_div)
{
- if (hid_div)
- rate = mult_frac(rate, 2, hid_div + 1);
+ if (pre_div)
+ rate = mult_frac(rate, 2, pre_div + 1);
if (mode)
rate = mult_frac(rate, m, n);
@@ -171,7 +178,7 @@ static unsigned long
__clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate, u32 cfg)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
- u32 hid_div, m = 0, n = 0, mode = 0, mask;
+ u32 pre_div, m = 0, n = 0, mode = 0, mask;
if (rcg->mnd_width) {
mask = BIT(rcg->mnd_width) - 1;
@@ -186,10 +193,10 @@ __clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate, u32 cfg)
}
mask = BIT(rcg->hid_width) - 1;
- hid_div = cfg >> CFG_SRC_DIV_SHIFT;
- hid_div &= mask;
+ pre_div = cfg >> CFG_SRC_DIV_SHIFT;
+ pre_div &= mask;
- return calc_rate(parent_rate, m, n, mode, hid_div);
+ return calc_rate(parent_rate, m, n, mode, pre_div);
}
static unsigned long
@@ -715,7 +722,7 @@ static int clk_edp_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
s64 src_rate = parent_rate;
s64 request;
u32 mask = BIT(rcg->hid_width) - 1;
- u32 hid_div;
+ u32 pre_div;
if (src_rate == 810000000)
frac = frac_table_810m;
@@ -731,8 +738,8 @@ static int clk_edp_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
continue;
regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
- &hid_div);
- f.pre_div = hid_div;
+ &pre_div);
+ f.pre_div = pre_div;
f.pre_div >>= CFG_SRC_DIV_SHIFT;
f.pre_div &= mask;
f.m = frac->num;
@@ -760,7 +767,7 @@ static int clk_edp_pixel_determine_rate(struct clk_hw *hw,
int delta = 100000;
s64 request;
u32 mask = BIT(rcg->hid_width) - 1;
- u32 hid_div;
+ u32 pre_div;
int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
/* Force the correct parent */
@@ -781,13 +788,13 @@ static int clk_edp_pixel_determine_rate(struct clk_hw *hw,
continue;
regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
- &hid_div);
- hid_div >>= CFG_SRC_DIV_SHIFT;
- hid_div &= mask;
+ &pre_div);
+ pre_div >>= CFG_SRC_DIV_SHIFT;
+ pre_div &= mask;
req->rate = calc_rate(req->best_parent_rate,
frac->num, frac->den,
- !!frac->den, hid_div);
+ !!frac->den, pre_div);
return 0;
}
@@ -974,7 +981,7 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long request;
int delta = 100000;
u32 mask = BIT(rcg->hid_width) - 1;
- u32 hid_div, cfg;
+ u32 pre_div, cfg;
int i, num_parents = clk_hw_get_num_parents(hw);
regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
@@ -995,8 +1002,8 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
continue;
regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
- &hid_div);
- f.pre_div = hid_div;
+ &pre_div);
+ f.pre_div = pre_div;
f.pre_div >>= CFG_SRC_DIV_SHIFT;
f.pre_div &= mask;
f.m = frac->num;
@@ -1564,7 +1571,7 @@ static int clk_rcg2_dp_set_rate(struct clk_hw *hw, unsigned long rate,
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
struct freq_tbl f = { 0 };
u32 mask = BIT(rcg->hid_width) - 1;
- u32 hid_div, cfg;
+ u32 pre_div, cfg;
int i, num_parents = clk_hw_get_num_parents(hw);
unsigned long num, den;
@@ -1576,7 +1583,7 @@ static int clk_rcg2_dp_set_rate(struct clk_hw *hw, unsigned long rate,
return -EINVAL;
regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
- hid_div = cfg;
+ pre_div = cfg;
cfg &= CFG_SRC_SEL_MASK;
cfg >>= CFG_SRC_SEL_SHIFT;
@@ -1587,7 +1594,7 @@ static int clk_rcg2_dp_set_rate(struct clk_hw *hw, unsigned long rate,
}
}
- f.pre_div = hid_div;
+ f.pre_div = pre_div;
f.pre_div >>= CFG_SRC_DIV_SHIFT;
f.pre_div &= mask;
--
2.39.2
^ permalink raw reply related
* [PATCH v4 01/27] power: supply: add undervoltage health status property
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
In-Reply-To: <20240913-starqltechn_integration_upstream-v4-0-2d2efd5c5877@gmail.com>
Add POWER_SUPPLY_HEALTH_UNDERVOLTAGE status for power supply
to report under voltage lockout failures.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
include/linux/power_supply.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 910d407ebe63..8682e6466544 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -58,6 +58,7 @@ enum {
POWER_SUPPLY_HEALTH_OVERHEAT,
POWER_SUPPLY_HEALTH_DEAD,
POWER_SUPPLY_HEALTH_OVERVOLTAGE,
+ POWER_SUPPLY_HEALTH_UNDERVOLTAGE,
POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
POWER_SUPPLY_HEALTH_COLD,
POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE,
--
2.39.2
^ permalink raw reply related
* [PATCH v4 00/27] This is continued work on Samsung S9(SM-9600) starqltechn
From: Dzmitry Sankouski @ 2024-09-13 15:07 UTC (permalink / raw)
To: Sebastian Reichel, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Neil Armstrong, Jessica Zhang, Sam Ravnborg,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lee Jones,
Dmitry Torokhov, Pavel Machek, Liam Girdwood, Mark Brown,
Uwe Kleine-König, Krzysztof Kozlowski, Chanwoo Choi,
Simona Vetter, cros-qcom-dts-watchers, Konrad Dybcio,
Simona Vetter, Konrad Dybcio
Cc: linux-pm, linux-kernel, linux-arm-msm, linux-clk, dri-devel,
devicetree, linux-input, linux-leds, linux-pwm, linux-samsung-soc,
Dzmitry Sankouski
Add support for new features:
- sound (headphones and mics only)
- gpu
- panel
- buttons
- MAX77705 MFD:
- charger
- fuelgauge
- haptic
- led
Changes in version 2:
- s2dos05 regulator:
- hex to decimal in regulator values
- fix compatible value
- remove interrupt specific code, because it's
empty in vendor kernel, and I cannot test it on
available hardware anyway.
Changes in version 3:
Version 3 has significant changes:
- more drivers added
- s2dos05 driver converted to MFD
- disable crypto patch removed(disabled on distro level)
- dts framebuffer node along with related patches removed,
because panel driver added
- fix 'make O=.output_arm64 CHECK_DTBS=y qcom/sdm845-samsung-starqltechn.dtb'
errors, but it still complains on 'monitored-battery' and
'power-supplies' though I have 'power-supply.yaml' link in charger
and fuel gauge bindings.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes in v4:
- Rewrite max77705, max77705_charger, max77705_fuel_gauge from scratch
- Reorder patches:
- squash max77705 subdevice bindings in core file because
no resources there
- split device tree changes
- Use _ as space for filenames in power/supply like the majority
- Replace gcc-845 freq_tbl frequencies patch with new approach,
based on automatic m/n/pre_div value generation
- Link to v3: https://lore.kernel.org/r/20240618-starqltechn_integration_upstream-v3-0-e3f6662017ac@gmail.com
---
Dzmitry Sankouski (27):
power: supply: add undervoltage health status property
clk: qcom: clk-rcg2: name refactoring
gcc-sdm845: Add general purpose clock ops
dt-bindings: panel: add Samsung s6e3ha8
dt-bindings: mfd: add maxim,max77705
dt-bindings: mfd: add samsung,s2dos05
drm/panel: Add support for S6E3HA8 panel driver
mfd: max77693: remove unused declarations
mfd: Add new driver for MAX77705 PMIC
input: max77693: add max77705 haptic support
power: supply: max77705: Add charger driver for Maxim 77705
power: supply: max77705: Add fuel gauge driver for Maxim 77705
leds: max77705: Add LEDs support
mfd: sec-core: add s2dos05 support
regulator: add s2dos05 regulator support
arm64: dts: qcom: sdm845: enable gmu
arm64: dts: qcom: starqltechn: remove wifi
arm64: dts: qcom: starqltechn: fix usb regulator mistake
arm64: dts: qcom: starqltechn: refactor node order
arm64: dts: qcom: starqltechn: remove excess reserved gpios
arm64: dts: qcom: starqltechn: add gpio keys
arm64: dts: qcom: starqltechn: add max77705 PMIC
arm64: dts: qcom: starqltechn: add display PMIC
arm64: dts: qcom: starqltechn: add touchscreen support
arm64: dts: qcom: starqltechn: add initial sound support
arm64: dts: qcom: starqltechn: add graphics support
arm64: dts: qcom: starqltechn: add modem support
.../bindings/display/panel/samsung,s6e3ha8.yaml | 75 +++
.../devicetree/bindings/mfd/maxim,max77705.yaml | 169 ++++++
.../devicetree/bindings/mfd/samsung,s2dos05.yaml | 99 ++++
MAINTAINERS | 12 +
arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi | 4 -
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 -
arch/arm64/boot/dts/qcom/sdm845-mtp.dts | 4 -
.../arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi | 4 -
.../boot/dts/qcom/sdm845-samsung-starqltechn.dts | 573 +++++++++++++++++++-
arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts | 4 -
.../boot/dts/qcom/sdm845-sony-xperia-tama.dtsi | 4 -
.../dts/qcom/sdm845-xiaomi-beryllium-common.dtsi | 4 -
arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts | 4 -
arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 -
drivers/clk/qcom/clk-rcg.h | 1 +
drivers/clk/qcom/clk-rcg2.c | 243 ++++++++-
drivers/clk/qcom/gcc-sdm845.c | 21 +-
drivers/gpu/drm/panel/Kconfig | 7 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-samsung-s6e3ha8.c | 350 ++++++++++++
drivers/input/misc/Kconfig | 4 +-
drivers/input/misc/Makefile | 1 +
drivers/input/misc/max77693-haptic.c | 15 +-
drivers/leds/Kconfig | 6 +
drivers/leds/Makefile | 1 +
drivers/leds/leds-max77705.c | 158 ++++++
drivers/mfd/Kconfig | 12 +
drivers/mfd/Makefile | 2 +
drivers/mfd/max77705.c | 248 +++++++++
drivers/mfd/sec-core.c | 11 +
drivers/power/supply/Kconfig | 13 +
drivers/power/supply/Makefile | 2 +
drivers/power/supply/max77705_charger.c | 585 +++++++++++++++++++++
drivers/power/supply/max77705_fuel_gauge.c | 348 ++++++++++++
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/s2dos05-regulator.c | 176 +++++++
include/linux/mfd/max77693-common.h | 6 +-
include/linux/mfd/max77693-private.h | 11 -
include/linux/mfd/max77705-private.h | 180 +++++++
include/linux/mfd/max77705_charger.h | 215 ++++++++
include/linux/mfd/samsung/core.h | 1 +
include/linux/power/max77705_fuelgauge.h | 65 +++
include/linux/power_supply.h | 1 +
include/linux/regulator/s2dos05.h | 73 +++
45 files changed, 3627 insertions(+), 101 deletions(-)
---
base-commit: 5acd9952f95fb4b7da6d09a3be39195a80845eb6
change-id: 20240617-starqltechn_integration_upstream-bc86850b2fe3
Best regards,
--
Dzmitry Sankouski <dsankouski@gmail.com>
^ permalink raw reply
* Re: [PATCH v4 27/28] gcc-sdm845: Add general purpose clock ops
From: Dzmitry Sankouski @ 2024-09-13 15:06 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: dmitry.baryshkov, Sebastian Reichel, Bjorn Andersson,
Michael Turquette, Stephen Boyd, Neil Armstrong, Jessica Zhang,
Sam Ravnborg, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Daniel Vetter, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lee Jones, Dmitry Torokhov, Pavel Machek,
Liam Girdwood, Mark Brown, Krzysztof Kozlowski, Konrad Dybcio,
Chanwoo Choi, linux-pm, linux-kernel, linux-arm-msm, linux-clk,
dri-devel, devicetree, linux-input, linux-leds, linux-pwm,
linux-samsung-soc
In-Reply-To: <uevafpb6r7rfutiqrm5asfvv7zfxcb3acrlxqpispele5er52x@eegonpzqlm7j>
вт, 10 сент. 2024 г. в 12:59, Uwe Kleine-König <u.kleine-koenig@baylibre.com>:
>
> Hello,
>
> On Fri, Jul 19, 2024 at 03:55:04PM +0300, Dzmitry Sankouski wrote:
> > SDM845 has "General Purpose" clocks that can be muxed to
> > SoC pins to clock various external devices.
> > Those clocks may be used as e.g. PWM sources for external peripherals.
> >
> > GPCLK can in theory have arbitrary value depending on the use case, so
> > the concept of frequency tables, used in rcg2 clock driver, is not
> > efficient, because it allows only defined frequencies.
> >
> > Introduce clk_rcg2_gp_ops, which automatically calculate clock
> > mnd values for arbitrary clock rate.
> >
> > Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
> > ---
> > drivers/clk/qcom/clk-rcg.h | 1 +
> > drivers/clk/qcom/clk-rcg2.c | 162 ++++++++++++++++++++++++++++++++++++++++--
> > drivers/clk/qcom/gcc-sdm845.c | 19 ++---
> > drivers/pwm/pwm-clk.c | 5 ++
>
> I don't understand why a change to some qcom clk implementation detail
> needs a change to drivers/pwm/pwm-clk.c in the same commit. I guess if
> the change to drivers/pwm/pwm-clk.c is needed it should better go into a
> separate patch with an appropriate commit log?!
>
You're right, I'll fix that. Also I heavily rewrote this patch, and
included it in
starqltechn patch series. Since this patch has the wrong version (sorry for my
mistake) and order numbering, please consider the next patch a successor of it.
--
Best regards,
Dzmitry
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox